]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 14 Jul 2008 20:37:29 +0000 (13:37 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 14 Jul 2008 20:37:29 +0000 (13:37 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6: (31 commits)
  avr32: Fix typo of IFSR in a comment in the PIO header file
  avr32: Power Management support ("standby" and "mem" modes)
  avr32: Add system device for the internal interrupt controller (intc)
  avr32: Add simple SRAM allocator
  avr32: Enable SDRAMC clock at startup
  rtc-at32ap700x: Enable wakeup
  macb: Basic suspend/resume support
  atmel_serial: Drain console TX shifter before suspending
  atmel_serial: Fix build on avr32 with CONFIG_PM enabled
  avr32: Use a quicklist for PTE allocation as well
  avr32: Use a quicklist for PGD allocation
  avr32: Cover the kernel page tables in the user PGDs
  avr32: Store virtual addresses in the PGD
  avr32: Remove useless zeroing of swapper_pg_dir at startup
  avr32: Clean up and optimize the TLB operations
  avr32: Rename at32ap.c -> pdc.c
  avr32: Move setup_platform() into chip-specific file
  avr32: Kill special exception handler sections
  avr32: Kill unneeded #include <asm/pgalloc.h> from asm/mmu_context.h
  avr32: Clean up time.c #includes
  ...

1092 files changed:
.gitignore
CREDITS
Documentation/ABI/testing/sysfs-block
Documentation/ABI/testing/sysfs-bus-css [new file with mode: 0644]
Documentation/HOWTO
Documentation/accounting/taskstats-struct.txt
Documentation/auxdisplay/cfag12864b
Documentation/auxdisplay/cfag12864b-example.c
Documentation/auxdisplay/ks0108
Documentation/block/data-integrity.txt [new file with mode: 0644]
Documentation/cgroups.txt
Documentation/controllers/devices.txt
Documentation/cpusets.txt
Documentation/feature-removal-schedule.txt
Documentation/ftrace.txt [new file with mode: 0644]
Documentation/i2c/writing-clients
Documentation/ioctl-number.txt
Documentation/kernel-parameters.txt
Documentation/networking/ip-sysctl.txt
Documentation/networking/s2io.txt
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
Documentation/video4linux/CARDLIST.au0828
Documentation/vm/slabinfo.c
Documentation/vm/slub.txt
MAINTAINERS
Makefile
arch/alpha/kernel/vmlinux.lds.S
arch/arm/common/dmabounce.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-realview/platsmp.c
arch/arm/plat-omap/dma.c
arch/blackfin/kernel/cplb-nompu/cplbinit.c
arch/blackfin/kernel/irqchip.c
arch/ia64/kernel/setup.c
arch/ia64/kernel/time.c
arch/mips/Kconfig
arch/mips/kernel/cevt-txx9.c
arch/mips/mm/c-r3k.c
arch/mips/mm/page.c
arch/mips/mm/sc-rm7k.c
arch/mips/sgi-ip32/ip32-irq.c
arch/mn10300/kernel/mn10300_ksyms.c
arch/mn10300/kernel/process.c
arch/mn10300/lib/Makefile
arch/mn10300/lib/__ucmpdi2.S [new file with mode: 0644]
arch/powerpc/boot/Makefile
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/of_platform.c
arch/powerpc/platforms/52xx/lite5200_pm.c
arch/s390/Kconfig
arch/s390/appldata/appldata.h
arch/s390/appldata/appldata_base.c
arch/s390/appldata/appldata_mem.c
arch/s390/appldata/appldata_net_sum.c
arch/s390/appldata/appldata_os.c
arch/s390/crypto/prng.c
arch/s390/hypfs/inode.c
arch/s390/kernel/Makefile
arch/s390/kernel/binfmt_elf32.c [deleted file]
arch/s390/kernel/compat_ptrace.h
arch/s390/kernel/debug.c
arch/s390/kernel/early.c
arch/s390/kernel/ipl.c
arch/s390/kernel/kprobes.c
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/mem_detect.c [new file with mode: 0644]
arch/s390/kernel/process.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/setup.c
arch/s390/kernel/time.c
arch/s390/kernel/topology.c
arch/s390/kernel/vtime.c
arch/s390/mm/init.c
arch/um/Makefile
arch/um/Makefile-i386
arch/um/Makefile-x86_64
arch/x86/Kconfig
arch/x86/kernel/.gitignore
arch/x86/kernel/acpi/realmode/wakeup.S
arch/x86/kernel/acpi/realmode/wakeup.h
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/efi_32.c
arch/x86/kernel/head_64.S
arch/x86/kernel/i387.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/traps_64.c
arch/x86/mm/init_64.c
arch/x86/mm/ioremap.c
arch/x86/pci/common.c
arch/x86/xen/mmu.c
block/Kconfig
block/Makefile
block/as-iosched.c
block/blk-core.c
block/blk-integrity.c [new file with mode: 0644]
block/blk-map.c
block/blk-merge.c
block/blk-settings.c
block/blk.h
block/blktrace.c
block/bsg.c
block/cfq-iosched.c
block/cmd-filter.c [new file with mode: 0644]
block/elevator.c
block/genhd.c
block/scsi_ioctl.c
crypto/chainiv.c
crypto/tcrypt.c
drivers/Makefile
drivers/acpi/bay.c
drivers/acpi/dock.c
drivers/acpi/glue.c
drivers/acpi/sleep/main.c
drivers/acpi/sleep/proc.c
drivers/ata/ahci.c
drivers/ata/libata-acpi.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/pata_sis.c
drivers/ata/sata_mv.c
drivers/ata/sata_sil24.c
drivers/ata/sata_uli.c
drivers/auxdisplay/Kconfig
drivers/auxdisplay/cfag12864b.c
drivers/auxdisplay/cfag12864bfb.c
drivers/auxdisplay/ks0108.c
drivers/base/node.c
drivers/block/DAC960.c
drivers/block/aoe/aoecmd.c
drivers/block/cciss.c
drivers/block/paride/pt.c
drivers/block/pktcdvd.c
drivers/block/xen-blkfront.c
drivers/cdrom/cdrom.c
drivers/char/Makefile
drivers/char/drm/Kconfig [deleted file]
drivers/char/drm/Makefile [deleted file]
drivers/char/drm/README.drm [deleted file]
drivers/char/drm/ati_pcigart.c [deleted file]
drivers/char/drm/drm.h [deleted file]
drivers/char/drm/drmP.h [deleted file]
drivers/char/drm/drm_agpsupport.c [deleted file]
drivers/char/drm/drm_auth.c [deleted file]
drivers/char/drm/drm_bufs.c [deleted file]
drivers/char/drm/drm_context.c [deleted file]
drivers/char/drm/drm_core.h [deleted file]
drivers/char/drm/drm_dma.c [deleted file]
drivers/char/drm/drm_drawable.c [deleted file]
drivers/char/drm/drm_drv.c [deleted file]
drivers/char/drm/drm_fops.c [deleted file]
drivers/char/drm/drm_hashtab.c [deleted file]
drivers/char/drm/drm_hashtab.h [deleted file]
drivers/char/drm/drm_ioc32.c [deleted file]
drivers/char/drm/drm_ioctl.c [deleted file]
drivers/char/drm/drm_irq.c [deleted file]
drivers/char/drm/drm_lock.c [deleted file]
drivers/char/drm/drm_memory.c [deleted file]
drivers/char/drm/drm_memory.h [deleted file]
drivers/char/drm/drm_memory_debug.h [deleted file]
drivers/char/drm/drm_mm.c [deleted file]
drivers/char/drm/drm_os_linux.h [deleted file]
drivers/char/drm/drm_pci.c [deleted file]
drivers/char/drm/drm_pciids.h [deleted file]
drivers/char/drm/drm_proc.c [deleted file]
drivers/char/drm/drm_sarea.h [deleted file]
drivers/char/drm/drm_scatter.c [deleted file]
drivers/char/drm/drm_sman.c [deleted file]
drivers/char/drm/drm_sman.h [deleted file]
drivers/char/drm/drm_stub.c [deleted file]
drivers/char/drm/drm_sysfs.c [deleted file]
drivers/char/drm/drm_vm.c [deleted file]
drivers/char/drm/i810_dma.c [deleted file]
drivers/char/drm/i810_drm.h [deleted file]
drivers/char/drm/i810_drv.c [deleted file]
drivers/char/drm/i810_drv.h [deleted file]
drivers/char/drm/i830_dma.c [deleted file]
drivers/char/drm/i830_drm.h [deleted file]
drivers/char/drm/i830_drv.c [deleted file]
drivers/char/drm/i830_drv.h [deleted file]
drivers/char/drm/i830_irq.c [deleted file]
drivers/char/drm/i915_dma.c [deleted file]
drivers/char/drm/i915_drm.h [deleted file]
drivers/char/drm/i915_drv.c [deleted file]
drivers/char/drm/i915_drv.h [deleted file]
drivers/char/drm/i915_ioc32.c [deleted file]
drivers/char/drm/i915_irq.c [deleted file]
drivers/char/drm/i915_mem.c [deleted file]
drivers/char/drm/mga_dma.c [deleted file]
drivers/char/drm/mga_drm.h [deleted file]
drivers/char/drm/mga_drv.c [deleted file]
drivers/char/drm/mga_drv.h [deleted file]
drivers/char/drm/mga_ioc32.c [deleted file]
drivers/char/drm/mga_irq.c [deleted file]
drivers/char/drm/mga_state.c [deleted file]
drivers/char/drm/mga_ucode.h [deleted file]
drivers/char/drm/mga_warp.c [deleted file]
drivers/char/drm/r128_cce.c [deleted file]
drivers/char/drm/r128_drm.h [deleted file]
drivers/char/drm/r128_drv.c [deleted file]
drivers/char/drm/r128_drv.h [deleted file]
drivers/char/drm/r128_ioc32.c [deleted file]
drivers/char/drm/r128_irq.c [deleted file]
drivers/char/drm/r128_state.c [deleted file]
drivers/char/drm/r300_cmdbuf.c [deleted file]
drivers/char/drm/r300_reg.h [deleted file]
drivers/char/drm/radeon_cp.c [deleted file]
drivers/char/drm/radeon_drm.h [deleted file]
drivers/char/drm/radeon_drv.c [deleted file]
drivers/char/drm/radeon_drv.h [deleted file]
drivers/char/drm/radeon_ioc32.c [deleted file]
drivers/char/drm/radeon_irq.c [deleted file]
drivers/char/drm/radeon_mem.c [deleted file]
drivers/char/drm/radeon_microcode.h [deleted file]
drivers/char/drm/radeon_state.c [deleted file]
drivers/char/drm/savage_bci.c [deleted file]
drivers/char/drm/savage_drm.h [deleted file]
drivers/char/drm/savage_drv.c [deleted file]
drivers/char/drm/savage_drv.h [deleted file]
drivers/char/drm/savage_state.c [deleted file]
drivers/char/drm/sis_drm.h [deleted file]
drivers/char/drm/sis_drv.c [deleted file]
drivers/char/drm/sis_drv.h [deleted file]
drivers/char/drm/sis_mm.c [deleted file]
drivers/char/drm/tdfx_drv.c [deleted file]
drivers/char/drm/tdfx_drv.h [deleted file]
drivers/char/drm/via_3d_reg.h [deleted file]
drivers/char/drm/via_dma.c [deleted file]
drivers/char/drm/via_dmablit.c [deleted file]
drivers/char/drm/via_dmablit.h [deleted file]
drivers/char/drm/via_drm.h [deleted file]
drivers/char/drm/via_drv.c [deleted file]
drivers/char/drm/via_drv.h [deleted file]
drivers/char/drm/via_irq.c [deleted file]
drivers/char/drm/via_map.c [deleted file]
drivers/char/drm/via_mm.c [deleted file]
drivers/char/drm/via_verifier.c [deleted file]
drivers/char/drm/via_verifier.h [deleted file]
drivers/char/drm/via_video.c [deleted file]
drivers/char/ipmi/ipmi_watchdog.c
drivers/char/pcmcia/cm4000_cs.c
drivers/char/pcmcia/cm4040_cs.c
drivers/char/pcmcia/ipwireless/hardware.c
drivers/char/pcmcia/ipwireless/main.c
drivers/char/rtc.c
drivers/char/tpm/tpm_tis.c
drivers/char/tty_io.c
drivers/connector/connector.c
drivers/firewire/fw-sbp2.c
drivers/gpio/Kconfig
drivers/gpio/pca953x.c
drivers/gpu/Makefile [new file with mode: 0644]
drivers/gpu/drm/Kconfig [new file with mode: 0644]
drivers/gpu/drm/Makefile [new file with mode: 0644]
drivers/gpu/drm/README.drm [new file with mode: 0644]
drivers/gpu/drm/ati_pcigart.c [new file with mode: 0644]
drivers/gpu/drm/drm_agpsupport.c [new file with mode: 0644]
drivers/gpu/drm/drm_auth.c [new file with mode: 0644]
drivers/gpu/drm/drm_bufs.c [new file with mode: 0644]
drivers/gpu/drm/drm_context.c [new file with mode: 0644]
drivers/gpu/drm/drm_dma.c [new file with mode: 0644]
drivers/gpu/drm/drm_drawable.c [new file with mode: 0644]
drivers/gpu/drm/drm_drv.c [new file with mode: 0644]
drivers/gpu/drm/drm_fops.c [new file with mode: 0644]
drivers/gpu/drm/drm_hashtab.c [new file with mode: 0644]
drivers/gpu/drm/drm_ioc32.c [new file with mode: 0644]
drivers/gpu/drm/drm_ioctl.c [new file with mode: 0644]
drivers/gpu/drm/drm_irq.c [new file with mode: 0644]
drivers/gpu/drm/drm_lock.c [new file with mode: 0644]
drivers/gpu/drm/drm_memory.c [new file with mode: 0644]
drivers/gpu/drm/drm_mm.c [new file with mode: 0644]
drivers/gpu/drm/drm_pci.c [new file with mode: 0644]
drivers/gpu/drm/drm_proc.c [new file with mode: 0644]
drivers/gpu/drm/drm_scatter.c [new file with mode: 0644]
drivers/gpu/drm/drm_sman.c [new file with mode: 0644]
drivers/gpu/drm/drm_stub.c [new file with mode: 0644]
drivers/gpu/drm/drm_sysfs.c [new file with mode: 0644]
drivers/gpu/drm/drm_vm.c [new file with mode: 0644]
drivers/gpu/drm/i810/Makefile [new file with mode: 0644]
drivers/gpu/drm/i810/i810_dma.c [new file with mode: 0644]
drivers/gpu/drm/i810/i810_drv.c [new file with mode: 0644]
drivers/gpu/drm/i810/i810_drv.h [new file with mode: 0644]
drivers/gpu/drm/i830/Makefile [new file with mode: 0644]
drivers/gpu/drm/i830/i830_dma.c [new file with mode: 0644]
drivers/gpu/drm/i830/i830_drv.c [new file with mode: 0644]
drivers/gpu/drm/i830/i830_drv.h [new file with mode: 0644]
drivers/gpu/drm/i830/i830_irq.c [new file with mode: 0644]
drivers/gpu/drm/i915/Makefile [new file with mode: 0644]
drivers/gpu/drm/i915/i915_dma.c [new file with mode: 0644]
drivers/gpu/drm/i915/i915_drv.c [new file with mode: 0644]
drivers/gpu/drm/i915/i915_drv.h [new file with mode: 0644]
drivers/gpu/drm/i915/i915_ioc32.c [new file with mode: 0644]
drivers/gpu/drm/i915/i915_irq.c [new file with mode: 0644]
drivers/gpu/drm/i915/i915_mem.c [new file with mode: 0644]
drivers/gpu/drm/mga/Makefile [new file with mode: 0644]
drivers/gpu/drm/mga/mga_dma.c [new file with mode: 0644]
drivers/gpu/drm/mga/mga_drv.c [new file with mode: 0644]
drivers/gpu/drm/mga/mga_drv.h [new file with mode: 0644]
drivers/gpu/drm/mga/mga_ioc32.c [new file with mode: 0644]
drivers/gpu/drm/mga/mga_irq.c [new file with mode: 0644]
drivers/gpu/drm/mga/mga_state.c [new file with mode: 0644]
drivers/gpu/drm/mga/mga_ucode.h [new file with mode: 0644]
drivers/gpu/drm/mga/mga_warp.c [new file with mode: 0644]
drivers/gpu/drm/r128/Makefile [new file with mode: 0644]
drivers/gpu/drm/r128/r128_cce.c [new file with mode: 0644]
drivers/gpu/drm/r128/r128_drv.c [new file with mode: 0644]
drivers/gpu/drm/r128/r128_drv.h [new file with mode: 0644]
drivers/gpu/drm/r128/r128_ioc32.c [new file with mode: 0644]
drivers/gpu/drm/r128/r128_irq.c [new file with mode: 0644]
drivers/gpu/drm/r128/r128_state.c [new file with mode: 0644]
drivers/gpu/drm/radeon/Makefile [new file with mode: 0644]
drivers/gpu/drm/radeon/r300_cmdbuf.c [new file with mode: 0644]
drivers/gpu/drm/radeon/r300_reg.h [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_cp.c [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_drv.c [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_drv.h [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_ioc32.c [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_irq.c [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_mem.c [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_microcode.h [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_state.c [new file with mode: 0644]
drivers/gpu/drm/savage/Makefile [new file with mode: 0644]
drivers/gpu/drm/savage/savage_bci.c [new file with mode: 0644]
drivers/gpu/drm/savage/savage_drv.c [new file with mode: 0644]
drivers/gpu/drm/savage/savage_drv.h [new file with mode: 0644]
drivers/gpu/drm/savage/savage_state.c [new file with mode: 0644]
drivers/gpu/drm/sis/Makefile [new file with mode: 0644]
drivers/gpu/drm/sis/sis_drv.c [new file with mode: 0644]
drivers/gpu/drm/sis/sis_drv.h [new file with mode: 0644]
drivers/gpu/drm/sis/sis_mm.c [new file with mode: 0644]
drivers/gpu/drm/tdfx/Makefile [new file with mode: 0644]
drivers/gpu/drm/tdfx/tdfx_drv.c [new file with mode: 0644]
drivers/gpu/drm/tdfx/tdfx_drv.h [new file with mode: 0644]
drivers/gpu/drm/via/Makefile [new file with mode: 0644]
drivers/gpu/drm/via/via_3d_reg.h [new file with mode: 0644]
drivers/gpu/drm/via/via_dma.c [new file with mode: 0644]
drivers/gpu/drm/via/via_dmablit.c [new file with mode: 0644]
drivers/gpu/drm/via/via_dmablit.h [new file with mode: 0644]
drivers/gpu/drm/via/via_drv.c [new file with mode: 0644]
drivers/gpu/drm/via/via_drv.h [new file with mode: 0644]
drivers/gpu/drm/via/via_irq.c [new file with mode: 0644]
drivers/gpu/drm/via/via_map.c [new file with mode: 0644]
drivers/gpu/drm/via/via_mm.c [new file with mode: 0644]
drivers/gpu/drm/via/via_verifier.c [new file with mode: 0644]
drivers/gpu/drm/via/via_verifier.h [new file with mode: 0644]
drivers/gpu/drm/via/via_video.c [new file with mode: 0644]
drivers/hwmon/hdaps.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/ide/Kconfig
drivers/ide/arm/Makefile
drivers/ide/arm/bast-ide.c [new file with mode: 0644]
drivers/ide/arm/palm_bk3710.c
drivers/ide/ide-probe.c
drivers/ide/ide-proc.c
drivers/ide/ide.c
drivers/ide/legacy/ide-cs.c
drivers/ide/pci/it8213.c
drivers/ide/pci/ns87415.c
drivers/infiniband/hw/cxgb3/iwch_provider.c
drivers/input/ff-core.c
drivers/isdn/i4l/isdn_common.c
drivers/md/dm-crypt.c
drivers/md/linear.c
drivers/md/md.c
drivers/md/raid0.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/common/ir-keymaps.c
drivers/media/common/tuners/tda18271-common.c
drivers/media/common/tuners/tda18271-fe.c
drivers/media/common/tuners/xc5000.c
drivers/media/common/tuners/xc5000_priv.h
drivers/media/dvb/dvb-usb/gl861.c
drivers/media/dvb/dvb-usb/umt-010.c
drivers/media/dvb/frontends/au8522.c
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/tda10023.c
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/av7110_hw.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/au0828/au0828-cards.c
drivers/media/video/cx18/Kconfig
drivers/media/video/cx18/cx18-av-core.c
drivers/media/video/cx18/cx18-av-core.h
drivers/media/video/cx18/cx18-cards.c
drivers/media/video/cx18/cx18-cards.h
drivers/media/video/cx18/cx18-dvb.c
drivers/media/video/cx18/cx18-gpio.c
drivers/media/video/cx18/cx18-gpio.h
drivers/media/video/cx18/cx18-i2c.c
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx88/cx88-alsa.c
drivers/media/video/em28xx/em28xx-audio.c
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-dvb.c
drivers/media/video/em28xx/em28xx-reg.h
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/ov7670.c
drivers/media/video/pxa_camera.c
drivers/media/video/saa7134/saa7134-alsa.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/soc_camera.c
drivers/media/video/uvc/Makefile [new file with mode: 0644]
drivers/media/video/uvc/uvc_ctrl.c [new file with mode: 0644]
drivers/media/video/uvc/uvc_driver.c [new file with mode: 0644]
drivers/media/video/uvc/uvc_isight.c [new file with mode: 0644]
drivers/media/video/uvc/uvc_queue.c [new file with mode: 0644]
drivers/media/video/uvc/uvc_status.c [new file with mode: 0644]
drivers/media/video/uvc/uvc_v4l2.c [new file with mode: 0644]
drivers/media/video/uvc/uvc_video.c [new file with mode: 0644]
drivers/media/video/uvc/uvcvideo.h [new file with mode: 0644]
drivers/media/video/videodev.c
drivers/media/video/vivi.c
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptspi.c
drivers/mmc/host/pxamci.c
drivers/mmc/host/sdhci.c
drivers/mtd/ftl.c
drivers/mtd/maps/pcmciamtd.c
drivers/net/3c59x.c
drivers/net/e100.c
drivers/net/e1000/e1000_ethtool.c
drivers/net/e1000e/netdev.c
drivers/net/ehea/ehea.h
drivers/net/ehea/ehea_main.c
drivers/net/forcedeth.c
drivers/net/fs_enet/mac-fcc.c
drivers/net/hamradio/dmascc.c
drivers/net/ibm_newemac/core.c
drivers/net/igb/igb_main.c
drivers/net/ipg.c
drivers/net/irda/nsc-ircc.c
drivers/net/irda/via-ircc.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/pasemi_mac.c
drivers/net/pcmcia/axnet_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/qla3xxx.c
drivers/net/r6040.c
drivers/net/s2io.c
drivers/net/s2io.h
drivers/net/tc35815.c
drivers/net/tun.c
drivers/net/wan/hdlc_fr.c
drivers/net/wan/x25_asy.c
drivers/net/wireless/b43/leds.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43legacy/dma.c
drivers/net/wireless/b43legacy/main.c
drivers/net/wireless/hostap/hostap_80211_rx.c
drivers/net/wireless/hostap/hostap_ap.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/hostap/hostap_hw.c
drivers/net/wireless/hostap/hostap_main.c
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/iwlwifi/iwl4965-base.c
drivers/net/wireless/libertas/if_usb.c
drivers/net/wireless/libertas/scan.c
drivers/net/wireless/prism54/islpci_eth.c
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/net/xen-netfront.c
drivers/pci/access.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.h
drivers/pci/quirks.c
drivers/pcmcia/Kconfig
drivers/pcmcia/Makefile
drivers/pcmcia/au1000_generic.h
drivers/pcmcia/au1000_pb1x00.c
drivers/pcmcia/au1000_xxs1500.c
drivers/pcmcia/bfin_cf_pcmcia.c [new file with mode: 0644]
drivers/pcmcia/cardbus.c
drivers/pcmcia/cistpl.c
drivers/pcmcia/cs.c
drivers/pcmcia/cs_internal.h
drivers/pcmcia/ds.c
drivers/pcmcia/hd64465_ss.c
drivers/pcmcia/i82092.c
drivers/pcmcia/i82092aa.h
drivers/pcmcia/i82365.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pcmcia/pcmcia_ioctl.c
drivers/pcmcia/pcmcia_resource.c
drivers/pcmcia/pxa2xx_base.c
drivers/pcmcia/rsrc_mgr.c
drivers/pcmcia/rsrc_nonstatic.c
drivers/pcmcia/soc_common.h
drivers/pcmcia/socket_sysfs.c
drivers/pcmcia/ti113x.h
drivers/rapidio/rio-driver.c
drivers/rtc/interface.c
drivers/rtc/rtc-fm3130.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-sa1100.c
drivers/rtc/rtc-x1205.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dcssblk.c
drivers/s390/block/xpram.c
drivers/s390/char/con3215.c
drivers/s390/char/con3270.c
drivers/s390/char/fs3270.c
drivers/s390/char/monreader.c
drivers/s390/char/raw3270.c
drivers/s390/char/sclp.c
drivers/s390/char/sclp_cmd.c
drivers/s390/char/sclp_con.c
drivers/s390/char/sclp_config.c
drivers/s390/char/sclp_cpi_sys.c
drivers/s390/char/sclp_quiesce.c
drivers/s390/char/sclp_rw.c
drivers/s390/char/sclp_sdias.c
drivers/s390/char/sclp_tty.c
drivers/s390/char/sclp_tty.h
drivers/s390/char/sclp_vt220.c
drivers/s390/char/tape_34xx.c
drivers/s390/char/tape_3590.c
drivers/s390/char/tape_core.c
drivers/s390/char/tty3270.c
drivers/s390/char/vmcp.c
drivers/s390/char/vmlogrdr.c
drivers/s390/char/vmur.c
drivers/s390/char/vmwatchdog.c
drivers/s390/char/zcore.c
drivers/s390/cio/Makefile
drivers/s390/cio/airq.c
drivers/s390/cio/chp.c
drivers/s390/cio/chp.h
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc.h
drivers/s390/cio/chsc_sch.c [new file with mode: 0644]
drivers/s390/cio/chsc_sch.h [new file with mode: 0644]
drivers/s390/cio/cio.c
drivers/s390/cio/cio.h
drivers/s390/cio/cmf.c
drivers/s390/cio/css.c
drivers/s390/cio/css.h
drivers/s390/cio/device.c
drivers/s390/cio/device.h
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_id.c
drivers/s390/cio/device_ops.c
drivers/s390/cio/device_pgid.c
drivers/s390/cio/device_status.c
drivers/s390/cio/fcx.c [new file with mode: 0644]
drivers/s390/cio/idset.h
drivers/s390/cio/io_sch.h
drivers/s390/cio/ioasm.h
drivers/s390/cio/isc.c [new file with mode: 0644]
drivers/s390/cio/itcw.c [new file with mode: 0644]
drivers/s390/cio/qdio.c
drivers/s390/cio/qdio.h
drivers/s390/cio/schid.h [deleted file]
drivers/s390/cio/scsw.c [new file with mode: 0644]
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_api.h
drivers/s390/crypto/zcrypt_cex2a.c
drivers/s390/crypto/zcrypt_error.h
drivers/s390/crypto/zcrypt_pcica.c
drivers/s390/crypto/zcrypt_pcicc.c
drivers/s390/crypto/zcrypt_pcixcc.c
drivers/s390/net/claw.c
drivers/s390/net/ctcm_fsms.c
drivers/s390/net/ctcm_main.c
drivers/s390/net/cu3088.c
drivers/s390/net/cu3088.h
drivers/s390/net/lcs.c
drivers/s390/net/netiucv.c
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/net/smsgiucv.c
drivers/s390/s390mach.c
drivers/s390/s390mach.h
drivers/scsi/esp_scsi.c
drivers/scsi/ipr.c
drivers/scsi/scsi_lib.c
drivers/scsi/ses.c
drivers/scsi/sg.c
drivers/scsi/sr.c
drivers/serial/8250.c
drivers/serial/serial_core.c
drivers/spi/spidev.c
drivers/ssb/driver_pcicore.c
drivers/thermal/Kconfig
drivers/thermal/thermal_sys.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/hcd.c
drivers/usb/core/hcd.h
drivers/usb/core/hub.c
drivers/usb/host/ehci.h
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-au1xxx.c
drivers/usb/host/ohci-ep93xx.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-lh7a404.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci-pnx4008.c
drivers/usb/host/ohci-pnx8550.c
drivers/usb/host/ohci-ppc-of.c
drivers/usb/host/ohci-ppc-soc.c
drivers/usb/host/ohci-ps3.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci-q.c
drivers/usb/host/ohci-s3c2410.c
drivers/usb/host/ohci-sa1111.c
drivers/usb/host/ohci-sh.c
drivers/usb/host/ohci-sm501.c
drivers/usb/host/ohci-ssb.c
drivers/usb/host/u132-hcd.c
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/ipaq.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/storage/unusual_devs.h
drivers/video/Kconfig
drivers/video/fb_defio.c
drivers/video/fsl-diu-fb.c
drivers/video/pxafb.c
drivers/video/w100fb.c
drivers/xen/xenbus/xenbus_client.c
drivers/xen/xenbus/xenbus_xs.c
fs/9p/v9fs_vfs.h
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/Kconfig
fs/Makefile
fs/bio-integrity.c [new file with mode: 0644]
fs/bio.c
fs/block_dev.c
fs/buffer.c
fs/cifs/cifsacl.c
fs/cifs/inode.c
fs/dcache.c
fs/ecryptfs/miscdev.c
fs/exec.c
fs/ext3/super.c
fs/ext4/super.c
fs/libfs.c
fs/locks.c
fs/namei.c
fs/namespace.c
fs/nfs/dir.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlmglue.c
fs/open.c
fs/pipe.c
fs/proc/base.c
fs/proc/task_mmu.c
fs/proc/task_nommu.c
fs/ramfs/file-mmu.c
fs/ramfs/file-nommu.c
fs/reiserfs/inode.c
fs/reiserfs/super.c
fs/splice.c
fs/udf/super.c
fs/utimes.c
fs/xfs/xfs_log.c
include/Kbuild
include/asm-avr32/setup.h
include/asm-frv/system.h
include/asm-generic/Kbuild.asm
include/asm-generic/atomic.h
include/asm-mips/atomic.h
include/asm-mips/mach-au1x00/au1xxx_psc.h
include/asm-powerpc/Kbuild
include/asm-powerpc/hugetlb.h
include/asm-powerpc/pgtable-ppc64.h
include/asm-s390/Kbuild
include/asm-s390/airq.h
include/asm-s390/ccwdev.h
include/asm-s390/chpid.h
include/asm-s390/chsc.h [new file with mode: 0644]
include/asm-s390/cio.h
include/asm-s390/elf.h
include/asm-s390/etr.h
include/asm-s390/fcx.h [new file with mode: 0644]
include/asm-s390/ipl.h
include/asm-s390/isc.h [new file with mode: 0644]
include/asm-s390/itcw.h [new file with mode: 0644]
include/asm-s390/pgtable.h
include/asm-s390/processor.h
include/asm-s390/ptrace.h
include/asm-s390/schid.h [new file with mode: 0644]
include/asm-s390/sclp.h
include/asm-s390/setup.h
include/asm-s390/sparsemem.h
include/asm-s390/timer.h
include/asm-s390/zcrypt.h
include/asm-x86/desc.h
include/asm-x86/kvm_para.h
include/asm-x86/msr.h
include/drm/Kbuild [new file with mode: 0644]
include/drm/drm.h [new file with mode: 0644]
include/drm/drmP.h [new file with mode: 0644]
include/drm/drm_core.h [new file with mode: 0644]
include/drm/drm_hashtab.h [new file with mode: 0644]
include/drm/drm_memory.h [new file with mode: 0644]
include/drm/drm_memory_debug.h [new file with mode: 0644]
include/drm/drm_os_linux.h [new file with mode: 0644]
include/drm/drm_pciids.h [new file with mode: 0644]
include/drm/drm_sarea.h [new file with mode: 0644]
include/drm/drm_sman.h [new file with mode: 0644]
include/drm/i810_drm.h [new file with mode: 0644]
include/drm/i830_drm.h [new file with mode: 0644]
include/drm/i915_drm.h [new file with mode: 0644]
include/drm/mga_drm.h [new file with mode: 0644]
include/drm/r128_drm.h [new file with mode: 0644]
include/drm/radeon_drm.h [new file with mode: 0644]
include/drm/savage_drm.h [new file with mode: 0644]
include/drm/sis_drm.h [new file with mode: 0644]
include/drm/via_drm.h [new file with mode: 0644]
include/linux/Kbuild
include/linux/audit.h
include/linux/bio.h
include/linux/blkdev.h
include/linux/blktrace_api.h
include/linux/capability.h
include/linux/cfag12864b.h
include/linux/cpumask.h
include/linux/dcache.h
include/linux/debug_locks.h
include/linux/firmware.h
include/linux/fs.h
include/linux/genhd.h
include/linux/i2c.h
include/linux/ide.h
include/linux/inet_lro.h
include/linux/input.h
include/linux/iocontext.h
include/linux/kernel.h
include/linux/ks0108.h
include/linux/mod_devicetable.h
include/linux/netdevice.h
include/linux/pci_ids.h
include/linux/ptrace.h
include/linux/rculist.h [new file with mode: 0644]
include/linux/securebits.h
include/linux/security.h
include/linux/slab.h
include/linux/slub_def.h
include/linux/thermal.h
include/linux/xfrm.h
include/media/cx25840.h
include/media/ir-common.h
include/media/v4l2-dev.h
include/net/mac80211.h
include/net/sch_generic.h
include/pcmcia/bulkmem.h [deleted file]
include/pcmcia/cistpl.h
include/pcmcia/cs.h
include/pcmcia/cs_types.h
include/pcmcia/ds.h
include/pcmcia/ss.h
include/pcmcia/version.h [deleted file]
include/sound/ad1843.h [new file with mode: 0644]
include/sound/control.h
include/sound/core.h
include/sound/cs4231-regs.h
include/sound/cs4231.h
include/sound/emu10k1.h
include/sound/seq_kernel.h
include/sound/soc-dapm.h
include/sound/soc.h
include/sound/uda1341.h
include/sound/version.h
kernel/audit.c
kernel/auditfilter.c
kernel/capability.c
kernel/cpuset.c
kernel/exit.c
kernel/fork.c
kernel/hrtimer.c
kernel/kprobes.c
kernel/printk.c
kernel/ptrace.c
kernel/rcuclassic.c
kernel/rcupreempt.c
kernel/sched.c
kernel/softlockup.c
kernel/workqueue.c
lib/bug.c
lib/debugobjects.c
lib/radix-tree.c
lib/ts_bm.c
lib/vsprintf.c
mm/Kconfig
mm/allocpercpu.c
mm/memory.c
mm/mempolicy.c
mm/migrate.c
mm/page_alloc.c
mm/slub.c
mm/sparse-vmemmap.c
net/bridge/br_if.c
net/can/af_can.c
net/can/bcm.c
net/can/raw.c
net/core/dev.c
net/core/fib_rules.c
net/core/filter.c
net/core/skbuff.c
net/ipv4/fib_trie.c
net/ipv4/inet_fragment.c
net/ipv4/inet_lro.c
net/ipv4/ip_fragment.c
net/ipv4/netfilter/nf_nat_snmp_basic.c
net/ipv4/tcp.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_probe.c
net/ipv6/addrconf.c
net/ipv6/exthdrs.c
net/ipv6/netfilter/ip6table_mangle.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/irda/irnetlink.c
net/iucv/af_iucv.c
net/iucv/iucv.c
net/mac80211/key.c
net/mac80211/main.c
net/mac80211/mlme.c
net/mac80211/rc80211_pid.h
net/mac80211/rc80211_pid_algo.c
net/mac80211/wext.c
net/mac80211/wme.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netlabel/netlabel_cipso_v4.c
net/netlabel/netlabel_mgmt.c
net/netlabel/netlabel_unlabeled.c
net/netlink/af_netlink.c
net/netlink/attr.c
net/sched/Kconfig
net/sched/sch_api.c
net/sched/sch_atm.c
net/sched/sch_cbq.c
net/sched/sch_dsmark.c
net/sched/sch_generic.c
net/sched/sch_hfsc.c
net/sched/sch_htb.c
net/sched/sch_ingress.c
net/sched/sch_prio.c
net/sched/sch_sfq.c
net/sctp/sm_statefuns.c
net/sctp/ulpevent.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/rpcb_clnt.c
net/unix/af_unix.c
net/wireless/reg.c
net/xfrm/xfrm_user.c
scripts/mod/file2alias.c
security/Kconfig
security/Makefile
security/capability.c
security/commoncap.c
security/device_cgroup.c
security/dummy.c [deleted file]
security/root_plug.c
security/security.c
security/selinux/hooks.c
security/selinux/include/audit.h
security/selinux/include/avc.h
security/selinux/include/objsec.h
security/selinux/include/security.h
security/selinux/netnode.c
security/selinux/netport.c
security/selinux/selinuxfs.c
security/selinux/ss/avtab.c
security/selinux/ss/context.h
security/selinux/ss/mls.c
security/selinux/ss/mls.h
security/selinux/ss/policydb.c
security/selinux/ss/services.c
security/selinux/ss/sidtab.c
security/selinux/ss/sidtab.h
security/smack/smack_lsm.c
sound/Kconfig
sound/aoa/Kconfig
sound/aoa/codecs/Kconfig
sound/aoa/fabrics/Kconfig
sound/aoa/soundbus/Kconfig
sound/arm/Kconfig
sound/arm/sa11xx-uda1341.c
sound/core/Kconfig
sound/core/control.c
sound/core/init.c
sound/core/memalloc.c
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_device.c
sound/core/sound.c
sound/core/timer.c
sound/drivers/Kconfig
sound/drivers/vx/vx_hwdep.c
sound/i2c/cs8427.c
sound/i2c/l3/uda1341.c
sound/isa/Kconfig
sound/isa/cs423x/cs4231_lib.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/isa/sb/Makefile
sound/isa/wavefront/wavefront_synth.c
sound/mips/Kconfig
sound/mips/Makefile
sound/mips/ad1843.c [new file with mode: 0644]
sound/mips/hal2.c [new file with mode: 0644]
sound/mips/hal2.h [new file with mode: 0644]
sound/mips/sgio2audio.c [new file with mode: 0644]
sound/oss/Kconfig
sound/oss/dmasound/dmasound_core.c
sound/oss/dmasound/dmasound_paula.c
sound/oss/dmasound/dmasound_q40.c
sound/oss/msnd.c
sound/oss/msnd.h
sound/oss/msnd_classic.h
sound/oss/msnd_pinnacle.c
sound/oss/msnd_pinnacle.h
sound/parisc/Kconfig
sound/pci/Kconfig
sound/pci/Makefile
sound/pci/ac97/Makefile
sound/pci/ac97/ac97_codec.c
sound/pci/ac97/ac97_patch.c
sound/pci/ac97/ak4531_codec.c [deleted file]
sound/pci/ak4531_codec.c [new file with mode: 0644]
sound/pci/au88x0/au88x0_game.c
sound/pci/azt3328.c
sound/pci/azt3328.h
sound/pci/ca0106/ca0106_main.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/memory.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_hwdep.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_proc.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/ice1712/envy24ht.h
sound/pci/ice1712/ice1712.h
sound/pci/ice1712/ice1724.c
sound/pci/maestro3.c
sound/pci/nm256/nm256.c
sound/pci/oxygen/hifier.c
sound/pci/oxygen/oxygen.c
sound/pci/oxygen/oxygen.h
sound/pci/oxygen/oxygen_io.c
sound/pci/oxygen/oxygen_lib.c
sound/pci/oxygen/oxygen_pcm.c
sound/pci/oxygen/virtuoso.c
sound/pci/pcxhr/pcxhr.c
sound/pci/pcxhr/pcxhr_core.c
sound/pci/trident/trident_main.c
sound/pci/trident/trident_memory.c
sound/pci/via82xx.c
sound/pci/ymfpci/ymfpci_main.c
sound/pcmcia/Kconfig
sound/pcmcia/vx/vxp_ops.c
sound/ppc/Kconfig
sound/ppc/daca.c
sound/ppc/tumbler.c
sound/sh/Kconfig
sound/soc/Kconfig
sound/soc/Makefile
sound/soc/at32/Kconfig [new file with mode: 0644]
sound/soc/at32/Makefile [new file with mode: 0644]
sound/soc/at32/at32-pcm.c [new file with mode: 0644]
sound/soc/at32/at32-pcm.h [new file with mode: 0644]
sound/soc/at32/at32-ssc.c [new file with mode: 0644]
sound/soc/at32/at32-ssc.h [new file with mode: 0644]
sound/soc/at32/playpaq_wm8510.c [new file with mode: 0644]
sound/soc/at91/Kconfig
sound/soc/at91/at91-pcm.c
sound/soc/at91/at91-ssc.c
sound/soc/at91/at91-ssc.h
sound/soc/at91/eti_b1_wm8731.c
sound/soc/au1x/Kconfig [new file with mode: 0644]
sound/soc/au1x/Makefile [new file with mode: 0644]
sound/soc/au1x/dbdma2.c [new file with mode: 0644]
sound/soc/au1x/psc-ac97.c [new file with mode: 0644]
sound/soc/au1x/psc-i2s.c [new file with mode: 0644]
sound/soc/au1x/psc.h [new file with mode: 0644]
sound/soc/au1x/sample-ac97.c [new file with mode: 0644]
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ac97.c
sound/soc/codecs/ac97.h
sound/soc/codecs/ak4535.c [new file with mode: 0644]
sound/soc/codecs/ak4535.h [new file with mode: 0644]
sound/soc/codecs/cs4270.c
sound/soc/codecs/cs4270.h
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/tlv320aic3x.h
sound/soc/codecs/uda1380.c [new file with mode: 0644]
sound/soc/codecs/uda1380.h [new file with mode: 0644]
sound/soc/codecs/wm8510.c [new file with mode: 0644]
sound/soc/codecs/wm8510.h [new file with mode: 0644]
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8731.h
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8750.h
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8753.h
sound/soc/codecs/wm8990.c [new file with mode: 0644]
sound/soc/codecs/wm8990.h [new file with mode: 0644]
sound/soc/codecs/wm9712.c
sound/soc/codecs/wm9712.h
sound/soc/codecs/wm9713.c
sound/soc/codecs/wm9713.h
sound/soc/davinci/Kconfig
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-i2s.c
sound/soc/davinci/davinci-i2s.h
sound/soc/davinci/davinci-pcm.c
sound/soc/fsl/Kconfig
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_dma.h
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/fsl_ssi.h
sound/soc/fsl/mpc8610_hpcd.c
sound/soc/omap/Kconfig
sound/soc/omap/n810.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcbsp.h
sound/soc/omap/omap-pcm.c
sound/soc/pxa/Kconfig
sound/soc/pxa/Makefile
sound/soc/pxa/corgi.c
sound/soc/pxa/em-x270.c [new file with mode: 0644]
sound/soc/pxa/poodle.c
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/pxa2xx-ac97.h
sound/soc/pxa/pxa2xx-i2s.c
sound/soc/pxa/pxa2xx-i2s.h
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/pxa/spitz.c
sound/soc/pxa/tosa.c
sound/soc/s3c24xx/Kconfig
sound/soc/s3c24xx/neo1973_wm8753.c
sound/soc/s3c24xx/s3c2412-i2s.c
sound/soc/s3c24xx/s3c2412-i2s.h
sound/soc/s3c24xx/s3c2443-ac97.c
sound/soc/s3c24xx/s3c24xx-ac97.h
sound/soc/s3c24xx/s3c24xx-i2s.c
sound/soc/s3c24xx/s3c24xx-i2s.h
sound/soc/s3c24xx/s3c24xx-pcm.c
sound/soc/s3c24xx/smdk2443_wm9710.c
sound/soc/sh/Kconfig
sound/soc/sh/dma-sh7760.c
sound/soc/sh/hac.c
sound/soc/sh/sh7760-ac97.c
sound/soc/sh/ssi.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/sparc/Kconfig
sound/sparc/dbri.c
sound/spi/Kconfig
sound/usb/Kconfig
sound/usb/caiaq/caiaq-audio.c
sound/usb/caiaq/caiaq-device.c
sound/usb/caiaq/caiaq-device.h
sound/usb/usbaudio.c
sound/usb/usbquirks.h
virt/kvm/ioapic.c

index 9bb1cb6d825d540bc92dfe5c34343438b860b009..869e1a3b64b6bf969eeced820691e955e03e3068 100644 (file)
@@ -3,6 +3,10 @@
 # subdirectories here. Add them in the ".gitignore" file
 # in that subdirectory instead.
 #
+# NOTE! Please use 'git-ls-files -i --exclude-standard'
+# command after changing this file, to see if there are
+# any tracked files which get ignored after the change.
+#
 # Normal rules
 #
 .*
 *.lst
 *.symtypes
 *.order
+*.elf
+*.bin
+*.gz
 
 #
 # Top-level generic files
 #
 tags
 TAGS
-vmlinux*
-!vmlinux.lds.S
-!vmlinux.lds.h
+vmlinux
 System.map
 Module.markers
 Module.symvers
 !.gitignore
+!.mailmap
 
 #
 # Generated include files
diff --git a/CREDITS b/CREDITS
index 8fec7b3f96d5668fa441bd50fc81626d34f0f0c2..e97bea06b59ff12bc827c0661fb57974a6eff4d6 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2611,8 +2611,9 @@ S: Perth, Western Australia
 S: Australia
 
 N: Miguel Ojeda Sandonis
-E: maxextreme@gmail.com
-W: http://maxextreme.googlepages.com/
+E: miguel.ojeda.sandonis@gmail.com
+W: http://miguelojeda.es
+W: http://jair.lab.fi.uva.es/~migojed/
 D: Author of the ks0108, cfag12864b and cfag12864bfb auxiliary display drivers.
 D: Maintainer of the auxiliary display drivers tree (drivers/auxdisplay/*)
 S: C/ Mieses 20, 9-B
index 4bd9ea539129036264b80dd926f156167bd51d6e..44f52a4f5903359eda2f2ffafff2d3341e437e62 100644 (file)
@@ -26,3 +26,37 @@ Description:
                I/O statistics of partition <part>. The format is the
                same as the above-written /sys/block/<disk>/stat
                format.
+
+
+What:          /sys/block/<disk>/integrity/format
+Date:          June 2008
+Contact:       Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+               Metadata format for integrity capable block device.
+               E.g. T10-DIF-TYPE1-CRC.
+
+
+What:          /sys/block/<disk>/integrity/read_verify
+Date:          June 2008
+Contact:       Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+               Indicates whether the block layer should verify the
+               integrity of read requests serviced by devices that
+               support sending integrity metadata.
+
+
+What:          /sys/block/<disk>/integrity/tag_size
+Date:          June 2008
+Contact:       Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+               Number of bytes of integrity tag space available per
+               512 bytes of data.
+
+
+What:          /sys/block/<disk>/integrity/write_generate
+Date:          June 2008
+Contact:       Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+               Indicates whether the block layer should automatically
+               generate checksums for write requests bound for
+               devices that support receiving integrity metadata.
diff --git a/Documentation/ABI/testing/sysfs-bus-css b/Documentation/ABI/testing/sysfs-bus-css
new file mode 100644 (file)
index 0000000..b585ec2
--- /dev/null
@@ -0,0 +1,35 @@
+What:          /sys/bus/css/devices/.../type
+Date:          March 2008
+Contact:       Cornelia Huck <cornelia.huck@de.ibm.com>
+               linux-s390@vger.kernel.org
+Description:   Contains the subchannel type, as reported by the hardware.
+               This attribute is present for all subchannel types.
+
+What:          /sys/bus/css/devices/.../modalias
+Date:          March 2008
+Contact:       Cornelia Huck <cornelia.huck@de.ibm.com>
+               linux-s390@vger.kernel.org
+Description:   Contains the module alias as reported with uevents.
+               It is of the format css:t<type> and present for all
+               subchannel types.
+
+What:          /sys/bus/css/drivers/io_subchannel/.../chpids
+Date:          December 2002
+Contact:       Cornelia Huck <cornelia.huck@de.ibm.com>
+               linux-s390@vger.kernel.org
+Description:   Contains the ids of the channel paths used by this
+               subchannel, as reported by the channel subsystem
+               during subchannel recognition.
+               Note: This is an I/O-subchannel specific attribute.
+Users:         s390-tools, HAL
+
+What:          /sys/bus/css/drivers/io_subchannel/.../pimpampom
+Date:          December 2002
+Contact:       Cornelia Huck <cornelia.huck@de.ibm.com>
+               linux-s390@vger.kernel.org
+Description:   Contains the PIM/PAM/POM values, as reported by the
+               channel subsystem when last queried by the common I/O
+               layer (this implies that this attribute is not neccessarily
+               in sync with the values current in the channel subsystem).
+               Note: This is an I/O-subchannel specific attribute.
+Users:         s390-tools, HAL
index 0291ade44c172882087b49cd6069267c12a4df3c..619e8caf30db88508a3f2859d140f41ce363f552 100644 (file)
@@ -377,7 +377,7 @@ Bug Reporting
 bugzilla.kernel.org is where the Linux kernel developers track kernel
 bugs.  Users are encouraged to report all bugs that they find in this
 tool.  For details on how to use the kernel bugzilla, please see:
-       http://test.kernel.org/bugzilla/faq.html
+       http://bugzilla.kernel.org/page.cgi?id=faq.html
 
 The file REPORTING-BUGS in the main kernel source directory has a good
 template for how to report a possible kernel bug, and details what kind
index 8aa7529f8258a12725f6d34b5a7b349aa104a48a..cd784f46bf8abefb9ed24257aaf5fcf4df2ecb00 100644 (file)
@@ -24,6 +24,8 @@ There are three different groups of fields in the struct taskstats:
 
 4) Per-task and per-thread context switch count statistics
 
+5) Time accounting for SMT machines
+
 Future extension should add fields to the end of the taskstats struct, and
 should not change the relative position of each field within the struct.
 
@@ -164,4 +166,8 @@ struct taskstats {
        __u64   nvcsw;                  /* Context voluntary switch counter */
        __u64   nivcsw;                 /* Context involuntary switch counter */
 
+5) Time accounting for SMT machines
+       __u64   ac_utimescaled;         /* utime scaled on frequency etc */
+       __u64   ac_stimescaled;         /* stime scaled on frequency etc */
+       __u64   cpu_scaled_run_real_total; /* scaled cpu_run_real_total */
 }
index b714183d412515abc2a39c32e898cdab52d21eff..eb7be393a51061c6e1cd844dc884edc1a276c53e 100644 (file)
@@ -3,7 +3,7 @@
        ===================================
 
 License:               GPLv2
-Author & Maintainer:   Miguel Ojeda Sandonis <maxextreme@gmail.com>
+Author & Maintainer:   Miguel Ojeda Sandonis
 Date:                  2006-10-27
 
 
@@ -22,7 +22,7 @@ Date:                 2006-10-27
 1. DRIVER INFORMATION
 ---------------------
 
-This driver support one cfag12864b display at time.
+This driver supports a cfag12864b LCD.
 
 
 ---------------------
index 7bfac354d4c9f0181d311a0d80e798fdf502f75c..2caeea5e49932e1c3e132a55794373c3fe65dbad 100644 (file)
@@ -4,7 +4,7 @@
  * Description: cfag12864b LCD userspace example program
  *     License: GPLv2
  *
- *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
+ *      Author: Copyright (C) Miguel Ojeda Sandonis
  *        Date: 2006-10-31
  *
  *  This program is free software; you can redistribute it and/or modify
index 92b03b60c613f3344bc5c771a65ad40e2f71da7a..8ddda0c8ceefa485f5fe1743a75d79e961e47174 100644 (file)
@@ -3,7 +3,7 @@
        ==========================================
 
 License:               GPLv2
-Author & Maintainer:   Miguel Ojeda Sandonis <maxextreme@gmail.com>
+Author & Maintainer:   Miguel Ojeda Sandonis
 Date:                  2006-10-27
 
 
@@ -21,7 +21,7 @@ Date:                 2006-10-27
 1. DRIVER INFORMATION
 ---------------------
 
-This driver support the ks0108 LCD controller.
+This driver supports the ks0108 LCD controller.
 
 
 ---------------------
diff --git a/Documentation/block/data-integrity.txt b/Documentation/block/data-integrity.txt
new file mode 100644 (file)
index 0000000..e9dc8d8
--- /dev/null
@@ -0,0 +1,327 @@
+----------------------------------------------------------------------
+1. INTRODUCTION
+
+Modern filesystems feature checksumming of data and metadata to
+protect against data corruption.  However, the detection of the
+corruption is done at read time which could potentially be months
+after the data was written.  At that point the original data that the
+application tried to write is most likely lost.
+
+The solution is to ensure that the disk is actually storing what the
+application meant it to.  Recent additions to both the SCSI family
+protocols (SBC Data Integrity Field, SCC protection proposal) as well
+as SATA/T13 (External Path Protection) try to remedy this by adding
+support for appending integrity metadata to an I/O.  The integrity
+metadata (or protection information in SCSI terminology) includes a
+checksum for each sector as well as an incrementing counter that
+ensures the individual sectors are written in the right order.  And
+for some protection schemes also that the I/O is written to the right
+place on disk.
+
+Current storage controllers and devices implement various protective
+measures, for instance checksumming and scrubbing.  But these
+technologies are working in their own isolated domains or at best
+between adjacent nodes in the I/O path.  The interesting thing about
+DIF and the other integrity extensions is that the protection format
+is well defined and every node in the I/O path can verify the
+integrity of the I/O and reject it if corruption is detected.  This
+allows not only corruption prevention but also isolation of the point
+of failure.
+
+----------------------------------------------------------------------
+2. THE DATA INTEGRITY EXTENSIONS
+
+As written, the protocol extensions only protect the path between
+controller and storage device.  However, many controllers actually
+allow the operating system to interact with the integrity metadata
+(IMD).  We have been working with several FC/SAS HBA vendors to enable
+the protection information to be transferred to and from their
+controllers.
+
+The SCSI Data Integrity Field works by appending 8 bytes of protection
+information to each sector.  The data + integrity metadata is stored
+in 520 byte sectors on disk.  Data + IMD are interleaved when
+transferred between the controller and target.  The T13 proposal is
+similar.
+
+Because it is highly inconvenient for operating systems to deal with
+520 (and 4104) byte sectors, we approached several HBA vendors and
+encouraged them to allow separation of the data and integrity metadata
+scatter-gather lists.
+
+The controller will interleave the buffers on write and split them on
+read.  This means that the Linux can DMA the data buffers to and from
+host memory without changes to the page cache.
+
+Also, the 16-bit CRC checksum mandated by both the SCSI and SATA specs
+is somewhat heavy to compute in software.  Benchmarks found that
+calculating this checksum had a significant impact on system
+performance for a number of workloads.  Some controllers allow a
+lighter-weight checksum to be used when interfacing with the operating
+system.  Emulex, for instance, supports the TCP/IP checksum instead.
+The IP checksum received from the OS is converted to the 16-bit CRC
+when writing and vice versa.  This allows the integrity metadata to be
+generated by Linux or the application at very low cost (comparable to
+software RAID5).
+
+The IP checksum is weaker than the CRC in terms of detecting bit
+errors.  However, the strength is really in the separation of the data
+buffers and the integrity metadata.  These two distinct buffers much
+match up for an I/O to complete.
+
+The separation of the data and integrity metadata buffers as well as
+the choice in checksums is referred to as the Data Integrity
+Extensions.  As these extensions are outside the scope of the protocol
+bodies (T10, T13), Oracle and its partners are trying to standardize
+them within the Storage Networking Industry Association.
+
+----------------------------------------------------------------------
+3. KERNEL CHANGES
+
+The data integrity framework in Linux enables protection information
+to be pinned to I/Os and sent to/received from controllers that
+support it.
+
+The advantage to the integrity extensions in SCSI and SATA is that
+they enable us to protect the entire path from application to storage
+device.  However, at the same time this is also the biggest
+disadvantage. It means that the protection information must be in a
+format that can be understood by the disk.
+
+Generally Linux/POSIX applications are agnostic to the intricacies of
+the storage devices they are accessing.  The virtual filesystem switch
+and the block layer make things like hardware sector size and
+transport protocols completely transparent to the application.
+
+However, this level of detail is required when preparing the
+protection information to send to a disk.  Consequently, the very
+concept of an end-to-end protection scheme is a layering violation.
+It is completely unreasonable for an application to be aware whether
+it is accessing a SCSI or SATA disk.
+
+The data integrity support implemented in Linux attempts to hide this
+from the application.  As far as the application (and to some extent
+the kernel) is concerned, the integrity metadata is opaque information
+that's attached to the I/O.
+
+The current implementation allows the block layer to automatically
+generate the protection information for any I/O.  Eventually the
+intent is to move the integrity metadata calculation to userspace for
+user data.  Metadata and other I/O that originates within the kernel
+will still use the automatic generation interface.
+
+Some storage devices allow each hardware sector to be tagged with a
+16-bit value.  The owner of this tag space is the owner of the block
+device.  I.e. the filesystem in most cases.  The filesystem can use
+this extra space to tag sectors as they see fit.  Because the tag
+space is limited, the block interface allows tagging bigger chunks by
+way of interleaving.  This way, 8*16 bits of information can be
+attached to a typical 4KB filesystem block.
+
+This also means that applications such as fsck and mkfs will need
+access to manipulate the tags from user space.  A passthrough
+interface for this is being worked on.
+
+
+----------------------------------------------------------------------
+4. BLOCK LAYER IMPLEMENTATION DETAILS
+
+4.1 BIO
+
+The data integrity patches add a new field to struct bio when
+CONFIG_BLK_DEV_INTEGRITY is enabled.  bio->bi_integrity is a pointer
+to a struct bip which contains the bio integrity payload.  Essentially
+a bip is a trimmed down struct bio which holds a bio_vec containing
+the integrity metadata and the required housekeeping information (bvec
+pool, vector count, etc.)
+
+A kernel subsystem can enable data integrity protection on a bio by
+calling bio_integrity_alloc(bio).  This will allocate and attach the
+bip to the bio.
+
+Individual pages containing integrity metadata can subsequently be
+attached using bio_integrity_add_page().
+
+bio_free() will automatically free the bip.
+
+
+4.2 BLOCK DEVICE
+
+Because the format of the protection data is tied to the physical
+disk, each block device has been extended with a block integrity
+profile (struct blk_integrity).  This optional profile is registered
+with the block layer using blk_integrity_register().
+
+The profile contains callback functions for generating and verifying
+the protection data, as well as getting and setting application tags.
+The profile also contains a few constants to aid in completing,
+merging and splitting the integrity metadata.
+
+Layered block devices will need to pick a profile that's appropriate
+for all subdevices.  blk_integrity_compare() can help with that.  DM
+and MD linear, RAID0 and RAID1 are currently supported.  RAID4/5/6
+will require extra work due to the application tag.
+
+
+----------------------------------------------------------------------
+5.0 BLOCK LAYER INTEGRITY API
+
+5.1 NORMAL FILESYSTEM
+
+    The normal filesystem is unaware that the underlying block device
+    is capable of sending/receiving integrity metadata.  The IMD will
+    be automatically generated by the block layer at submit_bio() time
+    in case of a WRITE.  A READ request will cause the I/O integrity
+    to be verified upon completion.
+
+    IMD generation and verification can be toggled using the
+
+      /sys/block/<bdev>/integrity/write_generate
+
+    and
+
+      /sys/block/<bdev>/integrity/read_verify
+
+    flags.
+
+
+5.2 INTEGRITY-AWARE FILESYSTEM
+
+    A filesystem that is integrity-aware can prepare I/Os with IMD
+    attached.  It can also use the application tag space if this is
+    supported by the block device.
+
+
+    int bdev_integrity_enabled(block_device, int rw);
+
+      bdev_integrity_enabled() will return 1 if the block device
+      supports integrity metadata transfer for the data direction
+      specified in 'rw'.
+
+      bdev_integrity_enabled() honors the write_generate and
+      read_verify flags in sysfs and will respond accordingly.
+
+
+    int bio_integrity_prep(bio);
+
+      To generate IMD for WRITE and to set up buffers for READ, the
+      filesystem must call bio_integrity_prep(bio).
+
+      Prior to calling this function, the bio data direction and start
+      sector must be set, and the bio should have all data pages
+      added.  It is up to the caller to ensure that the bio does not
+      change while I/O is in progress.
+
+      bio_integrity_prep() should only be called if
+      bio_integrity_enabled() returned 1.
+
+
+    int bio_integrity_tag_size(bio);
+
+      If the filesystem wants to use the application tag space it will
+      first have to find out how much storage space is available.
+      Because tag space is generally limited (usually 2 bytes per
+      sector regardless of sector size), the integrity framework
+      supports interleaving the information between the sectors in an
+      I/O.
+
+      Filesystems can call bio_integrity_tag_size(bio) to find out how
+      many bytes of storage are available for that particular bio.
+
+      Another option is bdev_get_tag_size(block_device) which will
+      return the number of available bytes per hardware sector.
+
+
+    int bio_integrity_set_tag(bio, void *tag_buf, len);
+
+      After a successful return from bio_integrity_prep(),
+      bio_integrity_set_tag() can be used to attach an opaque tag
+      buffer to a bio.  Obviously this only makes sense if the I/O is
+      a WRITE.
+
+
+    int bio_integrity_get_tag(bio, void *tag_buf, len);
+
+      Similarly, at READ I/O completion time the filesystem can
+      retrieve the tag buffer using bio_integrity_get_tag().
+
+
+6.3 PASSING EXISTING INTEGRITY METADATA
+
+    Filesystems that either generate their own integrity metadata or
+    are capable of transferring IMD from user space can use the
+    following calls:
+
+
+    struct bip * bio_integrity_alloc(bio, gfp_mask, nr_pages);
+
+      Allocates the bio integrity payload and hangs it off of the bio.
+      nr_pages indicate how many pages of protection data need to be
+      stored in the integrity bio_vec list (similar to bio_alloc()).
+
+      The integrity payload will be freed at bio_free() time.
+
+
+    int bio_integrity_add_page(bio, page, len, offset);
+
+      Attaches a page containing integrity metadata to an existing
+      bio.  The bio must have an existing bip,
+      i.e. bio_integrity_alloc() must have been called.  For a WRITE,
+      the integrity metadata in the pages must be in a format
+      understood by the target device with the notable exception that
+      the sector numbers will be remapped as the request traverses the
+      I/O stack.  This implies that the pages added using this call
+      will be modified during I/O!  The first reference tag in the
+      integrity metadata must have a value of bip->bip_sector.
+
+      Pages can be added using bio_integrity_add_page() as long as
+      there is room in the bip bio_vec array (nr_pages).
+
+      Upon completion of a READ operation, the attached pages will
+      contain the integrity metadata received from the storage device.
+      It is up to the receiver to process them and verify data
+      integrity upon completion.
+
+
+6.4 REGISTERING A BLOCK DEVICE AS CAPABLE OF EXCHANGING INTEGRITY
+    METADATA
+
+    To enable integrity exchange on a block device the gendisk must be
+    registered as capable:
+
+    int blk_integrity_register(gendisk, blk_integrity);
+
+      The blk_integrity struct is a template and should contain the
+      following:
+
+        static struct blk_integrity my_profile = {
+            .name                   = "STANDARDSBODY-TYPE-VARIANT-CSUM",
+            .generate_fn            = my_generate_fn,
+                   .verify_fn              = my_verify_fn,
+                   .get_tag_fn             = my_get_tag_fn,
+                   .set_tag_fn             = my_set_tag_fn,
+           .tuple_size             = sizeof(struct my_tuple_size),
+           .tag_size               = <tag bytes per hw sector>,
+        };
+
+      'name' is a text string which will be visible in sysfs.  This is
+      part of the userland API so chose it carefully and never change
+      it.  The format is standards body-type-variant.
+      E.g. T10-DIF-TYPE1-IP or T13-EPP-0-CRC.
+
+      'generate_fn' generates appropriate integrity metadata (for WRITE).
+
+      'verify_fn' verifies that the data buffer matches the integrity
+      metadata.
+
+      'tuple_size' must be set to match the size of the integrity
+      metadata per sector.  I.e. 8 for DIF and EPP.
+
+      'tag_size' must be set to identify how many bytes of tag space
+      are available per hardware sector.  For DIF this is either 2 or
+      0 depending on the value of the Control Mode Page ATO bit.
+
+      See 6.2 for a description of get_tag_fn and set_tag_fn.
+
+----------------------------------------------------------------------
+2007-12-24 Martin K. Petersen <martin.petersen@oracle.com>
index 824fc02744719ecb02b29177c11c55034229af35..d9014aa0eb68b469836b29afe932532b168a63ee 100644 (file)
@@ -390,6 +390,10 @@ If you have several tasks to attach, you have to do it one after another:
        ...
 # /bin/echo PIDn > tasks
 
+You can attach the current shell task by echoing 0:
+
+# echo 0 > tasks
+
 3. Kernel API
 =============
 
index 4dcea42432c279d4e58eb732010d0feae4e2a4ff..7cc6e6a60672c9e247d63a313d279a3a1739e3e2 100644 (file)
@@ -13,7 +13,7 @@ either an integer or * for all.  Access is a composition of r
 The root device cgroup starts with rwm to 'all'.  A child device
 cgroup gets a copy of the parent.  Administrators can then remove
 devices from the whitelist or add new entries.  A child cgroup can
-never receive a device access which is denied its parent.  However
+never receive a device access which is denied by its parent.  However
 when a device access is removed from a parent it will not also be
 removed from the child(ren).
 
@@ -29,7 +29,11 @@ allows cgroup 1 to read and mknod the device usually known as
 
        echo a > /cgroups/1/devices.deny
 
-will remove the default 'a *:* mrw' entry.
+will remove the default 'a *:* rwm' entry. Doing
+
+       echo a > /cgroups/1/devices.allow
+
+will add the 'a *:* rwm' entry to the whitelist.
 
 3. Security
 
index 353504de3084a645931788b6bd4d7e529428562e..1f5a924d1e56430bc3c8a0a6bb74e7524fab1670 100644 (file)
@@ -154,13 +154,15 @@ browsing and modifying the cpusets presently known to the kernel.  No
 new system calls are added for cpusets - all support for querying and
 modifying cpusets is via this cpuset file system.
 
-The /proc/<pid>/status file for each task has two added lines,
+The /proc/<pid>/status file for each task has four added lines,
 displaying the tasks cpus_allowed (on which CPUs it may be scheduled)
 and mems_allowed (on which Memory Nodes it may obtain memory),
-in the format seen in the following example:
+in the two formats seen in the following example:
 
   Cpus_allowed:   ffffffff,ffffffff,ffffffff,ffffffff
+  Cpus_allowed_list:      0-127
   Mems_allowed:   ffffffff,ffffffff
+  Mems_allowed_list:      0-63
 
 Each cpuset is represented by a directory in the cgroup file system
 containing (on top of the standard cgroup files) the following
@@ -544,6 +546,9 @@ otherwise initial value -1 that indicates the cpuset has no request.
  ( 4  : search nodes in a chunk of node [on NUMA system] )
  ( 5  : search system wide [on NUMA system] )
 
+The system default is architecture dependent.  The system default
+can be changed using the relax_domain_level= boot parameter.
+
 This file is per-cpuset and affect the sched domain where the cpuset
 belongs to.  Therefore if the flag 'sched_load_balance' of a cpuset
 is disabled, then 'sched_relax_domain_level' have no effect since
index 5b3f31faed56872b84fbd293494613f6d627a987..46ece3fba6f94c2924c94d6f96b4402984705102 100644 (file)
@@ -312,3 +312,12 @@ When:      2.6.26
 Why:   Implementation became generic; users should now include
        linux/semaphore.h instead.
 Who:   Matthew Wilcox <willy@linux.intel.com>
+
+---------------------------
+
+What:  CONFIG_THERMAL_HWMON
+When:  January 2009
+Why:   This option was introduced just to allow older lm-sensors userspace
+       to keep working over the upgrade to 2.6.26. At the scheduled time of
+       removal fixed lm-sensors (2.x or 3.x) should be readily available.
+Who:   Rene Herman <rene.herman@gmail.com>
diff --git a/Documentation/ftrace.txt b/Documentation/ftrace.txt
new file mode 100644 (file)
index 0000000..13e4bf0
--- /dev/null
@@ -0,0 +1,1353 @@
+               ftrace - Function Tracer
+               ========================
+
+Copyright 2008 Red Hat Inc.
+Author: Steven Rostedt <srostedt@redhat.com>
+
+
+Introduction
+------------
+
+Ftrace is an internal tracer designed to help out developers and
+designers of systems to find what is going on inside the kernel.
+It can be used for debugging or analyzing latencies and performance
+issues that take place outside of user-space.
+
+Although ftrace is the function tracer, it also includes an
+infrastructure that allows for other types of tracing. Some of the
+tracers that are currently in ftrace is a tracer to trace
+context switches, the time it takes for a high priority task to
+run after it was woken up, the time interrupts are disabled, and
+more.
+
+
+The File System
+---------------
+
+Ftrace uses the debugfs file system to hold the control files as well
+as the files to display output.
+
+To mount the debugfs system:
+
+  # mkdir /debug
+  # mount -t debugfs nodev /debug
+
+
+That's it! (assuming that you have ftrace configured into your kernel)
+
+After mounting the debugfs, you can see a directory called
+"tracing".  This directory contains the control and output files
+of ftrace. Here is a list of some of the key files:
+
+
+ Note: all time values are in microseconds.
+
+  current_tracer : This is used to set or display the current tracer
+               that is configured.
+
+  available_tracers : This holds the different types of tracers that
+               has been compiled into the kernel. The tracers
+               listed here can be configured by echoing in their
+               name into current_tracer.
+
+  tracing_enabled : This sets or displays whether the current_tracer
+               is activated and tracing or not. Echo 0 into this
+               file to disable the tracer or 1 (or non-zero) to
+               enable it.
+
+  trace : This file holds the output of the trace in a human readable
+               format.
+
+  latency_trace : This file shows the same trace but the information
+               is organized more to display possible latencies
+               in the system.
+
+  trace_pipe : The output is the same as the "trace" file but this
+               file is meant to be streamed with live tracing.
+               Reads from this file will block until new data
+               is retrieved. Unlike the "trace" and "latency_trace"
+               files, this file is a consumer. This means reading
+               from this file causes sequential reads to display
+               more current data. Once data is read from this
+               file, it is consumed, and will not be read
+               again with a sequential read. The "trace" and
+               "latency_trace" files are static, and if the
+               tracer isn't adding more data, they will display
+               the same information every time they are read.
+
+  iter_ctrl : This file lets the user control the amount of data
+               that is displayed in one of the above output
+               files.
+
+  trace_max_latency : Some of the tracers record the max latency.
+               For example, the time interrupts are disabled.
+               This time is saved in this file. The max trace
+               will also be stored, and displayed by either
+               "trace" or "latency_trace".  A new max trace will
+               only be recorded if the latency is greater than
+               the value in this file. (in microseconds)
+
+  trace_entries : This sets or displays the number of trace
+               entries each CPU buffer can hold. The tracer buffers
+               are the same size for each CPU, so care must be
+               taken when modifying the trace_entries. The number
+               of actually entries will be the number given
+               times the number of possible CPUS. The buffers
+               are saved as individual pages, and the actual entries
+               will always be rounded up to entries per page.
+
+               This can only be updated when the current_tracer
+               is set to "none".
+
+               NOTE: It is planned on changing the allocated buffers
+                     from being the number of possible CPUS to
+                     the number of online CPUS.
+
+  tracing_cpumask : This is a mask that lets the user only trace
+               on specified CPUS. The format is a hex string
+               representing the CPUS.
+
+  set_ftrace_filter : When dynamic ftrace is configured in, the
+               code is dynamically modified to disable calling
+               of the function profiler (mcount). This lets
+               tracing be configured in with practically no overhead
+               in performance.  This also has a side effect of
+               enabling or disabling specific functions to be
+               traced.  Echoing in names of functions into this
+               file will limit the trace to only those files.
+
+  set_ftrace_notrace: This has the opposite effect that
+               set_ftrace_filter has. Any function that is added
+               here will not be traced. If a function exists
+               in both set_ftrace_filter and set_ftrace_notrace
+               the function will _not_ bet traced.
+
+  available_filter_functions : When a function is encountered the first
+               time by the dynamic tracer, it is recorded and
+               later the call is converted into a nop. This file
+               lists the functions that have been recorded
+               by the dynamic tracer and these functions can
+               be used to set the ftrace filter by the above
+               "set_ftrace_filter" file.
+
+
+The Tracers
+-----------
+
+Here are the list of current tracers that can be configured.
+
+  ftrace - function tracer that uses mcount to trace all functions.
+               It is possible to filter out which functions that are
+               traced when dynamic ftrace is configured in.
+
+  sched_switch - traces the context switches between tasks.
+
+  irqsoff - traces the areas that disable interrupts and saves off
+               the trace with the longest max latency.
+               See tracing_max_latency.  When a new max is recorded,
+               it replaces the old trace. It is best to view this
+               trace with the latency_trace file.
+
+  preemptoff - Similar to irqsoff but traces and records the time
+               preemption is disabled.
+
+  preemptirqsoff - Similar to irqsoff and preemptoff, but traces and
+                records the largest time irqs and/or preemption is
+                disabled.
+
+  wakeup - Traces and records the max latency that it takes for
+               the highest priority task to get scheduled after
+               it has been woken up.
+
+  none - This is not a tracer. To remove all tracers from tracing
+               simply echo "none" into current_tracer.
+
+
+Examples of using the tracer
+----------------------------
+
+Here are typical examples of using the tracers with only controlling
+them with the debugfs interface (without using any user-land utilities).
+
+Output format:
+--------------
+
+Here's an example of the output format of the file "trace"
+
+                             --------
+# tracer: ftrace
+#
+#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
+#              | |      |          |         |
+            bash-4251  [01] 10152.583854: path_put <-path_walk
+            bash-4251  [01] 10152.583855: dput <-path_put
+            bash-4251  [01] 10152.583855: _atomic_dec_and_lock <-dput
+                             --------
+
+A header is printed with the trace that is represented. In this case
+the tracer is "ftrace". Then a header showing the format. Task name
+"bash", the task PID "4251", the CPU that it was running on
+"01", the timestamp in <secs>.<usecs> format, the function name that was
+traced "path_put" and the parent function that called this function
+"path_walk".
+
+The sched_switch tracer also includes tracing of task wake ups and
+context switches.
+
+     ksoftirqd/1-7     [01]  1453.070013:      7:115:R   +  2916:115:S
+     ksoftirqd/1-7     [01]  1453.070013:      7:115:R   +    10:115:S
+     ksoftirqd/1-7     [01]  1453.070013:      7:115:R ==>    10:115:R
+        events/1-10    [01]  1453.070013:     10:115:S ==>  2916:115:R
+     kondemand/1-2916  [01]  1453.070013:   2916:115:S ==>     7:115:R
+     ksoftirqd/1-7     [01]  1453.070013:      7:115:S ==>     0:140:R
+
+Wake ups are represented by a "+" and the context switches show
+"==>".  The format is:
+
+ Context switches:
+
+       Previous task              Next Task
+
+  <pid>:<prio>:<state>  ==>  <pid>:<prio>:<state>
+
+ Wake ups:
+
+       Current task               Task waking up
+
+  <pid>:<prio>:<state>    +  <pid>:<prio>:<state>
+
+The prio is the internal kernel priority, which is inverse to the
+priority that is usually displayed by user-space tools. Zero represents
+the highest priority (99). Prio 100 starts the "nice" priorities with
+100 being equal to nice -20 and 139 being nice 19. The prio "140" is
+reserved for the idle task which is the lowest priority thread (pid 0).
+
+
+Latency trace format
+--------------------
+
+For traces that display latency times, the latency_trace file gives
+a bit more information to see why a latency happened. Here's a typical
+trace.
+
+# tracer: irqsoff
+#
+irqsoff latency trace v1.1.5 on 2.6.26-rc8
+--------------------------------------------------------------------
+ latency: 97 us, #3/3, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
+    -----------------
+    | task: swapper-0 (uid:0 nice:0 policy:0 rt_prio:0)
+    -----------------
+ => started at: apic_timer_interrupt
+ => ended at:   do_softirq
+
+#                _------=> CPU#
+#               / _-----=> irqs-off
+#              | / _----=> need-resched
+#              || / _---=> hardirq/softirq
+#              ||| / _--=> preempt-depth
+#              |||| /
+#              |||||     delay
+#  cmd     pid ||||| time  |   caller
+#     \   /    |||||   \   |   /
+  <idle>-0     0d..1    0us+: trace_hardirqs_off_thunk (apic_timer_interrupt)
+  <idle>-0     0d.s.   97us : __do_softirq (do_softirq)
+  <idle>-0     0d.s1   98us : trace_hardirqs_on (do_softirq)
+
+
+vim:ft=help
+
+
+This shows that the current tracer is "irqsoff" tracing the time
+interrupts are disabled. It gives the trace version and the kernel
+this was executed on (2.6.26-rc8). Then it displays the max latency
+in microsecs (97 us). The number of trace entries displayed
+by the total number recorded (both are three: #3/3). The type of
+preemption that was used (PREEMPT). VP, KP, SP, and HP are always zero
+and reserved for later use. #P is the number of online CPUS (#P:2).
+
+The task is the process that was running when the latency happened.
+(swapper pid: 0).
+
+The start and stop that caused the latencies:
+
+  apic_timer_interrupt is where the interrupts were disabled.
+  do_softirq is where they were enabled again.
+
+The next lines after the header are the trace itself. The header
+explains which is which.
+
+  cmd: The name of the process in the trace.
+
+  pid: The PID of that process.
+
+  CPU#: The CPU that the process was running on.
+
+  irqs-off: 'd' interrupts are disabled. '.' otherwise.
+
+  need-resched: 'N' task need_resched is set, '.' otherwise.
+
+  hardirq/softirq:
+       'H' - hard irq happened inside a softirq.
+       'h' - hard irq is running
+       's' - soft irq is running
+       '.' - normal context.
+
+  preempt-depth: The level of preempt_disabled
+
+The above is mostly meaningful for kernel developers.
+
+  time: This differs from the trace output where as the trace output
+       contained a absolute timestamp. This timestamp is relative
+       to the start of the first entry in the the trace.
+
+  delay: This is just to help catch your eye a bit better. And
+       needs to be fixed to be only relative to the same CPU.
+       The marks is determined by the difference between this
+       current trace and the next trace.
+        '!' - greater than preempt_mark_thresh (default 100)
+        '+' - greater than 1 microsecond
+        ' ' - less than or equal to 1 microsecond.
+
+  The rest is the same as the 'trace' file.
+
+
+iter_ctrl
+---------
+
+The iter_ctrl file is used to control what gets printed in the trace
+output. To see what is available, simply cat the file:
+
+  cat /debug/tracing/iter_ctrl
+  print-parent nosym-offset nosym-addr noverbose noraw nohex nobin \
+ noblock nostacktrace nosched-tree
+
+To disable one of the options, echo in the option appended with "no".
+
+  echo noprint-parent > /debug/tracing/iter_ctrl
+
+To enable an option, leave off the "no".
+
+  echo sym-offest > /debug/tracing/iter_ctrl
+
+Here are the available options:
+
+  print-parent - On function traces, display the calling function
+               as well as the function being traced.
+
+  print-parent:
+   bash-4000  [01]  1477.606694: simple_strtoul <-strict_strtoul
+
+  noprint-parent:
+   bash-4000  [01]  1477.606694: simple_strtoul
+
+
+  sym-offset - Display not only the function name, but also the offset
+               in the function. For example, instead of seeing just
+               "ktime_get" you will see "ktime_get+0xb/0x20"
+
+  sym-offset:
+   bash-4000  [01]  1477.606694: simple_strtoul+0x6/0xa0
+
+  sym-addr - this will also display the function address as well as
+               the function name.
+
+  sym-addr:
+   bash-4000  [01]  1477.606694: simple_strtoul <c0339346>
+
+  verbose - This deals with the latency_trace file.
+
+    bash  4000 1 0 00000000 00010a95 [58127d26] 1720.415ms \
+    (+0.000ms): simple_strtoul (strict_strtoul)
+
+  raw - This will display raw numbers. This option is best for use with
+       user applications that can translate the raw numbers better than
+       having it done in the kernel.
+
+  hex - similar to raw, but the numbers will be in a hexadecimal format.
+
+  bin - This will print out the formats in raw binary.
+
+  block - TBD (needs update)
+
+  stacktrace - This is one of the options that changes the trace itself.
+               When a trace is recorded, so is the stack of functions.
+               This allows for back traces of trace sites.
+
+  sched-tree - TBD (any users??)
+
+
+sched_switch
+------------
+
+This tracer simply records schedule switches. Here's an example
+on how to implement it.
+
+ # echo sched_switch > /debug/tracing/current_tracer
+ # echo 1 > /debug/tracing/tracing_enabled
+ # sleep 1
+ # echo 0 > /debug/tracing/tracing_enabled
+ # cat /debug/tracing/trace
+
+# tracer: sched_switch
+#
+#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
+#              | |      |          |         |
+            bash-3997  [01]   240.132281:   3997:120:R   +  4055:120:R
+            bash-3997  [01]   240.132284:   3997:120:R ==>  4055:120:R
+           sleep-4055  [01]   240.132371:   4055:120:S ==>  3997:120:R
+            bash-3997  [01]   240.132454:   3997:120:R   +  4055:120:S
+            bash-3997  [01]   240.132457:   3997:120:R ==>  4055:120:R
+           sleep-4055  [01]   240.132460:   4055:120:D ==>  3997:120:R
+            bash-3997  [01]   240.132463:   3997:120:R   +  4055:120:D
+            bash-3997  [01]   240.132465:   3997:120:R ==>  4055:120:R
+          <idle>-0     [00]   240.132589:      0:140:R   +     4:115:S
+          <idle>-0     [00]   240.132591:      0:140:R ==>     4:115:R
+     ksoftirqd/0-4     [00]   240.132595:      4:115:S ==>     0:140:R
+          <idle>-0     [00]   240.132598:      0:140:R   +     4:115:S
+          <idle>-0     [00]   240.132599:      0:140:R ==>     4:115:R
+     ksoftirqd/0-4     [00]   240.132603:      4:115:S ==>     0:140:R
+           sleep-4055  [01]   240.133058:   4055:120:S ==>  3997:120:R
+ [...]
+
+
+As we have discussed previously about this format, the header shows
+the name of the trace and points to the options. The "FUNCTION"
+is a misnomer since here it represents the wake ups and context
+switches.
+
+The sched_switch only lists the wake ups (represented with '+')
+and context switches ('==>') with the previous task or current
+first followed by the next task or task waking up. The format for both
+of these is PID:KERNEL-PRIO:TASK-STATE. Remember that the KERNEL-PRIO
+is the inverse of the actual priority with zero (0) being the highest
+priority and the nice values starting at 100 (nice -20). Below is
+a quick chart to map the kernel priority to user land priorities.
+
+  Kernel priority: 0 to 99    ==> user RT priority 99 to 0
+  Kernel priority: 100 to 139 ==> user nice -20 to 19
+  Kernel priority: 140        ==> idle task priority
+
+The task states are:
+
+ R - running : wants to run, may not actually be running
+ S - sleep   : process is waiting to be woken up (handles signals)
+ D - deep sleep : process must be woken up (ignores signals)
+ T - stopped : process suspended
+ t - traced  : process is being traced (with something like gdb)
+ Z - zombie  : process waiting to be cleaned up
+ X - unknown
+
+
+ftrace_enabled
+--------------
+
+The following tracers give different output depending on whether
+or not the sysctl ftrace_enabled is set. To set ftrace_enabled,
+one can either use the sysctl function or set it via the proc
+file system interface.
+
+  sysctl kernel.ftrace_enabled=1
+
+ or
+
+  echo 1 > /proc/sys/kernel/ftrace_enabled
+
+To disable ftrace_enabled simply replace the '1' with '0' in
+the above commands.
+
+When ftrace_enabled is set the tracers will also record the functions
+that are within the trace. The descriptions of the tracers
+will also show an example with ftrace enabled.
+
+
+irqsoff
+-------
+
+When interrupts are disabled, the CPU can not react to any other
+external event (besides NMIs and SMIs). This prevents the timer
+interrupt from triggering or the mouse interrupt from letting the
+kernel know of a new mouse event. The result is a latency with the
+reaction time.
+
+The irqsoff tracer tracks the time interrupts are disabled and when
+they are re-enabled. When a new maximum latency is hit, it saves off
+the trace so that it may be retrieved at a later time. Every time a
+new maximum in reached, the old saved trace is discarded and the new
+trace is saved.
+
+To reset the maximum, echo 0 into tracing_max_latency. Here's an
+example:
+
+ # echo irqsoff > /debug/tracing/current_tracer
+ # echo 0 > /debug/tracing/tracing_max_latency
+ # echo 1 > /debug/tracing/tracing_enabled
+ # ls -ltr
+ [...]
+ # echo 0 > /debug/tracing/tracing_enabled
+ # cat /debug/tracing/latency_trace
+# tracer: irqsoff
+#
+irqsoff latency trace v1.1.5 on 2.6.26-rc8
+--------------------------------------------------------------------
+ latency: 6 us, #3/3, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
+    -----------------
+    | task: bash-4269 (uid:0 nice:0 policy:0 rt_prio:0)
+    -----------------
+ => started at: copy_page_range
+ => ended at:   copy_page_range
+
+#                _------=> CPU#
+#               / _-----=> irqs-off
+#              | / _----=> need-resched
+#              || / _---=> hardirq/softirq
+#              ||| / _--=> preempt-depth
+#              |||| /
+#              |||||     delay
+#  cmd     pid ||||| time  |   caller
+#     \   /    |||||   \   |   /
+    bash-4269  1...1    0us+: _spin_lock (copy_page_range)
+    bash-4269  1...1    7us : _spin_unlock (copy_page_range)
+    bash-4269  1...2    7us : trace_preempt_on (copy_page_range)
+
+
+vim:ft=help
+
+Here we see that that we had a latency of 6 microsecs (which is
+very good). The spin_lock in copy_page_range disabled interrupts.
+The difference between the 6 and the displayed timestamp 7us is
+because the clock must have incremented between the time of recording
+the max latency and recording the function that had that latency.
+
+Note the above had ftrace_enabled not set. If we set the ftrace_enabled
+we get a much larger output:
+
+# tracer: irqsoff
+#
+irqsoff latency trace v1.1.5 on 2.6.26-rc8
+--------------------------------------------------------------------
+ latency: 50 us, #101/101, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
+    -----------------
+    | task: ls-4339 (uid:0 nice:0 policy:0 rt_prio:0)
+    -----------------
+ => started at: __alloc_pages_internal
+ => ended at:   __alloc_pages_internal
+
+#                _------=> CPU#
+#               / _-----=> irqs-off
+#              | / _----=> need-resched
+#              || / _---=> hardirq/softirq
+#              ||| / _--=> preempt-depth
+#              |||| /
+#              |||||     delay
+#  cmd     pid ||||| time  |   caller
+#     \   /    |||||   \   |   /
+      ls-4339  0...1    0us+: get_page_from_freelist (__alloc_pages_internal)
+      ls-4339  0d..1    3us : rmqueue_bulk (get_page_from_freelist)
+      ls-4339  0d..1    3us : _spin_lock (rmqueue_bulk)
+      ls-4339  0d..1    4us : add_preempt_count (_spin_lock)
+      ls-4339  0d..2    4us : __rmqueue (rmqueue_bulk)
+      ls-4339  0d..2    5us : __rmqueue_smallest (__rmqueue)
+      ls-4339  0d..2    5us : __mod_zone_page_state (__rmqueue_smallest)
+      ls-4339  0d..2    6us : __rmqueue (rmqueue_bulk)
+      ls-4339  0d..2    6us : __rmqueue_smallest (__rmqueue)
+      ls-4339  0d..2    7us : __mod_zone_page_state (__rmqueue_smallest)
+      ls-4339  0d..2    7us : __rmqueue (rmqueue_bulk)
+      ls-4339  0d..2    8us : __rmqueue_smallest (__rmqueue)
+[...]
+      ls-4339  0d..2   46us : __rmqueue_smallest (__rmqueue)
+      ls-4339  0d..2   47us : __mod_zone_page_state (__rmqueue_smallest)
+      ls-4339  0d..2   47us : __rmqueue (rmqueue_bulk)
+      ls-4339  0d..2   48us : __rmqueue_smallest (__rmqueue)
+      ls-4339  0d..2   48us : __mod_zone_page_state (__rmqueue_smallest)
+      ls-4339  0d..2   49us : _spin_unlock (rmqueue_bulk)
+      ls-4339  0d..2   49us : sub_preempt_count (_spin_unlock)
+      ls-4339  0d..1   50us : get_page_from_freelist (__alloc_pages_internal)
+      ls-4339  0d..2   51us : trace_hardirqs_on (__alloc_pages_internal)
+
+
+vim:ft=help
+
+
+Here we traced a 50 microsecond latency. But we also see all the
+functions that were called during that time. Note that enabling
+function tracing we endure an added overhead. This overhead may
+extend the latency times. But never the less, this trace has provided
+some very helpful debugging.
+
+
+preemptoff
+----------
+
+When preemption is disabled we may be able to receive interrupts but
+the task can not be preempted and a higher priority task must wait
+for preemption to be enabled again before it can preempt a lower
+priority task.
+
+The preemptoff tracer traces the places that disables preemption.
+Like the irqsoff, it records the maximum latency that preemption
+was disabled. The control of preemptoff is much like the irqsoff.
+
+ # echo preemptoff > /debug/tracing/current_tracer
+ # echo 0 > /debug/tracing/tracing_max_latency
+ # echo 1 > /debug/tracing/tracing_enabled
+ # ls -ltr
+ [...]
+ # echo 0 > /debug/tracing/tracing_enabled
+ # cat /debug/tracing/latency_trace
+# tracer: preemptoff
+#
+preemptoff latency trace v1.1.5 on 2.6.26-rc8
+--------------------------------------------------------------------
+ latency: 29 us, #3/3, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
+    -----------------
+    | task: sshd-4261 (uid:0 nice:0 policy:0 rt_prio:0)
+    -----------------
+ => started at: do_IRQ
+ => ended at:   __do_softirq
+
+#                _------=> CPU#
+#               / _-----=> irqs-off
+#              | / _----=> need-resched
+#              || / _---=> hardirq/softirq
+#              ||| / _--=> preempt-depth
+#              |||| /
+#              |||||     delay
+#  cmd     pid ||||| time  |   caller
+#     \   /    |||||   \   |   /
+    sshd-4261  0d.h.    0us+: irq_enter (do_IRQ)
+    sshd-4261  0d.s.   29us : _local_bh_enable (__do_softirq)
+    sshd-4261  0d.s1   30us : trace_preempt_on (__do_softirq)
+
+
+vim:ft=help
+
+This has some more changes. Preemption was disabled when an interrupt
+came in (notice the 'h'), and was enabled while doing a softirq.
+(notice the 's'). But we also see that interrupts have been disabled
+when entering the preempt off section and leaving it (the 'd').
+We do not know if interrupts were enabled in the mean time.
+
+# tracer: preemptoff
+#
+preemptoff latency trace v1.1.5 on 2.6.26-rc8
+--------------------------------------------------------------------
+ latency: 63 us, #87/87, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
+    -----------------
+    | task: sshd-4261 (uid:0 nice:0 policy:0 rt_prio:0)
+    -----------------
+ => started at: remove_wait_queue
+ => ended at:   __do_softirq
+
+#                _------=> CPU#
+#               / _-----=> irqs-off
+#              | / _----=> need-resched
+#              || / _---=> hardirq/softirq
+#              ||| / _--=> preempt-depth
+#              |||| /
+#              |||||     delay
+#  cmd     pid ||||| time  |   caller
+#     \   /    |||||   \   |   /
+    sshd-4261  0d..1    0us : _spin_lock_irqsave (remove_wait_queue)
+    sshd-4261  0d..1    1us : _spin_unlock_irqrestore (remove_wait_queue)
+    sshd-4261  0d..1    2us : do_IRQ (common_interrupt)
+    sshd-4261  0d..1    2us : irq_enter (do_IRQ)
+    sshd-4261  0d..1    2us : idle_cpu (irq_enter)
+    sshd-4261  0d..1    3us : add_preempt_count (irq_enter)
+    sshd-4261  0d.h1    3us : idle_cpu (irq_enter)
+    sshd-4261  0d.h.    4us : handle_fasteoi_irq (do_IRQ)
+[...]
+    sshd-4261  0d.h.   12us : add_preempt_count (_spin_lock)
+    sshd-4261  0d.h1   12us : ack_ioapic_quirk_irq (handle_fasteoi_irq)
+    sshd-4261  0d.h1   13us : move_native_irq (ack_ioapic_quirk_irq)
+    sshd-4261  0d.h1   13us : _spin_unlock (handle_fasteoi_irq)
+    sshd-4261  0d.h1   14us : sub_preempt_count (_spin_unlock)
+    sshd-4261  0d.h1   14us : irq_exit (do_IRQ)
+    sshd-4261  0d.h1   15us : sub_preempt_count (irq_exit)
+    sshd-4261  0d..2   15us : do_softirq (irq_exit)
+    sshd-4261  0d...   15us : __do_softirq (do_softirq)
+    sshd-4261  0d...   16us : __local_bh_disable (__do_softirq)
+    sshd-4261  0d...   16us+: add_preempt_count (__local_bh_disable)
+    sshd-4261  0d.s4   20us : add_preempt_count (__local_bh_disable)
+    sshd-4261  0d.s4   21us : sub_preempt_count (local_bh_enable)
+    sshd-4261  0d.s5   21us : sub_preempt_count (local_bh_enable)
+[...]
+    sshd-4261  0d.s6   41us : add_preempt_count (__local_bh_disable)
+    sshd-4261  0d.s6   42us : sub_preempt_count (local_bh_enable)
+    sshd-4261  0d.s7   42us : sub_preempt_count (local_bh_enable)
+    sshd-4261  0d.s5   43us : add_preempt_count (__local_bh_disable)
+    sshd-4261  0d.s5   43us : sub_preempt_count (local_bh_enable_ip)
+    sshd-4261  0d.s6   44us : sub_preempt_count (local_bh_enable_ip)
+    sshd-4261  0d.s5   44us : add_preempt_count (__local_bh_disable)
+    sshd-4261  0d.s5   45us : sub_preempt_count (local_bh_enable)
+[...]
+    sshd-4261  0d.s.   63us : _local_bh_enable (__do_softirq)
+    sshd-4261  0d.s1   64us : trace_preempt_on (__do_softirq)
+
+
+The above is an example of the preemptoff trace with ftrace_enabled
+set. Here we see that interrupts were disabled the entire time.
+The irq_enter code lets us know that we entered an interrupt 'h'.
+Before that, the functions being traced still show that it is not
+in an interrupt, but we can see by the functions themselves that
+this is not the case.
+
+Notice that the __do_softirq when called doesn't have a preempt_count.
+It may seem that we missed a preempt enabled. What really happened
+is that the preempt count is held on the threads stack and we
+switched to the softirq stack (4K stacks in effect). The code
+does not copy the preempt count, but because interrupts are disabled
+we don't need to worry about it. Having a tracer like this is good
+to let people know what really happens inside the kernel.
+
+
+preemptirqsoff
+--------------
+
+Knowing the locations that have interrupts disabled or preemption
+disabled for the longest times is helpful. But sometimes we would
+like to know when either preemption and/or interrupts are disabled.
+
+The following code:
+
+    local_irq_disable();
+    call_function_with_irqs_off();
+    preempt_disable();
+    call_function_with_irqs_and_preemption_off();
+    local_irq_enable();
+    call_function_with_preemption_off();
+    preempt_enable();
+
+The irqsoff tracer will record the total length of
+call_function_with_irqs_off() and
+call_function_with_irqs_and_preemption_off().
+
+The preemptoff tracer will record the total length of
+call_function_with_irqs_and_preemption_off() and
+call_function_with_preemption_off().
+
+But neither will trace the time that interrupts and/or preemption
+is disabled. This total time is the time that we can not schedule.
+To record this time, use the preemptirqsoff tracer.
+
+Again, using this trace is much like the irqsoff and preemptoff tracers.
+
+ # echo preemptoff > /debug/tracing/current_tracer
+ # echo 0 > /debug/tracing/tracing_max_latency
+ # echo 1 > /debug/tracing/tracing_enabled
+ # ls -ltr
+ [...]
+ # echo 0 > /debug/tracing/tracing_enabled
+ # cat /debug/tracing/latency_trace
+# tracer: preemptirqsoff
+#
+preemptirqsoff latency trace v1.1.5 on 2.6.26-rc8
+--------------------------------------------------------------------
+ latency: 293 us, #3/3, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
+    -----------------
+    | task: ls-4860 (uid:0 nice:0 policy:0 rt_prio:0)
+    -----------------
+ => started at: apic_timer_interrupt
+ => ended at:   __do_softirq
+
+#                _------=> CPU#
+#               / _-----=> irqs-off
+#              | / _----=> need-resched
+#              || / _---=> hardirq/softirq
+#              ||| / _--=> preempt-depth
+#              |||| /
+#              |||||     delay
+#  cmd     pid ||||| time  |   caller
+#     \   /    |||||   \   |   /
+      ls-4860  0d...    0us!: trace_hardirqs_off_thunk (apic_timer_interrupt)
+      ls-4860  0d.s.  294us : _local_bh_enable (__do_softirq)
+      ls-4860  0d.s1  294us : trace_preempt_on (__do_softirq)
+
+
+vim:ft=help
+
+
+The trace_hardirqs_off_thunk is called from assembly on x86 when
+interrupts are disabled in the assembly code. Without the function
+tracing, we don't know if interrupts were enabled within the preemption
+points. We do see that it started with preemption enabled.
+
+Here is a trace with ftrace_enabled set:
+
+
+# tracer: preemptirqsoff
+#
+preemptirqsoff latency trace v1.1.5 on 2.6.26-rc8
+--------------------------------------------------------------------
+ latency: 105 us, #183/183, CPU#0 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
+    -----------------
+    | task: sshd-4261 (uid:0 nice:0 policy:0 rt_prio:0)
+    -----------------
+ => started at: write_chan
+ => ended at:   __do_softirq
+
+#                _------=> CPU#
+#               / _-----=> irqs-off
+#              | / _----=> need-resched
+#              || / _---=> hardirq/softirq
+#              ||| / _--=> preempt-depth
+#              |||| /
+#              |||||     delay
+#  cmd     pid ||||| time  |   caller
+#     \   /    |||||   \   |   /
+      ls-4473  0.N..    0us : preempt_schedule (write_chan)
+      ls-4473  0dN.1    1us : _spin_lock (schedule)
+      ls-4473  0dN.1    2us : add_preempt_count (_spin_lock)
+      ls-4473  0d..2    2us : put_prev_task_fair (schedule)
+[...]
+      ls-4473  0d..2   13us : set_normalized_timespec (ktime_get_ts)
+      ls-4473  0d..2   13us : __switch_to (schedule)
+    sshd-4261  0d..2   14us : finish_task_switch (schedule)
+    sshd-4261  0d..2   14us : _spin_unlock_irq (finish_task_switch)
+    sshd-4261  0d..1   15us : add_preempt_count (_spin_lock_irqsave)
+    sshd-4261  0d..2   16us : _spin_unlock_irqrestore (hrtick_set)
+    sshd-4261  0d..2   16us : do_IRQ (common_interrupt)
+    sshd-4261  0d..2   17us : irq_enter (do_IRQ)
+    sshd-4261  0d..2   17us : idle_cpu (irq_enter)
+    sshd-4261  0d..2   18us : add_preempt_count (irq_enter)
+    sshd-4261  0d.h2   18us : idle_cpu (irq_enter)
+    sshd-4261  0d.h.   18us : handle_fasteoi_irq (do_IRQ)
+    sshd-4261  0d.h.   19us : _spin_lock (handle_fasteoi_irq)
+    sshd-4261  0d.h.   19us : add_preempt_count (_spin_lock)
+    sshd-4261  0d.h1   20us : _spin_unlock (handle_fasteoi_irq)
+    sshd-4261  0d.h1   20us : sub_preempt_count (_spin_unlock)
+[...]
+    sshd-4261  0d.h1   28us : _spin_unlock (handle_fasteoi_irq)
+    sshd-4261  0d.h1   29us : sub_preempt_count (_spin_unlock)
+    sshd-4261  0d.h2   29us : irq_exit (do_IRQ)
+    sshd-4261  0d.h2   29us : sub_preempt_count (irq_exit)
+    sshd-4261  0d..3   30us : do_softirq (irq_exit)
+    sshd-4261  0d...   30us : __do_softirq (do_softirq)
+    sshd-4261  0d...   31us : __local_bh_disable (__do_softirq)
+    sshd-4261  0d...   31us+: add_preempt_count (__local_bh_disable)
+    sshd-4261  0d.s4   34us : add_preempt_count (__local_bh_disable)
+[...]
+    sshd-4261  0d.s3   43us : sub_preempt_count (local_bh_enable_ip)
+    sshd-4261  0d.s4   44us : sub_preempt_count (local_bh_enable_ip)
+    sshd-4261  0d.s3   44us : smp_apic_timer_interrupt (apic_timer_interrupt)
+    sshd-4261  0d.s3   45us : irq_enter (smp_apic_timer_interrupt)
+    sshd-4261  0d.s3   45us : idle_cpu (irq_enter)
+    sshd-4261  0d.s3   46us : add_preempt_count (irq_enter)
+    sshd-4261  0d.H3   46us : idle_cpu (irq_enter)
+    sshd-4261  0d.H3   47us : hrtimer_interrupt (smp_apic_timer_interrupt)
+    sshd-4261  0d.H3   47us : ktime_get (hrtimer_interrupt)
+[...]
+    sshd-4261  0d.H3   81us : tick_program_event (hrtimer_interrupt)
+    sshd-4261  0d.H3   82us : ktime_get (tick_program_event)
+    sshd-4261  0d.H3   82us : ktime_get_ts (ktime_get)
+    sshd-4261  0d.H3   83us : getnstimeofday (ktime_get_ts)
+    sshd-4261  0d.H3   83us : set_normalized_timespec (ktime_get_ts)
+    sshd-4261  0d.H3   84us : clockevents_program_event (tick_program_event)
+    sshd-4261  0d.H3   84us : lapic_next_event (clockevents_program_event)
+    sshd-4261  0d.H3   85us : irq_exit (smp_apic_timer_interrupt)
+    sshd-4261  0d.H3   85us : sub_preempt_count (irq_exit)
+    sshd-4261  0d.s4   86us : sub_preempt_count (irq_exit)
+    sshd-4261  0d.s3   86us : add_preempt_count (__local_bh_disable)
+[...]
+    sshd-4261  0d.s1   98us : sub_preempt_count (net_rx_action)
+    sshd-4261  0d.s.   99us : add_preempt_count (_spin_lock_irq)
+    sshd-4261  0d.s1   99us+: _spin_unlock_irq (run_timer_softirq)
+    sshd-4261  0d.s.  104us : _local_bh_enable (__do_softirq)
+    sshd-4261  0d.s.  104us : sub_preempt_count (_local_bh_enable)
+    sshd-4261  0d.s.  105us : _local_bh_enable (__do_softirq)
+    sshd-4261  0d.s1  105us : trace_preempt_on (__do_softirq)
+
+
+This is a very interesting trace. It started with the preemption of
+the ls task. We see that the task had the "need_resched" bit set
+with the 'N' in the trace.  Interrupts are disabled in the spin_lock
+and the trace started. We see that a schedule took place to run
+sshd.  When the interrupts were enabled we took an interrupt.
+On return of the interrupt the softirq ran. We took another interrupt
+while running the softirq as we see with the capital 'H'.
+
+
+wakeup
+------
+
+In Real-Time environment it is very important to know the wakeup
+time it takes for the highest priority task that wakes up to the
+time it executes. This is also known as "schedule latency".
+I stress the point that this is about RT tasks. It is also important
+to know the scheduling latency of non-RT tasks, but the average
+schedule latency is better for non-RT tasks. Tools like
+LatencyTop is more appropriate for such measurements.
+
+Real-Time environments is interested in the worst case latency.
+That is the longest latency it takes for something to happen, and
+not the average. We can have a very fast scheduler that may only
+have a large latency once in a while, but that would not work well
+with Real-Time tasks.  The wakeup tracer was designed to record
+the worst case wakeups of RT tasks. Non-RT tasks are not recorded
+because the tracer only records one worst case and tracing non-RT
+tasks that are unpredictable will overwrite the worst case latency
+of RT tasks.
+
+Since this tracer only deals with RT tasks, we will run this slightly
+different than we did with the previous tracers. Instead of performing
+an 'ls' we will run 'sleep 1' under 'chrt' which changes the
+priority of the task.
+
+ # echo wakeup > /debug/tracing/current_tracer
+ # echo 0 > /debug/tracing/tracing_max_latency
+ # echo 1 > /debug/tracing/tracing_enabled
+ # chrt -f 5 sleep 1
+ # echo 0 > /debug/tracing/tracing_enabled
+ # cat /debug/tracing/latency_trace
+# tracer: wakeup
+#
+wakeup latency trace v1.1.5 on 2.6.26-rc8
+--------------------------------------------------------------------
+ latency: 4 us, #2/2, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
+    -----------------
+    | task: sleep-4901 (uid:0 nice:0 policy:1 rt_prio:5)
+    -----------------
+
+#                _------=> CPU#
+#               / _-----=> irqs-off
+#              | / _----=> need-resched
+#              || / _---=> hardirq/softirq
+#              ||| / _--=> preempt-depth
+#              |||| /
+#              |||||     delay
+#  cmd     pid ||||| time  |   caller
+#     \   /    |||||   \   |   /
+  <idle>-0     1d.h4    0us+: try_to_wake_up (wake_up_process)
+  <idle>-0     1d..4    4us : schedule (cpu_idle)
+
+
+vim:ft=help
+
+
+Running this on an idle system we see that it only took 4 microseconds
+to perform the task switch.  Note, since the trace marker in the
+schedule is before the actual "switch" we stop the tracing when
+the recorded task is about to schedule in. This may change if
+we add a new marker at the end of the scheduler.
+
+Notice that the recorded task is 'sleep' with the PID of 4901 and it
+has an rt_prio of 5. This priority is user-space priority and not
+the internal kernel priority. The policy is 1 for SCHED_FIFO and 2
+for SCHED_RR.
+
+Doing the same with chrt -r 5 and ftrace_enabled set.
+
+# tracer: wakeup
+#
+wakeup latency trace v1.1.5 on 2.6.26-rc8
+--------------------------------------------------------------------
+ latency: 50 us, #60/60, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2)
+    -----------------
+    | task: sleep-4068 (uid:0 nice:0 policy:2 rt_prio:5)
+    -----------------
+
+#                _------=> CPU#
+#               / _-----=> irqs-off
+#              | / _----=> need-resched
+#              || / _---=> hardirq/softirq
+#              ||| / _--=> preempt-depth
+#              |||| /
+#              |||||     delay
+#  cmd     pid ||||| time  |   caller
+#     \   /    |||||   \   |   /
+ksoftirq-7     1d.H3    0us : try_to_wake_up (wake_up_process)
+ksoftirq-7     1d.H4    1us : sub_preempt_count (marker_probe_cb)
+ksoftirq-7     1d.H3    2us : check_preempt_wakeup (try_to_wake_up)
+ksoftirq-7     1d.H3    3us : update_curr (check_preempt_wakeup)
+ksoftirq-7     1d.H3    4us : calc_delta_mine (update_curr)
+ksoftirq-7     1d.H3    5us : __resched_task (check_preempt_wakeup)
+ksoftirq-7     1d.H3    6us : task_wake_up_rt (try_to_wake_up)
+ksoftirq-7     1d.H3    7us : _spin_unlock_irqrestore (try_to_wake_up)
+[...]
+ksoftirq-7     1d.H2   17us : irq_exit (smp_apic_timer_interrupt)
+ksoftirq-7     1d.H2   18us : sub_preempt_count (irq_exit)
+ksoftirq-7     1d.s3   19us : sub_preempt_count (irq_exit)
+ksoftirq-7     1..s2   20us : rcu_process_callbacks (__do_softirq)
+[...]
+ksoftirq-7     1..s2   26us : __rcu_process_callbacks (rcu_process_callbacks)
+ksoftirq-7     1d.s2   27us : _local_bh_enable (__do_softirq)
+ksoftirq-7     1d.s2   28us : sub_preempt_count (_local_bh_enable)
+ksoftirq-7     1.N.3   29us : sub_preempt_count (ksoftirqd)
+ksoftirq-7     1.N.2   30us : _cond_resched (ksoftirqd)
+ksoftirq-7     1.N.2   31us : __cond_resched (_cond_resched)
+ksoftirq-7     1.N.2   32us : add_preempt_count (__cond_resched)
+ksoftirq-7     1.N.2   33us : schedule (__cond_resched)
+ksoftirq-7     1.N.2   33us : add_preempt_count (schedule)
+ksoftirq-7     1.N.3   34us : hrtick_clear (schedule)
+ksoftirq-7     1dN.3   35us : _spin_lock (schedule)
+ksoftirq-7     1dN.3   36us : add_preempt_count (_spin_lock)
+ksoftirq-7     1d..4   37us : put_prev_task_fair (schedule)
+ksoftirq-7     1d..4   38us : update_curr (put_prev_task_fair)
+[...]
+ksoftirq-7     1d..5   47us : _spin_trylock (tracing_record_cmdline)
+ksoftirq-7     1d..5   48us : add_preempt_count (_spin_trylock)
+ksoftirq-7     1d..6   49us : _spin_unlock (tracing_record_cmdline)
+ksoftirq-7     1d..6   49us : sub_preempt_count (_spin_unlock)
+ksoftirq-7     1d..4   50us : schedule (__cond_resched)
+
+The interrupt went off while running ksoftirqd. This task runs at
+SCHED_OTHER. Why didn't we see the 'N' set early? This may be
+a harmless bug with x86_32 and 4K stacks. The need_reched() function
+that tests if we need to reschedule looks on the actual stack.
+Where as the setting of the NEED_RESCHED bit happens on the
+task's stack. But because we are in a hard interrupt, the test
+is with the interrupts stack which has that to be false. We don't
+see the 'N' until we switch back to the task's stack.
+
+ftrace
+------
+
+ftrace is not only the name of the tracing infrastructure, but it
+is also a name of one of the tracers. The tracer is the function
+tracer. Enabling the function tracer can be done from the
+debug file system. Make sure the ftrace_enabled is set otherwise
+this tracer is a nop.
+
+ # sysctl kernel.ftrace_enabled=1
+ # echo ftrace > /debug/tracing/current_tracer
+ # echo 1 > /debug/tracing/tracing_enabled
+ # usleep 1
+ # echo 0 > /debug/tracing/tracing_enabled
+ # cat /debug/tracing/trace
+# tracer: ftrace
+#
+#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
+#              | |      |          |         |
+            bash-4003  [00]   123.638713: finish_task_switch <-schedule
+            bash-4003  [00]   123.638714: _spin_unlock_irq <-finish_task_switch
+            bash-4003  [00]   123.638714: sub_preempt_count <-_spin_unlock_irq
+            bash-4003  [00]   123.638715: hrtick_set <-schedule
+            bash-4003  [00]   123.638715: _spin_lock_irqsave <-hrtick_set
+            bash-4003  [00]   123.638716: add_preempt_count <-_spin_lock_irqsave
+            bash-4003  [00]   123.638716: _spin_unlock_irqrestore <-hrtick_set
+            bash-4003  [00]   123.638717: sub_preempt_count <-_spin_unlock_irqrestore
+            bash-4003  [00]   123.638717: hrtick_clear <-hrtick_set
+            bash-4003  [00]   123.638718: sub_preempt_count <-schedule
+            bash-4003  [00]   123.638718: sub_preempt_count <-preempt_schedule
+            bash-4003  [00]   123.638719: wait_for_completion <-__stop_machine_run
+            bash-4003  [00]   123.638719: wait_for_common <-wait_for_completion
+            bash-4003  [00]   123.638720: _spin_lock_irq <-wait_for_common
+            bash-4003  [00]   123.638720: add_preempt_count <-_spin_lock_irq
+[...]
+
+
+Note: It is sometimes better to enable or disable tracing directly from
+a program, because the buffer may be overflowed by the echo commands
+before you get to the point you want to trace. It is also easier to
+stop the tracing at the point that you hit the part that you are
+interested in. Since the ftrace buffer is a ring buffer with the
+oldest data being overwritten, usually it is sufficient to start the
+tracer with an echo command but have you code stop it. Something
+like the following is usually appropriate for this.
+
+int trace_fd;
+[...]
+int main(int argc, char *argv[]) {
+       [...]
+       trace_fd = open("/debug/tracing/tracing_enabled", O_WRONLY);
+       [...]
+       if (condition_hit()) {
+       write(trace_fd, "0", 1);
+       }
+       [...]
+}
+
+
+dynamic ftrace
+--------------
+
+If CONFIG_DYNAMIC_FTRACE is set, then the system will run with
+virtually no overhead when function tracing is disabled. The way
+this works is the mcount function call (placed at the start of
+every kernel function, produced by the -pg switch in gcc), starts
+of pointing to a simple return.
+
+When dynamic ftrace is initialized, it calls kstop_machine to make it
+act like a uniprocessor so that it can freely modify code without
+worrying about other processors executing that same code.  At
+initialization, the mcount calls are change to call a "record_ip"
+function.  After this, the first time a kernel function is called,
+it has the calling address saved in a hash table.
+
+Later on the ftraced kernel thread is awoken and will again call
+kstop_machine if new functions have been recorded. The ftraced thread
+will change all calls to mcount to "nop".  Just calling mcount
+and having mcount return has shown a 10% overhead. By converting
+it to a nop, there is no recordable overhead to the system.
+
+One special side-effect to the recording of the functions being
+traced, is that we can now selectively choose which functions we
+want to trace and which ones we want the mcount calls to remain as
+nops.
+
+Two files that contain to the enabling and disabling of recorded
+functions are:
+
+  set_ftrace_filter
+
+and
+
+  set_ftrace_notrace
+
+A list of available functions that you can add to this files is listed
+in:
+
+   available_filter_functions
+
+ # cat /debug/tracing/available_filter_functions
+put_prev_task_idle
+kmem_cache_create
+pick_next_task_rt
+get_online_cpus
+pick_next_task_fair
+mutex_lock
+[...]
+
+If I'm only interested in sys_nanosleep and hrtimer_interrupt:
+
+ # echo sys_nanosleep hrtimer_interrupt \
+               > /debug/tracing/set_ftrace_filter
+ # echo ftrace > /debug/tracing/current_tracer
+ # echo 1 > /debug/tracing/tracing_enabled
+ # usleep 1
+ # echo 0 > /debug/tracing/tracing_enabled
+ # cat /debug/tracing/trace
+# tracer: ftrace
+#
+#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
+#              | |      |          |         |
+          usleep-4134  [00]  1317.070017: hrtimer_interrupt <-smp_apic_timer_interrupt
+          usleep-4134  [00]  1317.070111: sys_nanosleep <-syscall_call
+          <idle>-0     [00]  1317.070115: hrtimer_interrupt <-smp_apic_timer_interrupt
+
+To see what functions are being traced, you can cat the file:
+
+ # cat /debug/tracing/set_ftrace_filter
+hrtimer_interrupt
+sys_nanosleep
+
+
+Perhaps this isn't enough. The filters also allow simple wild cards.
+Only the following is currently available
+
+  <match>*  - will match functions that begins with <match>
+  *<match>  - will match functions that end with <match>
+  *<match>* - will match functions that have <match> in it
+
+Thats all the wild cards that are allowed.
+
+  <match>*<match> will not work.
+
+ # echo hrtimer_* > /debug/tracing/set_ftrace_filter
+
+Produces:
+
+# tracer: ftrace
+#
+#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
+#              | |      |          |         |
+            bash-4003  [00]  1480.611794: hrtimer_init <-copy_process
+            bash-4003  [00]  1480.611941: hrtimer_start <-hrtick_set
+            bash-4003  [00]  1480.611956: hrtimer_cancel <-hrtick_clear
+            bash-4003  [00]  1480.611956: hrtimer_try_to_cancel <-hrtimer_cancel
+          <idle>-0     [00]  1480.612019: hrtimer_get_next_event <-get_next_timer_interrupt
+          <idle>-0     [00]  1480.612025: hrtimer_get_next_event <-get_next_timer_interrupt
+          <idle>-0     [00]  1480.612032: hrtimer_get_next_event <-get_next_timer_interrupt
+          <idle>-0     [00]  1480.612037: hrtimer_get_next_event <-get_next_timer_interrupt
+          <idle>-0     [00]  1480.612382: hrtimer_get_next_event <-get_next_timer_interrupt
+
+
+Notice that we lost the sys_nanosleep.
+
+ # cat /debug/tracing/set_ftrace_filter
+hrtimer_run_queues
+hrtimer_run_pending
+hrtimer_init
+hrtimer_cancel
+hrtimer_try_to_cancel
+hrtimer_forward
+hrtimer_start
+hrtimer_reprogram
+hrtimer_force_reprogram
+hrtimer_get_next_event
+hrtimer_interrupt
+hrtimer_nanosleep
+hrtimer_wakeup
+hrtimer_get_remaining
+hrtimer_get_res
+hrtimer_init_sleeper
+
+
+This is because the '>' and '>>' act just like they do in bash.
+To rewrite the filters, use '>'
+To append to the filters, use '>>'
+
+To clear out a filter so that all functions will be recorded again.
+
+ # echo > /debug/tracing/set_ftrace_filter
+ # cat /debug/tracing/set_ftrace_filter
+ #
+
+Again, now we want to append.
+
+ # echo sys_nanosleep > /debug/tracing/set_ftrace_filter
+ # cat /debug/tracing/set_ftrace_filter
+sys_nanosleep
+ # echo hrtimer_* >> /debug/tracing/set_ftrace_filter
+ # cat /debug/tracing/set_ftrace_filter
+hrtimer_run_queues
+hrtimer_run_pending
+hrtimer_init
+hrtimer_cancel
+hrtimer_try_to_cancel
+hrtimer_forward
+hrtimer_start
+hrtimer_reprogram
+hrtimer_force_reprogram
+hrtimer_get_next_event
+hrtimer_interrupt
+sys_nanosleep
+hrtimer_nanosleep
+hrtimer_wakeup
+hrtimer_get_remaining
+hrtimer_get_res
+hrtimer_init_sleeper
+
+
+The set_ftrace_notrace prevents those functions from being traced.
+
+ # echo '*preempt*' '*lock*' > /debug/tracing/set_ftrace_notrace
+
+Produces:
+
+# tracer: ftrace
+#
+#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
+#              | |      |          |         |
+            bash-4043  [01]   115.281644: finish_task_switch <-schedule
+            bash-4043  [01]   115.281645: hrtick_set <-schedule
+            bash-4043  [01]   115.281645: hrtick_clear <-hrtick_set
+            bash-4043  [01]   115.281646: wait_for_completion <-__stop_machine_run
+            bash-4043  [01]   115.281647: wait_for_common <-wait_for_completion
+            bash-4043  [01]   115.281647: kthread_stop <-stop_machine_run
+            bash-4043  [01]   115.281648: init_waitqueue_head <-kthread_stop
+            bash-4043  [01]   115.281648: wake_up_process <-kthread_stop
+            bash-4043  [01]   115.281649: try_to_wake_up <-wake_up_process
+
+We can see that there's no more lock or preempt tracing.
+
+ftraced
+-------
+
+As mentioned above, when dynamic ftrace is configured in, a kernel
+thread wakes up once a second and checks to see if there are mcount
+calls that need to be converted into nops. If there is not, then
+it simply goes back to sleep. But if there is, it will call
+kstop_machine to convert the calls to nops.
+
+There may be a case that you do not want this added latency.
+Perhaps you are doing some audio recording and this activity might
+cause skips in the playback. There is an interface to disable
+and enable the ftraced kernel thread.
+
+ # echo 0 > /debug/tracing/ftraced_enabled
+
+This will disable the calling of the kstop_machine to update the
+mcount calls to nops. Remember that there's a large overhead
+to calling mcount. Without this kernel thread, that overhead will
+exist.
+
+Any write to the ftraced_enabled file will cause the kstop_machine
+to run if there are recorded calls to mcount. This means that a
+user can manually perform the updates when they want to by simply
+echoing a '0' into the ftraced_enabled file.
+
+The updates are also done at the beginning of enabling a tracer
+that uses ftrace function recording.
+
+
+trace_pipe
+----------
+
+The trace_pipe outputs the same as trace, but the effect on the
+tracing is different. Every read from trace_pipe is consumed.
+This means that subsequent reads will be different. The trace
+is live.
+
+ # echo ftrace > /debug/tracing/current_tracer
+ # cat /debug/tracing/trace_pipe > /tmp/trace.out &
+[1] 4153
+ # echo 1 > /debug/tracing/tracing_enabled
+ # usleep 1
+ # echo 0 > /debug/tracing/tracing_enabled
+ # cat /debug/tracing/trace
+# tracer: ftrace
+#
+#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
+#              | |      |          |         |
+
+ #
+ # cat /tmp/trace.out
+            bash-4043  [00] 41.267106: finish_task_switch <-schedule
+            bash-4043  [00] 41.267106: hrtick_set <-schedule
+            bash-4043  [00] 41.267107: hrtick_clear <-hrtick_set
+            bash-4043  [00] 41.267108: wait_for_completion <-__stop_machine_run
+            bash-4043  [00] 41.267108: wait_for_common <-wait_for_completion
+            bash-4043  [00] 41.267109: kthread_stop <-stop_machine_run
+            bash-4043  [00] 41.267109: init_waitqueue_head <-kthread_stop
+            bash-4043  [00] 41.267110: wake_up_process <-kthread_stop
+            bash-4043  [00] 41.267110: try_to_wake_up <-wake_up_process
+            bash-4043  [00] 41.267111: select_task_rq_rt <-try_to_wake_up
+
+
+Note, reading the trace_pipe will block until more input is added.
+By changing the tracer, trace_pipe will issue an EOF. We needed
+to set the ftrace tracer _before_ cating the trace_pipe file.
+
+
+trace entries
+-------------
+
+Having too much or not enough data can be troublesome in diagnosing
+some issue in the kernel. The file trace_entries is used to modify
+the size of the internal trace buffers. The numbers listed
+is the number of entries that can be recorded per CPU. To know
+the full size, multiply the number of possible CPUS with the
+number of entries.
+
+ # cat /debug/tracing/trace_entries
+65620
+
+Note, to modify this you must have tracing fulling disabled. To do that,
+echo "none" into the current_tracer.
+
+ # echo none > /debug/tracing/current_tracer
+ # echo 100000 > /debug/tracing/trace_entries
+ # cat /debug/tracing/trace_entries
+100045
+
+
+Notice that we echoed in 100,000 but the size is 100,045. The entries
+are held by individual pages. It allocates the number of pages it takes
+to fulfill the request. If more entries may fit on the last page
+it will add them.
+
+ # echo 1 > /debug/tracing/trace_entries
+ # cat /debug/tracing/trace_entries
+85
+
+This shows us that 85 entries can fit on a single page.
+
+The number of pages that will be allocated is a percentage of available
+memory. Allocating too much will produces an error.
+
+ # echo 1000000000000 > /debug/tracing/trace_entries
+-bash: echo: write error: Cannot allocate memory
+ # cat /debug/tracing/trace_entries
+85
+
index ee75cbace28d529cb690e573ec4c2cb67f75bd0f..d4cd4126d1adeca025e76a2511b0881cd6d0c00c 100644 (file)
@@ -25,12 +25,23 @@ routines, and should be zero-initialized except for fields with data you
 provide.  A client structure holds device-specific information like the
 driver model device node, and its I2C address.
 
+/* iff driver uses driver model ("new style") binding model: */
+
+static struct i2c_device_id foo_idtable[] = {
+       { "foo", my_id_for_foo },
+       { "bar", my_id_for_bar },
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, foo_idtable);
+
 static struct i2c_driver foo_driver = {
        .driver = {
                .name   = "foo",
        },
 
        /* iff driver uses driver model ("new style") binding model: */
+       .id_table       = foo_ids,
        .probe          = foo_probe,
        .remove         = foo_remove,
 
@@ -173,10 +184,9 @@ handle may be used during foo_probe().  If foo_probe() reports success
 (zero not a negative status code) it may save the handle and use it until
 foo_remove() returns.  That binding model is used by most Linux drivers.
 
-Drivers match devices when i2c_client.driver_name and the driver name are
-the same; this approach is used in several other busses that don't have
-device typing support in the hardware.  The driver and module name should
-match, so hotplug/coldplug mechanisms will modprobe the driver.
+The probe function is called when an entry in the id_table name field
+matches the device's name. It is passed the entry that was matched so
+the driver knows which one in the table matched.
 
 
 Device Creation (Standard driver model)
index 240ce7a56c40c9edfd141468ef2f2f1cf40dfab5..3bb5f466a90db3e971b42fb26c60d716a30878ed 100644 (file)
@@ -117,6 +117,7 @@ Code        Seq#    Include File            Comments
                                        <mailto:natalia@nikhefk.nikhef.nl>
 'c'    00-7F   linux/comstats.h        conflict!
 'c'    00-7F   linux/coda.h            conflict!
+'c'    80-9F   asm-s390/chsc.h
 'd'    00-FF   linux/char/drm/drm/h    conflict!
 'd'    00-DF   linux/video_decoder.h   conflict!
 'd'    F0-FF   linux/digi1.h
index e07c432c731ff9a516fe8b23228af0fe6fa1d29a..b52f47d588b40fea417bf4bca4ffdbfef4d02152 100644 (file)
@@ -295,7 +295,7 @@ and is between 256 and 4096 characters. It is defined in the file
                        when initialising the APIC and IO-APIC components.
 
        apm=            [APM] Advanced Power Management
-                       See header of arch/i386/kernel/apm.c.
+                       See header of arch/x86/kernel/apm_32.c.
 
        arcrimi=        [HW,NET] ARCnet - "RIM I" (entirely mem-mapped) cards
                        Format: <io>,<irq>,<nodeID>
@@ -638,7 +638,7 @@ and is between 256 and 4096 characters. It is defined in the file
 
        elanfreq=       [X86-32]
                        See comment before function elanfreq_setup() in
-                       arch/i386/kernel/cpu/cpufreq/elanfreq.c.
+                       arch/x86/kernel/cpu/cpufreq/elanfreq.c.
 
        elevator=       [IOSCHED]
                        Format: {"anticipatory" | "cfq" | "deadline" | "noop"}
@@ -1679,6 +1679,10 @@ and is between 256 and 4096 characters. It is defined in the file
                        Format: <reboot_mode>[,<reboot_mode2>[,...]]
                        See arch/*/kernel/reboot.c or arch/*/kernel/process.c                   
 
+       relax_domain_level=
+                       [KNL, SMP] Set scheduler's default relax_domain_level.
+                       See Documentation/cpusets.txt.
+
        reserve=        [KNL,BUGS] Force the kernel to ignore some iomem area
 
        reservetop=     [X86-32]
index 17a6e46fbd43abfce8ad5558f99200f8389ac650..946b66e1b65214f4becc5d2563f73180fe331837 100644 (file)
@@ -81,23 +81,23 @@ inet_peer_minttl - INTEGER
        Minimum time-to-live of entries.  Should be enough to cover fragment
        time-to-live on the reassembling side.  This minimum time-to-live  is
        guaranteed if the pool size is less than inet_peer_threshold.
-       Measured in jiffies(1).
+       Measured in seconds.
 
 inet_peer_maxttl - INTEGER
        Maximum time-to-live of entries.  Unused entries will expire after
        this period of time if there is no memory pressure on the pool (i.e.
        when the number of entries in the pool is very small).
-       Measured in jiffies(1).
+       Measured in seconds.
 
 inet_peer_gc_mintime - INTEGER
        Minimum interval between garbage collection passes.  This interval is
        in effect under high memory pressure on the pool.
-       Measured in jiffies(1).
+       Measured in seconds.
 
 inet_peer_gc_maxtime - INTEGER
        Minimum interval between garbage collection passes.  This interval is
        in effect under low (or absent) memory pressure on the pool.
-       Measured in jiffies(1).
+       Measured in seconds.
 
 TCP variables: 
 
@@ -148,9 +148,9 @@ tcp_available_congestion_control - STRING
        but not loaded.
 
 tcp_base_mss - INTEGER
-       The initial value of search_low to be used by Packetization Layer
-       Path MTU Discovery (MTU probing).  If MTU probing is enabled,
-       this is the inital MSS used by the connection.
+       The initial value of search_low to be used by the packetization layer
+       Path MTU discovery (MTU probing).  If MTU probing is enabled,
+       this is the initial MSS used by the connection.
 
 tcp_congestion_control - STRING
        Set the congestion control algorithm to be used for new
@@ -185,10 +185,9 @@ tcp_frto - INTEGER
        timeouts.  It is particularly beneficial in wireless environments
        where packet loss is typically due to random radio interference
        rather than intermediate router congestion.  F-RTO is sender-side
-       only modification.  Therefore it does not require any support from
-       the peer, but in a typical case, however, where wireless link is
-       the local access link and most of the data flows downlink, the
-       faraway servers should have F-RTO enabled to take advantage of it.
+       only modification. Therefore it does not require any support from
+       the peer.
+
        If set to 1, basic version is enabled.  2 enables SACK enhanced
        F-RTO if flow uses SACK.  The basic version can be used also when
        SACK is in use though scenario(s) with it exists where F-RTO
@@ -276,7 +275,7 @@ tcp_mem - vector of 3 INTEGERs: min, pressure, max
        memory.
 
 tcp_moderate_rcvbuf - BOOLEAN
-       If set, TCP performs receive buffer autotuning, attempting to
+       If set, TCP performs receive buffer auto-tuning, attempting to
        automatically size the buffer (no greater than tcp_rmem[2]) to
        match the size required by the path for full throughput.  Enabled by
        default.
@@ -336,7 +335,7 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
        pressure.
        Default: 8K
 
-       default: default size of receive buffer used by TCP sockets.
+       default: initial size of receive buffer used by TCP sockets.
        This value overrides net.core.rmem_default used by other protocols.
        Default: 87380 bytes. This value results in window of 65535 with
        default setting of tcp_adv_win_scale and tcp_app_win:0 and a bit
@@ -344,8 +343,10 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
 
        max: maximal size of receive buffer allowed for automatically
        selected receiver buffers for TCP socket. This value does not override
-       net.core.rmem_max, "static" selection via SO_RCVBUF does not use this.
-       Default: 87380*2 bytes.
+       net.core.rmem_max.  Calling setsockopt() with SO_RCVBUF disables
+       automatic tuning of that socket's receive buffer size, in which
+       case this value is ignored.
+       Default: between 87380B and 4MB, depending on RAM size.
 
 tcp_sack - BOOLEAN
        Enable select acknowledgments (SACKS).
@@ -358,7 +359,7 @@ tcp_slow_start_after_idle - BOOLEAN
        Default: 1
 
 tcp_stdurg - BOOLEAN
-       Use the Host requirements interpretation of the TCP urg pointer field.
+       Use the Host requirements interpretation of the TCP urgent pointer field.
        Most hosts use the older BSD interpretation, so if you turn this on
        Linux might not communicate correctly with them.
        Default: FALSE
@@ -371,12 +372,12 @@ tcp_synack_retries - INTEGER
 tcp_syncookies - BOOLEAN
        Only valid when the kernel was compiled with CONFIG_SYNCOOKIES
        Send out syncookies when the syn backlog queue of a socket
-       overflows. This is to prevent against the common 'syn flood attack'
+       overflows. This is to prevent against the common 'SYN flood attack'
        Default: FALSE
 
        Note, that syncookies is fallback facility.
        It MUST NOT be used to help highly loaded servers to stand
-       against legal connection rate. If you see synflood warnings
+       against legal connection rate. If you see SYN flood warnings
        in your logs, but investigation shows that they occur
        because of overload with legal connections, you should tune
        another parameters until this warning disappear.
@@ -386,7 +387,7 @@ tcp_syncookies - BOOLEAN
        to use TCP extensions, can result in serious degradation
        of some services (f.e. SMTP relaying), visible not by you,
        but your clients and relays, contacting you. While you see
-       synflood warnings in logs not being really flooded, your server
+       SYN flood warnings in logs not being really flooded, your server
        is seriously misconfigured.
 
 tcp_syn_retries - INTEGER
@@ -419,19 +420,21 @@ tcp_window_scaling - BOOLEAN
        Enable window scaling as defined in RFC1323.
 
 tcp_wmem - vector of 3 INTEGERs: min, default, max
-       min: Amount of memory reserved for send buffers for TCP socket.
+       min: Amount of memory reserved for send buffers for TCP sockets.
        Each TCP socket has rights to use it due to fact of its birth.
        Default: 4K
 
-       default: Amount of memory allowed for send buffers for TCP socket
-       by default. This value overrides net.core.wmem_default used
-       by other protocols, it is usually lower than net.core.wmem_default.
+       default: initial size of send buffer used by TCP sockets.  This
+       value overrides net.core.wmem_default used by other protocols.
+       It is usually lower than net.core.wmem_default.
        Default: 16K
 
-       max: Maximal amount of memory allowed for automatically selected
-       send buffers for TCP socket. This value does not override
-       net.core.wmem_max, "static" selection via SO_SNDBUF does not use this.
-       Default: 128K
+       max: Maximal amount of memory allowed for automatically tuned
+       send buffers for TCP sockets. This value does not override
+       net.core.wmem_max.  Calling setsockopt() with SO_SNDBUF disables
+       automatic tuning of that socket's send buffer size, in which case
+       this value is ignored.
+       Default: between 64K and 4MB, depending on RAM size.
 
 tcp_workaround_signed_windows - BOOLEAN
        If set, assume no receipt of a window scaling option means the
@@ -794,10 +797,6 @@ tag - INTEGER
        Allows you to write a number, which can be used as required.
        Default value is 0.
 
-(1) Jiffie: internal timeunit for the kernel. On the i386 1/100s, on the
-Alpha 1/1024s. See the HZ define in /usr/include/asm/param.h for the exact
-value on your system. 
-
 Alexey Kuznetsov.
 kuznet@ms2.inr.ac.ru
 
@@ -1064,24 +1063,193 @@ bridge-nf-filter-pppoe-tagged - BOOLEAN
        Default: 1
 
 
-UNDOCUMENTED:
+proc/sys/net/sctp/* Variables:
+
+addip_enable - BOOLEAN
+       Enable or disable extension of  Dynamic Address Reconfiguration
+       (ADD-IP) functionality specified in RFC5061.  This extension provides
+       the ability to dynamically add and remove new addresses for the SCTP
+       associations.
+
+       1: Enable extension.
+
+       0: Disable extension.
+
+       Default: 0
+
+addip_noauth_enable - BOOLEAN
+       Dynamic Address Reconfiguration (ADD-IP) requires the use of
+       authentication to protect the operations of adding or removing new
+       addresses.  This requirement is mandated so that unauthorized hosts
+       would not be able to hijack associations.  However, older
+       implementations may not have implemented this requirement while
+       allowing the ADD-IP extension.  For reasons of interoperability,
+       we provide this variable to control the enforcement of the
+       authentication requirement.
+
+       1: Allow ADD-IP extension to be used without authentication.  This
+          should only be set in a closed environment for interoperability
+          with older implementations.
+
+       0: Enforce the authentication requirement
+
+       Default: 0
+
+auth_enable - BOOLEAN
+       Enable or disable Authenticated Chunks extension.  This extension
+       provides the ability to send and receive authenticated chunks and is
+       required for secure operation of Dynamic Address Reconfiguration
+       (ADD-IP) extension.
+
+       1: Enable this extension.
+       0: Disable this extension.
+
+       Default: 0
+
+prsctp_enable - BOOLEAN
+       Enable or disable the Partial Reliability extension (RFC3758) which
+       is used to notify peers that a given DATA should no longer be expected.
+
+       1: Enable extension
+       0: Disable
+
+       Default: 1
+
+max_burst - INTEGER
+       The limit of the number of new packets that can be initially sent.  It
+       controls how bursty the generated traffic can be.
+
+       Default: 4
+
+association_max_retrans - INTEGER
+       Set the maximum number for retransmissions that an association can
+       attempt deciding that the remote end is unreachable.  If this value
+       is exceeded, the association is terminated.
+
+       Default: 10
+
+max_init_retransmits - INTEGER
+       The maximum number of retransmissions of INIT and COOKIE-ECHO chunks
+       that an association will attempt before declaring the destination
+       unreachable and terminating.
+
+       Default: 8
+
+path_max_retrans - INTEGER
+       The maximum number of retransmissions that will be attempted on a given
+       path.  Once this threshold is exceeded, the path is considered
+       unreachable, and new traffic will use a different path when the
+       association is multihomed.
+
+       Default: 5
+
+rto_initial - INTEGER
+       The initial round trip timeout value in milliseconds that will be used
+       in calculating round trip times.  This is the initial time interval
+       for retransmissions.
 
-dev_weight FIXME
-discovery_slots FIXME
-discovery_timeout FIXME
-fast_poll_increase FIXME
-ip6_queue_maxlen FIXME
-lap_keepalive_time FIXME
-lo_cong FIXME
-max_baud_rate FIXME
-max_dgram_qlen FIXME
-max_noreply_time FIXME
-max_tx_data_size FIXME
-max_tx_window FIXME
-min_tx_turn_time FIXME
-mod_cong FIXME
-no_cong FIXME
-no_cong_thresh FIXME
-slot_timeout FIXME
-warn_noreply_time FIXME
+       Default: 3000
+
+rto_max - INTEGER
+       The maximum value (in milliseconds) of the round trip timeout.  This
+       is the largest time interval that can elapse between retransmissions.
+
+       Default: 60000
+
+rto_min - INTEGER
+       The minimum value (in milliseconds) of the round trip timeout.  This
+       is the smallest time interval the can elapse between retransmissions.
+
+       Default: 1000
+
+hb_interval - INTEGER
+       The interval (in milliseconds) between HEARTBEAT chunks.  These chunks
+       are sent at the specified interval on idle paths to probe the state of
+       a given path between 2 associations.
+
+       Default: 30000
+
+sack_timeout - INTEGER
+       The amount of time (in milliseconds) that the implementation will wait
+       to send a SACK.
+
+       Default: 200
+
+valid_cookie_life - INTEGER
+       The default lifetime of the SCTP cookie (in milliseconds).  The cookie
+       is used during association establishment.
+
+       Default: 60000
+
+cookie_preserve_enable - BOOLEAN
+       Enable or disable the ability to extend the lifetime of the SCTP cookie
+       that is used during the establishment phase of SCTP association
+
+       1: Enable cookie lifetime extension.
+       0: Disable
+
+       Default: 1
+
+rcvbuf_policy - INTEGER
+       Determines if the receive buffer is attributed to the socket or to
+       association.   SCTP supports the capability to create multiple
+       associations on a single socket.  When using this capability, it is
+       possible that a single stalled association that's buffering a lot
+       of data may block other associations from delivering their data by
+       consuming all of the receive buffer space.  To work around this,
+       the rcvbuf_policy could be set to attribute the receiver buffer space
+       to each association instead of the socket.  This prevents the described
+       blocking.
+
+       1: rcvbuf space is per association
+       0: recbuf space is per socket
+
+       Default: 0
+
+sndbuf_policy - INTEGER
+       Similar to rcvbuf_policy above, this applies to send buffer space.
+
+       1: Send buffer is tracked per association
+       0: Send buffer is tracked per socket.
+
+       Default: 0
+
+sctp_mem - vector of 3 INTEGERs: min, pressure, max
+       Number of pages allowed for queueing by all SCTP sockets.
+
+       min: Below this number of pages SCTP is not bothered about its
+       memory appetite. When amount of memory allocated by SCTP exceeds
+       this number, SCTP starts to moderate memory usage.
+
+       pressure: This value was introduced to follow format of tcp_mem.
+
+       max: Number of pages allowed for queueing by all SCTP sockets.
+
+       Default is calculated at boot time from amount of available memory.
+
+sctp_rmem - vector of 3 INTEGERs: min, default, max
+       See tcp_rmem for a description.
+
+sctp_wmem  - vector of 3 INTEGERs: min, default, max
+       See tcp_wmem for a description.
+
+UNDOCUMENTED:
 
+/proc/sys/net/core/*
+       dev_weight FIXME
+
+/proc/sys/net/unix/*
+       max_dgram_qlen FIXME
+
+/proc/sys/net/irda/*
+       fast_poll_increase FIXME
+       warn_noreply_time FIXME
+       discovery_slots FIXME
+       slot_timeout FIXME
+       max_baud_rate FIXME
+       discovery_timeout FIXME
+       lap_keepalive_time FIXME
+       max_noreply_time FIXME
+       max_tx_data_size FIXME
+       max_tx_window FIXME
+       min_tx_turn_time FIXME
index 4bde53e85f3f02df27191234af82b3ba06b9f7a5..1e28e2ddb90a6e202ce65bd60778ff701afa8ee1 100644 (file)
@@ -83,9 +83,9 @@ Valid range: Limited by memory on system
 Default: 30 
 
 e. intr_type
-Specifies interrupt type. Possible values 1(INTA), 2(MSI), 3(MSI-X)
-Valid range: 1-3
-Default: 
+Specifies interrupt type. Possible values 0(INTA), 2(MSI-X)
+Valid values: 0, 2
+Default: 2
 
 5.  Performance suggestions
 General:
index 0bbee38acd263f6e88605ac71e3bd12c8ca3bf70..72aff61e731509d7c87f3a3913aa3b4e965ab9c5 100644 (file)
@@ -753,8 +753,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
     [Multiple options for each card instance]
     model      - force the model name
-    position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)
+    position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF)
     probe_mask  - Bitmask to probe codecs (default = -1, meaning all slots)
+    bdl_pos_adj        - Specifies the DMA IRQ timing delay in samples.
+               Passing -1 will make the driver to choose the appropriate
+               value based on the controller chip.
     
     [Single (global) options]
     single_cmd  - Use single immediate commands to communicate with
@@ -845,7 +848,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
        ALC269
          basic         Basic preset
 
-       ALC662
+       ALC662/663
          3stack-dig    3-stack (2-channel) with SPDIF
          3stack-6ch     3-stack (6-channel)
          3stack-6ch-dig 3-stack (6-channel) with SPDIF
@@ -853,6 +856,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          lenovo-101e    Lenovo laptop
          eeepc-p701    ASUS Eeepc P701
          eeepc-ep20    ASUS Eeepc EP20
+         m51va         ASUS M51VA
+         g71v          ASUS G71V
+         h13           ASUS H13
+         g50v          ASUS G50V
          auto          auto-config reading BIOS (default)
 
        ALC882/885
@@ -1091,7 +1098,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     This occurs when the access to non-existing or non-working codec slot
     (likely a modem one) causes a stall of the communication via HD-audio
     bus.  You can see which codec slots are probed by enabling
-    CONFIG_SND_DEBUG_DETECT, or simply from the file name of the codec
+    CONFIG_SND_DEBUG_VERBOSE, or simply from the file name of the codec
     proc files.  Then limit the slots to probe by probe_mask option.
     For example, probe_mask=1 means to probe only the first slot, and
     probe_mask=4 means only the third slot.
@@ -2267,6 +2274,10 @@ case above again, the first two slots are already reserved.  If any
 other driver (e.g. snd-usb-audio) is loaded before snd-interwave or
 snd-ens1371, it will be assigned to the third or later slot.
 
+When a module name is given with '!', the slot will be given for any
+modules but that name.  For example, "slots=!snd-pcsp" will reserve
+the first slot for any modules but snd-pcsp. 
+
 
 ALSA PCM devices to OSS devices mapping
 =======================================
index b03df4d4795c6767b79bed4125b07bbdf64fc823..e13c4e67029f497899d4cbc545f67fd073d36e1f 100644 (file)
@@ -6127,8 +6127,8 @@ struct _snd_pcm_runtime {
 
       <para>
         <function>snd_printdd()</function> is compiled in only when
-      <constant>CONFIG_SND_DEBUG_DETECT</constant> is set. Please note
-      that <constant>DEBUG_DETECT</constant> is not set as default
+      <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is set. Please note
+      that <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is not set as default
       even if you configure the alsa-driver with
       <option>--with-debug=full</option> option. You need to give
       explicitly <option>--with-debug=detect</option> option instead. 
index aaae360312e479a547d583c8c1d172d3106fa48d..86d1c8e7b18f3c31b39dca8176acc3e9bdfdf96a 100644 (file)
@@ -1,4 +1,4 @@
   0 -> Unknown board                            (au0828)
-  1 -> Hauppauge HVR950Q                        (au0828)        [2040:7200]
+  1 -> Hauppauge HVR950Q                        (au0828)        [2040:7200,2040:7210,2040:7217,2040:721b,2040:721f,2040:7280,0fd9:0008]
   2 -> Hauppauge HVR850                         (au0828)        [2040:7240]
   3 -> DViCO FusionHDTV USB                     (au0828)        [0fe9:d620]
index e4230ed16ee7d1b45e757fd0c1c3a39848542c59..df3227605d59bf594c3a962a7bf08d9e8d5097a9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Slabinfo: Tool to get reports about slabs
  *
- * (C) 2007 sgi, Christoph Lameter <clameter@sgi.com>
+ * (C) 2007 sgi, Christoph Lameter
  *
  * Compile by:
  *
@@ -99,7 +99,7 @@ void fatal(const char *x, ...)
 
 void usage(void)
 {
-       printf("slabinfo 5/7/2007. (c) 2007 sgi. clameter@sgi.com\n\n"
+       printf("slabinfo 5/7/2007. (c) 2007 sgi.\n\n"
                "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
                "-a|--aliases           Show aliases\n"
                "-A|--activity          Most active slabs first\n"
index 7c13f22a0c9ee44aac54dd0c40ea65a828a545d9..bb1f5c6e28b3eaf89fc2f8a3b401311c855f8b26 100644 (file)
@@ -266,4 +266,4 @@ of other objects.
 
        slub_debug=FZ,dentry
 
-Christoph Lameter, <clameter@sgi.com>, May 30, 2007
+Christoph Lameter, May 30, 2007
index 8f0ec46a7096132683b5ba7368c239c6519f127d..56a2f678019e7c067e62ce7a95c1fb86ade5df2d 100644 (file)
@@ -763,9 +763,10 @@ S: Maintained
 
 AUXILIARY DISPLAY DRIVERS
 P:     Miguel Ojeda Sandonis
-M:     maxextreme@gmail.com
+M:     miguel.ojeda.sandonis@gmail.com
 L:     linux-kernel@vger.kernel.org
-W:     http://auxdisplay.googlepages.com/
+W:     http://miguelojeda.es/auxdisplay.htm
+W:     http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
 S:     Maintained
 
 AVR32 ARCHITECTURE
@@ -1055,16 +1056,18 @@ S:      Supported
 
 CFAG12864B LCD DRIVER
 P:     Miguel Ojeda Sandonis
-M:     maxextreme@gmail.com
+M:     miguel.ojeda.sandonis@gmail.com
 L:     linux-kernel@vger.kernel.org
-W:     http://auxdisplay.googlepages.com/
+W:     http://miguelojeda.es/auxdisplay.htm
+W:     http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
 S:     Maintained
 
 CFAG12864BFB LCD FRAMEBUFFER DRIVER
 P:     Miguel Ojeda Sandonis
-M:     maxextreme@gmail.com
+M:     miguel.ojeda.sandonis@gmail.com
 L:     linux-kernel@vger.kernel.org
-W:     http://auxdisplay.googlepages.com/
+W:     http://miguelojeda.es/auxdisplay.htm
+W:     http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
 S:     Maintained
 
 CFG80211 and NL80211
@@ -1420,6 +1423,14 @@ M:       kristen.c.accardi@intel.com
 L:     linux-acpi@vger.kernel.org
 S:     Supported
 
+DOCUMENTATION (/Documentation directory)
+P:     Michael Kerrisk
+M:     mtk.manpages@gmail.com
+P:     Randy Dunlap
+M:     rdunlap@xenotime.net
+L:     linux-doc@vger.kernel.org
+S:     Maintained
+
 DOUBLETALK DRIVER
 P:     James R. Van Zandt
 M:     jrv@vanzandt.mv.com
@@ -1626,13 +1637,13 @@ S:      Maintained
 
 EXT3 FILE SYSTEM
 P:     Stephen Tweedie, Andrew Morton
-M:     sct@redhat.com, akpm@linux-foundation.org, adilger@clusterfs.com
+M:     sct@redhat.com, akpm@linux-foundation.org, adilger@sun.com
 L:     linux-ext4@vger.kernel.org
 S:     Maintained
 
 EXT4 FILE SYSTEM
 P:     Stephen Tweedie, Andrew Morton
-M:     sct@redhat.com, akpm@linux-foundation.org, adilger@clusterfs.com
+M:     sct@redhat.com, akpm@linux-foundation.org, adilger@sun.com
 L:     linux-ext4@vger.kernel.org
 S:     Maintained
 
@@ -2428,9 +2439,10 @@ S:       Maintained
 
 KS0108 LCD CONTROLLER DRIVER
 P:     Miguel Ojeda Sandonis
-M:     maxextreme@gmail.com
+M:     miguel.ojeda.sandonis@gmail.com
 L:     linux-kernel@vger.kernel.org
-W:     http://auxdisplay.googlepages.com/
+W:     http://miguelojeda.es/auxdisplay.htm
+W:     http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
 S:     Maintained
 
 LAPB module
@@ -2474,9 +2486,11 @@ M:       James.Bottomley@HansenPartnership.com
 W:     http://www.hansenpartnership.com/voyager
 S:     Maintained
 
-LINUX FOR POWERPC
+LINUX FOR POWERPC (32-BIT AND 64-BIT)
 P:     Paul Mackerras
 M:     paulus@samba.org
+P:     Benjamin Herrenschmidt
+M:     benh@kernel.crashing.org
 W:     http://www.penguinppc.org/
 L:     linuxppc-dev@ozlabs.org
 T:     git kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc.git
@@ -2516,13 +2530,6 @@ W:       http://wiki.secretlab.ca/index.php/Linux_on_Xilinx_Virtex
 L:     linuxppc-dev@ozlabs.org
 S:     Maintained
 
-LINUX FOR POWERPC BOOT CODE
-P:     Tom Rini
-M:     trini@kernel.crashing.org
-W:     http://www.penguinppc.org/
-L:     linuxppc-dev@ozlabs.org
-S:     Maintained
-
 LINUX FOR POWERPC EMBEDDED PPC8XX
 P:     Vitaly Bordug
 M:     vitb@kernel.crashing.org
@@ -2551,17 +2558,6 @@ P:       Arnaldo Carvalho de Melo
 M:     acme@ghostprotocols.net
 S:     Maintained
 
-LINUX FOR 64BIT POWERPC
-P:     Paul Mackerras
-M:     paulus@samba.org
-M:     paulus@au.ibm.com
-P:     Anton Blanchard
-M:     anton@samba.org
-M:     anton@au.ibm.com
-W:     http://www.penguinppc.org/ppc64/
-L:     linuxppc-dev@ozlabs.org
-S:     Supported
-
 LINUX SECURITY MODULE (LSM) FRAMEWORK
 P:     Chris Wright
 M:     chrisw@sous-sol.org
@@ -2680,8 +2676,8 @@ S:        Supported
 MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
 P:     Michael Kerrisk
 M:     mtk.manpages@gmail.com
-W:     ftp://ftp.kernel.org/pub/linux/docs/manpages
-S:     Maintained
+W:     http://www.kernel.org/doc/man-pages
+S:     Supported
 
 MARVELL LIBERTAS WIRELESS DRIVER
 P:     Dan Williams
@@ -2814,6 +2810,12 @@ W:       https://tango.0pointer.de/mailman/listinfo/s270-linux
 W:     http://0pointer.de/lennart/tchibo.html
 S:     Maintained
 
+MULTIFUNCTION DEVICES (MFD)
+P:     Samuel Ortiz
+M:     sameo@openedhand.com
+L:     linux-kernel@vger.kernel.org
+S:     Supported
+
 MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
 P:     Pierre Ossman
 M:     drzeus-mmc@drzeus.cx
@@ -3080,8 +3082,8 @@ L:        linux-scsi@vger.kernel.org
 S:     Maintained
 
 OPROFILE
-P:     Philippe Elie
-M:     phil.el@wanadoo.fr
+P:     Robert Richter
+M:     robert.richter@amd.com
 L:     oprofile-list@lists.sf.net
 S:     Maintained
 
@@ -3195,8 +3197,8 @@ L:        netdev@vger.kernel.org
 S:     Maintained
 
 PER-TASK DELAY ACCOUNTING
-P:     Shailabh Nagar
-M:     nagar@watson.ibm.com
+P:     Balbir Singh
+M:     balbir@linux.vnet.ibm.com
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
@@ -3688,7 +3690,7 @@ S:        Maintained
 
 SLAB ALLOCATOR
 P:     Christoph Lameter
-M:     clameter@sgi.com
+M:     cl@linux-foundation.org
 P:     Pekka Enberg
 M:     penberg@cs.helsinki.fi
 P:     Matt Mackall
@@ -3898,8 +3900,8 @@ M:        hch@infradead.org
 S:     Maintained
 
 TASKSTATS STATISTICS INTERFACE
-P:     Shailabh Nagar
-M:     nagar@watson.ibm.com
+P:     Balbir Singh
+M:     balbir@linux.vnet.ibm.com
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
@@ -3995,7 +3997,8 @@ W:        http://www.buzzard.org.uk/toshiba/
 S:     Maintained
 
 TPM DEVICE DRIVER
-P:     Kylene Hall
+P:     Debora Velarde
+P:     Rajiv Andrade
 M:     tpmdd-devel@lists.sourceforge.net
 W:     http://tpmdd.sourceforge.net
 P:     Marcel Selhorst
@@ -4314,6 +4317,14 @@ L:       netdev@vger.kernel.org
 W:     http://www.linux-usb.org/usbnet
 S:     Maintained
 
+USB VIDEO CLASS
+P:     Laurent Pinchart
+M:     laurent.pinchart@skynet.be
+L:     linx-uvc-devel@berlios.de
+L:     video4linux-list@redhat.com
+W:     http://linux-uvc.berlios.de
+S:     Maintained
+
 USB W996[87]CF DRIVER
 P:     Luca Risolia
 M:     luca.risolia@studio.unibo.it
index 6aff5f47c21d1f13c633de4f14835688c49244db..e3c5eb66ec52dee13127e3b2b83f84c3184bd8be 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 26
-EXTRAVERSION = -rc8
+EXTRAVERSION =
 NAME = Rotary Wombat
 
 # *DOCUMENTATION*
index f13249be17c50736e23686158854799164582aeb..ef37fc1acaeae91eb7bb9ac1010444856ce177b2 100644 (file)
@@ -25,6 +25,13 @@ SECTIONS
        } :kernel
        _etext = .;     /* End of text section */
 
+       NOTES :kernel :note
+       .dummy : {
+               *(.dummy)
+       } :kernel
+
+       RODATA
+
        /* Exception table */
        . = ALIGN(16);
        __ex_table : {
@@ -33,13 +40,6 @@ SECTIONS
                __stop___ex_table = .;
        }
 
-       NOTES :kernel :note
-       .dummy : {
-               *(.dummy)
-       } :kernel
-
-       RODATA
-
        /* Will be freed after init */
        . = ALIGN(PAGE_SIZE);
        /* Init code and data */
index 52fc6a883281120f7c80e2d332247971658b1ffa..2744673314b470cb84b68d1ff9a040a0356d34af 100644 (file)
@@ -650,7 +650,8 @@ EXPORT_SYMBOL(dma_map_sg);
 EXPORT_SYMBOL(dma_unmap_sg);
 EXPORT_SYMBOL(dma_sync_single_for_cpu);
 EXPORT_SYMBOL(dma_sync_single_for_device);
-EXPORT_SYMBOL(dma_sync_sg);
+EXPORT_SYMBOL(dma_sync_sg_for_cpu);
+EXPORT_SYMBOL(dma_sync_sg_for_device);
 EXPORT_SYMBOL(dmabounce_register_dev);
 EXPORT_SYMBOL(dmabounce_unregister_dev);
 
index 02cede295e89795b02e77f9167c70f375c06fd48..dbf68dc50ae2fa1502a21edea0eba88dbee4b52b 100644 (file)
@@ -42,7 +42,7 @@
 #define GPMC_STATUS            0x54
 #define GPMC_PREFETCH_CONFIG1  0x1e0
 #define GPMC_PREFETCH_CONFIG2  0x1e4
-#define GPMC_PREFETCH_CONTROL  0x1e8
+#define GPMC_PREFETCH_CONTROL  0x1ec
 #define GPMC_PREFETCH_STATUS   0x1f0
 #define GPMC_ECC_CONFIG                0x1f4
 #define GPMC_ECC_CONTROL       0x1f8
index 3e57428affeedac7f32b8fd883bb159810b63181..8e813ed575194d95af51fb326747e8cd86b975c8 100644 (file)
@@ -74,6 +74,8 @@ static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
+       trace_hardirqs_off();
+
        /*
         * the primary core may have used a "cross call" soft interrupt
         * to get this processor out of WFI in the BootMonitor - make
index c00eda588cd81b2ad87d51646a27b7ffcd577549..39c637b0ffeacdceba864caf3a23c1e7f0eeb3b4 100644 (file)
@@ -501,8 +501,6 @@ static inline void omap_enable_channel_irq(int lch)
 
        /* Enable some nice interrupts. */
        OMAP_DMA_CICR_REG(lch) = dma_chan[lch].enabled_irqs;
-
-       dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
 }
 
 static void omap_disable_channel_irq(int lch)
index 917325bfbd849723899d6bfaa26e21c39d566ed8..6be0c50122e8c627102fbcbe5692cc26013b0135 100644 (file)
@@ -254,7 +254,8 @@ close_cplbtab(struct cplb_tab *table)
 }
 
 /* helper function */
-static void __fill_code_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
+static void __init
+__fill_code_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
 {
        if (cplb_data[i].psize) {
                fill_cplbtab(t,
@@ -291,7 +292,8 @@ static void __fill_code_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_en
        }
 }
 
-static void __fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
+static void __init
+__fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
 {
        if (cplb_data[i].psize) {
                fill_cplbtab(t,
index 73647c158774e0acd31efcf3e7385dd2b104365a..07402f57c9dea2f401bb40110f92dc57e5601281 100644 (file)
@@ -60,9 +60,14 @@ static struct irq_chip bad_chip = {
 };
 
 static struct irq_desc bad_irq_desc = {
+       .status = IRQ_DISABLED,
        .chip = &bad_chip,
        .handle_irq = handle_bad_irq,
        .depth = 1,
+       .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
+#ifdef CONFIG_SMP
+       .affinity = CPU_MASK_ALL
+#endif
 };
 
 int show_interrupts(struct seq_file *p, void *v)
index 4ae15c8c2488fa8741086943ea58ee915bfbf69a..632cda8f2e7667fab870c85dd97af1fb2ed118f7 100644 (file)
@@ -547,7 +547,8 @@ setup_arch (char **cmdline_p)
 # ifdef CONFIG_ACPI_NUMA
        acpi_numa_init();
        per_cpu_scan_finalize((cpus_weight(early_cpu_possible_map) == 0 ?
-               32 : cpus_weight(early_cpu_possible_map)), additional_cpus);
+               32 : cpus_weight(early_cpu_possible_map)),
+               additional_cpus > 0 ? additional_cpus : 0);
 # endif
 #else
 # ifdef CONFIG_SMP
index 8c73643f2d664a5d9f8dd103ed67e5e5bbf037d4..aad1b7b1fff95e19ee19d3175ce3f9a5a7c8c1a6 100644 (file)
@@ -117,6 +117,7 @@ void account_system_vtime(struct task_struct *tsk)
 
        local_irq_restore(flags);
 }
+EXPORT_SYMBOL_GPL(account_system_vtime);
 
 /*
  * Called from the timer interrupt handler to charge accumulated user time
index e5a7c5d96364f73f5cf700a9ac70d9ee67d3bda8..24c5dee9176872d5358eb228a6228071fe28da25 100644 (file)
@@ -1006,7 +1006,7 @@ config BOOT_ELF32
 config MIPS_L1_CACHE_SHIFT
        int
        default "4" if MACH_DECSTATION
-       default "7" if SGI_IP27 || SGI_IP28 || SNI_RM
+       default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM
        default "4" if PMC_MSP4200_EVAL
        default "5"
 
index 795cb8fb0d740b6de17b17de1d12b61c7036d80c..b5fc4eb412d2e53b3544f0d67f032cecf4933095 100644 (file)
@@ -161,6 +161,9 @@ void __init txx9_tmr_init(unsigned long baseaddr)
        struct txx9_tmr_reg __iomem *tmrptr;
 
        tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
+       /* Start once to make CounterResetEnable effective */
+       __raw_writel(TXx9_TMTCR_CRE | TXx9_TMTCR_TCE, &tmrptr->tcr);
+       /* Stop and reset the counter */
        __raw_writel(TXx9_TMTCR_CRE, &tmrptr->tcr);
        __raw_writel(0, &tmrptr->tisr);
        __raw_writel(0xffffffff, &tmrptr->cpra);
index 76935e320214bf200106b78bd4b8ed7037c1f72c..27a5b466c85ce0ef4f859ea47402dfd2d77f112c 100644 (file)
@@ -26,7 +26,7 @@
 static unsigned long icache_size, dcache_size;         /* Size in bytes */
 static unsigned long icache_lsize, dcache_lsize;       /* Size in bytes */
 
-unsigned long __init r3k_cache_size(unsigned long ca_flags)
+unsigned long __cpuinit r3k_cache_size(unsigned long ca_flags)
 {
        unsigned long flags, status, dummy, size;
        volatile unsigned long *p;
@@ -61,7 +61,7 @@ unsigned long __init r3k_cache_size(unsigned long ca_flags)
        return size * sizeof(*p);
 }
 
-unsigned long __init r3k_cache_lsize(unsigned long ca_flags)
+unsigned long __cpuinit r3k_cache_lsize(unsigned long ca_flags)
 {
        unsigned long flags, status, lsize, i;
        volatile unsigned long *p;
@@ -90,7 +90,7 @@ unsigned long __init r3k_cache_lsize(unsigned long ca_flags)
        return lsize * sizeof(*p);
 }
 
-static void __init r3k_probe_cache(void)
+static void __cpuinit r3k_probe_cache(void)
 {
        dcache_size = r3k_cache_size(ST0_ISC);
        if (dcache_size)
index 1edf0cbbeede7e888d05e05c6a61603e2ad62483..1417c6494858cb383d3c3a254f28ab2f619485ad 100644 (file)
@@ -235,13 +235,12 @@ static void __cpuinit set_prefetch_parameters(void)
        }
        /*
         * Too much unrolling will overflow the available space in
-        * clear_space_array / copy_page_array. 8 words sounds generous,
-        * but a R4000 with 128 byte L2 line length can exceed even that.
+        * clear_space_array / copy_page_array.
         */
-       half_clear_loop_size = min(8 * clear_word_size,
+       half_clear_loop_size = min(16 * clear_word_size,
                                   max(cache_line_size >> 1,
                                       4 * clear_word_size));
-       half_copy_loop_size = min(8 * copy_word_size,
+       half_copy_loop_size = min(16 * copy_word_size,
                                  max(cache_line_size >> 1,
                                      4 * copy_word_size));
 }
@@ -263,21 +262,23 @@ static inline void __cpuinit build_clear_pref(u32 **buf, int off)
        if (pref_bias_clear_store) {
                uasm_i_pref(buf, pref_dst_mode, pref_bias_clear_store + off,
                            A0);
-       } else if (cpu_has_cache_cdex_s) {
-               uasm_i_cache(buf, Create_Dirty_Excl_SD, off, A0);
-       } else if (cpu_has_cache_cdex_p) {
-               if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) {
-                       uasm_i_nop(buf);
-                       uasm_i_nop(buf);
-                       uasm_i_nop(buf);
-                       uasm_i_nop(buf);
-               }
+       } else if (cache_line_size == (half_clear_loop_size << 1)) {
+               if (cpu_has_cache_cdex_s) {
+                       uasm_i_cache(buf, Create_Dirty_Excl_SD, off, A0);
+               } else if (cpu_has_cache_cdex_p) {
+                       if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) {
+                               uasm_i_nop(buf);
+                               uasm_i_nop(buf);
+                               uasm_i_nop(buf);
+                               uasm_i_nop(buf);
+                       }
 
-               if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
-                       uasm_i_lw(buf, ZERO, ZERO, AT);
+                       if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
+                               uasm_i_lw(buf, ZERO, ZERO, AT);
 
-               uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0);
-       }
+                       uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0);
+               }
+               }
 }
 
 void __cpuinit build_clear_page(void)
@@ -403,20 +404,22 @@ static inline void build_copy_store_pref(u32 **buf, int off)
        if (pref_bias_copy_store) {
                uasm_i_pref(buf, pref_dst_mode, pref_bias_copy_store + off,
                            A0);
-       } else if (cpu_has_cache_cdex_s) {
-               uasm_i_cache(buf, Create_Dirty_Excl_SD, off, A0);
-       } else if (cpu_has_cache_cdex_p) {
-               if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) {
-                       uasm_i_nop(buf);
-                       uasm_i_nop(buf);
-                       uasm_i_nop(buf);
-                       uasm_i_nop(buf);
-               }
+       } else if (cache_line_size == (half_copy_loop_size << 1)) {
+               if (cpu_has_cache_cdex_s) {
+                       uasm_i_cache(buf, Create_Dirty_Excl_SD, off, A0);
+               } else if (cpu_has_cache_cdex_p) {
+                       if (R4600_V1_HIT_CACHEOP_WAR && cpu_is_r4600_v1_x()) {
+                               uasm_i_nop(buf);
+                               uasm_i_nop(buf);
+                               uasm_i_nop(buf);
+                               uasm_i_nop(buf);
+                       }
 
-               if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
-                       uasm_i_lw(buf, ZERO, ZERO, AT);
+                       if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x())
+                               uasm_i_lw(buf, ZERO, ZERO, AT);
 
-               uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0);
+                       uasm_i_cache(buf, Create_Dirty_Excl_D, off, A0);
+               }
        }
 }
 
index fc227f3b1199750bfbdb6fb350274b4d51fef915..e3abfb2d7e8624c249f69b8d46253a922af1251a 100644 (file)
@@ -86,7 +86,7 @@ static void rm7k_sc_inv(unsigned long addr, unsigned long size)
 /*
  * This function is executed in uncached address space.
  */
-static __init void __rm7k_sc_enable(void)
+static __cpuinit void __rm7k_sc_enable(void)
 {
        int i;
 
@@ -107,7 +107,7 @@ static __init void __rm7k_sc_enable(void)
        }
 }
 
-static __init void rm7k_sc_enable(void)
+static __cpuinit void rm7k_sc_enable(void)
 {
        if (read_c0_config() & RM7K_CONF_SE)
                return;
index b0ea0e43ba482b542f533d172277c6c03cee7bbd..0d6b6663d5f6756e1beb4c1426573a7424bc8c25 100644 (file)
@@ -425,6 +425,11 @@ static void ip32_irq0(void)
        BUILD_BUG_ON(MACEISA_SERIAL2_RDMAOR_IRQ - MACEISA_AUDIO_SW_IRQ != 31);
 
        crime_int = crime->istat & crime_mask;
+
+       /* crime sometime delivers spurious interrupts, ignore them */
+       if (unlikely(crime_int == 0))
+               return;
+
        irq = MACE_VID_IN1_IRQ + __ffs(crime_int);
 
        if (crime_int & CRIME_MACEISA_INT_MASK) {
index 6d19628634e3a0fb5635d6a4f2e959c16a2b5c47..f9eb9753a4043341c79d33bd5d328ab028dce308 100644 (file)
  */
 #include <linux/module.h>
 #include <asm/uaccess.h>
+#include <asm/pgtable.h>
 
 
+EXPORT_SYMBOL(empty_zero_page);
+
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
 
@@ -31,7 +34,9 @@ extern u64 __ashrdi3(u64, unsigned);
 extern u64 __ashldi3(u64, unsigned);
 extern u64 __lshrdi3(u64, unsigned);
 extern s64 __negdi2(s64);
+extern int __ucmpdi2(u64, u64);
 EXPORT_SYMBOL(__ashrdi3);
 EXPORT_SYMBOL(__ashldi3);
 EXPORT_SYMBOL(__lshrdi3);
 EXPORT_SYMBOL(__negdi2);
+EXPORT_SYMBOL(__ucmpdi2);
index 9c623c88387bbb4ee844c39f43513398131588b5..b28c9a60445bda4df1f4f83de51346b121e36067 100644 (file)
@@ -153,6 +153,7 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
        return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0,
                       NULL, NULL);
 }
+EXPORT_SYMBOL(kernel_thread);
 
 /*
  * free current thread data structures etc..
index fdfa9ec5b5bbec14a0471599ec76bdae5e6ada5c..0cd2346f4c136884a7320679a2a76557c312e6e0 100644 (file)
@@ -4,4 +4,4 @@
 
 lib-y = delay.o usercopy.o checksum.o bitops.o memcpy.o memmove.o memset.o
 lib-y += do_csum.o
-lib-y += __ashldi3.o __ashrdi3.o __lshrdi3.o negdi2.o
+lib-y += __ashldi3.o __ashrdi3.o __lshrdi3.o negdi2.o __ucmpdi2.o
diff --git a/arch/mn10300/lib/__ucmpdi2.S b/arch/mn10300/lib/__ucmpdi2.S
new file mode 100644 (file)
index 0000000..60dcbdf
--- /dev/null
@@ -0,0 +1,43 @@
+/* __ucmpdi2.S: 64-bit unsigned compare
+ *
+ * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.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.
+ */
+
+
+        .text
+        .p2align       4
+
+###############################################################################
+#
+# int __ucmpdi2(unsigned long long a [D0:D1],
+#              unsigned long long b [(SP,12),(SP,16)])
+#
+# - returns 0, 1, or 2 as a <, =, > b respectively.
+#
+###############################################################################
+        .globl         __ucmpdi2
+        .type          __ucmpdi2,@function
+__ucmpdi2:
+       mov             (12,sp),a0              # b.lsw
+       mov             (16,sp),a1              # b.msw
+
+       sub             a0,d0
+       subc            a1,d1                   # may clear Z, never sets it
+       bne             __ucmpdi2_differ        # a.msw != b.msw
+       mov             +1,d0
+       rets
+
+__ucmpdi2_differ:
+       # C flag is set if LE, clear if GE
+       subc            d0,d0                   # -1 if LE, 0 if GE
+       add             +1,d0                   #  0 if LE, 1 if GE
+       add             d0,d0                   #  0 if LE, 2 if GE
+       rets
+
+       .size           __ucmpdi2, .-__ucmpdi2
index 1cee2f9fdf06bb0255d182ddb40bede780b88c6f..095e04db1c0e1f75e39cbd01c6419c8b890295c2 100644 (file)
@@ -273,7 +273,8 @@ endif
 initrd-  := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-))
 initrd-y := $(patsubst zImage%, zImage.initrd%, \
                $(patsubst dtbImage%, dtbImage.initrd%, \
-               $(patsubst treeImage%, treeImage.initrd%, $(image-y))))
+               $(patsubst simpleImage%, simpleImage.initrd%, \
+               $(patsubst treeImage%, treeImage.initrd%, $(image-y)))))
 initrd-y := $(filter-out $(image-y), $(initrd-y))
 targets        += $(image-y) $(initrd-y)
 
index 61dd17449ddceb06267babf5373505984f7abd9c..4d96e1db55ee276c6c7a1e5e7b063c38d926b338 100644 (file)
@@ -33,13 +33,14 @@ static struct legacy_serial_info {
        phys_addr_t                     taddr;
 } legacy_serial_infos[MAX_LEGACY_SERIAL_PORTS];
 
-static struct __initdata of_device_id parents[] = {
+static struct __initdata of_device_id legacy_serial_parents[] = {
        {.type = "soc",},
        {.type = "tsi-bridge",},
        {.type = "opb", },
        {.compatible = "ibm,opb",},
        {.compatible = "simple-bus",},
        {.compatible = "wrs,epld-localbus",},
+       {},
 };
 
 static unsigned int legacy_serial_count;
@@ -136,6 +137,11 @@ static int __init add_legacy_soc_port(struct device_node *np,
        if (of_get_property(np, "clock-frequency", NULL) == NULL)
                return -1;
 
+       /* if reg-shift or offset, don't try to use it */
+       if ((of_get_property(np, "reg-shift", NULL) != NULL) ||
+               (of_get_property(np, "reg-offset", NULL) != NULL))
+               return -1;
+
        /* if rtas uses this device, don't try to use it as well */
        if (of_get_property(np, "used-by-rtas", NULL) != NULL)
                return -1;
@@ -322,7 +328,7 @@ void __init find_legacy_serial_ports(void)
                struct device_node *parent = of_get_parent(np);
                if (!parent)
                        continue;
-               if (of_match_node(parents, parent) != NULL) {
+               if (of_match_node(legacy_serial_parents, parent) != NULL) {
                        index = add_legacy_soc_port(np, np);
                        if (index >= 0 && np == stdout)
                                legacy_serial_console = index;
index e79ad8afda0737fed27aa043fa8ca726b8a5411a..3f37a6e6277163d715b9d1b2988984fed19c789a 100644 (file)
@@ -76,6 +76,8 @@ struct of_device* of_platform_device_create(struct device_node *np,
                return NULL;
 
        dev->dma_mask = 0xffffffffUL;
+       dev->dev.coherent_dma_mask = DMA_32BIT_MASK;
+
        dev->dev.bus = &of_platform_bus_type;
 
        /* We do not fill the DMA ops for platform devices by default.
index 41c7fd91e99e5836cbaef5c7d6803334bc37a206..fe92e65103edad4851465f0a00b4615011c76676 100644 (file)
@@ -14,6 +14,7 @@ static struct mpc52xx_sdma __iomem *bes;
 static struct mpc52xx_xlb __iomem *xlb;
 static struct mpc52xx_gpio __iomem *gps;
 static struct mpc52xx_gpio_wkup __iomem *gpw;
+static void __iomem *pci;
 static void __iomem *sram;
 static const int sram_size = 0x4000;   /* 16 kBytes */
 static void __iomem *mbar;
@@ -50,6 +51,8 @@ static int lite5200_pm_prepare(void)
                { .type = "builtin", .compatible = "mpc5200", }, /* efika */
                {}
        };
+       u64 regaddr64 = 0;
+       const u32 *regaddr_p;
 
        /* deep sleep? let mpc52xx code handle that */
        if (lite5200_pm_target_state == PM_SUSPEND_STANDBY)
@@ -60,8 +63,12 @@ static int lite5200_pm_prepare(void)
 
        /* map registers */
        np = of_find_matching_node(NULL, immr_ids);
-       mbar = of_iomap(np, 0);
+       regaddr_p = of_get_address(np, 0, NULL, NULL);
+       if (regaddr_p)
+               regaddr64 = of_translate_address(np, regaddr_p);
        of_node_put(np);
+
+       mbar = ioremap((u32) regaddr64, 0xC000);
        if (!mbar) {
                printk(KERN_ERR "%s:%i Error mapping registers\n", __func__, __LINE__);
                return -ENOSYS;
@@ -71,6 +78,7 @@ static int lite5200_pm_prepare(void)
        pic = mbar + 0x500;
        gps = mbar + 0xb00;
        gpw = mbar + 0xc00;
+       pci = mbar + 0xd00;
        bes = mbar + 0x1200;
        xlb = mbar + 0x1f00;
        sram = mbar + 0x8000;
@@ -85,6 +93,7 @@ static struct mpc52xx_sdma sbes;
 static struct mpc52xx_xlb sxlb;
 static struct mpc52xx_gpio sgps;
 static struct mpc52xx_gpio_wkup sgpw;
+static char spci[0x200];
 
 static void lite5200_save_regs(void)
 {
@@ -94,6 +103,7 @@ static void lite5200_save_regs(void)
        _memcpy_fromio(&sxlb, xlb, sizeof(*xlb));
        _memcpy_fromio(&sgps, gps, sizeof(*gps));
        _memcpy_fromio(&sgpw, gpw, sizeof(*gpw));
+       _memcpy_fromio(spci, pci, 0x200);
 
        _memcpy_fromio(saved_sram, sram, sram_size);
 }
@@ -103,6 +113,8 @@ static void lite5200_restore_regs(void)
        int i;
        _memcpy_toio(sram, saved_sram, sram_size);
 
+       /* PCI Configuration */
+       _memcpy_toio(pci, spci, 0x200);
 
        /*
         * GPIOs. Interrupt Master Enable has higher address then other
index 107e492cb47efa8fab159a8714d89cdcac29d5ae..5dc8f8028d520b6c0a09dd4e0a6ffb70d4891d84 100644 (file)
@@ -146,6 +146,7 @@ config MATHEMU
 config COMPAT
        bool "Kernel support for 31 bit emulation"
        depends on 64BIT
+       select COMPAT_BINFMT_ELF
        help
          Select this option if you want to enable your system kernel to
          handle system-calls from ELF binaries for 31 bit ESA.  This option
@@ -312,6 +313,10 @@ config ARCH_SPARSEMEM_DEFAULT
 config ARCH_SELECT_MEMORY_MODEL
        def_bool y
 
+config ARCH_ENABLE_MEMORY_HOTPLUG
+       def_bool y
+       depends on SPARSEMEM
+
 source "mm/Kconfig"
 
 comment "I/O subsystem configuration"
@@ -344,6 +349,22 @@ config QDIO_DEBUG
 
          If unsure, say N.
 
+config CHSC_SCH
+       tristate "Support for CHSC subchannels"
+       help
+         This driver allows usage of CHSC subchannels. A CHSC subchannel
+         is usually present on LPAR only.
+         The driver creates a device /dev/chsc, which may be used to
+         obtain I/O configuration information about the machine and
+         to issue asynchronous chsc commands (DANGEROUS).
+         You will usually only want to use this interface on a special
+         LPAR designated for system management.
+
+         To compile this driver as a module, choose M here: the
+         module will be called chsc_sch.
+
+         If unsure, say N.
+
 comment "Misc"
 
 config IPL
index db3ae8505103812a49b0d7e5a675251ec005f928..17a2636fec0a4a2395b5ba67496c504d3c50b550 100644 (file)
@@ -3,13 +3,11 @@
  *
  * Definitions and interface for Linux - z/VM Monitor Stream.
  *
- * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ * Copyright IBM Corp. 2003, 2008
  *
  * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
  */
 
-//#define APPLDATA_DEBUG                       /* Debug messages on/off */
-
 #define APPLDATA_MAX_REC_SIZE    4024  /* Maximum size of the */
                                        /* data buffer */
 #define APPLDATA_MAX_PROCS 100
 #define P_ERROR(x...)  printk(KERN_ERR MY_PRINT_NAME " error: " x)
 #define P_WARNING(x...)        printk(KERN_WARNING MY_PRINT_NAME " status: " x)
 
-#ifdef APPLDATA_DEBUG
-#define P_DEBUG(x...)   printk(KERN_DEBUG MY_PRINT_NAME " debug: " x)
-#else
-#define P_DEBUG(x...)   do {} while (0)
-#endif
-
 struct appldata_ops {
        struct list_head list;
        struct ctl_table_header *sysctl_header;
index ad40729bec3d9a062925b2b2db3bf7d990d0ea3e..9cb3d92447a35651c5c67d5f495a5d1fa5981b2f 100644 (file)
@@ -5,7 +5,7 @@
  * Exports appldata_register_ops() and appldata_unregister_ops() for the
  * data gathering modules.
  *
- * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ * Copyright IBM Corp. 2003, 2008
  *
  * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
  */
@@ -108,9 +108,6 @@ static LIST_HEAD(appldata_ops_list);
  */
 static void appldata_timer_function(unsigned long data)
 {
-       P_DEBUG("   -= Timer =-\n");
-       P_DEBUG("CPU: %i, expire_count: %i\n", smp_processor_id(),
-               atomic_read(&appldata_expire_count));
        if (atomic_dec_and_test(&appldata_expire_count)) {
                atomic_set(&appldata_expire_count, num_online_cpus());
                queue_work(appldata_wq, (struct work_struct *) data);
@@ -128,14 +125,11 @@ static void appldata_work_fn(struct work_struct *work)
        struct appldata_ops *ops;
        int i;
 
-       P_DEBUG("  -= Work Queue =-\n");
        i = 0;
        get_online_cpus();
        spin_lock(&appldata_ops_lock);
        list_for_each(lh, &appldata_ops_list) {
                ops = list_entry(lh, struct appldata_ops, list);
-               P_DEBUG("list_for_each loop: %i) active = %u, name = %s\n",
-                       ++i, ops->active, ops->name);
                if (ops->active == 1) {
                        ops->callback(ops->data);
                }
@@ -212,7 +206,6 @@ __appldata_vtimer_setup(int cmd)
                                                 0, 1);
                }
                appldata_timer_active = 1;
-               P_INFO("Monitoring timer started.\n");
                break;
        case APPLDATA_DEL_TIMER:
                for_each_online_cpu(i)
@@ -221,7 +214,6 @@ __appldata_vtimer_setup(int cmd)
                        break;
                appldata_timer_active = 0;
                atomic_set(&appldata_expire_count, num_online_cpus());
-               P_INFO("Monitoring timer stopped.\n");
                break;
        case APPLDATA_MOD_TIMER:
                per_cpu_interval = (u64) (appldata_interval*1000 /
@@ -313,10 +305,8 @@ appldata_interval_handler(ctl_table *ctl, int write, struct file *filp,
        }
        interval = 0;
        sscanf(buf, "%i", &interval);
-       if (interval <= 0) {
-               P_ERROR("Timer CPU interval has to be > 0!\n");
+       if (interval <= 0)
                return -EINVAL;
-       }
 
        get_online_cpus();
        spin_lock(&appldata_timer_lock);
@@ -324,9 +314,6 @@ appldata_interval_handler(ctl_table *ctl, int write, struct file *filp,
        __appldata_vtimer_setup(APPLDATA_MOD_TIMER);
        spin_unlock(&appldata_timer_lock);
        put_online_cpus();
-
-       P_INFO("Monitoring CPU interval set to %u milliseconds.\n",
-                interval);
 out:
        *lenp = len;
        *ppos += len;
@@ -406,23 +393,16 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
                        P_ERROR("START DIAG 0xDC for %s failed, "
                                "return code: %d\n", ops->name, rc);
                        module_put(ops->owner);
-               } else {
-                       P_INFO("Monitoring %s data enabled, "
-                               "DIAG 0xDC started.\n", ops->name);
+               } else
                        ops->active = 1;
-               }
        } else if ((buf[0] == '0') && (ops->active == 1)) {
                ops->active = 0;
                rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
                                (unsigned long) ops->data, ops->size,
                                ops->mod_lvl);
-               if (rc != 0) {
+               if (rc != 0)
                        P_ERROR("STOP DIAG 0xDC for %s failed, "
                                "return code: %d\n", ops->name, rc);
-               } else {
-                       P_INFO("Monitoring %s data disabled, "
-                               "DIAG 0xDC stopped.\n", ops->name);
-               }
                module_put(ops->owner);
        }
        spin_unlock(&appldata_ops_lock);
@@ -468,7 +448,6 @@ int appldata_register_ops(struct appldata_ops *ops)
        ops->sysctl_header = register_sysctl_table(ops->ctl_table);
        if (!ops->sysctl_header)
                goto out;
-       P_INFO("%s-ops registered!\n", ops->name);
        return 0;
 out:
        spin_lock(&appldata_ops_lock);
@@ -490,7 +469,6 @@ void appldata_unregister_ops(struct appldata_ops *ops)
        spin_unlock(&appldata_ops_lock);
        unregister_sysctl_table(ops->sysctl_header);
        kfree(ops->ctl_table);
-       P_INFO("%s-ops unregistered!\n", ops->name);
 }
 /********************** module-ops management <END> **************************/
 
@@ -553,14 +531,9 @@ static int __init appldata_init(void)
 {
        int i;
 
-       P_DEBUG("sizeof(parameter_list) = %lu\n",
-               sizeof(struct appldata_parameter_list));
-
        appldata_wq = create_singlethread_workqueue("appldata");
-       if (!appldata_wq) {
-               P_ERROR("Could not create work queue\n");
+       if (!appldata_wq)
                return -ENOMEM;
-       }
 
        get_online_cpus();
        for_each_online_cpu(i)
@@ -571,8 +544,6 @@ static int __init appldata_init(void)
        register_hotcpu_notifier(&appldata_nb);
 
        appldata_sysctl_header = register_sysctl_table(appldata_dir_table);
-
-       P_DEBUG("Base interface initialized.\n");
        return 0;
 }
 
@@ -584,7 +555,9 @@ EXPORT_SYMBOL_GPL(appldata_register_ops);
 EXPORT_SYMBOL_GPL(appldata_unregister_ops);
 EXPORT_SYMBOL_GPL(appldata_diag);
 
+#ifdef CONFIG_SWAP
 EXPORT_SYMBOL_GPL(si_swapinfo);
+#endif
 EXPORT_SYMBOL_GPL(nr_threads);
 EXPORT_SYMBOL_GPL(nr_running);
 EXPORT_SYMBOL_GPL(nr_iowait);
index 51181ccdb87b255699a3857f24d0ddac80e45699..3ed56b7d1b2f3d1cf8b68eb274e9fab40b012080 100644 (file)
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
-#include <asm/io.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
+#include <asm/io.h>
 
 #include "appldata.h"
 
 
-#define MY_PRINT_NAME "appldata_mem"           /* for debug messages, etc. */
 #define P2K(x) ((x) << (PAGE_SHIFT - 10))      /* Converts #Pages to KB */
 
 /*
@@ -70,30 +69,6 @@ static struct appldata_mem_data {
 } __attribute__((packed)) appldata_mem_data;
 
 
-static inline void appldata_debug_print(struct appldata_mem_data *mem_data)
-{
-       P_DEBUG("--- MEM - RECORD ---\n");
-       P_DEBUG("pgpgin     = %8lu KB\n", mem_data->pgpgin);
-       P_DEBUG("pgpgout    = %8lu KB\n", mem_data->pgpgout);
-       P_DEBUG("pswpin     = %8lu Pages\n", mem_data->pswpin);
-       P_DEBUG("pswpout    = %8lu Pages\n", mem_data->pswpout);
-       P_DEBUG("pgalloc    = %8lu \n", mem_data->pgalloc);
-       P_DEBUG("pgfault    = %8lu \n", mem_data->pgfault);
-       P_DEBUG("pgmajfault = %8lu \n", mem_data->pgmajfault);
-       P_DEBUG("sharedram  = %8lu KB\n", mem_data->sharedram);
-       P_DEBUG("totalram   = %8lu KB\n", mem_data->totalram);
-       P_DEBUG("freeram    = %8lu KB\n", mem_data->freeram);
-       P_DEBUG("totalhigh  = %8lu KB\n", mem_data->totalhigh);
-       P_DEBUG("freehigh   = %8lu KB\n", mem_data->freehigh);
-       P_DEBUG("bufferram  = %8lu KB\n", mem_data->bufferram);
-       P_DEBUG("cached     = %8lu KB\n", mem_data->cached);
-       P_DEBUG("totalswap  = %8lu KB\n", mem_data->totalswap);
-       P_DEBUG("freeswap   = %8lu KB\n", mem_data->freeswap);
-       P_DEBUG("sync_count_1 = %u\n", mem_data->sync_count_1);
-       P_DEBUG("sync_count_2 = %u\n", mem_data->sync_count_2);
-       P_DEBUG("timestamp    = %lX\n", mem_data->timestamp);
-}
-
 /*
  * appldata_get_mem_data()
  *
@@ -140,9 +115,6 @@ static void appldata_get_mem_data(void *data)
 
        mem_data->timestamp = get_clock();
        mem_data->sync_count_2++;
-#ifdef APPLDATA_DEBUG
-       appldata_debug_print(mem_data);
-#endif
 }
 
 
@@ -164,17 +136,7 @@ static struct appldata_ops ops = {
  */
 static int __init appldata_mem_init(void)
 {
-       int rc;
-
-       P_DEBUG("sizeof(mem) = %lu\n", sizeof(struct appldata_mem_data));
-
-       rc = appldata_register_ops(&ops);
-       if (rc != 0) {
-               P_ERROR("Error registering ops, rc = %i\n", rc);
-       } else {
-               P_DEBUG("%s-ops registered!\n", ops.name);
-       }
-       return rc;
+       return appldata_register_ops(&ops);
 }
 
 /*
@@ -185,7 +147,6 @@ static int __init appldata_mem_init(void)
 static void __exit appldata_mem_exit(void)
 {
        appldata_unregister_ops(&ops);
-       P_DEBUG("%s-ops unregistered!\n", ops.name);
 }
 
 
index 4d8344336001c8d90edeb7b731fd6558a726d016..3b746556e1a39ddce7dcac254538c521b3e835a1 100644 (file)
@@ -21,9 +21,6 @@
 #include "appldata.h"
 
 
-#define MY_PRINT_NAME  "appldata_net_sum"      /* for debug messages, etc. */
-
-
 /*
  * Network data
  *
@@ -60,26 +57,6 @@ static struct appldata_net_sum_data {
 } __attribute__((packed)) appldata_net_sum_data;
 
 
-static inline void appldata_print_debug(struct appldata_net_sum_data *net_data)
-{
-       P_DEBUG("--- NET - RECORD ---\n");
-
-       P_DEBUG("nr_interfaces = %u\n", net_data->nr_interfaces);
-       P_DEBUG("rx_packets    = %8lu\n", net_data->rx_packets);
-       P_DEBUG("tx_packets    = %8lu\n", net_data->tx_packets);
-       P_DEBUG("rx_bytes      = %8lu\n", net_data->rx_bytes);
-       P_DEBUG("tx_bytes      = %8lu\n", net_data->tx_bytes);
-       P_DEBUG("rx_errors     = %8lu\n", net_data->rx_errors);
-       P_DEBUG("tx_errors     = %8lu\n", net_data->tx_errors);
-       P_DEBUG("rx_dropped    = %8lu\n", net_data->rx_dropped);
-       P_DEBUG("tx_dropped    = %8lu\n", net_data->tx_dropped);
-       P_DEBUG("collisions    = %8lu\n", net_data->collisions);
-
-       P_DEBUG("sync_count_1 = %u\n", net_data->sync_count_1);
-       P_DEBUG("sync_count_2 = %u\n", net_data->sync_count_2);
-       P_DEBUG("timestamp    = %lX\n", net_data->timestamp);
-}
-
 /*
  * appldata_get_net_sum_data()
  *
@@ -135,9 +112,6 @@ static void appldata_get_net_sum_data(void *data)
 
        net_data->timestamp = get_clock();
        net_data->sync_count_2++;
-#ifdef APPLDATA_DEBUG
-       appldata_print_debug(net_data);
-#endif
 }
 
 
@@ -159,17 +133,7 @@ static struct appldata_ops ops = {
  */
 static int __init appldata_net_init(void)
 {
-       int rc;
-
-       P_DEBUG("sizeof(net) = %lu\n", sizeof(struct appldata_net_sum_data));
-
-       rc = appldata_register_ops(&ops);
-       if (rc != 0) {
-               P_ERROR("Error registering ops, rc = %i\n", rc);
-       } else {
-               P_DEBUG("%s-ops registered!\n", ops.name);
-       }
-       return rc;
+       return appldata_register_ops(&ops);
 }
 
 /*
@@ -180,7 +144,6 @@ static int __init appldata_net_init(void)
 static void __exit appldata_net_exit(void)
 {
        appldata_unregister_ops(&ops);
-       P_DEBUG("%s-ops unregistered!\n", ops.name);
 }
 
 
index 6b3eafe104533587e9e439a5852d5020164959ca..eb44f9f8ab917c85a4d3ea6476408b4c86bb343b 100644 (file)
@@ -89,44 +89,6 @@ static struct appldata_ops ops = {
 };
 
 
-static inline void appldata_print_debug(struct appldata_os_data *os_data)
-{
-       int a0, a1, a2, i;
-
-       P_DEBUG("--- OS - RECORD ---\n");
-       P_DEBUG("nr_threads   = %u\n", os_data->nr_threads);
-       P_DEBUG("nr_running   = %u\n", os_data->nr_running);
-       P_DEBUG("nr_iowait    = %u\n", os_data->nr_iowait);
-       P_DEBUG("avenrun(int) = %8x / %8x / %8x\n", os_data->avenrun[0],
-               os_data->avenrun[1], os_data->avenrun[2]);
-       a0 = os_data->avenrun[0];
-       a1 = os_data->avenrun[1];
-       a2 = os_data->avenrun[2];
-       P_DEBUG("avenrun(float) = %d.%02d / %d.%02d / %d.%02d\n",
-               LOAD_INT(a0), LOAD_FRAC(a0), LOAD_INT(a1), LOAD_FRAC(a1),
-               LOAD_INT(a2), LOAD_FRAC(a2));
-
-       P_DEBUG("nr_cpus = %u\n", os_data->nr_cpus);
-       for (i = 0; i < os_data->nr_cpus; i++) {
-               P_DEBUG("cpu%u : user = %u, nice = %u, system = %u, "
-                       "idle = %u, irq = %u, softirq = %u, iowait = %u, "
-                       "steal = %u\n",
-                               os_data->os_cpu[i].cpu_id,
-                               os_data->os_cpu[i].per_cpu_user,
-                               os_data->os_cpu[i].per_cpu_nice,
-                               os_data->os_cpu[i].per_cpu_system,
-                               os_data->os_cpu[i].per_cpu_idle,
-                               os_data->os_cpu[i].per_cpu_irq,
-                               os_data->os_cpu[i].per_cpu_softirq,
-                               os_data->os_cpu[i].per_cpu_iowait,
-                               os_data->os_cpu[i].per_cpu_steal);
-       }
-
-       P_DEBUG("sync_count_1 = %u\n", os_data->sync_count_1);
-       P_DEBUG("sync_count_2 = %u\n", os_data->sync_count_2);
-       P_DEBUG("timestamp    = %lX\n", os_data->timestamp);
-}
-
 /*
  * appldata_get_os_data()
  *
@@ -180,13 +142,10 @@ static void appldata_get_os_data(void *data)
                                           APPLDATA_START_INTERVAL_REC,
                                           (unsigned long) ops.data, new_size,
                                           ops.mod_lvl);
-                       if (rc != 0) {
+                       if (rc != 0)
                                P_ERROR("os: START NEW DIAG 0xDC failed, "
                                        "return code: %d, new size = %i\n", rc,
                                        new_size);
-                               P_INFO("os: stopping old record now\n");
-                       } else
-                               P_INFO("os: new record size = %i\n", new_size);
 
                        rc = appldata_diag(APPLDATA_RECORD_OS_ID,
                                           APPLDATA_STOP_REC,
@@ -204,9 +163,6 @@ static void appldata_get_os_data(void *data)
        }
        os_data->timestamp = get_clock();
        os_data->sync_count_2++;
-#ifdef APPLDATA_DEBUG
-       appldata_print_debug(os_data);
-#endif
 }
 
 
@@ -227,12 +183,9 @@ static int __init appldata_os_init(void)
                rc = -ENOMEM;
                goto out;
        }
-       P_DEBUG("max. sizeof(os) = %i, sizeof(os_cpu) = %lu\n", max_size,
-               sizeof(struct appldata_os_per_cpu));
 
        appldata_os_data = kzalloc(max_size, GFP_DMA);
        if (appldata_os_data == NULL) {
-               P_ERROR("No memory for %s!\n", ops.name);
                rc = -ENOMEM;
                goto out;
        }
@@ -240,17 +193,12 @@ static int __init appldata_os_init(void)
        appldata_os_data->per_cpu_size = sizeof(struct appldata_os_per_cpu);
        appldata_os_data->cpu_offset   = offsetof(struct appldata_os_data,
                                                        os_cpu);
-       P_DEBUG("cpu offset = %u\n", appldata_os_data->cpu_offset);
 
        ops.data = appldata_os_data;
        ops.callback  = &appldata_get_os_data;
        rc = appldata_register_ops(&ops);
-       if (rc != 0) {
-               P_ERROR("Error registering ops, rc = %i\n", rc);
+       if (rc != 0)
                kfree(appldata_os_data);
-       } else {
-               P_DEBUG("%s-ops registered!\n", ops.name);
-       }
 out:
        return rc;
 }
@@ -264,7 +212,6 @@ static void __exit appldata_os_exit(void)
 {
        appldata_unregister_ops(&ops);
        kfree(appldata_os_data);
-       P_DEBUG("%s-ops unregistered!\n", ops.name);
 }
 
 
index 0cfefddd83755366fee0dae7634ccca6342b21dd..6a4300b3ff52023f68ab2c614a117084cf3a0015 100644 (file)
@@ -185,11 +185,8 @@ static int __init prng_init(void)
        prng_seed(16);
 
        ret = misc_register(&prng_dev);
-       if (ret) {
-               printk(KERN_WARNING
-                      "Could not register misc device for PRNG.\n");
+       if (ret)
                goto out_buf;
-       }
        return 0;
 
 out_buf:
index 4b010ff814c9caa3f439cb7e849aa8c501bdace1..7383781f3e6a60ba3c632b1f0d3b26c7800c6ecf 100644 (file)
@@ -150,33 +150,24 @@ static ssize_t hypfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
                              unsigned long nr_segs, loff_t offset)
 {
        char *data;
-       size_t len;
+       ssize_t ret;
        struct file *filp = iocb->ki_filp;
        /* XXX: temporary */
        char __user *buf = iov[0].iov_base;
        size_t count = iov[0].iov_len;
 
-       if (nr_segs != 1) {
-               count = -EINVAL;
-               goto out;
-       }
+       if (nr_segs != 1)
+               return -EINVAL;
 
        data = filp->private_data;
-       len = strlen(data);
-       if (offset > len) {
-               count = 0;
-               goto out;
-       }
-       if (count > len - offset)
-               count = len - offset;
-       if (copy_to_user(buf, data + offset, count)) {
-               count = -EFAULT;
-               goto out;
-       }
-       iocb->ki_pos += count;
+       ret = simple_read_from_buffer(buf, count, &offset, data, strlen(data));
+       if (ret <= 0)
+               return ret;
+
+       iocb->ki_pos += ret;
        file_accessed(filp);
-out:
-       return count;
+
+       return ret;
 }
 static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
                              unsigned long nr_segs, loff_t offset)
index 6302f508258866120b2625198ec411c8f455202c..50f657e773449e29d1fa2d64ad5c8e87047f9bd2 100644 (file)
@@ -7,9 +7,14 @@
 #
 CFLAGS_smp.o   := -Wno-nonnull
 
+#
+# Pass UTS_MACHINE for user_regset definition
+#
+CFLAGS_ptrace.o                += -DUTS_MACHINE='"$(UTS_MACHINE)"'
+
 obj-y  :=  bitmap.o traps.o time.o process.o base.o early.o \
             setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
-           s390_ext.o debug.o irq.o ipl.o dis.o diag.o
+           s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o
 
 obj-y  += $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y  += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
@@ -23,7 +28,7 @@ obj-$(CONFIG_AUDIT)           += audit.o
 compat-obj-$(CONFIG_AUDIT)     += compat_audit.o
 obj-$(CONFIG_COMPAT)           += compat_linux.o compat_signal.o \
                                        compat_wrapper.o compat_exec_domain.o \
-                                       binfmt_elf32.o $(compat-obj-y)
+                                       $(compat-obj-y)
 
 obj-$(CONFIG_VIRT_TIMER)       += vtime.o
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c
deleted file mode 100644 (file)
index 3e1c315..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Support for 32-bit Linux for S390 ELF binaries.
- *
- * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Gerhard Tonn (ton@de.ibm.com)
- *
- * Heavily inspired by the 32-bit Sparc compat code which is
- * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com)
- * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek   (jj@ultra.linux.cz)
- */
-
-#define __ASMS390_ELF_H
-
-#include <linux/time.h>
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS      ELFCLASS32
-#define ELF_DATA       ELFDATA2MSB
-#define ELF_ARCH       EM_S390
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) \
-       (((x)->e_machine == EM_S390 || (x)->e_machine == EM_S390_OLD) \
-         && (x)->e_ident[EI_CLASS] == ELF_CLASS)
-
-/* ELF register definitions */
-#define NUM_GPRS      16
-#define NUM_FPRS      16
-#define NUM_ACRS      16    
-
-/* For SVR4/S390 the function pointer to be registered with `atexit` is
-   passed in R14. */
-#define ELF_PLAT_INIT(_r, load_addr) \
-       do { \
-               _r->gprs[14] = 0; \
-       } while(0)
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE       4096
-
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-#define ELF_ET_DYN_BASE         (TASK_SIZE / 3 * 2)
-
-/* Wow, the "main" arch needs arch dependent functions too.. :) */
-
-/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
-   now struct_user_regs, they are different) */
-
-#define ELF_CORE_COPY_REGS(pr_reg, regs) dump_regs32(regs, &pr_reg);
-
-#define ELF_CORE_COPY_TASK_REGS(tsk, regs) dump_task_regs32(tsk, regs)
-
-#define ELF_CORE_COPY_FPREGS(tsk, fpregs) dump_task_fpu(tsk, fpregs)
-
-/* This yields a mask that user programs can use to figure out what
-   instruction set this CPU supports. */
-
-#define ELF_HWCAP (0)
-
-/* This yields a string that ld.so will use to load implementation
-   specific libraries for optimization.  This is more specific in
-   intent than poking at uname or /proc/cpuinfo.
-
-   For the moment, we have only optimizations for the Intel generations,
-   but that could change... */
-
-#define ELF_PLATFORM (NULL)
-
-#define SET_PERSONALITY(ex, ibcs2)                     \
-do {                                                   \
-       if (ibcs2)                                      \
-               set_personality(PER_SVR4);              \
-       else if (current->personality != PER_LINUX32)   \
-               set_personality(PER_LINUX);             \
-       set_thread_flag(TIF_31BIT);                     \
-} while (0)
-
-#include "compat_linux.h"
-
-typedef _s390_fp_regs32 elf_fpregset_t;
-
-typedef struct
-{
-       
-       _psw_t32        psw;
-       __u32           gprs[__NUM_GPRS]; 
-       __u32           acrs[__NUM_ACRS]; 
-       __u32           orig_gpr2;
-} s390_regs32;
-typedef s390_regs32 elf_gregset_t;
-
-static inline int dump_regs32(struct pt_regs *ptregs, elf_gregset_t *regs)
-{
-       int i;
-
-       memcpy(&regs->psw.mask, &ptregs->psw.mask, 4);
-       memcpy(&regs->psw.addr, (char *)&ptregs->psw.addr + 4, 4);
-       for (i = 0; i < NUM_GPRS; i++)
-               regs->gprs[i] = ptregs->gprs[i];
-       save_access_regs(regs->acrs);
-       regs->orig_gpr2 = ptregs->orig_gpr2;
-       return 1;
-}
-
-static inline int dump_task_regs32(struct task_struct *tsk, elf_gregset_t *regs)
-{
-       struct pt_regs *ptregs = task_pt_regs(tsk);
-       int i;
-
-       memcpy(&regs->psw.mask, &ptregs->psw.mask, 4);
-       memcpy(&regs->psw.addr, (char *)&ptregs->psw.addr + 4, 4);
-       for (i = 0; i < NUM_GPRS; i++)
-               regs->gprs[i] = ptregs->gprs[i];
-       memcpy(regs->acrs, tsk->thread.acrs, sizeof(regs->acrs));
-       regs->orig_gpr2 = ptregs->orig_gpr2;
-       return 1;
-}
-
-static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
-{
-       if (tsk == current)
-               save_fp_regs((s390_fp_regs *) fpregs);
-       else
-               memcpy(fpregs, &tsk->thread.fp_regs, sizeof(elf_fpregset_t));
-       return 1;
-}
-
-#include <asm/processor.h>
-#include <asm/pgalloc.h>
-#include <linux/module.h>
-#include <linux/elfcore.h>
-#include <linux/binfmts.h>
-#include <linux/compat.h>
-
-#define elf_prstatus elf_prstatus32
-struct elf_prstatus32
-{
-       struct elf_siginfo pr_info;     /* Info associated with signal */
-       short   pr_cursig;              /* Current signal */
-       u32     pr_sigpend;     /* Set of pending signals */
-       u32     pr_sighold;     /* Set of held signals */
-       pid_t   pr_pid;
-       pid_t   pr_ppid;
-       pid_t   pr_pgrp;
-       pid_t   pr_sid;
-       struct compat_timeval pr_utime; /* User time */
-       struct compat_timeval pr_stime; /* System time */
-       struct compat_timeval pr_cutime;        /* Cumulative user time */
-       struct compat_timeval pr_cstime;        /* Cumulative system time */
-       elf_gregset_t pr_reg;   /* GP registers */
-       int pr_fpvalid;         /* True if math co-processor being used.  */
-};
-
-#define elf_prpsinfo elf_prpsinfo32
-struct elf_prpsinfo32
-{
-       char    pr_state;       /* numeric process state */
-       char    pr_sname;       /* char for pr_state */
-       char    pr_zomb;        /* zombie */
-       char    pr_nice;        /* nice val */
-       u32     pr_flag;        /* flags */
-       u16     pr_uid;
-       u16     pr_gid;
-       pid_t   pr_pid, pr_ppid, pr_pgrp, pr_sid;
-       /* Lots missing */
-       char    pr_fname[16];   /* filename of executable */
-       char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
-};
-
-#include <linux/highuid.h>
-
-/*
-#define init_elf_binfmt init_elf32_binfmt
-*/
-
-#undef start_thread
-#define start_thread                    start_thread31 
-
-static inline void start_thread31(struct pt_regs *regs, unsigned long new_psw,
-                                 unsigned long new_stackp)
-{
-       set_fs(USER_DS);
-       regs->psw.mask  = psw_user32_bits;
-       regs->psw.addr  = new_psw;
-       regs->gprs[15]  = new_stackp;
-       crst_table_downgrade(current->mm, 1UL << 31);
-}
-
-MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit Linux for S390 binaries,"
-                   " Copyright 2000 IBM Corporation"); 
-MODULE_AUTHOR("Gerhard Tonn <ton@de.ibm.com>");
-
-#undef MODULE_DESCRIPTION
-#undef MODULE_AUTHOR
-
-#undef cputime_to_timeval
-#define cputime_to_timeval cputime_to_compat_timeval
-static inline void
-cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
-{
-       value->tv_usec = cputime % 1000000;
-       value->tv_sec = cputime / 1000000;
-}
-
-#include "../../../fs/binfmt_elf.c"
-
index 419aef913ee1233c0ab6af25c81ef21a1a22061f..cde81fa64f89bf17bc586dce3f973e77f55985e8 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _PTRACE32_H
 #define _PTRACE32_H
 
-#include "compat_linux.h"  /* needed for _psw_t32 */
+#include "compat_linux.h"  /* needed for psw_compat_t */
 
 typedef struct {
        __u32 cr[3];
@@ -38,7 +38,7 @@ typedef struct {
 
 struct user_regs_struct32
 {
-       _psw_t32 psw;
+       psw_compat_t psw;
        u32 gprs[NUM_GPRS];
        u32 acrs[NUM_ACRS];
        u32 orig_gpr2;
index c93d1296cc0a7eeff66feaa20e9666bb5e31b6fa..d80fcd4a7fe14210aac75d33d824fa9c6eb1c4a7 100644 (file)
@@ -1079,7 +1079,6 @@ __init debug_init(void)
        s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
        mutex_lock(&debug_mutex);
        debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
-       printk(KERN_INFO "debug: Initialization complete\n");
        initialized = 1;
        mutex_unlock(&debug_mutex);
 
@@ -1193,7 +1192,6 @@ debug_get_uint(char *buf)
        for(; isspace(*buf); buf++);
        rc = simple_strtoul(buf, &buf, 10);
        if(*buf){
-               printk("debug: no integer specified!\n");
                rc = -EINVAL;
        }
        return rc;
@@ -1340,19 +1338,12 @@ static void debug_flush(debug_info_t* id, int area)
                                memset(id->areas[i][j], 0, PAGE_SIZE);
                        }
                }
-                printk(KERN_INFO "debug: %s: all areas flushed\n",id->name);
         } else if(area >= 0 && area < id->nr_areas) {
                 id->active_entries[area] = 0;
                id->active_pages[area] = 0;
                for(i = 0; i < id->pages_per_area; i++) {
                        memset(id->areas[area][i],0,PAGE_SIZE);
                }
-                printk(KERN_INFO "debug: %s: area %i has been flushed\n",
-                        id->name, area);
-        } else {
-                printk(KERN_INFO
-                      "debug: %s: area %i cannot be flushed (range: %i - %i)\n",
-                        id->name, area, 0, id->nr_areas-1);
         }
         spin_unlock_irqrestore(&id->lock,flags);
 }
index d0e09684b9ce8c4f0924017a51f86e12ddec93d5..2a2ca268b1dd6e6bc38115496674ee965f8ef29a 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/pfn.h>
 #include <linux/uaccess.h>
+#include <asm/ebcdic.h>
 #include <asm/ipl.h>
 #include <asm/lowcore.h>
 #include <asm/processor.h>
 /*
  * Create a Kernel NSS if the SAVESYS= parameter is defined
  */
-#define DEFSYS_CMD_SIZE                96
+#define DEFSYS_CMD_SIZE                128
 #define SAVESYS_CMD_SIZE       32
 
 char kernel_nss_name[NSS_NAME_SIZE + 1];
 
+static void __init setup_boot_command_line(void);
+
+
 #ifdef CONFIG_SHARED_KERNEL
+int __init savesys_ipl_nss(char *cmd, const int cmdlen);
+
+asm(
+       "       .section .init.text,\"ax\",@progbits\n"
+       "       .align  4\n"
+       "       .type   savesys_ipl_nss, @function\n"
+       "savesys_ipl_nss:\n"
+#ifdef CONFIG_64BIT
+       "       stmg    6,15,48(15)\n"
+       "       lgr     14,3\n"
+       "       sam31\n"
+       "       diag    2,14,0x8\n"
+       "       sam64\n"
+       "       lgr     2,14\n"
+       "       lmg     6,15,48(15)\n"
+#else
+       "       stm     6,15,24(15)\n"
+       "       lr      14,3\n"
+       "       diag    2,14,0x8\n"
+       "       lr      2,14\n"
+       "       lm      6,15,24(15)\n"
+#endif
+       "       br      14\n"
+       "       .size   savesys_ipl_nss, .-savesys_ipl_nss\n");
+
 static noinline __init void create_kernel_nss(void)
 {
        unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size;
@@ -39,6 +68,7 @@ static noinline __init void create_kernel_nss(void)
        unsigned int sinitrd_pfn, einitrd_pfn;
 #endif
        int response;
+       size_t len;
        char *savesys_ptr;
        char upper_command_line[COMMAND_LINE_SIZE];
        char defsys_cmd[DEFSYS_CMD_SIZE];
@@ -49,8 +79,8 @@ static noinline __init void create_kernel_nss(void)
                return;
 
        /* Convert COMMAND_LINE to upper case */
-       for (i = 0; i < strlen(COMMAND_LINE); i++)
-               upper_command_line[i] = toupper(COMMAND_LINE[i]);
+       for (i = 0; i < strlen(boot_command_line); i++)
+               upper_command_line[i] = toupper(boot_command_line[i]);
 
        savesys_ptr = strstr(upper_command_line, "SAVESYS=");
 
@@ -83,7 +113,8 @@ static noinline __init void create_kernel_nss(void)
        }
 #endif
 
-       sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size);
+       sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK PARMREGS=0-13",
+               defsys_cmd, min_size);
        sprintf(savesys_cmd, "SAVESYS %s \n IPL %s",
                kernel_nss_name, kernel_nss_name);
 
@@ -94,13 +125,24 @@ static noinline __init void create_kernel_nss(void)
                return;
        }
 
-       __cpcmd(savesys_cmd, NULL, 0, &response);
+       len = strlen(savesys_cmd);
+       ASCEBC(savesys_cmd, len);
+       response = savesys_ipl_nss(savesys_cmd, len);
 
-       if (response != strlen(savesys_cmd)) {
+       /* On success: response is equal to the command size,
+        *             max SAVESYS_CMD_SIZE
+        * On error: response contains the numeric portion of cp error message.
+        *           for SAVESYS it will be >= 263
+        */
+       if (response > SAVESYS_CMD_SIZE) {
                kernel_nss_name[0] = '\0';
                return;
        }
 
+       /* re-setup boot command line with new ipl vm parms */
+       ipl_update_parameters();
+       setup_boot_command_line();
+
        ipl_flags = IPL_NSS_VALID;
 }
 
@@ -141,109 +183,11 @@ static noinline __init void detect_machine_type(void)
        if (cpuinfo->cpu_id.version == 0xff)
                machine_flags |= MACHINE_FLAG_VM;
 
-       /* Running on a P/390 ? */
-       if (cpuinfo->cpu_id.machine == 0x7490)
-               machine_flags |= MACHINE_FLAG_P390;
-
        /* Running under KVM ? */
        if (cpuinfo->cpu_id.version == 0xfe)
                machine_flags |= MACHINE_FLAG_KVM;
 }
 
-#ifdef CONFIG_64BIT
-static noinline __init int memory_fast_detect(void)
-{
-       unsigned long val0 = 0;
-       unsigned long val1 = 0xc;
-       int ret = -ENOSYS;
-
-       if (ipl_flags & IPL_NSS_VALID)
-               return -ENOSYS;
-
-       asm volatile(
-               "       diag    %1,%2,0x260\n"
-               "0:     lhi     %0,0\n"
-               "1:\n"
-               EX_TABLE(0b,1b)
-               : "+d" (ret), "+d" (val0), "+d" (val1) : : "cc");
-
-       if (ret || val0 != val1)
-               return -ENOSYS;
-
-       memory_chunk[0].size = val0 + 1;
-       return 0;
-}
-#else
-static inline int memory_fast_detect(void)
-{
-       return -ENOSYS;
-}
-#endif
-
-static inline __init unsigned long __tprot(unsigned long addr)
-{
-       int cc = -1;
-
-       asm volatile(
-               "       tprot   0(%1),0\n"
-               "0:     ipm     %0\n"
-               "       srl     %0,28\n"
-               "1:\n"
-               EX_TABLE(0b,1b)
-               : "+d" (cc) : "a" (addr) : "cc");
-       return (unsigned long)cc;
-}
-
-/* Checking memory in 128KB increments. */
-#define CHUNK_INCR     (1UL << 17)
-#define ADDR2G         (1UL << 31)
-
-static noinline __init void find_memory_chunks(unsigned long memsize)
-{
-       unsigned long addr = 0, old_addr = 0;
-       unsigned long old_cc = CHUNK_READ_WRITE;
-       unsigned long cc;
-       int chunk = 0;
-
-       while (chunk < MEMORY_CHUNKS) {
-               cc = __tprot(addr);
-               while (cc == old_cc) {
-                       addr += CHUNK_INCR;
-                       if (memsize && addr >= memsize)
-                               break;
-#ifndef CONFIG_64BIT
-                       if (addr == ADDR2G)
-                               break;
-#endif
-                       cc = __tprot(addr);
-               }
-
-               if (old_addr != addr &&
-                   (old_cc == CHUNK_READ_WRITE || old_cc == CHUNK_READ_ONLY)) {
-                       memory_chunk[chunk].addr = old_addr;
-                       memory_chunk[chunk].size = addr - old_addr;
-                       memory_chunk[chunk].type = old_cc;
-                       chunk++;
-               }
-
-               old_addr = addr;
-               old_cc = cc;
-
-#ifndef CONFIG_64BIT
-               if (addr == ADDR2G)
-                       break;
-#endif
-               /*
-                * Finish memory detection at the first hole
-                * if storage size is unknown.
-                */
-               if (cc == -1UL && !memsize)
-                       break;
-               if (memsize && addr >= memsize)
-                       break;
-       }
-}
-
 static __init void early_pgm_check_handler(void)
 {
        unsigned long addr;
@@ -380,23 +324,61 @@ static __init void detect_machine_facilities(void)
 #endif
 }
 
+static __init void rescue_initrd(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+       /*
+        * Move the initrd right behind the bss section in case it starts
+        * within the bss section. So we don't overwrite it when the bss
+        * section gets cleared.
+        */
+       if (!INITRD_START || !INITRD_SIZE)
+               return;
+       if (INITRD_START >= (unsigned long) __bss_stop)
+               return;
+       memmove(__bss_stop, (void *) INITRD_START, INITRD_SIZE);
+       INITRD_START = (unsigned long) __bss_stop;
+#endif
+}
+
+/* Set up boot command line */
+static void __init setup_boot_command_line(void)
+{
+       char *parm = NULL;
+
+       /* copy arch command line */
+       strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
+       boot_command_line[ARCH_COMMAND_LINE_SIZE - 1] = 0;
+
+       /* append IPL PARM data to the boot command line */
+       if (MACHINE_IS_VM) {
+               parm = boot_command_line + strlen(boot_command_line);
+               *parm++ = ' ';
+               get_ipl_vmparm(parm);
+               if (parm[0] == '=')
+                       memmove(boot_command_line, parm + 1, strlen(parm));
+       }
+}
+
+
 /*
  * Save ipl parameters, clear bss memory, initialize storage keys
  * and create a kernel NSS at startup if the SAVESYS= parm is defined
  */
 void __init startup_init(void)
 {
-       unsigned long long memsize;
-
        ipl_save_parameters();
+       rescue_initrd();
        clear_bss_section();
        init_kernel_storage_key();
        lockdep_init();
        lockdep_off();
-       detect_machine_type();
-       create_kernel_nss();
        sort_main_extable();
        setup_lowcore_early();
+       detect_machine_type();
+       ipl_update_parameters();
+       setup_boot_command_line();
+       create_kernel_nss();
        detect_mvpg();
        detect_ieee();
        detect_csp();
@@ -404,18 +386,7 @@ void __init startup_init(void)
        detect_diag44();
        detect_machine_facilities();
        setup_hpage();
-       sclp_read_info_early();
        sclp_facilities_detect();
-       memsize = sclp_memory_detect();
-#ifndef CONFIG_64BIT
-       /*
-        * Can't deal with more than 2G in 31 bit addressing mode, so
-        * limit the value in order to avoid strange side effects.
-        */
-       if (memsize > ADDR2G)
-               memsize = ADDR2G;
-#endif
-       if (memory_fast_detect() < 0)
-               find_memory_chunks((unsigned long) memsize);
+       detect_memory_layout(memory_chunk);
        lockdep_on();
 }
index 532542447d661a34537e42ff69571616d8874865..54b2779b5e2fa49b45cecfb929b0ec6fdba9c3ae 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/ctype.h>
+#include <linux/fs.h>
 #include <asm/ipl.h>
 #include <asm/smp.h>
 #include <asm/setup.h>
@@ -22,6 +23,7 @@
 #include <asm/ebcdic.h>
 #include <asm/reset.h>
 #include <asm/sclp.h>
+#include <asm/setup.h>
 
 #define IPL_PARM_BLOCK_VERSION 0
 
@@ -121,6 +123,7 @@ enum ipl_method {
        REIPL_METHOD_FCP_RO_VM,
        REIPL_METHOD_FCP_DUMP,
        REIPL_METHOD_NSS,
+       REIPL_METHOD_NSS_DIAG,
        REIPL_METHOD_DEFAULT,
 };
 
@@ -134,14 +137,15 @@ enum dump_method {
 
 static int diag308_set_works = 0;
 
+static struct ipl_parameter_block ipl_block;
+
 static int reipl_capabilities = IPL_TYPE_UNKNOWN;
 
 static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
 static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
 static struct ipl_parameter_block *reipl_block_fcp;
 static struct ipl_parameter_block *reipl_block_ccw;
-
-static char reipl_nss_name[NSS_NAME_SIZE + 1];
+static struct ipl_parameter_block *reipl_block_nss;
 
 static int dump_capabilities = DUMP_TYPE_NONE;
 static enum dump_type dump_type = DUMP_TYPE_NONE;
@@ -263,6 +267,56 @@ static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
 
 static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
 
+/* VM IPL PARM routines */
+static void reipl_get_ascii_vmparm(char *dest,
+                                  const struct ipl_parameter_block *ipb)
+{
+       int i;
+       int len = 0;
+       char has_lowercase = 0;
+
+       if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
+           (ipb->ipl_info.ccw.vm_parm_len > 0)) {
+
+               len = ipb->ipl_info.ccw.vm_parm_len;
+               memcpy(dest, ipb->ipl_info.ccw.vm_parm, len);
+               /* If at least one character is lowercase, we assume mixed
+                * case; otherwise we convert everything to lowercase.
+                */
+               for (i = 0; i < len; i++)
+                       if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */
+                           (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */
+                           (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */
+                               has_lowercase = 1;
+                               break;
+                       }
+               if (!has_lowercase)
+                       EBC_TOLOWER(dest, len);
+               EBCASC(dest, len);
+       }
+       dest[len] = 0;
+}
+
+void get_ipl_vmparm(char *dest)
+{
+       if (diag308_set_works && (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW))
+               reipl_get_ascii_vmparm(dest, &ipl_block);
+       else
+               dest[0] = 0;
+}
+
+static ssize_t ipl_vm_parm_show(struct kobject *kobj,
+                               struct kobj_attribute *attr, char *page)
+{
+       char parm[DIAG308_VMPARM_SIZE + 1] = {};
+
+       get_ipl_vmparm(parm);
+       return sprintf(page, "%s\n", parm);
+}
+
+static struct kobj_attribute sys_ipl_vm_parm_attr =
+       __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL);
+
 static ssize_t sys_ipl_device_show(struct kobject *kobj,
                                   struct kobj_attribute *attr, char *page)
 {
@@ -285,14 +339,8 @@ static struct kobj_attribute sys_ipl_device_attr =
 static ssize_t ipl_parameter_read(struct kobject *kobj, struct bin_attribute *attr,
                                  char *buf, loff_t off, size_t count)
 {
-       unsigned int size = IPL_PARMBLOCK_SIZE;
-
-       if (off > size)
-               return 0;
-       if (off + count > size)
-               count = size - off;
-       memcpy(buf, (void *)IPL_PARMBLOCK_START + off, count);
-       return count;
+       return memory_read_from_buffer(buf, count, &off, IPL_PARMBLOCK_START,
+                                       IPL_PARMBLOCK_SIZE);
 }
 
 static struct bin_attribute ipl_parameter_attr = {
@@ -310,12 +358,7 @@ static ssize_t ipl_scp_data_read(struct kobject *kobj, struct bin_attribute *att
        unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
        void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
 
-       if (off > size)
-               return 0;
-       if (off + count > size)
-               count = size - off;
-       memcpy(buf, scp_data + off, count);
-       return count;
+       return memory_read_from_buffer(buf, count, &off, scp_data, size);
 }
 
 static struct bin_attribute ipl_scp_data_attr = {
@@ -370,15 +413,27 @@ static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
 static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
        __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
 
-static struct attribute *ipl_ccw_attrs[] = {
+static struct attribute *ipl_ccw_attrs_vm[] = {
        &sys_ipl_type_attr.attr,
        &sys_ipl_device_attr.attr,
        &sys_ipl_ccw_loadparm_attr.attr,
+       &sys_ipl_vm_parm_attr.attr,
        NULL,
 };
 
-static struct attribute_group ipl_ccw_attr_group = {
-       .attrs = ipl_ccw_attrs,
+static struct attribute *ipl_ccw_attrs_lpar[] = {
+       &sys_ipl_type_attr.attr,
+       &sys_ipl_device_attr.attr,
+       &sys_ipl_ccw_loadparm_attr.attr,
+       NULL,
+};
+
+static struct attribute_group ipl_ccw_attr_group_vm = {
+       .attrs = ipl_ccw_attrs_vm,
+};
+
+static struct attribute_group ipl_ccw_attr_group_lpar = {
+       .attrs = ipl_ccw_attrs_lpar
 };
 
 /* NSS ipl device attributes */
@@ -388,6 +443,8 @@ DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name);
 static struct attribute *ipl_nss_attrs[] = {
        &sys_ipl_type_attr.attr,
        &sys_ipl_nss_name_attr.attr,
+       &sys_ipl_ccw_loadparm_attr.attr,
+       &sys_ipl_vm_parm_attr.attr,
        NULL,
 };
 
@@ -450,7 +507,12 @@ static int __init ipl_init(void)
        }
        switch (ipl_info.type) {
        case IPL_TYPE_CCW:
-               rc = sysfs_create_group(&ipl_kset->kobj, &ipl_ccw_attr_group);
+               if (MACHINE_IS_VM)
+                       rc = sysfs_create_group(&ipl_kset->kobj,
+                                               &ipl_ccw_attr_group_vm);
+               else
+                       rc = sysfs_create_group(&ipl_kset->kobj,
+                                               &ipl_ccw_attr_group_lpar);
                break;
        case IPL_TYPE_FCP:
        case IPL_TYPE_FCP_DUMP:
@@ -481,6 +543,83 @@ static struct shutdown_action __refdata ipl_action = {
  * reipl shutdown action: Reboot Linux on shutdown.
  */
 
+/* VM IPL PARM attributes */
+static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb,
+                                         char *page)
+{
+       char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
+
+       reipl_get_ascii_vmparm(vmparm, ipb);
+       return sprintf(page, "%s\n", vmparm);
+}
+
+static ssize_t reipl_generic_vmparm_store(struct ipl_parameter_block *ipb,
+                                         size_t vmparm_max,
+                                         const char *buf, size_t len)
+{
+       int i, ip_len;
+
+       /* ignore trailing newline */
+       ip_len = len;
+       if ((len > 0) && (buf[len - 1] == '\n'))
+               ip_len--;
+
+       if (ip_len > vmparm_max)
+               return -EINVAL;
+
+       /* parm is used to store kernel options, check for common chars */
+       for (i = 0; i < ip_len; i++)
+               if (!(isalnum(buf[i]) || isascii(buf[i]) || isprint(buf[i])))
+                       return -EINVAL;
+
+       memset(ipb->ipl_info.ccw.vm_parm, 0, DIAG308_VMPARM_SIZE);
+       ipb->ipl_info.ccw.vm_parm_len = ip_len;
+       if (ip_len > 0) {
+               ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
+               memcpy(ipb->ipl_info.ccw.vm_parm, buf, ip_len);
+               ASCEBC(ipb->ipl_info.ccw.vm_parm, ip_len);
+       } else {
+               ipb->ipl_info.ccw.vm_flags &= ~DIAG308_VM_FLAGS_VP_VALID;
+       }
+
+       return len;
+}
+
+/* NSS wrapper */
+static ssize_t reipl_nss_vmparm_show(struct kobject *kobj,
+                                    struct kobj_attribute *attr, char *page)
+{
+       return reipl_generic_vmparm_show(reipl_block_nss, page);
+}
+
+static ssize_t reipl_nss_vmparm_store(struct kobject *kobj,
+                                     struct kobj_attribute *attr,
+                                     const char *buf, size_t len)
+{
+       return reipl_generic_vmparm_store(reipl_block_nss, 56, buf, len);
+}
+
+/* CCW wrapper */
+static ssize_t reipl_ccw_vmparm_show(struct kobject *kobj,
+                                    struct kobj_attribute *attr, char *page)
+{
+       return reipl_generic_vmparm_show(reipl_block_ccw, page);
+}
+
+static ssize_t reipl_ccw_vmparm_store(struct kobject *kobj,
+                                     struct kobj_attribute *attr,
+                                     const char *buf, size_t len)
+{
+       return reipl_generic_vmparm_store(reipl_block_ccw, 64, buf, len);
+}
+
+static struct kobj_attribute sys_reipl_nss_vmparm_attr =
+       __ATTR(parm, S_IRUGO | S_IWUSR, reipl_nss_vmparm_show,
+                                       reipl_nss_vmparm_store);
+static struct kobj_attribute sys_reipl_ccw_vmparm_attr =
+       __ATTR(parm, S_IRUGO | S_IWUSR, reipl_ccw_vmparm_show,
+                                       reipl_ccw_vmparm_store);
+
 /* FCP reipl device attributes */
 
 DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n",
@@ -513,27 +652,26 @@ static struct attribute_group reipl_fcp_attr_group = {
 DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
        reipl_block_ccw->ipl_info.ccw.devno);
 
-static void reipl_get_ascii_loadparm(char *loadparm)
+static void reipl_get_ascii_loadparm(char *loadparm,
+                                    struct ipl_parameter_block *ibp)
 {
-       memcpy(loadparm, &reipl_block_ccw->ipl_info.ccw.load_param,
-              LOADPARM_LEN);
+       memcpy(loadparm, ibp->ipl_info.ccw.load_parm, LOADPARM_LEN);
        EBCASC(loadparm, LOADPARM_LEN);
        loadparm[LOADPARM_LEN] = 0;
        strstrip(loadparm);
 }
 
-static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj,
-                                      struct kobj_attribute *attr, char *page)
+static ssize_t reipl_generic_loadparm_show(struct ipl_parameter_block *ipb,
+                                          char *page)
 {
        char buf[LOADPARM_LEN + 1];
 
-       reipl_get_ascii_loadparm(buf);
+       reipl_get_ascii_loadparm(buf, ipb);
        return sprintf(page, "%s\n", buf);
 }
 
-static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
-                                       struct kobj_attribute *attr,
-                                       const char *buf, size_t len)
+static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
+                                           const char *buf, size_t len)
 {
        int i, lp_len;
 
@@ -552,35 +690,128 @@ static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
                return -EINVAL;
        }
        /* initialize loadparm with blanks */
-       memset(&reipl_block_ccw->ipl_info.ccw.load_param, ' ', LOADPARM_LEN);
+       memset(ipb->ipl_info.ccw.load_parm, ' ', LOADPARM_LEN);
        /* copy and convert to ebcdic */
-       memcpy(&reipl_block_ccw->ipl_info.ccw.load_param, buf, lp_len);
-       ASCEBC(reipl_block_ccw->ipl_info.ccw.load_param, LOADPARM_LEN);
+       memcpy(ipb->ipl_info.ccw.load_parm, buf, lp_len);
+       ASCEBC(ipb->ipl_info.ccw.load_parm, LOADPARM_LEN);
        return len;
 }
 
+/* NSS wrapper */
+static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
+                                      struct kobj_attribute *attr, char *page)
+{
+       return reipl_generic_loadparm_show(reipl_block_nss, page);
+}
+
+static ssize_t reipl_nss_loadparm_store(struct kobject *kobj,
+                                       struct kobj_attribute *attr,
+                                       const char *buf, size_t len)
+{
+       return reipl_generic_loadparm_store(reipl_block_nss, buf, len);
+}
+
+/* CCW wrapper */
+static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj,
+                                      struct kobj_attribute *attr, char *page)
+{
+       return reipl_generic_loadparm_show(reipl_block_ccw, page);
+}
+
+static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
+                                       struct kobj_attribute *attr,
+                                       const char *buf, size_t len)
+{
+       return reipl_generic_loadparm_store(reipl_block_ccw, buf, len);
+}
+
 static struct kobj_attribute sys_reipl_ccw_loadparm_attr =
-       __ATTR(loadparm, 0644, reipl_ccw_loadparm_show,
-              reipl_ccw_loadparm_store);
+       __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_ccw_loadparm_show,
+                                           reipl_ccw_loadparm_store);
 
-static struct attribute *reipl_ccw_attrs[] = {
+static struct attribute *reipl_ccw_attrs_vm[] = {
        &sys_reipl_ccw_device_attr.attr,
        &sys_reipl_ccw_loadparm_attr.attr,
+       &sys_reipl_ccw_vmparm_attr.attr,
        NULL,
 };
 
-static struct attribute_group reipl_ccw_attr_group = {
+static struct attribute *reipl_ccw_attrs_lpar[] = {
+       &sys_reipl_ccw_device_attr.attr,
+       &sys_reipl_ccw_loadparm_attr.attr,
+       NULL,
+};
+
+static struct attribute_group reipl_ccw_attr_group_vm = {
+       .name  = IPL_CCW_STR,
+       .attrs = reipl_ccw_attrs_vm,
+};
+
+static struct attribute_group reipl_ccw_attr_group_lpar = {
        .name  = IPL_CCW_STR,
-       .attrs = reipl_ccw_attrs,
+       .attrs = reipl_ccw_attrs_lpar,
 };
 
 
 /* NSS reipl device attributes */
+static void reipl_get_ascii_nss_name(char *dst,
+                                    struct ipl_parameter_block *ipb)
+{
+       memcpy(dst, ipb->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
+       EBCASC(dst, NSS_NAME_SIZE);
+       dst[NSS_NAME_SIZE] = 0;
+}
+
+static ssize_t reipl_nss_name_show(struct kobject *kobj,
+                                  struct kobj_attribute *attr, char *page)
+{
+       char nss_name[NSS_NAME_SIZE + 1] = {};
 
-DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name);
+       reipl_get_ascii_nss_name(nss_name, reipl_block_nss);
+       return sprintf(page, "%s\n", nss_name);
+}
+
+static ssize_t reipl_nss_name_store(struct kobject *kobj,
+                                   struct kobj_attribute *attr,
+                                   const char *buf, size_t len)
+{
+       int nss_len;
+
+       /* ignore trailing newline */
+       nss_len = len;
+       if ((len > 0) && (buf[len - 1] == '\n'))
+               nss_len--;
+
+       if (nss_len > NSS_NAME_SIZE)
+               return -EINVAL;
+
+       memset(reipl_block_nss->ipl_info.ccw.nss_name, 0x40, NSS_NAME_SIZE);
+       if (nss_len > 0) {
+               reipl_block_nss->ipl_info.ccw.vm_flags |=
+                       DIAG308_VM_FLAGS_NSS_VALID;
+               memcpy(reipl_block_nss->ipl_info.ccw.nss_name, buf, nss_len);
+               ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
+               EBC_TOUPPER(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
+       } else {
+               reipl_block_nss->ipl_info.ccw.vm_flags &=
+                       ~DIAG308_VM_FLAGS_NSS_VALID;
+       }
+
+       return len;
+}
+
+static struct kobj_attribute sys_reipl_nss_name_attr =
+       __ATTR(name, S_IRUGO | S_IWUSR, reipl_nss_name_show,
+                                       reipl_nss_name_store);
+
+static struct kobj_attribute sys_reipl_nss_loadparm_attr =
+       __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nss_loadparm_show,
+                                           reipl_nss_loadparm_store);
 
 static struct attribute *reipl_nss_attrs[] = {
        &sys_reipl_nss_name_attr.attr,
+       &sys_reipl_nss_loadparm_attr.attr,
+       &sys_reipl_nss_vmparm_attr.attr,
        NULL,
 };
 
@@ -617,7 +848,10 @@ static int reipl_set_type(enum ipl_type type)
                reipl_method = REIPL_METHOD_FCP_DUMP;
                break;
        case IPL_TYPE_NSS:
-               reipl_method = REIPL_METHOD_NSS;
+               if (diag308_set_works)
+                       reipl_method = REIPL_METHOD_NSS_DIAG;
+               else
+                       reipl_method = REIPL_METHOD_NSS;
                break;
        case IPL_TYPE_UNKNOWN:
                reipl_method = REIPL_METHOD_DEFAULT;
@@ -655,11 +889,38 @@ static struct kobj_attribute reipl_type_attr =
 
 static struct kset *reipl_kset;
 
+static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb,
+                          const enum ipl_method m)
+{
+       char loadparm[LOADPARM_LEN + 1] = {};
+       char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
+       char nss_name[NSS_NAME_SIZE + 1] = {};
+       size_t pos = 0;
+
+       reipl_get_ascii_loadparm(loadparm, ipb);
+       reipl_get_ascii_nss_name(nss_name, ipb);
+       reipl_get_ascii_vmparm(vmparm, ipb);
+
+       switch (m) {
+       case REIPL_METHOD_CCW_VM:
+               pos = sprintf(dst, "IPL %X CLEAR", ipb->ipl_info.ccw.devno);
+               break;
+       case REIPL_METHOD_NSS:
+               pos = sprintf(dst, "IPL %s", nss_name);
+               break;
+       default:
+               break;
+       }
+       if (strlen(loadparm) > 0)
+               pos += sprintf(dst + pos, " LOADPARM '%s'", loadparm);
+       if (strlen(vmparm) > 0)
+               sprintf(dst + pos, " PARM %s", vmparm);
+}
+
 static void reipl_run(struct shutdown_trigger *trigger)
 {
        struct ccw_dev_id devid;
-       static char buf[100];
-       char loadparm[LOADPARM_LEN + 1];
+       static char buf[128];
 
        switch (reipl_method) {
        case REIPL_METHOD_CCW_CIO:
@@ -668,13 +929,7 @@ static void reipl_run(struct shutdown_trigger *trigger)
                reipl_ccw_dev(&devid);
                break;
        case REIPL_METHOD_CCW_VM:
-               reipl_get_ascii_loadparm(loadparm);
-               if (strlen(loadparm) == 0)
-                       sprintf(buf, "IPL %X CLEAR",
-                               reipl_block_ccw->ipl_info.ccw.devno);
-               else
-                       sprintf(buf, "IPL %X CLEAR LOADPARM '%s'",
-                               reipl_block_ccw->ipl_info.ccw.devno, loadparm);
+               get_ipl_string(buf, reipl_block_ccw, REIPL_METHOD_CCW_VM);
                __cpcmd(buf, NULL, 0, NULL);
                break;
        case REIPL_METHOD_CCW_DIAG:
@@ -691,8 +946,12 @@ static void reipl_run(struct shutdown_trigger *trigger)
        case REIPL_METHOD_FCP_RO_VM:
                __cpcmd("IPL", NULL, 0, NULL);
                break;
+       case REIPL_METHOD_NSS_DIAG:
+               diag308(DIAG308_SET, reipl_block_nss);
+               diag308(DIAG308_IPL, NULL);
+               break;
        case REIPL_METHOD_NSS:
-               sprintf(buf, "IPL %s", reipl_nss_name);
+               get_ipl_string(buf, reipl_block_nss, REIPL_METHOD_NSS);
                __cpcmd(buf, NULL, 0, NULL);
                break;
        case REIPL_METHOD_DEFAULT:
@@ -707,16 +966,36 @@ static void reipl_run(struct shutdown_trigger *trigger)
        disabled_wait((unsigned long) __builtin_return_address(0));
 }
 
-static void __init reipl_probe(void)
+static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
 {
-       void *buffer;
+       ipb->hdr.len = IPL_PARM_BLK_CCW_LEN;
+       ipb->hdr.version = IPL_PARM_BLOCK_VERSION;
+       ipb->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
+       ipb->hdr.pbt = DIAG308_IPL_TYPE_CCW;
+}
 
-       buffer = (void *) get_zeroed_page(GFP_KERNEL);
-       if (!buffer)
-               return;
-       if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK)
-               diag308_set_works = 1;
-       free_page((unsigned long)buffer);
+static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
+{
+       /* LOADPARM */
+       /* check if read scp info worked and set loadparm */
+       if (sclp_ipl_info.is_valid)
+               memcpy(ipb->ipl_info.ccw.load_parm,
+                               &sclp_ipl_info.loadparm, LOADPARM_LEN);
+       else
+               /* read scp info failed: set empty loadparm (EBCDIC blanks) */
+               memset(ipb->ipl_info.ccw.load_parm, 0x40, LOADPARM_LEN);
+       ipb->hdr.flags = DIAG308_FLAGS_LP_VALID;
+
+       /* VM PARM */
+       if (MACHINE_IS_VM && diag308_set_works &&
+           (ipl_block.ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID)) {
+
+               ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
+               ipb->ipl_info.ccw.vm_parm_len =
+                                       ipl_block.ipl_info.ccw.vm_parm_len;
+               memcpy(ipb->ipl_info.ccw.vm_parm,
+                      ipl_block.ipl_info.ccw.vm_parm, DIAG308_VMPARM_SIZE);
+       }
 }
 
 static int __init reipl_nss_init(void)
@@ -725,10 +1004,31 @@ static int __init reipl_nss_init(void)
 
        if (!MACHINE_IS_VM)
                return 0;
+
+       reipl_block_nss = (void *) get_zeroed_page(GFP_KERNEL);
+       if (!reipl_block_nss)
+               return -ENOMEM;
+
+       if (!diag308_set_works)
+               sys_reipl_nss_vmparm_attr.attr.mode = S_IRUGO;
+
        rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group);
        if (rc)
                return rc;
-       strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
+
+       reipl_block_ccw_init(reipl_block_nss);
+       if (ipl_info.type == IPL_TYPE_NSS) {
+               memset(reipl_block_nss->ipl_info.ccw.nss_name,
+                       ' ', NSS_NAME_SIZE);
+               memcpy(reipl_block_nss->ipl_info.ccw.nss_name,
+                       kernel_nss_name, strlen(kernel_nss_name));
+               ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
+               reipl_block_nss->ipl_info.ccw.vm_flags |=
+                       DIAG308_VM_FLAGS_NSS_VALID;
+
+               reipl_block_ccw_fill_parms(reipl_block_nss);
+       }
+
        reipl_capabilities |= IPL_TYPE_NSS;
        return 0;
 }
@@ -740,28 +1040,27 @@ static int __init reipl_ccw_init(void)
        reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
        if (!reipl_block_ccw)
                return -ENOMEM;
-       rc = sysfs_create_group(&reipl_kset->kobj, &reipl_ccw_attr_group);
-       if (rc) {
-               free_page((unsigned long)reipl_block_ccw);
-               return rc;
+
+       if (MACHINE_IS_VM) {
+               if (!diag308_set_works)
+                       sys_reipl_ccw_vmparm_attr.attr.mode = S_IRUGO;
+               rc = sysfs_create_group(&reipl_kset->kobj,
+                                       &reipl_ccw_attr_group_vm);
+       } else {
+               if(!diag308_set_works)
+                       sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
+               rc = sysfs_create_group(&reipl_kset->kobj,
+                                       &reipl_ccw_attr_group_lpar);
        }
-       reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
-       reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
-       reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
-       reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
-       reipl_block_ccw->hdr.flags = DIAG308_FLAGS_LP_VALID;
-       /* check if read scp info worked and set loadparm */
-       if (sclp_ipl_info.is_valid)
-               memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
-                      &sclp_ipl_info.loadparm, LOADPARM_LEN);
-       else
-               /* read scp info failed: set empty loadparm (EBCDIC blanks) */
-               memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
-                      LOADPARM_LEN);
-       if (!MACHINE_IS_VM && !diag308_set_works)
-               sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
-       if (ipl_info.type == IPL_TYPE_CCW)
+       if (rc)
+               return rc;
+
+       reipl_block_ccw_init(reipl_block_ccw);
+       if (ipl_info.type == IPL_TYPE_CCW) {
                reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
+               reipl_block_ccw_fill_parms(reipl_block_ccw);
+       }
+
        reipl_capabilities |= IPL_TYPE_CCW;
        return 0;
 }
@@ -1298,7 +1597,6 @@ static void __init shutdown_actions_init(void)
 
 static int __init s390_ipl_init(void)
 {
-       reipl_probe();
        sclp_get_ipl_info(&sclp_ipl_info);
        shutdown_actions_init();
        shutdown_triggers_init();
@@ -1405,6 +1703,12 @@ void __init setup_ipl(void)
        atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
 }
 
+void __init ipl_update_parameters(void)
+{
+       if (diag308(DIAG308_STORE, &ipl_block) == DIAG308_RC_OK)
+               diag308_set_works = 1;
+}
+
 void __init ipl_save_parameters(void)
 {
        struct cio_iplinfo iplinfo;
index ed04d1372d5d0c536b4a24713bf10d041bc79458..288ad490a6dd7ce931c0622c353d078eaf7a9799 100644 (file)
@@ -41,10 +41,8 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        if (is_prohibited_opcode((kprobe_opcode_t *) p->addr))
                return -EINVAL;
 
-       if ((unsigned long)p->addr & 0x01) {
-               printk("Attempt to register kprobe at an unaligned address\n");
+       if ((unsigned long)p->addr & 0x01)
                return -EINVAL;
-               }
 
        /* Use the get_insn_slot() facility for correctness */
        if (!(p->ainsn.insn = get_insn_slot()))
index 3c77dd36994cec6b71544a345a670d56353017d5..131d7ee8b416d8f6f8bb7f053c3799a3803e97ef 100644 (file)
@@ -52,7 +52,6 @@ void machine_kexec_cleanup(struct kimage *image)
 
 void machine_shutdown(void)
 {
-       printk(KERN_INFO "kexec: machine_shutdown called\n");
 }
 
 void machine_kexec(struct kimage *image)
diff --git a/arch/s390/kernel/mem_detect.c b/arch/s390/kernel/mem_detect.c
new file mode 100644 (file)
index 0000000..18ed7ab
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *    Copyright IBM Corp. 2008
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/ipl.h>
+#include <asm/sclp.h>
+#include <asm/setup.h>
+
+static int memory_fast_detect(struct mem_chunk *chunk)
+{
+       unsigned long val0 = 0;
+       unsigned long val1 = 0xc;
+       int rc = -EOPNOTSUPP;
+
+       if (ipl_flags & IPL_NSS_VALID)
+               return -EOPNOTSUPP;
+       asm volatile(
+               "       diag    %1,%2,0x260\n"
+               "0:     lhi     %0,0\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "+d" (rc), "+d" (val0), "+d" (val1) : : "cc");
+
+       if (rc || val0 != val1)
+               return -EOPNOTSUPP;
+       chunk->size = val0 + 1;
+       return 0;
+}
+
+static inline int tprot(unsigned long addr)
+{
+       int rc = -EFAULT;
+
+       asm volatile(
+               "       tprot   0(%1),0\n"
+               "0:     ipm     %0\n"
+               "       srl     %0,28\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "+d" (rc) : "a" (addr) : "cc");
+       return rc;
+}
+
+#define ADDR2G (1ULL << 31)
+
+static void find_memory_chunks(struct mem_chunk chunk[])
+{
+       unsigned long long memsize, rnmax, rzm;
+       unsigned long addr = 0, size;
+       int i = 0, type;
+
+       rzm = sclp_get_rzm();
+       rnmax = sclp_get_rnmax();
+       memsize = rzm * rnmax;
+       if (!rzm)
+               rzm = 1ULL << 17;
+       if (sizeof(long) == 4) {
+               rzm = min(ADDR2G, rzm);
+               memsize = memsize ? min(ADDR2G, memsize) : ADDR2G;
+       }
+       do {
+               size = 0;
+               type = tprot(addr);
+               do {
+                       size += rzm;
+                       if (memsize && addr + size >= memsize)
+                               break;
+               } while (type == tprot(addr + size));
+               if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) {
+                       chunk[i].addr = addr;
+                       chunk[i].size = size;
+                       chunk[i].type = type;
+                       i++;
+               }
+               addr += size;
+       } while (addr < memsize && i < MEMORY_CHUNKS);
+}
+
+void detect_memory_layout(struct mem_chunk chunk[])
+{
+       unsigned long flags, cr0;
+
+       memset(chunk, 0, MEMORY_CHUNKS * sizeof(struct mem_chunk));
+       if (memory_fast_detect(&chunk[0]) == 0)
+               return;
+       /* Disable IRQs, DAT and low address protection so tprot does the
+        * right thing and we don't get scheduled away with low address
+        * protection disabled.
+        */
+       flags = __raw_local_irq_stnsm(0xf8);
+       __ctl_store(cr0, 0, 0);
+       __ctl_clear_bit(0, 28);
+       find_memory_chunks(chunk);
+       __ctl_load(cr0, 0, 0);
+       __raw_local_irq_ssm(flags);
+}
+EXPORT_SYMBOL(detect_memory_layout);
index 7920861109d2aa074de0ca9ae96f2c99d3c44b24..85defd01d2937c36ccd0a92b18932969dfb8520f 100644 (file)
@@ -75,46 +75,19 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
        return sf->gprs[8];
 }
 
-/*
- * Need to know about CPUs going idle?
- */
-static ATOMIC_NOTIFIER_HEAD(idle_chain);
 DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
 
-int register_idle_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&idle_chain, nb);
-}
-EXPORT_SYMBOL(register_idle_notifier);
-
-int unregister_idle_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&idle_chain, nb);
-}
-EXPORT_SYMBOL(unregister_idle_notifier);
-
 static int s390_idle_enter(void)
 {
        struct s390_idle_data *idle;
-       int nr_calls = 0;
-       void *hcpu;
-       int rc;
 
-       hcpu = (void *)(long)smp_processor_id();
-       rc = __atomic_notifier_call_chain(&idle_chain, S390_CPU_IDLE, hcpu, -1,
-                                         &nr_calls);
-       if (rc == NOTIFY_BAD) {
-               nr_calls--;
-               __atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
-                                            hcpu, nr_calls, NULL);
-               return rc;
-       }
        idle = &__get_cpu_var(s390_idle);
        spin_lock(&idle->lock);
        idle->idle_count++;
        idle->in_idle = 1;
        idle->idle_enter = get_clock();
        spin_unlock(&idle->lock);
+       vtime_stop_cpu_timer();
        return NOTIFY_OK;
 }
 
@@ -122,13 +95,12 @@ void s390_idle_leave(void)
 {
        struct s390_idle_data *idle;
 
+       vtime_start_cpu_timer();
        idle = &__get_cpu_var(s390_idle);
        spin_lock(&idle->lock);
        idle->idle_time += get_clock() - idle->idle_enter;
        idle->in_idle = 0;
        spin_unlock(&idle->lock);
-       atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
-                                  (void *)(long) smp_processor_id());
 }
 
 extern void s390_handle_mcck(void);
index 35827b9bd4d1827f102f79f3e999bbb69c52f5ab..2815bfe348a6f92e67b64e04e0b70cbecde6bc58 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/security.h>
 #include <linux/audit.h>
 #include <linux/signal.h>
+#include <linux/elf.h>
+#include <linux/regset.h>
 
 #include <asm/segment.h>
 #include <asm/page.h>
 #include "compat_ptrace.h"
 #endif
 
+enum s390_regset {
+       REGSET_GENERAL,
+       REGSET_FP,
+};
+
 static void
 FixPerRegisters(struct task_struct *task)
 {
@@ -126,24 +133,10 @@ ptrace_disable(struct task_struct *child)
  * struct user contain pad bytes that should be read as zeroes.
  * Lovely...
  */
-static int
-peek_user(struct task_struct *child, addr_t addr, addr_t data)
+static unsigned long __peek_user(struct task_struct *child, addr_t addr)
 {
        struct user *dummy = NULL;
-       addr_t offset, tmp, mask;
-
-       /*
-        * Stupid gdb peeks/pokes the access registers in 64 bit with
-        * an alignment of 4. Programmers from hell...
-        */
-       mask = __ADDR_MASK;
-#ifdef CONFIG_64BIT
-       if (addr >= (addr_t) &dummy->regs.acrs &&
-           addr < (addr_t) &dummy->regs.orig_gpr2)
-               mask = 3;
-#endif
-       if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
-               return -EIO;
+       addr_t offset, tmp;
 
        if (addr < (addr_t) &dummy->regs.acrs) {
                /*
@@ -197,24 +190,18 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data)
        } else
                tmp = 0;
 
-       return put_user(tmp, (addr_t __user *) data);
+       return tmp;
 }
 
-/*
- * Write a word to the user area of a process at location addr. This
- * operation does have an additional problem compared to peek_user.
- * Stores to the program status word and on the floating point
- * control register needs to get checked for validity.
- */
 static int
-poke_user(struct task_struct *child, addr_t addr, addr_t data)
+peek_user(struct task_struct *child, addr_t addr, addr_t data)
 {
        struct user *dummy = NULL;
-       addr_t offset, mask;
+       addr_t tmp, mask;
 
        /*
         * Stupid gdb peeks/pokes the access registers in 64 bit with
-        * an alignment of 4. Programmers from hell indeed...
+        * an alignment of 4. Programmers from hell...
         */
        mask = __ADDR_MASK;
 #ifdef CONFIG_64BIT
@@ -225,6 +212,21 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
        if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
                return -EIO;
 
+       tmp = __peek_user(child, addr);
+       return put_user(tmp, (addr_t __user *) data);
+}
+
+/*
+ * Write a word to the user area of a process at location addr. This
+ * operation does have an additional problem compared to peek_user.
+ * Stores to the program status word and on the floating point
+ * control register needs to get checked for validity.
+ */
+static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
+{
+       struct user *dummy = NULL;
+       addr_t offset;
+
        if (addr < (addr_t) &dummy->regs.acrs) {
                /*
                 * psw and gprs are stored on the stack
@@ -292,6 +294,28 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
        return 0;
 }
 
+static int
+poke_user(struct task_struct *child, addr_t addr, addr_t data)
+{
+       struct user *dummy = NULL;
+       addr_t mask;
+
+       /*
+        * Stupid gdb peeks/pokes the access registers in 64 bit with
+        * an alignment of 4. Programmers from hell indeed...
+        */
+       mask = __ADDR_MASK;
+#ifdef CONFIG_64BIT
+       if (addr >= (addr_t) &dummy->regs.acrs &&
+           addr < (addr_t) &dummy->regs.orig_gpr2)
+               mask = 3;
+#endif
+       if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
+               return -EIO;
+
+       return __poke_user(child, addr, data);
+}
+
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
        ptrace_area parea; 
@@ -367,18 +391,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 /*
  * Same as peek_user but for a 31 bit program.
  */
-static int
-peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
+static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
 {
        struct user32 *dummy32 = NULL;
        per_struct32 *dummy_per32 = NULL;
        addr_t offset;
        __u32 tmp;
 
-       if (!test_thread_flag(TIF_31BIT) ||
-           (addr & 3) || addr > sizeof(struct user) - 3)
-               return -EIO;
-
        if (addr < (addr_t) &dummy32->regs.acrs) {
                /*
                 * psw and gprs are stored on the stack
@@ -435,25 +454,32 @@ peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
        } else
                tmp = 0;
 
+       return tmp;
+}
+
+static int peek_user_compat(struct task_struct *child,
+                           addr_t addr, addr_t data)
+{
+       __u32 tmp;
+
+       if (!test_thread_flag(TIF_31BIT) ||
+           (addr & 3) || addr > sizeof(struct user) - 3)
+               return -EIO;
+
+       tmp = __peek_user_compat(child, addr);
        return put_user(tmp, (__u32 __user *) data);
 }
 
 /*
  * Same as poke_user but for a 31 bit program.
  */
-static int
-poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
+static int __poke_user_compat(struct task_struct *child,
+                             addr_t addr, addr_t data)
 {
        struct user32 *dummy32 = NULL;
        per_struct32 *dummy_per32 = NULL;
+       __u32 tmp = (__u32) data;
        addr_t offset;
-       __u32 tmp;
-
-       if (!test_thread_flag(TIF_31BIT) ||
-           (addr & 3) || addr > sizeof(struct user32) - 3)
-               return -EIO;
-
-       tmp = (__u32) data;
 
        if (addr < (addr_t) &dummy32->regs.acrs) {
                /*
@@ -528,6 +554,16 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
        return 0;
 }
 
+static int poke_user_compat(struct task_struct *child,
+                           addr_t addr, addr_t data)
+{
+       if (!test_thread_flag(TIF_31BIT) ||
+           (addr & 3) || addr > sizeof(struct user32) - 3)
+               return -EIO;
+
+       return __poke_user_compat(child, addr, data);
+}
+
 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        compat_ulong_t caddr, compat_ulong_t cdata)
 {
@@ -539,11 +575,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
        switch (request) {
        case PTRACE_PEEKUSR:
                /* read the word at location addr in the USER area. */
-               return peek_user_emu31(child, addr, data);
+               return peek_user_compat(child, addr, data);
 
        case PTRACE_POKEUSR:
                /* write the word at location addr in the USER area */
-               return poke_user_emu31(child, addr, data);
+               return poke_user_compat(child, addr, data);
 
        case PTRACE_PEEKUSR_AREA:
        case PTRACE_POKEUSR_AREA:
@@ -555,13 +591,13 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                copied = 0;
                while (copied < parea.len) {
                        if (request == PTRACE_PEEKUSR_AREA)
-                               ret = peek_user_emu31(child, addr, data);
+                               ret = peek_user_compat(child, addr, data);
                        else {
                                __u32 utmp;
                                if (get_user(utmp,
                                             (__u32 __force __user *) data))
                                        return -EFAULT;
-                               ret = poke_user_emu31(child, addr, utmp);
+                               ret = poke_user_compat(child, addr, utmp);
                        }
                        if (ret)
                                return ret;
@@ -610,3 +646,240 @@ syscall_trace(struct pt_regs *regs, int entryexit)
                                    regs->gprs[2], regs->orig_gpr2, regs->gprs[3],
                                    regs->gprs[4], regs->gprs[5]);
 }
+
+/*
+ * user_regset definitions.
+ */
+
+static int s390_regs_get(struct task_struct *target,
+                        const struct user_regset *regset,
+                        unsigned int pos, unsigned int count,
+                        void *kbuf, void __user *ubuf)
+{
+       if (target == current)
+               save_access_regs(target->thread.acrs);
+
+       if (kbuf) {
+               unsigned long *k = kbuf;
+               while (count > 0) {
+                       *k++ = __peek_user(target, pos);
+                       count -= sizeof(*k);
+                       pos += sizeof(*k);
+               }
+       } else {
+               unsigned long __user *u = ubuf;
+               while (count > 0) {
+                       if (__put_user(__peek_user(target, pos), u++))
+                               return -EFAULT;
+                       count -= sizeof(*u);
+                       pos += sizeof(*u);
+               }
+       }
+       return 0;
+}
+
+static int s390_regs_set(struct task_struct *target,
+                        const struct user_regset *regset,
+                        unsigned int pos, unsigned int count,
+                        const void *kbuf, const void __user *ubuf)
+{
+       int rc = 0;
+
+       if (target == current)
+               save_access_regs(target->thread.acrs);
+
+       if (kbuf) {
+               const unsigned long *k = kbuf;
+               while (count > 0 && !rc) {
+                       rc = __poke_user(target, pos, *k++);
+                       count -= sizeof(*k);
+                       pos += sizeof(*k);
+               }
+       } else {
+               const unsigned long  __user *u = ubuf;
+               while (count > 0 && !rc) {
+                       unsigned long word;
+                       rc = __get_user(word, u++);
+                       if (rc)
+                               break;
+                       rc = __poke_user(target, pos, word);
+                       count -= sizeof(*u);
+                       pos += sizeof(*u);
+               }
+       }
+
+       if (rc == 0 && target == current)
+               restore_access_regs(target->thread.acrs);
+
+       return rc;
+}
+
+static int s390_fpregs_get(struct task_struct *target,
+                          const struct user_regset *regset, unsigned int pos,
+                          unsigned int count, void *kbuf, void __user *ubuf)
+{
+       if (target == current)
+               save_fp_regs(&target->thread.fp_regs);
+
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                  &target->thread.fp_regs, 0, -1);
+}
+
+static int s390_fpregs_set(struct task_struct *target,
+                          const struct user_regset *regset, unsigned int pos,
+                          unsigned int count, const void *kbuf,
+                          const void __user *ubuf)
+{
+       int rc = 0;
+
+       if (target == current)
+               save_fp_regs(&target->thread.fp_regs);
+
+       /* If setting FPC, must validate it first. */
+       if (count > 0 && pos < offsetof(s390_fp_regs, fprs)) {
+               u32 fpc[2] = { target->thread.fp_regs.fpc, 0 };
+               rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fpc,
+                                       0, offsetof(s390_fp_regs, fprs));
+               if (rc)
+                       return rc;
+               if ((fpc[0] & ~FPC_VALID_MASK) != 0 || fpc[1] != 0)
+                       return -EINVAL;
+               target->thread.fp_regs.fpc = fpc[0];
+       }
+
+       if (rc == 0 && count > 0)
+               rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                       target->thread.fp_regs.fprs,
+                                       offsetof(s390_fp_regs, fprs), -1);
+
+       if (rc == 0 && target == current)
+               restore_fp_regs(&target->thread.fp_regs);
+
+       return rc;
+}
+
+static const struct user_regset s390_regsets[] = {
+       [REGSET_GENERAL] = {
+               .core_note_type = NT_PRSTATUS,
+               .n = sizeof(s390_regs) / sizeof(long),
+               .size = sizeof(long),
+               .align = sizeof(long),
+               .get = s390_regs_get,
+               .set = s390_regs_set,
+       },
+       [REGSET_FP] = {
+               .core_note_type = NT_PRFPREG,
+               .n = sizeof(s390_fp_regs) / sizeof(long),
+               .size = sizeof(long),
+               .align = sizeof(long),
+               .get = s390_fpregs_get,
+               .set = s390_fpregs_set,
+       },
+};
+
+static const struct user_regset_view user_s390_view = {
+       .name = UTS_MACHINE,
+       .e_machine = EM_S390,
+       .regsets = s390_regsets,
+       .n = ARRAY_SIZE(s390_regsets)
+};
+
+#ifdef CONFIG_COMPAT
+static int s390_compat_regs_get(struct task_struct *target,
+                               const struct user_regset *regset,
+                               unsigned int pos, unsigned int count,
+                               void *kbuf, void __user *ubuf)
+{
+       if (target == current)
+               save_access_regs(target->thread.acrs);
+
+       if (kbuf) {
+               compat_ulong_t *k = kbuf;
+               while (count > 0) {
+                       *k++ = __peek_user_compat(target, pos);
+                       count -= sizeof(*k);
+                       pos += sizeof(*k);
+               }
+       } else {
+               compat_ulong_t __user *u = ubuf;
+               while (count > 0) {
+                       if (__put_user(__peek_user_compat(target, pos), u++))
+                               return -EFAULT;
+                       count -= sizeof(*u);
+                       pos += sizeof(*u);
+               }
+       }
+       return 0;
+}
+
+static int s390_compat_regs_set(struct task_struct *target,
+                               const struct user_regset *regset,
+                               unsigned int pos, unsigned int count,
+                               const void *kbuf, const void __user *ubuf)
+{
+       int rc = 0;
+
+       if (target == current)
+               save_access_regs(target->thread.acrs);
+
+       if (kbuf) {
+               const compat_ulong_t *k = kbuf;
+               while (count > 0 && !rc) {
+                       rc = __poke_user_compat(target, pos, *k++);
+                       count -= sizeof(*k);
+                       pos += sizeof(*k);
+               }
+       } else {
+               const compat_ulong_t  __user *u = ubuf;
+               while (count > 0 && !rc) {
+                       compat_ulong_t word;
+                       rc = __get_user(word, u++);
+                       if (rc)
+                               break;
+                       rc = __poke_user_compat(target, pos, word);
+                       count -= sizeof(*u);
+                       pos += sizeof(*u);
+               }
+       }
+
+       if (rc == 0 && target == current)
+               restore_access_regs(target->thread.acrs);
+
+       return rc;
+}
+
+static const struct user_regset s390_compat_regsets[] = {
+       [REGSET_GENERAL] = {
+               .core_note_type = NT_PRSTATUS,
+               .n = sizeof(s390_compat_regs) / sizeof(compat_long_t),
+               .size = sizeof(compat_long_t),
+               .align = sizeof(compat_long_t),
+               .get = s390_compat_regs_get,
+               .set = s390_compat_regs_set,
+       },
+       [REGSET_FP] = {
+               .core_note_type = NT_PRFPREG,
+               .n = sizeof(s390_fp_regs) / sizeof(compat_long_t),
+               .size = sizeof(compat_long_t),
+               .align = sizeof(compat_long_t),
+               .get = s390_fpregs_get,
+               .set = s390_fpregs_set,
+       },
+};
+
+static const struct user_regset_view user_s390_compat_view = {
+       .name = "s390",
+       .e_machine = EM_S390,
+       .regsets = s390_compat_regsets,
+       .n = ARRAY_SIZE(s390_compat_regsets)
+};
+#endif
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+#ifdef CONFIG_COMPAT
+       if (test_tsk_thread_flag(task, TIF_31BIT))
+               return &user_s390_compat_view;
+#endif
+       return &user_s390_view;
+}
index 2bc70b6e876a4310991e884d5a1f92dde1a78681..b358e18273b07f2e1e31315e77835fd84f880bfc 100644 (file)
@@ -77,7 +77,7 @@ unsigned long machine_flags;
 unsigned long elf_hwcap = 0;
 char elf_platform[ELF_PLATFORM_SIZE];
 
-struct mem_chunk __meminitdata memory_chunk[MEMORY_CHUNKS];
+struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
 volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
 static unsigned long __initdata memory_end;
 
@@ -205,12 +205,6 @@ static void __init conmode_default(void)
                        SET_CONSOLE_SCLP;
 #endif
                }
-        } else if (MACHINE_IS_P390) {
-#if defined(CONFIG_TN3215_CONSOLE)
-               SET_CONSOLE_3215;
-#elif defined(CONFIG_TN3270_CONSOLE)
-               SET_CONSOLE_3270;
-#endif
        } else {
 #if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
                SET_CONSOLE_SCLP;
@@ -221,18 +215,17 @@ static void __init conmode_default(void)
 #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
 static void __init setup_zfcpdump(unsigned int console_devno)
 {
-       static char str[64];
+       static char str[41];
 
        if (ipl_info.type != IPL_TYPE_FCP_DUMP)
                return;
        if (console_devno != -1)
-               sprintf(str, "cio_ignore=all,!0.0.%04x,!0.0.%04x",
+               sprintf(str, " cio_ignore=all,!0.0.%04x,!0.0.%04x",
                        ipl_info.data.fcp.dev_id.devno, console_devno);
        else
-               sprintf(str, "cio_ignore=all,!0.0.%04x",
+               sprintf(str, " cio_ignore=all,!0.0.%04x",
                        ipl_info.data.fcp.dev_id.devno);
-       strcat(COMMAND_LINE, " ");
-       strcat(COMMAND_LINE, str);
+       strcat(boot_command_line, str);
        console_loglevel = 2;
 }
 #else
@@ -289,32 +282,6 @@ static int __init early_parse_mem(char *p)
 }
 early_param("mem", early_parse_mem);
 
-/*
- * "ipldelay=XXX[sm]" sets ipl delay in seconds or minutes
- */
-static int __init early_parse_ipldelay(char *p)
-{
-       unsigned long delay = 0;
-
-       delay = simple_strtoul(p, &p, 0);
-
-       switch (*p) {
-       case 's':
-       case 'S':
-               delay *= 1000000;
-               break;
-       case 'm':
-       case 'M':
-               delay *= 60 * 1000000;
-       }
-
-       /* now wait for the requested amount of time */
-       udelay(delay);
-
-       return 0;
-}
-early_param("ipldelay", early_parse_ipldelay);
-
 #ifdef CONFIG_S390_SWITCH_AMODE
 #ifdef CONFIG_PGSTE
 unsigned int switch_amode = 1;
@@ -804,11 +771,9 @@ setup_arch(char **cmdline_p)
                printk("We are running native (64 bit mode)\n");
 #endif /* CONFIG_64BIT */
 
-       /* Save unparsed command line copy for /proc/cmdline */
-       strlcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-
-       *cmdline_p = COMMAND_LINE;
-       *(*cmdline_p + COMMAND_LINE_SIZE - 1) = '\0';
+       /* Have one command line that is parsed and saved in /proc/cmdline */
+       /* boot_command_line has been already set up in early.c */
+       *cmdline_p = boot_command_line;
 
         ROOT_DEV = Root_RAM0;
 
index 7aec676fefd593fcc7305613a6d1e3e4964cdbb0..7418bebb547fad641cb79a8b209e8d12d8b842c7 100644 (file)
@@ -3,7 +3,7 @@
  *    Time of day based timer functions.
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999, 2008
  *    Author(s): Hartmut Penner (hp@de.ibm.com),
  *               Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
@@ -31,6 +31,7 @@
 #include <linux/notifier.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/bootmem.h>
 #include <asm/uaccess.h>
 #include <asm/delay.h>
 #include <asm/s390_ext.h>
@@ -162,7 +163,7 @@ void init_cpu_timer(void)
        /* Enable clock comparator timer interrupt. */
        __ctl_set_bit(0,11);
 
-       /* Always allow ETR external interrupts, even without an ETR. */
+       /* Always allow the timing alert external interrupt. */
        __ctl_set_bit(0, 4);
 }
 
@@ -170,8 +171,21 @@ static void clock_comparator_interrupt(__u16 code)
 {
 }
 
+static void etr_timing_alert(struct etr_irq_parm *);
+static void stp_timing_alert(struct stp_irq_parm *);
+
+static void timing_alert_interrupt(__u16 code)
+{
+       if (S390_lowcore.ext_params & 0x00c40000)
+               etr_timing_alert((struct etr_irq_parm *)
+                                &S390_lowcore.ext_params);
+       if (S390_lowcore.ext_params & 0x00038000)
+               stp_timing_alert((struct stp_irq_parm *)
+                                &S390_lowcore.ext_params);
+}
+
 static void etr_reset(void);
-static void etr_ext_handler(__u16);
+static void stp_reset(void);
 
 /*
  * Get the TOD clock running.
@@ -181,6 +195,7 @@ static u64 __init reset_tod_clock(void)
        u64 time;
 
        etr_reset();
+       stp_reset();
        if (store_clock(&time) == 0)
                return time;
        /* TOD clock not running. Set the clock to Unix Epoch. */
@@ -231,8 +246,9 @@ void __init time_init(void)
        if (clocksource_register(&clocksource_tod) != 0)
                panic("Could not register TOD clock source");
 
-       /* request the etr external interrupt */
-       if (register_early_external_interrupt(0x1406, etr_ext_handler,
+       /* request the timing alert external interrupt */
+       if (register_early_external_interrupt(0x1406,
+                                             timing_alert_interrupt,
                                              &ext_int_etr_cc) != 0)
                panic("Couldn't request external interrupt 0x1406");
 
@@ -244,11 +260,113 @@ void __init time_init(void)
 #endif
 }
 
+/*
+ * The time is "clock". old is what we think the time is.
+ * Adjust the value by a multiple of jiffies and add the delta to ntp.
+ * "delay" is an approximation how long the synchronization took. If
+ * the time correction is positive, then "delay" is subtracted from
+ * the time difference and only the remaining part is passed to ntp.
+ */
+static unsigned long long adjust_time(unsigned long long old,
+                                     unsigned long long clock,
+                                     unsigned long long delay)
+{
+       unsigned long long delta, ticks;
+       struct timex adjust;
+
+       if (clock > old) {
+               /* It is later than we thought. */
+               delta = ticks = clock - old;
+               delta = ticks = (delta < delay) ? 0 : delta - delay;
+               delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
+               adjust.offset = ticks * (1000000 / HZ);
+       } else {
+               /* It is earlier than we thought. */
+               delta = ticks = old - clock;
+               delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
+               delta = -delta;
+               adjust.offset = -ticks * (1000000 / HZ);
+       }
+       jiffies_timer_cc += delta;
+       if (adjust.offset != 0) {
+               printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n",
+                      adjust.offset);
+               adjust.modes = ADJ_OFFSET_SINGLESHOT;
+               do_adjtimex(&adjust);
+       }
+       return delta;
+}
+
+static DEFINE_PER_CPU(atomic_t, clock_sync_word);
+static unsigned long clock_sync_flags;
+
+#define CLOCK_SYNC_HAS_ETR     0
+#define CLOCK_SYNC_HAS_STP     1
+#define CLOCK_SYNC_ETR         2
+#define CLOCK_SYNC_STP         3
+
+/*
+ * The synchronous get_clock function. It will write the current clock
+ * value to the clock pointer and return 0 if the clock is in sync with
+ * the external time source. If the clock mode is local it will return
+ * -ENOSYS and -EAGAIN if the clock is not in sync with the external
+ * reference.
+ */
+int get_sync_clock(unsigned long long *clock)
+{
+       atomic_t *sw_ptr;
+       unsigned int sw0, sw1;
+
+       sw_ptr = &get_cpu_var(clock_sync_word);
+       sw0 = atomic_read(sw_ptr);
+       *clock = get_clock();
+       sw1 = atomic_read(sw_ptr);
+       put_cpu_var(clock_sync_sync);
+       if (sw0 == sw1 && (sw0 & 0x80000000U))
+               /* Success: time is in sync. */
+               return 0;
+       if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags) &&
+           !test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags))
+               return -ENOSYS;
+       if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags) &&
+           !test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
+               return -EACCES;
+       return -EAGAIN;
+}
+EXPORT_SYMBOL(get_sync_clock);
+
+/*
+ * Make get_sync_clock return -EAGAIN.
+ */
+static void disable_sync_clock(void *dummy)
+{
+       atomic_t *sw_ptr = &__get_cpu_var(clock_sync_word);
+       /*
+        * Clear the in-sync bit 2^31. All get_sync_clock calls will
+        * fail until the sync bit is turned back on. In addition
+        * increase the "sequence" counter to avoid the race of an
+        * etr event and the complete recovery against get_sync_clock.
+        */
+       atomic_clear_mask(0x80000000, sw_ptr);
+       atomic_inc(sw_ptr);
+}
+
+/*
+ * Make get_sync_clock return 0 again.
+ * Needs to be called from a context disabled for preemption.
+ */
+static void enable_sync_clock(void)
+{
+       atomic_t *sw_ptr = &__get_cpu_var(clock_sync_word);
+       atomic_set_mask(0x80000000, sw_ptr);
+}
+
 /*
  * External Time Reference (ETR) code.
  */
 static int etr_port0_online;
 static int etr_port1_online;
+static int etr_steai_available;
 
 static int __init early_parse_etr(char *p)
 {
@@ -273,12 +391,6 @@ enum etr_event {
        ETR_EVENT_UPDATE,
 };
 
-enum etr_flags {
-       ETR_FLAG_ENOSYS,
-       ETR_FLAG_EACCES,
-       ETR_FLAG_STEAI,
-};
-
 /*
  * Valid bit combinations of the eacr register are (x = don't care):
  * e0 e1 dp p0 p1 ea es sl
@@ -305,73 +417,17 @@ enum etr_flags {
  */
 static struct etr_eacr etr_eacr;
 static u64 etr_tolec;                  /* time of last eacr update */
-static unsigned long etr_flags;
 static struct etr_aib etr_port0;
 static int etr_port0_uptodate;
 static struct etr_aib etr_port1;
 static int etr_port1_uptodate;
 static unsigned long etr_events;
 static struct timer_list etr_timer;
-static DEFINE_PER_CPU(atomic_t, etr_sync_word);
 
 static void etr_timeout(unsigned long dummy);
 static void etr_work_fn(struct work_struct *work);
 static DECLARE_WORK(etr_work, etr_work_fn);
 
-/*
- * The etr get_clock function. It will write the current clock value
- * to the clock pointer and return 0 if the clock is in sync with the
- * external time source. If the clock mode is local it will return
- * -ENOSYS and -EAGAIN if the clock is not in sync with the external
- * reference. This function is what ETR is all about..
- */
-int get_sync_clock(unsigned long long *clock)
-{
-       atomic_t *sw_ptr;
-       unsigned int sw0, sw1;
-
-       sw_ptr = &get_cpu_var(etr_sync_word);
-       sw0 = atomic_read(sw_ptr);
-       *clock = get_clock();
-       sw1 = atomic_read(sw_ptr);
-       put_cpu_var(etr_sync_sync);
-       if (sw0 == sw1 && (sw0 & 0x80000000U))
-               /* Success: time is in sync. */
-               return 0;
-       if (test_bit(ETR_FLAG_ENOSYS, &etr_flags))
-               return -ENOSYS;
-       if (test_bit(ETR_FLAG_EACCES, &etr_flags))
-               return -EACCES;
-       return -EAGAIN;
-}
-EXPORT_SYMBOL(get_sync_clock);
-
-/*
- * Make get_sync_clock return -EAGAIN.
- */
-static void etr_disable_sync_clock(void *dummy)
-{
-       atomic_t *sw_ptr = &__get_cpu_var(etr_sync_word);
-       /*
-        * Clear the in-sync bit 2^31. All get_sync_clock calls will
-        * fail until the sync bit is turned back on. In addition
-        * increase the "sequence" counter to avoid the race of an
-        * etr event and the complete recovery against get_sync_clock.
-        */
-       atomic_clear_mask(0x80000000, sw_ptr);
-       atomic_inc(sw_ptr);
-}
-
-/*
- * Make get_sync_clock return 0 again.
- * Needs to be called from a context disabled for preemption.
- */
-static void etr_enable_sync_clock(void)
-{
-       atomic_t *sw_ptr = &__get_cpu_var(etr_sync_word);
-       atomic_set_mask(0x80000000, sw_ptr);
-}
-
 /*
  * Reset ETR attachment.
  */
@@ -381,15 +437,13 @@ static void etr_reset(void)
                .e0 = 0, .e1 = 0, ._pad0 = 4, .dp = 0,
                .p0 = 0, .p1 = 0, ._pad1 = 0, .ea = 0,
                .es = 0, .sl = 0 };
-       if (etr_setr(&etr_eacr) == 0)
+       if (etr_setr(&etr_eacr) == 0) {
                etr_tolec = get_clock();
-       else {
-               set_bit(ETR_FLAG_ENOSYS, &etr_flags);
-               if (etr_port0_online || etr_port1_online) {
-                       printk(KERN_WARNING "Running on non ETR capable "
-                              "machine, only local mode available.\n");
-                       etr_port0_online = etr_port1_online = 0;
-               }
+               set_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags);
+       } else if (etr_port0_online || etr_port1_online) {
+               printk(KERN_WARNING "Running on non ETR capable "
+                      "machine, only local mode available.\n");
+               etr_port0_online = etr_port1_online = 0;
        }
 }
 
@@ -397,14 +451,12 @@ static int __init etr_init(void)
 {
        struct etr_aib aib;
 
-       if (test_bit(ETR_FLAG_ENOSYS, &etr_flags))
+       if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags))
                return 0;
        /* Check if this machine has the steai instruction. */
        if (etr_steai(&aib, ETR_STEAI_STEPPING_PORT) == 0)
-               set_bit(ETR_FLAG_STEAI, &etr_flags);
+               etr_steai_available = 1;
        setup_timer(&etr_timer, etr_timeout, 0UL);
-       if (!etr_port0_online && !etr_port1_online)
-               set_bit(ETR_FLAG_EACCES, &etr_flags);
        if (etr_port0_online) {
                set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
                schedule_work(&etr_work);
@@ -435,7 +487,8 @@ void etr_switch_to_local(void)
 {
        if (!etr_eacr.sl)
                return;
-       etr_disable_sync_clock(NULL);
+       if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
+               disable_sync_clock(NULL);
        set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events);
        schedule_work(&etr_work);
 }
@@ -450,23 +503,21 @@ void etr_sync_check(void)
 {
        if (!etr_eacr.es)
                return;
-       etr_disable_sync_clock(NULL);
+       if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
+               disable_sync_clock(NULL);
        set_bit(ETR_EVENT_SYNC_CHECK, &etr_events);
        schedule_work(&etr_work);
 }
 
 /*
- * ETR external interrupt. There are two causes:
+ * ETR timing alert. There are two causes:
  * 1) port state change, check the usability of the port
  * 2) port alert, one of the ETR-data-validity bits (v1-v2 bits of the
  *    sldr-status word) or ETR-data word 1 (edf1) or ETR-data word 3 (edf3)
  *    or ETR-data word 4 (edf4) has changed.
  */
-static void etr_ext_handler(__u16 code)
+static void etr_timing_alert(struct etr_irq_parm *intparm)
 {
-       struct etr_interruption_parameter *intparm =
-               (struct etr_interruption_parameter *) &S390_lowcore.ext_params;
-
        if (intparm->pc0)
                /* ETR port 0 state change. */
                set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
@@ -591,58 +642,23 @@ static int etr_aib_follows(struct etr_aib *a1, struct etr_aib *a2, int p)
        return 1;
 }
 
-/*
- * The time is "clock". old is what we think the time is.
- * Adjust the value by a multiple of jiffies and add the delta to ntp.
- * "delay" is an approximation how long the synchronization took. If
- * the time correction is positive, then "delay" is subtracted from
- * the time difference and only the remaining part is passed to ntp.
- */
-static unsigned long long etr_adjust_time(unsigned long long old,
-                                         unsigned long long clock,
-                                         unsigned long long delay)
-{
-       unsigned long long delta, ticks;
-       struct timex adjust;
-
-       if (clock > old) {
-               /* It is later than we thought. */
-               delta = ticks = clock - old;
-               delta = ticks = (delta < delay) ? 0 : delta - delay;
-               delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
-               adjust.offset = ticks * (1000000 / HZ);
-       } else {
-               /* It is earlier than we thought. */
-               delta = ticks = old - clock;
-               delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
-               delta = -delta;
-               adjust.offset = -ticks * (1000000 / HZ);
-       }
-       jiffies_timer_cc += delta;
-       if (adjust.offset != 0) {
-               printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n",
-                      adjust.offset);
-               adjust.modes = ADJ_OFFSET_SINGLESHOT;
-               do_adjtimex(&adjust);
-       }
-       return delta;
-}
-
-static struct {
+struct clock_sync_data {
        int in_sync;
        unsigned long long fixup_cc;
-} etr_sync;
+};
 
-static void etr_sync_cpu_start(void *dummy)
+static void clock_sync_cpu_start(void *dummy)
 {
-       etr_enable_sync_clock();
+       struct clock_sync_data *sync = dummy;
+
+       enable_sync_clock();
        /*
         * This looks like a busy wait loop but it isn't. etr_sync_cpus
         * is called on all other cpus while the TOD clocks is stopped.
         * __udelay will stop the cpu on an enabled wait psw until the
         * TOD is running again.
         */
-       while (etr_sync.in_sync == 0) {
+       while (sync->in_sync == 0) {
                __udelay(1);
                /*
                 * A different cpu changes *in_sync. Therefore use
@@ -650,17 +666,17 @@ static void etr_sync_cpu_start(void *dummy)
                 */
                barrier();
        }
-       if (etr_sync.in_sync != 1)
+       if (sync->in_sync != 1)
                /* Didn't work. Clear per-cpu in sync bit again. */
-               etr_disable_sync_clock(NULL);
+               disable_sync_clock(NULL);
        /*
         * This round of TOD syncing is done. Set the clock comparator
         * to the next tick and let the processor continue.
         */
-       fixup_clock_comparator(etr_sync.fixup_cc);
+       fixup_clock_comparator(sync->fixup_cc);
 }
 
-static void etr_sync_cpu_end(void *dummy)
+static void clock_sync_cpu_end(void *dummy)
 {
 }
 
@@ -672,6 +688,7 @@ static void etr_sync_cpu_end(void *dummy)
 static int etr_sync_clock(struct etr_aib *aib, int port)
 {
        struct etr_aib *sync_port;
+       struct clock_sync_data etr_sync;
        unsigned long long clock, old_clock, delay, delta;
        int follows;
        int rc;
@@ -690,9 +707,9 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
         */
        memset(&etr_sync, 0, sizeof(etr_sync));
        preempt_disable();
-       smp_call_function(etr_sync_cpu_start, NULL, 0, 0);
+       smp_call_function(clock_sync_cpu_start, &etr_sync, 0, 0);
        local_irq_disable();
-       etr_enable_sync_clock();
+       enable_sync_clock();
 
        /* Set clock to next OTE. */
        __ctl_set_bit(14, 21);
@@ -707,13 +724,13 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
                /* Adjust Linux timing variables. */
                delay = (unsigned long long)
                        (aib->edf2.etv - sync_port->edf2.etv) << 32;
-               delta = etr_adjust_time(old_clock, clock, delay);
+               delta = adjust_time(old_clock, clock, delay);
                etr_sync.fixup_cc = delta;
                fixup_clock_comparator(delta);
                /* Verify that the clock is properly set. */
                if (!etr_aib_follows(sync_port, aib, port)) {
                        /* Didn't work. */
-                       etr_disable_sync_clock(NULL);
+                       disable_sync_clock(NULL);
                        etr_sync.in_sync = -EAGAIN;
                        rc = -EAGAIN;
                } else {
@@ -724,12 +741,12 @@ static int etr_sync_clock(struct etr_aib *aib, int port)
                /* Could not set the clock ?!? */
                __ctl_clear_bit(0, 29);
                __ctl_clear_bit(14, 21);
-               etr_disable_sync_clock(NULL);
+               disable_sync_clock(NULL);
                etr_sync.in_sync = -EAGAIN;
                rc = -EAGAIN;
        }
        local_irq_enable();
-       smp_call_function(etr_sync_cpu_end,NULL,0,0);
+       smp_call_function(clock_sync_cpu_end, NULL, 0, 0);
        preempt_enable();
        return rc;
 }
@@ -832,7 +849,7 @@ static struct etr_eacr etr_handle_update(struct etr_aib *aib,
         * Do not try to get the alternate port aib if the clock
         * is not in sync yet.
         */
-       if (!eacr.es)
+       if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags) && !eacr.es)
                return eacr;
 
        /*
@@ -840,7 +857,7 @@ static struct etr_eacr etr_handle_update(struct etr_aib *aib,
         * the other port immediately. If only stetr is available the
         * data-port bit toggle has to be used.
         */
-       if (test_bit(ETR_FLAG_STEAI, &etr_flags)) {
+       if (etr_steai_available) {
                if (eacr.p0 && !etr_port0_uptodate) {
                        etr_steai_cv(&etr_port0, ETR_STEAI_PORT_0);
                        etr_port0_uptodate = 1;
@@ -909,10 +926,10 @@ static void etr_work_fn(struct work_struct *work)
        if (!eacr.ea) {
                /* Both ports offline. Reset everything. */
                eacr.dp = eacr.es = eacr.sl = 0;
-               on_each_cpu(etr_disable_sync_clock, NULL, 0, 1);
+               on_each_cpu(disable_sync_clock, NULL, 0, 1);
                del_timer_sync(&etr_timer);
                etr_update_eacr(eacr);
-               set_bit(ETR_FLAG_EACCES, &etr_flags);
+               clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
                return;
        }
 
@@ -953,7 +970,6 @@ static void etr_work_fn(struct work_struct *work)
                        eacr.e1 = 1;
                sync_port = (etr_port0_uptodate &&
                             etr_port_valid(&etr_port0, 0)) ? 0 : -1;
-               clear_bit(ETR_FLAG_EACCES, &etr_flags);
        } else if (eacr.p1 && aib.esw.psc1 == etr_lpsc_pps_mode) {
                eacr.sl = 0;
                eacr.e0 = 0;
@@ -962,7 +978,6 @@ static void etr_work_fn(struct work_struct *work)
                        eacr.es = 0;
                sync_port = (etr_port1_uptodate &&
                             etr_port_valid(&etr_port1, 1)) ? 1 : -1;
-               clear_bit(ETR_FLAG_EACCES, &etr_flags);
        } else if (eacr.p0 && aib.esw.psc0 == etr_lpsc_operational_step) {
                eacr.sl = 1;
                eacr.e0 = 1;
@@ -976,7 +991,6 @@ static void etr_work_fn(struct work_struct *work)
                        eacr.e1 = 1;
                sync_port = (etr_port0_uptodate &&
                             etr_port_valid(&etr_port0, 0)) ? 0 : -1;
-               clear_bit(ETR_FLAG_EACCES, &etr_flags);
        } else if (eacr.p1 && aib.esw.psc1 == etr_lpsc_operational_step) {
                eacr.sl = 1;
                eacr.e0 = 0;
@@ -985,19 +999,22 @@ static void etr_work_fn(struct work_struct *work)
                        eacr.es = 0;
                sync_port = (etr_port1_uptodate &&
                             etr_port_valid(&etr_port1, 1)) ? 1 : -1;
-               clear_bit(ETR_FLAG_EACCES, &etr_flags);
        } else {
                /* Both ports not usable. */
                eacr.es = eacr.sl = 0;
                sync_port = -1;
-               set_bit(ETR_FLAG_EACCES, &etr_flags);
+               clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
        }
 
+       if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
+               eacr.es = 0;
+
        /*
         * If the clock is in sync just update the eacr and return.
         * If there is no valid sync port wait for a port update.
         */
-       if (eacr.es || sync_port < 0) {
+       if (test_bit(CLOCK_SYNC_STP, &clock_sync_flags) ||
+           eacr.es || sync_port < 0) {
                etr_update_eacr(eacr);
                etr_set_tolec_timeout(now);
                return;
@@ -1018,11 +1035,13 @@ static void etr_work_fn(struct work_struct *work)
         * and set up a timer to try again after 0.5 seconds
         */
        etr_update_eacr(eacr);
+       set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
        if (now < etr_tolec + (1600000 << 12) ||
            etr_sync_clock(&aib, sync_port) != 0) {
                /* Sync failed. Try again in 1/2 second. */
                eacr.es = 0;
                etr_update_eacr(eacr);
+               clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
                etr_set_sync_timeout();
        } else
                etr_set_tolec_timeout(now);
@@ -1097,8 +1116,8 @@ static ssize_t etr_online_store(struct sys_device *dev,
        value = simple_strtoul(buf, NULL, 0);
        if (value != 0 && value != 1)
                return -EINVAL;
-       if (test_bit(ETR_FLAG_ENOSYS, &etr_flags))
-               return -ENOSYS;
+       if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags))
+               return -EOPNOTSUPP;
        if (dev == &etr_port0_dev) {
                if (etr_port0_online == value)
                        return count;   /* Nothing to do. */
@@ -1292,3 +1311,318 @@ out:
 }
 
 device_initcall(etr_init_sysfs);
+
+/*
+ * Server Time Protocol (STP) code.
+ */
+static int stp_online;
+static struct stp_sstpi stp_info;
+static void *stp_page;
+
+static void stp_work_fn(struct work_struct *work);
+static DECLARE_WORK(stp_work, stp_work_fn);
+
+static int __init early_parse_stp(char *p)
+{
+       if (strncmp(p, "off", 3) == 0)
+               stp_online = 0;
+       else if (strncmp(p, "on", 2) == 0)
+               stp_online = 1;
+       return 0;
+}
+early_param("stp", early_parse_stp);
+
+/*
+ * Reset STP attachment.
+ */
+static void stp_reset(void)
+{
+       int rc;
+
+       stp_page = alloc_bootmem_pages(PAGE_SIZE);
+       rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
+       if (rc == 1)
+               set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags);
+       else if (stp_online) {
+               printk(KERN_WARNING "Running on non STP capable machine.\n");
+               free_bootmem((unsigned long) stp_page, PAGE_SIZE);
+               stp_page = NULL;
+               stp_online = 0;
+       }
+}
+
+static int __init stp_init(void)
+{
+       if (test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags) && stp_online)
+               schedule_work(&stp_work);
+       return 0;
+}
+
+arch_initcall(stp_init);
+
+/*
+ * STP timing alert. There are three causes:
+ * 1) timing status change
+ * 2) link availability change
+ * 3) time control parameter change
+ * In all three cases we are only interested in the clock source state.
+ * If a STP clock source is now available use it.
+ */
+static void stp_timing_alert(struct stp_irq_parm *intparm)
+{
+       if (intparm->tsc || intparm->lac || intparm->tcpc)
+               schedule_work(&stp_work);
+}
+
+/*
+ * STP sync check machine check. This is called when the timing state
+ * changes from the synchronized state to the unsynchronized state.
+ * After a STP sync check the clock is not in sync. The machine check
+ * is broadcasted to all cpus at the same time.
+ */
+void stp_sync_check(void)
+{
+       if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
+               return;
+       disable_sync_clock(NULL);
+       schedule_work(&stp_work);
+}
+
+/*
+ * STP island condition machine check. This is called when an attached
+ * server  attempts to communicate over an STP link and the servers
+ * have matching CTN ids and have a valid stratum-1 configuration
+ * but the configurations do not match.
+ */
+void stp_island_check(void)
+{
+       if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
+               return;
+       disable_sync_clock(NULL);
+       schedule_work(&stp_work);
+}
+
+/*
+ * STP tasklet. Check for the STP state and take over the clock
+ * synchronization if the STP clock source is usable.
+ */
+static void stp_work_fn(struct work_struct *work)
+{
+       struct clock_sync_data stp_sync;
+       unsigned long long old_clock, delta;
+       int rc;
+
+       if (!stp_online) {
+               chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
+               return;
+       }
+
+       rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0xb0e0);
+       if (rc)
+               return;
+
+       rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi));
+       if (rc || stp_info.c == 0)
+               return;
+
+       /*
+        * Catch all other cpus and make them wait until we have
+        * successfully synced the clock. smp_call_function will
+        * return after all other cpus are in clock_sync_cpu_start.
+        */
+       memset(&stp_sync, 0, sizeof(stp_sync));
+       preempt_disable();
+       smp_call_function(clock_sync_cpu_start, &stp_sync, 0, 0);
+       local_irq_disable();
+       enable_sync_clock();
+
+       set_bit(CLOCK_SYNC_STP, &clock_sync_flags);
+       if (test_and_clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
+               schedule_work(&etr_work);
+
+       rc = 0;
+       if (stp_info.todoff[0] || stp_info.todoff[1] ||
+           stp_info.todoff[2] || stp_info.todoff[3] ||
+           stp_info.tmd != 2) {
+               old_clock = get_clock();
+               rc = chsc_sstpc(stp_page, STP_OP_SYNC, 0);
+               if (rc == 0) {
+                       delta = adjust_time(old_clock, get_clock(), 0);
+                       fixup_clock_comparator(delta);
+                       rc = chsc_sstpi(stp_page, &stp_info,
+                                       sizeof(struct stp_sstpi));
+                       if (rc == 0 && stp_info.tmd != 2)
+                               rc = -EAGAIN;
+               }
+       }
+       if (rc) {
+               disable_sync_clock(NULL);
+               stp_sync.in_sync = -EAGAIN;
+               clear_bit(CLOCK_SYNC_STP, &clock_sync_flags);
+               if (etr_port0_online || etr_port1_online)
+                       schedule_work(&etr_work);
+       } else
+               stp_sync.in_sync = 1;
+
+       local_irq_enable();
+       smp_call_function(clock_sync_cpu_end, NULL, 0, 0);
+       preempt_enable();
+}
+
+/*
+ * STP class sysfs interface functions
+ */
+static struct sysdev_class stp_sysclass = {
+       .name   = "stp",
+};
+
+static ssize_t stp_ctn_id_show(struct sysdev_class *class, char *buf)
+{
+       if (!stp_online)
+               return -ENODATA;
+       return sprintf(buf, "%016llx\n",
+                      *(unsigned long long *) stp_info.ctnid);
+}
+
+static SYSDEV_CLASS_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL);
+
+static ssize_t stp_ctn_type_show(struct sysdev_class *class, char *buf)
+{
+       if (!stp_online)
+               return -ENODATA;
+       return sprintf(buf, "%i\n", stp_info.ctn);
+}
+
+static SYSDEV_CLASS_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL);
+
+static ssize_t stp_dst_offset_show(struct sysdev_class *class, char *buf)
+{
+       if (!stp_online || !(stp_info.vbits & 0x2000))
+               return -ENODATA;
+       return sprintf(buf, "%i\n", (int)(s16) stp_info.dsto);
+}
+
+static SYSDEV_CLASS_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL);
+
+static ssize_t stp_leap_seconds_show(struct sysdev_class *class, char *buf)
+{
+       if (!stp_online || !(stp_info.vbits & 0x8000))
+               return -ENODATA;
+       return sprintf(buf, "%i\n", (int)(s16) stp_info.leaps);
+}
+
+static SYSDEV_CLASS_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL);
+
+static ssize_t stp_stratum_show(struct sysdev_class *class, char *buf)
+{
+       if (!stp_online)
+               return -ENODATA;
+       return sprintf(buf, "%i\n", (int)(s16) stp_info.stratum);
+}
+
+static SYSDEV_CLASS_ATTR(stratum, 0400, stp_stratum_show, NULL);
+
+static ssize_t stp_time_offset_show(struct sysdev_class *class, char *buf)
+{
+       if (!stp_online || !(stp_info.vbits & 0x0800))
+               return -ENODATA;
+       return sprintf(buf, "%i\n", (int) stp_info.tto);
+}
+
+static SYSDEV_CLASS_ATTR(time_offset, 0400, stp_time_offset_show, NULL);
+
+static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, char *buf)
+{
+       if (!stp_online || !(stp_info.vbits & 0x4000))
+               return -ENODATA;
+       return sprintf(buf, "%i\n", (int)(s16) stp_info.tzo);
+}
+
+static SYSDEV_CLASS_ATTR(time_zone_offset, 0400,
+                        stp_time_zone_offset_show, NULL);
+
+static ssize_t stp_timing_mode_show(struct sysdev_class *class, char *buf)
+{
+       if (!stp_online)
+               return -ENODATA;
+       return sprintf(buf, "%i\n", stp_info.tmd);
+}
+
+static SYSDEV_CLASS_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL);
+
+static ssize_t stp_timing_state_show(struct sysdev_class *class, char *buf)
+{
+       if (!stp_online)
+               return -ENODATA;
+       return sprintf(buf, "%i\n", stp_info.tst);
+}
+
+static SYSDEV_CLASS_ATTR(timing_state, 0400, stp_timing_state_show, NULL);
+
+static ssize_t stp_online_show(struct sysdev_class *class, char *buf)
+{
+       return sprintf(buf, "%i\n", stp_online);
+}
+
+static ssize_t stp_online_store(struct sysdev_class *class,
+                               const char *buf, size_t count)
+{
+       unsigned int value;
+
+       value = simple_strtoul(buf, NULL, 0);
+       if (value != 0 && value != 1)
+               return -EINVAL;
+       if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags))
+               return -EOPNOTSUPP;
+       stp_online = value;
+       schedule_work(&stp_work);
+       return count;
+}
+
+/*
+ * Can't use SYSDEV_CLASS_ATTR because the attribute should be named
+ * stp/online but attr_online already exists in this file ..
+ */
+static struct sysdev_class_attribute attr_stp_online = {
+       .attr = { .name = "online", .mode = 0600 },
+       .show   = stp_online_show,
+       .store  = stp_online_store,
+};
+
+static struct sysdev_class_attribute *stp_attributes[] = {
+       &attr_ctn_id,
+       &attr_ctn_type,
+       &attr_dst_offset,
+       &attr_leap_seconds,
+       &attr_stp_online,
+       &attr_stratum,
+       &attr_time_offset,
+       &attr_time_zone_offset,
+       &attr_timing_mode,
+       &attr_timing_state,
+       NULL
+};
+
+static int __init stp_init_sysfs(void)
+{
+       struct sysdev_class_attribute **attr;
+       int rc;
+
+       rc = sysdev_class_register(&stp_sysclass);
+       if (rc)
+               goto out;
+       for (attr = stp_attributes; *attr; attr++) {
+               rc = sysdev_class_create_file(&stp_sysclass, *attr);
+               if (rc)
+                       goto out_unreg;
+       }
+       return 0;
+out_unreg:
+       for (; attr >= stp_attributes; attr--)
+               sysdev_class_remove_file(&stp_sysclass, *attr);
+       sysdev_class_unregister(&stp_sysclass);
+out:
+       return rc;
+}
+
+device_initcall(stp_init_sysfs);
index 661a07217057a37b8d08b7ad85c8d4a2508a2bd0..212d618b00952a17152e9985b8a3d27a3ac657cd 100644 (file)
@@ -313,8 +313,6 @@ void __init s390_init_cpu_topology(void)
                machine_has_topology_irq = 1;
 
        tl_info = alloc_bootmem_pages(PAGE_SIZE);
-       if (!tl_info)
-               goto error;
        info = tl_info;
        stsi(info, 15, 1, 2);
 
index ca90ee3f930edc0ffc364d8a094826df731b3415..0fa5dc5d68e1dc2973459d60a71c491f59c6b631 100644 (file)
@@ -136,7 +136,7 @@ static inline void set_vtimer(__u64 expires)
 }
 #endif
 
-static void start_cpu_timer(void)
+void vtime_start_cpu_timer(void)
 {
        struct vtimer_queue *vt_list;
 
@@ -150,7 +150,7 @@ static void start_cpu_timer(void)
                set_vtimer(vt_list->idle);
 }
 
-static void stop_cpu_timer(void)
+void vtime_stop_cpu_timer(void)
 {
        struct vtimer_queue *vt_list;
 
@@ -318,8 +318,7 @@ static void internal_add_vtimer(struct vtimer_list *timer)
        vt_list = &per_cpu(virt_cpu_timer, timer->cpu);
        spin_lock_irqsave(&vt_list->lock, flags);
 
-       if (timer->cpu != smp_processor_id())
-               printk("internal_add_vtimer: BUG, running on wrong CPU");
+       BUG_ON(timer->cpu != smp_processor_id());
 
        /* if list is empty we only have to set the timer */
        if (list_empty(&vt_list->list)) {
@@ -353,25 +352,12 @@ static void internal_add_vtimer(struct vtimer_list *timer)
        put_cpu();
 }
 
-static inline int prepare_vtimer(struct vtimer_list *timer)
+static inline void prepare_vtimer(struct vtimer_list *timer)
 {
-       if (!timer->function) {
-               printk("add_virt_timer: uninitialized timer\n");
-               return -EINVAL;
-       }
-
-       if (!timer->expires || timer->expires > VTIMER_MAX_SLICE) {
-               printk("add_virt_timer: invalid timer expire value!\n");
-               return -EINVAL;
-       }
-
-       if (vtimer_pending(timer)) {
-               printk("add_virt_timer: timer pending\n");
-               return -EBUSY;
-       }
-
+       BUG_ON(!timer->function);
+       BUG_ON(!timer->expires || timer->expires > VTIMER_MAX_SLICE);
+       BUG_ON(vtimer_pending(timer));
        timer->cpu = get_cpu();
-       return 0;
 }
 
 /*
@@ -382,10 +368,7 @@ void add_virt_timer(void *new)
        struct vtimer_list *timer;
 
        timer = (struct vtimer_list *)new;
-
-       if (prepare_vtimer(timer) < 0)
-               return;
-
+       prepare_vtimer(timer);
        timer->interval = 0;
        internal_add_vtimer(timer);
 }
@@ -399,10 +382,7 @@ void add_virt_timer_periodic(void *new)
        struct vtimer_list *timer;
 
        timer = (struct vtimer_list *)new;
-
-       if (prepare_vtimer(timer) < 0)
-               return;
-
+       prepare_vtimer(timer);
        timer->interval = timer->expires;
        internal_add_vtimer(timer);
 }
@@ -423,15 +403,8 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
        unsigned long flags;
        int cpu;
 
-       if (!timer->function) {
-               printk("mod_virt_timer: uninitialized timer\n");
-               return  -EINVAL;
-       }
-
-       if (!expires || expires > VTIMER_MAX_SLICE) {
-               printk("mod_virt_timer: invalid expire range\n");
-               return -EINVAL;
-       }
+       BUG_ON(!timer->function);
+       BUG_ON(!expires || expires > VTIMER_MAX_SLICE);
 
        /*
         * This is a common optimization triggered by the
@@ -444,6 +417,9 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
        cpu = get_cpu();
        vt_list = &per_cpu(virt_cpu_timer, cpu);
 
+       /* check if we run on the right CPU */
+       BUG_ON(timer->cpu != cpu);
+
        /* disable interrupts before test if timer is pending */
        spin_lock_irqsave(&vt_list->lock, flags);
 
@@ -458,14 +434,6 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
                return 0;
        }
 
-       /* check if we run on the right CPU */
-       if (timer->cpu != cpu) {
-               printk("mod_virt_timer: running on wrong CPU, check your code\n");
-               spin_unlock_irqrestore(&vt_list->lock, flags);
-               put_cpu();
-               return -EINVAL;
-       }
-
        list_del_init(&timer->entry);
        timer->expires = expires;
 
@@ -536,24 +504,6 @@ void init_cpu_vtimer(void)
 
 }
 
-static int vtimer_idle_notify(struct notifier_block *self,
-                             unsigned long action, void *hcpu)
-{
-       switch (action) {
-       case S390_CPU_IDLE:
-               stop_cpu_timer();
-               break;
-       case S390_CPU_NOT_IDLE:
-               start_cpu_timer();
-               break;
-       }
-       return NOTIFY_OK;
-}
-
-static struct notifier_block vtimer_idle_nb = {
-       .notifier_call = vtimer_idle_notify,
-};
-
 void __init vtime_init(void)
 {
        /* request the cpu timer external interrupt */
@@ -561,9 +511,6 @@ void __init vtime_init(void)
                                              &ext_int_info_timer) != 0)
                panic("Couldn't request external interrupt 0x1005");
 
-       if (register_idle_notifier(&vtimer_idle_nb))
-               panic("Couldn't register idle notifier");
-
        /* Enable cpu timer interrupts on the boot cpu. */
        init_cpu_vtimer();
 }
index 05598649b3260f8689845ea2815914ffdd08e902..388cc742005544b05747d32a485e88c5c37cf5a6 100644 (file)
@@ -202,3 +202,22 @@ void free_initrd_mem(unsigned long start, unsigned long end)
         }
 }
 #endif
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+int arch_add_memory(int nid, u64 start, u64 size)
+{
+       struct pglist_data *pgdat;
+       struct zone *zone;
+       int rc;
+
+       pgdat = NODE_DATA(nid);
+       zone = pgdat->node_zones + ZONE_NORMAL;
+       rc = vmem_add_mapping(start, size);
+       if (rc)
+               return rc;
+       rc = __add_pages(zone, PFN_DOWN(start), PFN_DOWN(size));
+       if (rc)
+               vmem_remove_mapping(start, size);
+       return rc;
+}
+#endif /* CONFIG_MEMORY_HOTPLUG */
index dbeab15e7bb7c160db7dda887a4c9d14982f742c..ca40397017b98007a1504fb5761624bda030aeab 100644 (file)
@@ -77,7 +77,6 @@ include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
 KERNEL_DEFINES = $(strip -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \
                         -Dmktime=kernel_mktime $(ARCH_KERNEL_DEFINES))
 KBUILD_CFLAGS += $(KERNEL_DEFINES)
-KBUILD_CFLAGS += $(call cc-option,-fno-unit-at-a-time,)
 
 PHONY += linux
 
index 561e373bd8500f1f07ed4cc52b203dc903585f70..302cbe504543c04ea709f030b74425fd6cb859e2 100644 (file)
@@ -32,4 +32,11 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2)
 # an unresolved reference.
 cflags-y += -ffreestanding
 
+# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
+# a lot more stack due to the lack of sharing of stacklots.  Also, gcc
+# 4.3.0 needs -funit-at-a-time for extern inline functions.
+KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \
+                       echo $(call cc-option,-fno-unit-at-a-time); \
+                       else echo $(call cc-option,-funit-at-a-time); fi ;)
+
 KBUILD_CFLAGS += $(cflags-y)
index 8ed362f93582e9723aaacde7325553f9de435383..a9cd7e77a7abcf01f1bdef701d2beda93d0aea93 100644 (file)
@@ -21,3 +21,6 @@ HEADER_ARCH := x86
 
 LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
 LINK-y += -m64
+
+# Do unit-at-a-time unconditionally on x86_64, following the host
+KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
index e0edaaa6920af63832979a04d4f525acafe64e8a..bf07b6f50fa178268f9d81388a615a7a8abff32b 100644 (file)
@@ -966,8 +966,8 @@ config NUMA_EMU
          number of nodes. This is only useful for debugging.
 
 config NODES_SHIFT
-       int "Max num nodes shift(1-15)"
-       range 1 15  if X86_64
+       int "Max num nodes shift(1-9)"
+       range 1 9  if X86_64
        default "6" if X86_64
        default "4" if X86_NUMAQ
        default "3"
index 4ea38a39aed4e254f84606b65c5421a5bbe1045b..08f4fd7314696ad6c2e78b5ca32db4a9a1c61be3 100644 (file)
@@ -1,2 +1,3 @@
 vsyscall.lds
 vsyscall_32.lds
+vmlinux.lds
index f9b77fb37e5b7ccb9ca4e07f74296fe00f572daa..3355973b12ac6f8ca11ea0f5486a6643373d8042 100644 (file)
@@ -5,6 +5,7 @@
 #include <asm/msr-index.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/processor-flags.h>
 
        .code16
        .section ".header", "a"
@@ -24,6 +25,11 @@ pmode_gdt:   .quad   0
 realmode_flags:        .long   0
 real_magic:    .long   0
 trampoline_segment:    .word 0
+_pad1:         .byte   0
+wakeup_jmp:    .byte   0xea    /* ljmpw */
+wakeup_jmp_off:        .word   3f
+wakeup_jmp_seg:        .word   0
+wakeup_gdt:    .quad   0, 0, 0
 signature:     .long   0x51ee1111
 
        .text
@@ -34,11 +40,34 @@ _start:
        cli
        cld
 
+       /* Apparently some dimwit BIOS programmers don't know how to
+          program a PM to RM transition, and we might end up here with
+          junk in the data segment descriptor registers.  The only way
+          to repair that is to go into PM and fix it ourselves... */
+       movw    $16, %cx
+       lgdtl   %cs:wakeup_gdt
+       movl    %cr0, %eax
+       orb     $X86_CR0_PE, %al
+       movl    %eax, %cr0
+       jmp     1f
+1:     ljmpw   $8, $2f
+2:
+       movw    %cx, %ds
+       movw    %cx, %es
+       movw    %cx, %ss
+       movw    %cx, %fs
+       movw    %cx, %gs
+
+       andb    $~X86_CR0_PE, %al
+       movl    %eax, %cr0
+       jmp     wakeup_jmp
+3:
        /* Set up segments */
        movw    %cs, %ax
        movw    %ax, %ds
        movw    %ax, %es
        movw    %ax, %ss
+       lidtl   wakeup_idt
 
        movl    $wakeup_stack_end, %esp
 
@@ -98,7 +127,14 @@ bogus_real_magic:
        jmp     1b
 
        .data
-       .balign 4
+       .balign 8
+
+       /* This is the standard real-mode IDT */
+wakeup_idt:
+       .word   0xffff          /* limit */
+       .long   0               /* address */
+       .word   0
+
        .globl  HEAP, heap_end
 HEAP:
        .long   wakeup_heap
index ef8166fe8020ec0aaf7de3b1f57f3662f6c20527..69d38d0b2b6436cd83886a6200405eef603c6eda 100644 (file)
@@ -24,6 +24,11 @@ struct wakeup_header {
        u32 realmode_flags;
        u32 real_magic;
        u16 trampoline_segment; /* segment with trampoline code, 64-bit only */
+       u8  _pad1;
+       u8  wakeup_jmp;
+       u16 wakeup_jmp_off;
+       u16 wakeup_jmp_seg;
+       u64 wakeup_gdt[3];
        u32 signature;          /* To check we have correct structure */
 } __attribute__((__packed__));
 
index afc25ee9964b6628ba4808e13b48c192caeec87b..36af01f029eddbfe7b2bdc05a0f2b59ab5c3666a 100644 (file)
@@ -50,6 +50,20 @@ int acpi_save_state_mem(void)
 
        header->video_mode = saved_video_mode;
 
+       header->wakeup_jmp_seg = acpi_wakeup_address >> 4;
+       /* GDT[0]: GDT self-pointer */
+       header->wakeup_gdt[0] =
+               (u64)(sizeof(header->wakeup_gdt) - 1) +
+               ((u64)(acpi_wakeup_address +
+                       ((char *)&header->wakeup_gdt - (char *)acpi_realmode))
+                               << 16);
+       /* GDT[1]: real-mode-like code segment */
+       header->wakeup_gdt[1] = (0x009bULL << 40) +
+               ((u64)acpi_wakeup_address << 16) + 0xffff;
+       /* GDT[2]: real-mode-like data segment */
+       header->wakeup_gdt[2] = (0x0093ULL << 40) +
+               ((u64)acpi_wakeup_address << 16) + 0xffff;
+
 #ifndef CONFIG_64BIT
        store_gdt((struct desc_ptr *)&header->pmode_gdt);
 
@@ -111,7 +125,7 @@ void __init acpi_reserve_bootmem(void)
                return;
        }
 
-       acpi_wakeup_address = acpi_realmode;
+       acpi_wakeup_address = virt_to_phys((void *)acpi_realmode);
 }
 
 
index 5d23d85624d46c130cc595517b05c773a6daa2c8..4b63c8e1f13b1b078a42dc113403c1952c52f3cc 100644 (file)
@@ -49,13 +49,13 @@ void efi_call_phys_prelog(void)
        local_irq_save(efi_rt_eflags);
 
        /*
-        * If I don't have PSE, I should just duplicate two entries in page
-        * directory. If I have PSE, I just need to duplicate one entry in
+        * If I don't have PAE, I should just duplicate two entries in page
+        * directory. If I have PAE, I just need to duplicate one entry in
         * page directory.
         */
        cr4 = read_cr4();
 
-       if (cr4 & X86_CR4_PSE) {
+       if (cr4 & X86_CR4_PAE) {
                efi_bak_pg_dir_pointer[0].pgd =
                    swapper_pg_dir[pgd_index(0)].pgd;
                swapper_pg_dir[0].pgd =
@@ -93,7 +93,7 @@ void efi_call_phys_epilog(void)
 
        cr4 = read_cr4();
 
-       if (cr4 & X86_CR4_PSE) {
+       if (cr4 & X86_CR4_PAE) {
                swapper_pg_dir[pgd_index(0)].pgd =
                    efi_bak_pg_dir_pointer[0].pgd;
        } else {
index 10a1955bb1d17df7f90bff735ae733b648f58c15..b817974ef9420bba5702327a1089156dcb5d72c3 100644 (file)
@@ -128,7 +128,7 @@ ident_complete:
        /* Fixup phys_base */
        addq    %rbp, phys_base(%rip)
 
-#ifdef CONFIG_SMP
+#ifdef CONFIG_X86_TRAMPOLINE
        addq    %rbp, trampoline_level4_pgt + 0(%rip)
        addq    %rbp, trampoline_level4_pgt + (511*8)(%rip)
 #endif
index eb9ddd8efb828175e7be0efcc0616257c67c5943..95e80e5033c3b5c36fb66fd5ac7be4d99f04d421 100644 (file)
@@ -162,7 +162,7 @@ int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
        int ret;
 
        if (!cpu_has_fxsr)
-               return -ENODEV;
+               return -EIO;
 
        ret = init_fpu(target);
        if (ret)
@@ -179,7 +179,7 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
        int ret;
 
        if (!cpu_has_fxsr)
-               return -ENODEV;
+               return -EIO;
 
        ret = init_fpu(target);
        if (ret)
index 56078d61c79315847ee3a2e761184846b9e1345f..3e1cecedde42747261c94053a53191ffa7291107 100644 (file)
@@ -996,7 +996,6 @@ do_rest:
 #endif
                cpu_clear(cpu, cpu_callout_map); /* was set by do_boot_cpu() */
                cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
-               cpu_clear(cpu, cpu_possible_map);
                cpu_clear(cpu, cpu_present_map);
                per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID;
        }
index adff76ea97c4732de4b7766272c8b6ad26ace478..f1a95d1059531e3cb0f5f920dc4bb1a04d7c573c 100644 (file)
@@ -104,30 +104,7 @@ int kstack_depth_to_print = 12;
 
 void printk_address(unsigned long address, int reliable)
 {
-#ifdef CONFIG_KALLSYMS
-       unsigned long offset = 0, symsize;
-       const char *symname;
-       char *modname;
-       char *delim = ":";
-       char namebuf[KSYM_NAME_LEN];
-       char reliab[4] = "";
-
-       symname = kallsyms_lookup(address, &symsize, &offset,
-                                       &modname, namebuf);
-       if (!symname) {
-               printk(" [<%016lx>]\n", address);
-               return;
-       }
-       if (!reliable)
-               strcpy(reliab, "? ");
-
-       if (!modname)
-               modname = delim = "";
-       printk(" [<%016lx>] %s%s%s%s%s+0x%lx/0x%lx\n",
-               address, reliab, delim, modname, delim, symname, offset, symsize);
-#else
-       printk(" [<%016lx>]\n", address);
-#endif
+       printk(" [<%016lx>] %s%pS\n", address, reliable ? "": "? ", (void *) address);
 }
 
 static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
index 156e6d7b0e329cd84b06342dffd37e46ec28ac9a..819dad973b1375bc5da5a90297c5c41788d2a652 100644 (file)
@@ -135,7 +135,7 @@ static __init void *spp_getpage(void)
        return ptr;
 }
 
-static void
+static __init void
 set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
 {
        pgd_t *pgd;
@@ -214,7 +214,7 @@ void __init cleanup_highmap(void)
 }
 
 /* NOTE: this is meant to be run only at boot */
-void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
+void __init __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
 {
        unsigned long address = __fix_to_virt(idx);
 
@@ -526,7 +526,8 @@ static void __init early_memtest(unsigned long start, unsigned long end)
                                t_size = end - t_start;
 
                        printk(KERN_CONT "\n  %016llx - %016llx pattern %d",
-                               t_start, t_start + t_size, pattern);
+                               (unsigned long long)t_start,
+                               (unsigned long long)t_start + t_size, pattern);
 
                        memtest(t_start, t_size, pattern);
 
index 2b2bb3f9b683156b7ef25aac9ccfeca69e90d364..d1b867101e5f01e74d296e52cdbd0d4801dd43e5 100644 (file)
@@ -300,6 +300,29 @@ void __iomem *ioremap_cache(resource_size_t phys_addr, unsigned long size)
 }
 EXPORT_SYMBOL(ioremap_cache);
 
+static void __iomem *ioremap_default(resource_size_t phys_addr,
+                                       unsigned long size)
+{
+       unsigned long flags;
+       void *ret;
+       int err;
+
+       /*
+        * - WB for WB-able memory and no other conflicting mappings
+        * - UC_MINUS for non-WB-able memory with no other conflicting mappings
+        * - Inherit from confliting mappings otherwise
+        */
+       err = reserve_memtype(phys_addr, phys_addr + size, -1, &flags);
+       if (err < 0)
+               return NULL;
+
+       ret = (void *) __ioremap_caller(phys_addr, size, flags,
+                                       __builtin_return_address(0));
+
+       free_memtype(phys_addr, phys_addr + size);
+       return (void __iomem *)ret;
+}
+
 /**
  * iounmap - Free a IO remapping
  * @addr: virtual address from ioremap_*
@@ -365,7 +388,7 @@ void *xlate_dev_mem_ptr(unsigned long phys)
        if (page_is_ram(start >> PAGE_SHIFT))
                return __va(phys);
 
-       addr = (void *)ioremap(start, PAGE_SIZE);
+       addr = (void *)ioremap_default(start, PAGE_SIZE);
        if (addr)
                addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
 
index 940185ecaeda5bdfe6d737759d55e1b87ec11fe8..6e64aaf00d1dd9473fff8cfd0e6e09074a31443c 100644 (file)
@@ -328,18 +328,18 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
 #endif
        {
                .callback = set_bf_sort,
-               .ident = "HP ProLiant DL360",
+               .ident = "HP ProLiant DL385 G2",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL360"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"),
                },
        },
        {
                .callback = set_bf_sort,
-               .ident = "HP ProLiant DL380",
+               .ident = "HP ProLiant DL585 G2",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL380"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"),
                },
        },
        {}
index df40bf74ea751da4a0556a5b6603af1f3989a39b..4e527e7893a8c134481aac1c3e7ed621882745ad 100644 (file)
@@ -185,7 +185,7 @@ static pteval_t pte_mfn_to_pfn(pteval_t val)
        if (val & _PAGE_PRESENT) {
                unsigned long mfn = (val & PTE_MASK) >> PAGE_SHIFT;
                pteval_t flags = val & ~PTE_MASK;
-               val = (mfn_to_pfn(mfn) << PAGE_SHIFT) | flags;
+               val = ((pteval_t)mfn_to_pfn(mfn) << PAGE_SHIFT) | flags;
        }
 
        return val;
@@ -196,7 +196,7 @@ static pteval_t pte_pfn_to_mfn(pteval_t val)
        if (val & _PAGE_PRESENT) {
                unsigned long pfn = (val & PTE_MASK) >> PAGE_SHIFT;
                pteval_t flags = val & ~PTE_MASK;
-               val = (pfn_to_mfn(pfn) << PAGE_SHIFT) | flags;
+               val = ((pteval_t)pfn_to_mfn(pfn) << PAGE_SHIFT) | flags;
        }
 
        return val;
index 3e97f2bc446f367fb8a3ffd28972d20a4176564f..1ab7c15c8d7a58bc2df639a759a0b719bb2c25da 100644 (file)
@@ -81,6 +81,18 @@ config BLK_DEV_BSG
 
          If unsure, say N.
 
+config BLK_DEV_INTEGRITY
+       bool "Block layer data integrity support"
+       ---help---
+       Some storage devices allow extra information to be
+       stored/retrieved to help protect the data.  The block layer
+       data integrity option provides hooks which can be used by
+       filesystems to ensure better data integrity.
+
+       Say yes here if you have a storage device that provides the
+       T10/SCSI Data Integrity Field or the T13/ATA External Path
+       Protection.  If in doubt, say N.
+
 endif # BLOCK
 
 config BLOCK_COMPAT
index 5a43c7d795942d1b478483e9464f1d58d471a15d..208000b0750d28589262daaaf819d5d6ff227105 100644 (file)
@@ -4,7 +4,8 @@
 
 obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \
                        blk-barrier.o blk-settings.o blk-ioc.o blk-map.o \
-                       blk-exec.o blk-merge.o ioctl.o genhd.o scsi_ioctl.o
+                       blk-exec.o blk-merge.o ioctl.o genhd.o scsi_ioctl.o \
+                       cmd-filter.o
 
 obj-$(CONFIG_BLK_DEV_BSG)      += bsg.o
 obj-$(CONFIG_IOSCHED_NOOP)     += noop-iosched.o
@@ -14,3 +15,4 @@ obj-$(CONFIG_IOSCHED_CFQ)     += cfq-iosched.o
 
 obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o
 obj-$(CONFIG_BLOCK_COMPAT)     += compat_ioctl.o
+obj-$(CONFIG_BLK_DEV_INTEGRITY)        += blk-integrity.o
index 8c3946787dbbbaedd3381a195ab7851e84ec8272..9735acb5b4f51544b831ecb07bd037f88d99090f 100644 (file)
@@ -151,6 +151,7 @@ enum arq_state {
 
 static DEFINE_PER_CPU(unsigned long, ioc_count);
 static struct completion *ioc_gone;
+static DEFINE_SPINLOCK(ioc_gone_lock);
 
 static void as_move_to_dispatch(struct as_data *ad, struct request *rq);
 static void as_antic_stop(struct as_data *ad);
@@ -164,8 +165,19 @@ static void free_as_io_context(struct as_io_context *aic)
 {
        kfree(aic);
        elv_ioc_count_dec(ioc_count);
-       if (ioc_gone && !elv_ioc_count_read(ioc_count))
-               complete(ioc_gone);
+       if (ioc_gone) {
+               /*
+                * AS scheduler is exiting, grab exit lock and check
+                * the pending io context count. If it hits zero,
+                * complete ioc_gone and set it back to NULL.
+                */
+               spin_lock(&ioc_gone_lock);
+               if (ioc_gone && !elv_ioc_count_read(ioc_count)) {
+                       complete(ioc_gone);
+                       ioc_gone = NULL;
+               }
+               spin_unlock(&ioc_gone_lock);
+       }
 }
 
 static void as_trim(struct io_context *ioc)
@@ -831,6 +843,8 @@ static void as_completed_request(struct request_queue *q, struct request *rq)
        }
 
        if (ad->changed_batch && ad->nr_dispatched == 1) {
+               ad->current_batch_expires = jiffies +
+                                       ad->batch_expire[ad->batch_data_dir];
                kblockd_schedule_work(&ad->antic_work);
                ad->changed_batch = 0;
 
@@ -1491,7 +1505,7 @@ static void __exit as_exit(void)
        /* ioc_gone's update must be visible before reading ioc_count */
        smp_wmb();
        if (elv_ioc_count_read(ioc_count))
-               wait_for_completion(ioc_gone);
+               wait_for_completion(&all_gone);
        synchronize_rcu();
 }
 
index 1905aaba49fb2cd1d999bce222949c938fa3e9e5..dbc7f42b5d2bba5c252137923ec66d3beef482e1 100644 (file)
@@ -143,6 +143,10 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
 
                bio->bi_size -= nbytes;
                bio->bi_sector += (nbytes >> 9);
+
+               if (bio_integrity(bio))
+                       bio_integrity_advance(bio, nbytes);
+
                if (bio->bi_size == 0)
                        bio_endio(bio, error);
        } else {
@@ -201,8 +205,7 @@ void blk_plug_device(struct request_queue *q)
        if (blk_queue_stopped(q))
                return;
 
-       if (!test_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
-               __set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags);
+       if (!queue_flag_test_and_set(QUEUE_FLAG_PLUGGED, q)) {
                mod_timer(&q->unplug_timer, jiffies + q->unplug_delay);
                blk_add_trace_generic(q, NULL, 0, BLK_TA_PLUG);
        }
@@ -217,10 +220,9 @@ int blk_remove_plug(struct request_queue *q)
 {
        WARN_ON(!irqs_disabled());
 
-       if (!test_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
+       if (!queue_flag_test_and_clear(QUEUE_FLAG_PLUGGED, q))
                return 0;
 
-       queue_flag_clear(QUEUE_FLAG_PLUGGED, q);
        del_timer(&q->unplug_timer);
        return 1;
 }
@@ -324,8 +326,7 @@ void blk_start_queue(struct request_queue *q)
         * one level of recursion is ok and is much faster than kicking
         * the unplug handling
         */
-       if (!test_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
-               queue_flag_set(QUEUE_FLAG_REENTER, q);
+       if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
                q->request_fn(q);
                queue_flag_clear(QUEUE_FLAG_REENTER, q);
        } else {
@@ -390,8 +391,7 @@ void __blk_run_queue(struct request_queue *q)
         * handling reinvoke the handler shortly if we already got there.
         */
        if (!elv_queue_empty(q)) {
-               if (!test_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
-                       queue_flag_set(QUEUE_FLAG_REENTER, q);
+               if (!queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
                        q->request_fn(q);
                        queue_flag_clear(QUEUE_FLAG_REENTER, q);
                } else {
@@ -1381,6 +1381,9 @@ end_io:
                 */
                blk_partition_remap(bio);
 
+               if (bio_integrity_enabled(bio) && bio_integrity_prep(bio))
+                       goto end_io;
+
                if (old_sector != -1)
                        blk_add_trace_remap(q, bio, old_dev, bio->bi_sector,
                                            old_sector);
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
new file mode 100644 (file)
index 0000000..3f1a847
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * blk-integrity.c - Block layer data integrity extensions
+ *
+ * Copyright (C) 2007, 2008 Oracle Corporation
+ * Written by: Martin K. Petersen <martin.petersen@oracle.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.
+ *
+ * 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/mempool.h>
+#include <linux/bio.h>
+#include <linux/scatterlist.h>
+
+#include "blk.h"
+
+static struct kmem_cache *integrity_cachep;
+
+/**
+ * blk_rq_count_integrity_sg - Count number of integrity scatterlist elements
+ * @rq:                request with integrity metadata attached
+ *
+ * Description: Returns the number of elements required in a
+ * scatterlist corresponding to the integrity metadata in a request.
+ */
+int blk_rq_count_integrity_sg(struct request *rq)
+{
+       struct bio_vec *iv, *ivprv;
+       struct req_iterator iter;
+       unsigned int segments;
+
+       ivprv = NULL;
+       segments = 0;
+
+       rq_for_each_integrity_segment(iv, rq, iter) {
+
+               if (!ivprv || !BIOVEC_PHYS_MERGEABLE(ivprv, iv))
+                       segments++;
+
+               ivprv = iv;
+       }
+
+       return segments;
+}
+EXPORT_SYMBOL(blk_rq_count_integrity_sg);
+
+/**
+ * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
+ * @rq:                request with integrity metadata attached
+ * @sglist:    target scatterlist
+ *
+ * Description: Map the integrity vectors in request into a
+ * scatterlist.  The scatterlist must be big enough to hold all
+ * elements.  I.e. sized using blk_rq_count_integrity_sg().
+ */
+int blk_rq_map_integrity_sg(struct request *rq, struct scatterlist *sglist)
+{
+       struct bio_vec *iv, *ivprv;
+       struct req_iterator iter;
+       struct scatterlist *sg;
+       unsigned int segments;
+
+       ivprv = NULL;
+       sg = NULL;
+       segments = 0;
+
+       rq_for_each_integrity_segment(iv, rq, iter) {
+
+               if (ivprv) {
+                       if (!BIOVEC_PHYS_MERGEABLE(ivprv, iv))
+                               goto new_segment;
+
+                       sg->length += iv->bv_len;
+               } else {
+new_segment:
+                       if (!sg)
+                               sg = sglist;
+                       else {
+                               sg->page_link &= ~0x02;
+                               sg = sg_next(sg);
+                       }
+
+                       sg_set_page(sg, iv->bv_page, iv->bv_len, iv->bv_offset);
+                       segments++;
+               }
+
+               ivprv = iv;
+       }
+
+       if (sg)
+               sg_mark_end(sg);
+
+       return segments;
+}
+EXPORT_SYMBOL(blk_rq_map_integrity_sg);
+
+/**
+ * blk_integrity_compare - Compare integrity profile of two block devices
+ * @b1:                Device to compare
+ * @b2:                Device to compare
+ *
+ * Description: Meta-devices like DM and MD need to verify that all
+ * sub-devices use the same integrity format before advertising to
+ * upper layers that they can send/receive integrity metadata.  This
+ * function can be used to check whether two block devices have
+ * compatible integrity formats.
+ */
+int blk_integrity_compare(struct block_device *bd1, struct block_device *bd2)
+{
+       struct blk_integrity *b1 = bd1->bd_disk->integrity;
+       struct blk_integrity *b2 = bd2->bd_disk->integrity;
+
+       BUG_ON(bd1->bd_disk == NULL);
+       BUG_ON(bd2->bd_disk == NULL);
+
+       if (!b1 || !b2)
+               return 0;
+
+       if (b1->sector_size != b2->sector_size) {
+               printk(KERN_ERR "%s: %s/%s sector sz %u != %u\n", __func__,
+                      bd1->bd_disk->disk_name, bd2->bd_disk->disk_name,
+                      b1->sector_size, b2->sector_size);
+               return -1;
+       }
+
+       if (b1->tuple_size != b2->tuple_size) {
+               printk(KERN_ERR "%s: %s/%s tuple sz %u != %u\n", __func__,
+                      bd1->bd_disk->disk_name, bd2->bd_disk->disk_name,
+                      b1->tuple_size, b2->tuple_size);
+               return -1;
+       }
+
+       if (b1->tag_size && b2->tag_size && (b1->tag_size != b2->tag_size)) {
+               printk(KERN_ERR "%s: %s/%s tag sz %u != %u\n", __func__,
+                      bd1->bd_disk->disk_name, bd2->bd_disk->disk_name,
+                      b1->tag_size, b2->tag_size);
+               return -1;
+       }
+
+       if (strcmp(b1->name, b2->name)) {
+               printk(KERN_ERR "%s: %s/%s type %s != %s\n", __func__,
+                      bd1->bd_disk->disk_name, bd2->bd_disk->disk_name,
+                      b1->name, b2->name);
+               return -1;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(blk_integrity_compare);
+
+struct integrity_sysfs_entry {
+       struct attribute attr;
+       ssize_t (*show)(struct blk_integrity *, char *);
+       ssize_t (*store)(struct blk_integrity *, const char *, size_t);
+};
+
+static ssize_t integrity_attr_show(struct kobject *kobj, struct attribute *attr,
+                                  char *page)
+{
+       struct blk_integrity *bi =
+               container_of(kobj, struct blk_integrity, kobj);
+       struct integrity_sysfs_entry *entry =
+               container_of(attr, struct integrity_sysfs_entry, attr);
+
+       return entry->show(bi, page);
+}
+
+static ssize_t integrity_attr_store(struct kobject *kobj,
+                                   struct attribute *attr, const char *page,
+                                   size_t count)
+{
+       struct blk_integrity *bi =
+               container_of(kobj, struct blk_integrity, kobj);
+       struct integrity_sysfs_entry *entry =
+               container_of(attr, struct integrity_sysfs_entry, attr);
+       ssize_t ret = 0;
+
+       if (entry->store)
+               ret = entry->store(bi, page, count);
+
+       return ret;
+}
+
+static ssize_t integrity_format_show(struct blk_integrity *bi, char *page)
+{
+       if (bi != NULL && bi->name != NULL)
+               return sprintf(page, "%s\n", bi->name);
+       else
+               return sprintf(page, "none\n");
+}
+
+static ssize_t integrity_tag_size_show(struct blk_integrity *bi, char *page)
+{
+       if (bi != NULL)
+               return sprintf(page, "%u\n", bi->tag_size);
+       else
+               return sprintf(page, "0\n");
+}
+
+static ssize_t integrity_read_store(struct blk_integrity *bi,
+                                   const char *page, size_t count)
+{
+       char *p = (char *) page;
+       unsigned long val = simple_strtoul(p, &p, 10);
+
+       if (val)
+               bi->flags |= INTEGRITY_FLAG_READ;
+       else
+               bi->flags &= ~INTEGRITY_FLAG_READ;
+
+       return count;
+}
+
+static ssize_t integrity_read_show(struct blk_integrity *bi, char *page)
+{
+       return sprintf(page, "%d\n", (bi->flags & INTEGRITY_FLAG_READ) != 0);
+}
+
+static ssize_t integrity_write_store(struct blk_integrity *bi,
+                                    const char *page, size_t count)
+{
+       char *p = (char *) page;
+       unsigned long val = simple_strtoul(p, &p, 10);
+
+       if (val)
+               bi->flags |= INTEGRITY_FLAG_WRITE;
+       else
+               bi->flags &= ~INTEGRITY_FLAG_WRITE;
+
+       return count;
+}
+
+static ssize_t integrity_write_show(struct blk_integrity *bi, char *page)
+{
+       return sprintf(page, "%d\n", (bi->flags & INTEGRITY_FLAG_WRITE) != 0);
+}
+
+static struct integrity_sysfs_entry integrity_format_entry = {
+       .attr = { .name = "format", .mode = S_IRUGO },
+       .show = integrity_format_show,
+};
+
+static struct integrity_sysfs_entry integrity_tag_size_entry = {
+       .attr = { .name = "tag_size", .mode = S_IRUGO },
+       .show = integrity_tag_size_show,
+};
+
+static struct integrity_sysfs_entry integrity_read_entry = {
+       .attr = { .name = "read_verify", .mode = S_IRUGO | S_IWUSR },
+       .show = integrity_read_show,
+       .store = integrity_read_store,
+};
+
+static struct integrity_sysfs_entry integrity_write_entry = {
+       .attr = { .name = "write_generate", .mode = S_IRUGO | S_IWUSR },
+       .show = integrity_write_show,
+       .store = integrity_write_store,
+};
+
+static struct attribute *integrity_attrs[] = {
+       &integrity_format_entry.attr,
+       &integrity_tag_size_entry.attr,
+       &integrity_read_entry.attr,
+       &integrity_write_entry.attr,
+       NULL,
+};
+
+static struct sysfs_ops integrity_ops = {
+       .show   = &integrity_attr_show,
+       .store  = &integrity_attr_store,
+};
+
+static int __init blk_dev_integrity_init(void)
+{
+       integrity_cachep = kmem_cache_create("blkdev_integrity",
+                                            sizeof(struct blk_integrity),
+                                            0, SLAB_PANIC, NULL);
+       return 0;
+}
+subsys_initcall(blk_dev_integrity_init);
+
+static void blk_integrity_release(struct kobject *kobj)
+{
+       struct blk_integrity *bi =
+               container_of(kobj, struct blk_integrity, kobj);
+
+       kmem_cache_free(integrity_cachep, bi);
+}
+
+static struct kobj_type integrity_ktype = {
+       .default_attrs  = integrity_attrs,
+       .sysfs_ops      = &integrity_ops,
+       .release        = blk_integrity_release,
+};
+
+/**
+ * blk_integrity_register - Register a gendisk as being integrity-capable
+ * @disk:      struct gendisk pointer to make integrity-aware
+ * @template:  integrity profile
+ *
+ * Description: When a device needs to advertise itself as being able
+ * to send/receive integrity metadata it must use this function to
+ * register the capability with the block layer.  The template is a
+ * blk_integrity struct with values appropriate for the underlying
+ * hardware.  See Documentation/block/data-integrity.txt.
+ */
+int blk_integrity_register(struct gendisk *disk, struct blk_integrity *template)
+{
+       struct blk_integrity *bi;
+
+       BUG_ON(disk == NULL);
+       BUG_ON(template == NULL);
+
+       if (disk->integrity == NULL) {
+               bi = kmem_cache_alloc(integrity_cachep,
+                                               GFP_KERNEL | __GFP_ZERO);
+               if (!bi)
+                       return -1;
+
+               if (kobject_init_and_add(&bi->kobj, &integrity_ktype,
+                                        &disk->dev.kobj, "%s", "integrity")) {
+                       kmem_cache_free(integrity_cachep, bi);
+                       return -1;
+               }
+
+               kobject_uevent(&bi->kobj, KOBJ_ADD);
+
+               bi->flags |= INTEGRITY_FLAG_READ | INTEGRITY_FLAG_WRITE;
+               bi->sector_size = disk->queue->hardsect_size;
+               disk->integrity = bi;
+       } else
+               bi = disk->integrity;
+
+       /* Use the provided profile as template */
+       bi->name = template->name;
+       bi->generate_fn = template->generate_fn;
+       bi->verify_fn = template->verify_fn;
+       bi->tuple_size = template->tuple_size;
+       bi->set_tag_fn = template->set_tag_fn;
+       bi->get_tag_fn = template->get_tag_fn;
+       bi->tag_size = template->tag_size;
+
+       return 0;
+}
+EXPORT_SYMBOL(blk_integrity_register);
+
+/**
+ * blk_integrity_unregister - Remove block integrity profile
+ * @disk:      disk whose integrity profile to deallocate
+ *
+ * Description: This function frees all memory used by the block
+ * integrity profile.  To be called at device teardown.
+ */
+void blk_integrity_unregister(struct gendisk *disk)
+{
+       struct blk_integrity *bi;
+
+       if (!disk || !disk->integrity)
+               return;
+
+       bi = disk->integrity;
+
+       kobject_uevent(&bi->kobj, KOBJ_REMOVE);
+       kobject_del(&bi->kobj);
+       kobject_put(&disk->dev.kobj);
+       kmem_cache_free(integrity_cachep, bi);
+}
+EXPORT_SYMBOL(blk_integrity_unregister);
index 0b1af5a3537ca0728407c8acfedfaba44338cd19..ddd96fb11a7d71638a32e3e9060aac1f1adac808 100644 (file)
@@ -210,6 +210,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
        if (!bio_flagged(bio, BIO_USER_MAPPED))
                rq->cmd_flags |= REQ_COPY_USER;
 
+       blk_queue_bounce(q, &bio);
        bio_get(bio);
        blk_rq_bio_prep(q, rq, bio);
        rq->buffer = rq->data = NULL;
@@ -268,6 +269,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
        int reading = rq_data_dir(rq) == READ;
        int do_copy = 0;
        struct bio *bio;
+       unsigned long stack_mask = ~(THREAD_SIZE - 1);
 
        if (len > (q->max_hw_sectors << 9))
                return -EINVAL;
@@ -278,6 +280,10 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
        alignment = queue_dma_alignment(q) | q->dma_pad_mask;
        do_copy = ((kaddr & alignment) || (len & alignment));
 
+       if (!((kaddr & stack_mask) ^
+             ((unsigned long)current->stack & stack_mask)))
+               do_copy = 1;
+
        if (do_copy)
                bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading);
        else
index 651136aae76e45ba821205a830a919a3d6d105c5..5efc9e7a68b777fe42cc53b2a7bf3add00adff2a 100644 (file)
@@ -441,6 +441,9 @@ static int attempt_merge(struct request_queue *q, struct request *req,
            || next->special)
                return 0;
 
+       if (blk_integrity_rq(req) != blk_integrity_rq(next))
+               return 0;
+
        /*
         * If we are allowed to merge, then append bio list
         * from next to rq and release next. merge_requests_fn
index 8dd86418f35d88229fdebc890e28cbfb62705c55..dfc77012843ffbf9e67fa8996d40099f2db667fe 100644 (file)
@@ -302,11 +302,10 @@ EXPORT_SYMBOL(blk_queue_stack_limits);
  * @q:     the request queue for the device
  * @mask:  pad mask
  *
- * Set pad mask.  Direct IO requests are padded to the mask specified.
+ * Set dma pad mask.
  *
- * Appending pad buffer to a request modifies ->data_len such that it
- * includes the pad buffer.  The original requested data length can be
- * obtained using blk_rq_raw_data_len().
+ * Appending pad buffer to a request modifies the last entry of a
+ * scatter list such that it includes the pad buffer.
  **/
 void blk_queue_dma_pad(struct request_queue *q, unsigned int mask)
 {
@@ -314,6 +313,23 @@ void blk_queue_dma_pad(struct request_queue *q, unsigned int mask)
 }
 EXPORT_SYMBOL(blk_queue_dma_pad);
 
+/**
+ * blk_queue_update_dma_pad - update pad mask
+ * @q:     the request queue for the device
+ * @mask:  pad mask
+ *
+ * Update dma pad mask.
+ *
+ * Appending pad buffer to a request modifies the last entry of a
+ * scatter list such that it includes the pad buffer.
+ **/
+void blk_queue_update_dma_pad(struct request_queue *q, unsigned int mask)
+{
+       if (mask > q->dma_pad_mask)
+               q->dma_pad_mask = mask;
+}
+EXPORT_SYMBOL(blk_queue_update_dma_pad);
+
 /**
  * blk_queue_dma_drain - Set up a drain buffer for excess dma.
  * @q:  the request queue for the device
index 59776ab4742aae29678d34886665dc437dadd00c..c79f30e1df52d8388c6c89505e97756f2f906098 100644 (file)
@@ -51,4 +51,12 @@ static inline int queue_congestion_off_threshold(struct request_queue *q)
        return q->nr_congestion_off;
 }
 
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+
+#define rq_for_each_integrity_segment(bvl, _rq, _iter)         \
+       __rq_for_each_bio(_iter.bio, _rq)                       \
+               bip_for_each_vec(bvl, _iter.bio->bi_integrity, _iter.i)
+
+#endif /* BLK_DEV_INTEGRITY */
+
 #endif
index 8d3a277802603dd89c252784ea94f8dcc2d4b6d1..eb9651ccb241c28ce666300c02830ffea65df691 100644 (file)
@@ -244,6 +244,7 @@ err:
 static void blk_trace_cleanup(struct blk_trace *bt)
 {
        relay_close(bt->rchan);
+       debugfs_remove(bt->msg_file);
        debugfs_remove(bt->dropped_file);
        blk_remove_tree(bt->dir);
        free_percpu(bt->sequence);
@@ -291,6 +292,44 @@ static const struct file_operations blk_dropped_fops = {
        .read =         blk_dropped_read,
 };
 
+static int blk_msg_open(struct inode *inode, struct file *filp)
+{
+       filp->private_data = inode->i_private;
+
+       return 0;
+}
+
+static ssize_t blk_msg_write(struct file *filp, const char __user *buffer,
+                               size_t count, loff_t *ppos)
+{
+       char *msg;
+       struct blk_trace *bt;
+
+       if (count > BLK_TN_MAX_MSG)
+               return -EINVAL;
+
+       msg = kmalloc(count, GFP_KERNEL);
+       if (msg == NULL)
+               return -ENOMEM;
+
+       if (copy_from_user(msg, buffer, count)) {
+               kfree(msg);
+               return -EFAULT;
+       }
+
+       bt = filp->private_data;
+       __trace_note_message(bt, "%s", msg);
+       kfree(msg);
+
+       return count;
+}
+
+static const struct file_operations blk_msg_fops = {
+       .owner =        THIS_MODULE,
+       .open =         blk_msg_open,
+       .write =        blk_msg_write,
+};
+
 /*
  * Keep track of how many times we encountered a full subbuffer, to aid
  * the user space app in telling how many lost events there were.
@@ -380,6 +419,10 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
        if (!bt->dropped_file)
                goto err;
 
+       bt->msg_file = debugfs_create_file("msg", 0222, dir, bt, &blk_msg_fops);
+       if (!bt->msg_file)
+               goto err;
+
        bt->rchan = relay_open("trace", dir, buts->buf_size,
                                buts->buf_nr, &blk_relay_callbacks, bt);
        if (!bt->rchan)
@@ -409,6 +452,8 @@ err:
        if (dir)
                blk_remove_tree(dir);
        if (bt) {
+               if (bt->msg_file)
+                       debugfs_remove(bt->msg_file);
                if (bt->dropped_file)
                        debugfs_remove(bt->dropped_file);
                free_percpu(bt->sequence);
index f0b7cd3432160203ea6c650088ccfcd4acf2a3f6..93e757d7174b8b7a5ff6aeaee124915bfda5ccf7 100644 (file)
@@ -44,11 +44,12 @@ struct bsg_device {
        char name[BUS_ID_SIZE];
        int max_queue;
        unsigned long flags;
+       struct blk_scsi_cmd_filter *cmd_filter;
+       mode_t *f_mode;
 };
 
 enum {
        BSG_F_BLOCK             = 1,
-       BSG_F_WRITE_PERM        = 2,
 };
 
 #define BSG_DEFAULT_CMDS       64
@@ -172,7 +173,7 @@ unlock:
 }
 
 static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
-                               struct sg_io_v4 *hdr, int has_write_perm)
+                               struct sg_io_v4 *hdr, struct bsg_device *bd)
 {
        if (hdr->request_len > BLK_MAX_CDB) {
                rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL);
@@ -185,7 +186,8 @@ static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
                return -EFAULT;
 
        if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) {
-               if (blk_verify_command(rq->cmd, has_write_perm))
+               if (blk_cmd_filter_verify_command(bd->cmd_filter, rq->cmd,
+                                                bd->f_mode))
                        return -EPERM;
        } else if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
@@ -263,8 +265,7 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr)
        rq = blk_get_request(q, rw, GFP_KERNEL);
        if (!rq)
                return ERR_PTR(-ENOMEM);
-       ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, test_bit(BSG_F_WRITE_PERM,
-                                                      &bd->flags));
+       ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, bd);
        if (ret)
                goto out;
 
@@ -566,12 +567,23 @@ static inline void bsg_set_block(struct bsg_device *bd, struct file *file)
                set_bit(BSG_F_BLOCK, &bd->flags);
 }
 
-static inline void bsg_set_write_perm(struct bsg_device *bd, struct file *file)
+static void bsg_set_cmd_filter(struct bsg_device *bd,
+                          struct file *file)
 {
-       if (file->f_mode & FMODE_WRITE)
-               set_bit(BSG_F_WRITE_PERM, &bd->flags);
-       else
-               clear_bit(BSG_F_WRITE_PERM, &bd->flags);
+       struct inode *inode;
+       struct gendisk *disk;
+
+       if (!file)
+               return;
+
+       inode = file->f_dentry->d_inode;
+       if (!inode)
+               return;
+
+       disk = inode->i_bdev->bd_disk;
+
+       bd->cmd_filter = &disk->cmd_filter;
+       bd->f_mode = &file->f_mode;
 }
 
 /*
@@ -595,6 +607,8 @@ bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
        dprintk("%s: read %Zd bytes\n", bd->name, count);
 
        bsg_set_block(bd, file);
+       bsg_set_cmd_filter(bd, file);
+
        bytes_read = 0;
        ret = __bsg_read(buf, count, bd, NULL, &bytes_read);
        *ppos = bytes_read;
@@ -668,7 +682,7 @@ bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
        dprintk("%s: write %Zd bytes\n", bd->name, count);
 
        bsg_set_block(bd, file);
-       bsg_set_write_perm(bd, file);
+       bsg_set_cmd_filter(bd, file);
 
        bytes_written = 0;
        ret = __bsg_write(bd, buf, count, &bytes_written);
@@ -709,11 +723,12 @@ static void bsg_kref_release_function(struct kref *kref)
 {
        struct bsg_class_device *bcd =
                container_of(kref, struct bsg_class_device, ref);
+       struct device *parent = bcd->parent;
 
        if (bcd->release)
                bcd->release(bcd->parent);
 
-       put_device(bcd->parent);
+       put_device(parent);
 }
 
 static int bsg_put_device(struct bsg_device *bd)
@@ -771,7 +786,9 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
        }
 
        bd->queue = rq;
+
        bsg_set_block(bd, file);
+       bsg_set_cmd_filter(bd, file);
 
        atomic_set(&bd->ref_count, 1);
        mutex_lock(&bsg_mutex);
index d01b411c72f053225c2faee733e4299afeeec51b..1e2aff812ee2b278bd831809269c4d6c76234858 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/elevator.h>
 #include <linux/rbtree.h>
 #include <linux/ioprio.h>
+#include <linux/blktrace_api.h>
 
 /*
  * tunables
@@ -41,13 +42,14 @@ static int cfq_slice_idle = HZ / 125;
 
 #define RQ_CIC(rq)             \
        ((struct cfq_io_context *) (rq)->elevator_private)
-#define RQ_CFQQ(rq)            ((rq)->elevator_private2)
+#define RQ_CFQQ(rq)            (struct cfq_queue *) ((rq)->elevator_private2)
 
 static struct kmem_cache *cfq_pool;
 static struct kmem_cache *cfq_ioc_pool;
 
 static DEFINE_PER_CPU(unsigned long, ioc_count);
 static struct completion *ioc_gone;
+static DEFINE_SPINLOCK(ioc_gone_lock);
 
 #define CFQ_PRIO_LISTS         IOPRIO_BE_NR
 #define cfq_class_idle(cfqq)   ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
@@ -155,6 +157,7 @@ struct cfq_queue {
        unsigned short ioprio, org_ioprio;
        unsigned short ioprio_class, org_ioprio_class;
 
+       pid_t pid;
 };
 
 enum cfqq_state_flags {
@@ -198,6 +201,11 @@ CFQ_CFQQ_FNS(slice_new);
 CFQ_CFQQ_FNS(sync);
 #undef CFQ_CFQQ_FNS
 
+#define cfq_log_cfqq(cfqd, cfqq, fmt, args...) \
+       blk_add_trace_msg((cfqd)->queue, "cfq%d " fmt, (cfqq)->pid, ##args)
+#define cfq_log(cfqd, fmt, args...)    \
+       blk_add_trace_msg((cfqd)->queue, "cfq " fmt, ##args)
+
 static void cfq_dispatch_insert(struct request_queue *, struct request *);
 static struct cfq_queue *cfq_get_queue(struct cfq_data *, int,
                                       struct io_context *, gfp_t);
@@ -234,8 +242,10 @@ static inline int cfq_bio_sync(struct bio *bio)
  */
 static inline void cfq_schedule_dispatch(struct cfq_data *cfqd)
 {
-       if (cfqd->busy_queues)
+       if (cfqd->busy_queues) {
+               cfq_log(cfqd, "schedule dispatch");
                kblockd_schedule_work(&cfqd->unplug_work);
+       }
 }
 
 static int cfq_queue_empty(struct request_queue *q)
@@ -270,6 +280,7 @@ static inline void
 cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
        cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies;
+       cfq_log_cfqq(cfqd, cfqq, "set_slice=%lu", cfqq->slice_end - jiffies);
 }
 
 /*
@@ -539,6 +550,7 @@ static void cfq_resort_rr_list(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  */
 static void cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
+       cfq_log_cfqq(cfqd, cfqq, "add_to_rr");
        BUG_ON(cfq_cfqq_on_rr(cfqq));
        cfq_mark_cfqq_on_rr(cfqq);
        cfqd->busy_queues++;
@@ -552,6 +564,7 @@ static void cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
  */
 static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
+       cfq_log_cfqq(cfqd, cfqq, "del_from_rr");
        BUG_ON(!cfq_cfqq_on_rr(cfqq));
        cfq_clear_cfqq_on_rr(cfqq);
 
@@ -638,6 +651,8 @@ static void cfq_activate_request(struct request_queue *q, struct request *rq)
        struct cfq_data *cfqd = q->elevator->elevator_data;
 
        cfqd->rq_in_driver++;
+       cfq_log_cfqq(cfqd, RQ_CFQQ(rq), "activate rq, drv=%d",
+                                               cfqd->rq_in_driver);
 
        /*
         * If the depth is larger 1, it really could be queueing. But lets
@@ -657,6 +672,8 @@ static void cfq_deactivate_request(struct request_queue *q, struct request *rq)
 
        WARN_ON(!cfqd->rq_in_driver);
        cfqd->rq_in_driver--;
+       cfq_log_cfqq(cfqd, RQ_CFQQ(rq), "deactivate rq, drv=%d",
+                                               cfqd->rq_in_driver);
 }
 
 static void cfq_remove_request(struct request *rq)
@@ -746,6 +763,7 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd,
                                   struct cfq_queue *cfqq)
 {
        if (cfqq) {
+               cfq_log_cfqq(cfqd, cfqq, "set_active");
                cfqq->slice_end = 0;
                cfq_clear_cfqq_must_alloc_slice(cfqq);
                cfq_clear_cfqq_fifo_expire(cfqq);
@@ -763,6 +781,8 @@ static void
 __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                    int timed_out)
 {
+       cfq_log_cfqq(cfqd, cfqq, "slice expired t=%d", timed_out);
+
        if (cfq_cfqq_wait_request(cfqq))
                del_timer(&cfqd->idle_slice_timer);
 
@@ -772,8 +792,10 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
        /*
         * store what was left of this slice, if the queue idled/timed out
         */
-       if (timed_out && !cfq_cfqq_slice_new(cfqq))
+       if (timed_out && !cfq_cfqq_slice_new(cfqq)) {
                cfqq->slice_resid = cfqq->slice_end - jiffies;
+               cfq_log_cfqq(cfqd, cfqq, "resid=%ld", cfqq->slice_resid);
+       }
 
        cfq_resort_rr_list(cfqd, cfqq);
 
@@ -865,6 +887,12 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
        if (!cfqd->cfq_slice_idle || !cfq_cfqq_idle_window(cfqq))
                return;
 
+       /*
+        * still requests with the driver, don't idle
+        */
+       if (cfqd->rq_in_driver)
+               return;
+
        /*
         * task has exited, don't wait
         */
@@ -892,6 +920,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
                sl = min(sl, msecs_to_jiffies(CFQ_MIN_TT));
 
        mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
+       cfq_log(cfqd, "arm_idle: %lu", sl);
 }
 
 /*
@@ -902,6 +931,8 @@ static void cfq_dispatch_insert(struct request_queue *q, struct request *rq)
        struct cfq_data *cfqd = q->elevator->elevator_data;
        struct cfq_queue *cfqq = RQ_CFQQ(rq);
 
+       cfq_log_cfqq(cfqd, cfqq, "dispatch_insert");
+
        cfq_remove_request(rq);
        cfqq->dispatched++;
        elv_dispatch_sort(q, rq);
@@ -931,8 +962,9 @@ static struct request *cfq_check_fifo(struct cfq_queue *cfqq)
        rq = rq_entry_fifo(cfqq->fifo.next);
 
        if (time_before(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo]))
-               return NULL;
+               rq = NULL;
 
+       cfq_log_cfqq(cfqd, cfqq, "fifo=%p", rq);
        return rq;
 }
 
@@ -1072,6 +1104,7 @@ static int cfq_forced_dispatch(struct cfq_data *cfqd)
 
        BUG_ON(cfqd->busy_queues);
 
+       cfq_log(cfqd, "forced_dispatch=%d\n", dispatched);
        return dispatched;
 }
 
@@ -1112,6 +1145,7 @@ static int cfq_dispatch_requests(struct request_queue *q, int force)
                dispatched += __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
        }
 
+       cfq_log(cfqd, "dispatched=%d", dispatched);
        return dispatched;
 }
 
@@ -1130,6 +1164,7 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
        if (!atomic_dec_and_test(&cfqq->ref))
                return;
 
+       cfq_log_cfqq(cfqd, cfqq, "put_queue");
        BUG_ON(rb_first(&cfqq->sort_list));
        BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
        BUG_ON(cfq_cfqq_on_rr(cfqq));
@@ -1177,8 +1212,19 @@ static void cfq_cic_free_rcu(struct rcu_head *head)
        kmem_cache_free(cfq_ioc_pool, cic);
        elv_ioc_count_dec(ioc_count);
 
-       if (ioc_gone && !elv_ioc_count_read(ioc_count))
-               complete(ioc_gone);
+       if (ioc_gone) {
+               /*
+                * CFQ scheduler is exiting, grab exit lock and check
+                * the pending io context count. If it hits zero,
+                * complete ioc_gone and set it back to NULL
+                */
+               spin_lock(&ioc_gone_lock);
+               if (ioc_gone && !elv_ioc_count_read(ioc_count)) {
+                       complete(ioc_gone);
+                       ioc_gone = NULL;
+               }
+               spin_unlock(&ioc_gone_lock);
+       }
 }
 
 static void cfq_cic_free(struct cfq_io_context *cic)
@@ -1427,6 +1473,8 @@ retry:
                                cfq_mark_cfqq_idle_window(cfqq);
                        cfq_mark_cfqq_sync(cfqq);
                }
+               cfqq->pid = current->pid;
+               cfq_log_cfqq(cfqd, cfqq, "alloced");
        }
 
        if (new_cfqq)
@@ -1675,7 +1723,7 @@ static void
 cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                       struct cfq_io_context *cic)
 {
-       int enable_idle;
+       int old_idle, enable_idle;
 
        /*
         * Don't idle for async or idle io prio class
@@ -1683,7 +1731,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
        if (!cfq_cfqq_sync(cfqq) || cfq_class_idle(cfqq))
                return;
 
-       enable_idle = cfq_cfqq_idle_window(cfqq);
+       enable_idle = old_idle = cfq_cfqq_idle_window(cfqq);
 
        if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
            (cfqd->hw_tag && CIC_SEEKY(cic)))
@@ -1695,10 +1743,13 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                        enable_idle = 1;
        }
 
-       if (enable_idle)
-               cfq_mark_cfqq_idle_window(cfqq);
-       else
-               cfq_clear_cfqq_idle_window(cfqq);
+       if (old_idle != enable_idle) {
+               cfq_log_cfqq(cfqd, cfqq, "idle=%d", enable_idle);
+               if (enable_idle)
+                       cfq_mark_cfqq_idle_window(cfqq);
+               else
+                       cfq_clear_cfqq_idle_window(cfqq);
+       }
 }
 
 /*
@@ -1757,6 +1808,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
  */
 static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
+       cfq_log_cfqq(cfqd, cfqq, "preempt");
        cfq_slice_expired(cfqd, 1);
 
        /*
@@ -1818,6 +1870,7 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq)
        struct cfq_data *cfqd = q->elevator->elevator_data;
        struct cfq_queue *cfqq = RQ_CFQQ(rq);
 
+       cfq_log_cfqq(cfqd, cfqq, "insert_request");
        cfq_init_prio_data(cfqq, RQ_CIC(rq)->ioc);
 
        cfq_add_rq_rb(rq);
@@ -1835,6 +1888,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
        unsigned long now;
 
        now = jiffies;
+       cfq_log_cfqq(cfqd, cfqq, "complete");
 
        WARN_ON(!cfqd->rq_in_driver);
        WARN_ON(!cfqq->dispatched);
@@ -2004,6 +2058,7 @@ queue_fail:
 
        cfq_schedule_dispatch(cfqd);
        spin_unlock_irqrestore(q->queue_lock, flags);
+       cfq_log(cfqd, "set_request fail");
        return 1;
 }
 
@@ -2029,6 +2084,8 @@ static void cfq_idle_slice_timer(unsigned long data)
        unsigned long flags;
        int timed_out = 1;
 
+       cfq_log(cfqd, "idle timer fired");
+
        spin_lock_irqsave(cfqd->queue->queue_lock, flags);
 
        cfqq = cfqd->active_queue;
@@ -2317,7 +2374,7 @@ static void __exit cfq_exit(void)
         * pending RCU callbacks
         */
        if (elv_ioc_count_read(ioc_count))
-               wait_for_completion(ioc_gone);
+               wait_for_completion(&all_gone);
        cfq_slab_kill();
 }
 
diff --git a/block/cmd-filter.c b/block/cmd-filter.c
new file mode 100644 (file)
index 0000000..eec4404
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2004 Peter M. Jones <pjones@redhat.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.
+ *
+ * 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 Licens
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
+ *
+ */
+
+#include <linux/list.h>
+#include <linux/genhd.h>
+#include <linux/spinlock.h>
+#include <linux/parser.h>
+#include <linux/capability.h>
+#include <linux/bitops.h>
+
+#include <scsi/scsi.h>
+#include <linux/cdrom.h>
+
+int blk_cmd_filter_verify_command(struct blk_scsi_cmd_filter *filter,
+                                 unsigned char *cmd, mode_t *f_mode)
+{
+       /* root can do any command. */
+       if (capable(CAP_SYS_RAWIO))
+               return 0;
+
+       /* if there's no filter set, assume we're filtering everything out */
+       if (!filter)
+               return -EPERM;
+
+       /* Anybody who can open the device can do a read-safe command */
+       if (test_bit(cmd[0], filter->read_ok))
+               return 0;
+
+       /* Write-safe commands require a writable open */
+       if (test_bit(cmd[0], filter->write_ok) && (*f_mode & FMODE_WRITE))
+               return 0;
+
+       return -EPERM;
+}
+EXPORT_SYMBOL(blk_cmd_filter_verify_command);
+
+int blk_verify_command(struct file *file, unsigned char *cmd)
+{
+       struct gendisk *disk;
+       struct inode *inode;
+
+       if (!file)
+               return -EINVAL;
+
+       inode = file->f_dentry->d_inode;
+       if (!inode)
+               return -EINVAL;
+
+       disk = inode->i_bdev->bd_disk;
+
+       return blk_cmd_filter_verify_command(&disk->cmd_filter,
+                                                cmd, &file->f_mode);
+}
+EXPORT_SYMBOL(blk_verify_command);
+
+/* and now, the sysfs stuff */
+static ssize_t rcf_cmds_show(struct blk_scsi_cmd_filter *filter, char *page,
+                            int rw)
+{
+       char *npage = page;
+       unsigned long *okbits;
+       int i;
+
+       if (rw == READ)
+               okbits = filter->read_ok;
+       else
+               okbits = filter->write_ok;
+
+       for (i = 0; i < BLK_SCSI_MAX_CMDS; i++) {
+               if (test_bit(i, okbits)) {
+                       sprintf(npage, "%02x", i);
+                       npage += 2;
+                       if (i < BLK_SCSI_MAX_CMDS - 1)
+                               sprintf(npage++, " ");
+               }
+       }
+
+       if (npage != page)
+               npage += sprintf(npage, "\n");
+
+       return npage - page;
+}
+
+static ssize_t rcf_readcmds_show(struct blk_scsi_cmd_filter *filter, char *page)
+{
+       return rcf_cmds_show(filter, page, READ);
+}
+
+static ssize_t rcf_writecmds_show(struct blk_scsi_cmd_filter *filter,
+                                char *page)
+{
+       return rcf_cmds_show(filter, page, WRITE);
+}
+
+static ssize_t rcf_cmds_store(struct blk_scsi_cmd_filter *filter,
+                             const char *page, size_t count, int rw)
+{
+       ssize_t ret = 0;
+       unsigned long okbits[BLK_SCSI_CMD_PER_LONG], *target_okbits;
+       int cmd, status, len;
+       substring_t ss;
+
+       memset(&okbits, 0, sizeof(okbits));
+
+       for (len = strlen(page); len > 0; len -= 3) {
+               if (len < 2)
+                       break;
+               ss.from = (char *) page + ret;
+               ss.to = (char *) page + ret + 2;
+               ret += 3;
+               status = match_hex(&ss, &cmd);
+               /* either of these cases means invalid input, so do nothing. */
+               if (status || cmd >= BLK_SCSI_MAX_CMDS)
+                       return -EINVAL;
+
+               __set_bit(cmd, okbits);
+       }
+
+       if (rw == READ)
+               target_okbits = filter->read_ok;
+       else
+               target_okbits = filter->write_ok;
+
+       memmove(target_okbits, okbits, sizeof(okbits));
+       return count;
+}
+
+static ssize_t rcf_readcmds_store(struct blk_scsi_cmd_filter *filter,
+                                 const char *page, size_t count)
+{
+       return rcf_cmds_store(filter, page, count, READ);
+}
+
+static ssize_t rcf_writecmds_store(struct blk_scsi_cmd_filter *filter,
+                                  const char *page, size_t count)
+{
+       return rcf_cmds_store(filter, page, count, WRITE);
+}
+
+struct rcf_sysfs_entry {
+       struct attribute attr;
+       ssize_t (*show)(struct blk_scsi_cmd_filter *, char *);
+       ssize_t (*store)(struct blk_scsi_cmd_filter *, const char *, size_t);
+};
+
+static struct rcf_sysfs_entry rcf_readcmds_entry = {
+       .attr = { .name = "read_table", .mode = S_IRUGO | S_IWUSR },
+       .show = rcf_readcmds_show,
+       .store = rcf_readcmds_store,
+};
+
+static struct rcf_sysfs_entry rcf_writecmds_entry = {
+       .attr = {.name = "write_table", .mode = S_IRUGO | S_IWUSR },
+       .show = rcf_writecmds_show,
+       .store = rcf_writecmds_store,
+};
+
+static struct attribute *default_attrs[] = {
+       &rcf_readcmds_entry.attr,
+       &rcf_writecmds_entry.attr,
+       NULL,
+};
+
+#define to_rcf(atr) container_of((atr), struct rcf_sysfs_entry, attr)
+
+static ssize_t
+rcf_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+{
+       struct rcf_sysfs_entry *entry = to_rcf(attr);
+       struct blk_scsi_cmd_filter *filter;
+
+       filter = container_of(kobj, struct blk_scsi_cmd_filter, kobj);
+       if (entry->show)
+               return entry->show(filter, page);
+
+       return 0;
+}
+
+static ssize_t
+rcf_attr_store(struct kobject *kobj, struct attribute *attr,
+                       const char *page, size_t length)
+{
+       struct rcf_sysfs_entry *entry = to_rcf(attr);
+       struct blk_scsi_cmd_filter *filter;
+
+       if (!capable(CAP_SYS_RAWIO))
+               return -EPERM;
+
+       if (!entry->store)
+               return -EINVAL;
+
+       filter = container_of(kobj, struct blk_scsi_cmd_filter, kobj);
+       return entry->store(filter, page, length);
+}
+
+static struct sysfs_ops rcf_sysfs_ops = {
+       .show = rcf_attr_show,
+       .store = rcf_attr_store,
+};
+
+static struct kobj_type rcf_ktype = {
+       .sysfs_ops = &rcf_sysfs_ops,
+       .default_attrs = default_attrs,
+};
+
+#ifndef MAINTENANCE_IN_CMD
+#define MAINTENANCE_IN_CMD 0xa3
+#endif
+
+static void rcf_set_defaults(struct blk_scsi_cmd_filter *filter)
+{
+       /* Basic read-only commands */
+       __set_bit(TEST_UNIT_READY, filter->read_ok);
+       __set_bit(REQUEST_SENSE, filter->read_ok);
+       __set_bit(READ_6, filter->read_ok);
+       __set_bit(READ_10, filter->read_ok);
+       __set_bit(READ_12, filter->read_ok);
+       __set_bit(READ_16, filter->read_ok);
+       __set_bit(READ_BUFFER, filter->read_ok);
+       __set_bit(READ_DEFECT_DATA, filter->read_ok);
+       __set_bit(READ_CAPACITY, filter->read_ok);
+       __set_bit(READ_LONG, filter->read_ok);
+       __set_bit(INQUIRY, filter->read_ok);
+       __set_bit(MODE_SENSE, filter->read_ok);
+       __set_bit(MODE_SENSE_10, filter->read_ok);
+       __set_bit(LOG_SENSE, filter->read_ok);
+       __set_bit(START_STOP, filter->read_ok);
+       __set_bit(GPCMD_VERIFY_10, filter->read_ok);
+       __set_bit(VERIFY_16, filter->read_ok);
+       __set_bit(REPORT_LUNS, filter->read_ok);
+       __set_bit(SERVICE_ACTION_IN, filter->read_ok);
+       __set_bit(RECEIVE_DIAGNOSTIC, filter->read_ok);
+       __set_bit(MAINTENANCE_IN_CMD, filter->read_ok);
+       __set_bit(GPCMD_READ_BUFFER_CAPACITY, filter->read_ok);
+
+       /* Audio CD commands */
+       __set_bit(GPCMD_PLAY_CD, filter->read_ok);
+       __set_bit(GPCMD_PLAY_AUDIO_10, filter->read_ok);
+       __set_bit(GPCMD_PLAY_AUDIO_MSF, filter->read_ok);
+       __set_bit(GPCMD_PLAY_AUDIO_TI, filter->read_ok);
+       __set_bit(GPCMD_PAUSE_RESUME, filter->read_ok);
+
+       /* CD/DVD data reading */
+       __set_bit(GPCMD_READ_CD, filter->read_ok);
+       __set_bit(GPCMD_READ_CD_MSF, filter->read_ok);
+       __set_bit(GPCMD_READ_DISC_INFO, filter->read_ok);
+       __set_bit(GPCMD_READ_CDVD_CAPACITY, filter->read_ok);
+       __set_bit(GPCMD_READ_DVD_STRUCTURE, filter->read_ok);
+       __set_bit(GPCMD_READ_HEADER, filter->read_ok);
+       __set_bit(GPCMD_READ_TRACK_RZONE_INFO, filter->read_ok);
+       __set_bit(GPCMD_READ_SUBCHANNEL, filter->read_ok);
+       __set_bit(GPCMD_READ_TOC_PMA_ATIP, filter->read_ok);
+       __set_bit(GPCMD_REPORT_KEY, filter->read_ok);
+       __set_bit(GPCMD_SCAN, filter->read_ok);
+       __set_bit(GPCMD_GET_CONFIGURATION, filter->read_ok);
+       __set_bit(GPCMD_READ_FORMAT_CAPACITIES, filter->read_ok);
+       __set_bit(GPCMD_GET_EVENT_STATUS_NOTIFICATION, filter->read_ok);
+       __set_bit(GPCMD_GET_PERFORMANCE, filter->read_ok);
+       __set_bit(GPCMD_SEEK, filter->read_ok);
+       __set_bit(GPCMD_STOP_PLAY_SCAN, filter->read_ok);
+
+       /* Basic writing commands */
+       __set_bit(WRITE_6, filter->write_ok);
+       __set_bit(WRITE_10, filter->write_ok);
+       __set_bit(WRITE_VERIFY, filter->write_ok);
+       __set_bit(WRITE_12, filter->write_ok);
+       __set_bit(WRITE_VERIFY_12, filter->write_ok);
+       __set_bit(WRITE_16, filter->write_ok);
+       __set_bit(WRITE_LONG, filter->write_ok);
+       __set_bit(WRITE_LONG_2, filter->write_ok);
+       __set_bit(ERASE, filter->write_ok);
+       __set_bit(GPCMD_MODE_SELECT_10, filter->write_ok);
+       __set_bit(MODE_SELECT, filter->write_ok);
+       __set_bit(LOG_SELECT, filter->write_ok);
+       __set_bit(GPCMD_BLANK, filter->write_ok);
+       __set_bit(GPCMD_CLOSE_TRACK, filter->write_ok);
+       __set_bit(GPCMD_FLUSH_CACHE, filter->write_ok);
+       __set_bit(GPCMD_FORMAT_UNIT, filter->write_ok);
+       __set_bit(GPCMD_REPAIR_RZONE_TRACK, filter->write_ok);
+       __set_bit(GPCMD_RESERVE_RZONE_TRACK, filter->write_ok);
+       __set_bit(GPCMD_SEND_DVD_STRUCTURE, filter->write_ok);
+       __set_bit(GPCMD_SEND_EVENT, filter->write_ok);
+       __set_bit(GPCMD_SEND_KEY, filter->write_ok);
+       __set_bit(GPCMD_SEND_OPC, filter->write_ok);
+       __set_bit(GPCMD_SEND_CUE_SHEET, filter->write_ok);
+       __set_bit(GPCMD_SET_SPEED, filter->write_ok);
+       __set_bit(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, filter->write_ok);
+       __set_bit(GPCMD_LOAD_UNLOAD, filter->write_ok);
+       __set_bit(GPCMD_SET_STREAMING, filter->write_ok);
+}
+
+int blk_register_filter(struct gendisk *disk)
+{
+       int ret;
+       struct blk_scsi_cmd_filter *filter = &disk->cmd_filter;
+       struct kobject *parent = kobject_get(disk->holder_dir->parent);
+
+       if (!parent)
+               return -ENODEV;
+
+       ret = kobject_init_and_add(&filter->kobj, &rcf_ktype, parent,
+                                "%s", "cmd_filter");
+
+       if (ret < 0)
+               return ret;
+
+       rcf_set_defaults(filter);
+       return 0;
+}
+
+void blk_unregister_filter(struct gendisk *disk)
+{
+       struct blk_scsi_cmd_filter *filter = &disk->cmd_filter;
+
+       kobject_put(&filter->kobj);
+       kobject_put(disk->holder_dir->parent);
+}
+
index 902dd1344d56dfb9000ba5701dbb250bcf835d27..ed6f8f32d27ee8d09f5c3673852d416bad228862 100644 (file)
@@ -86,6 +86,12 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio)
        if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special)
                return 0;
 
+       /*
+        * only merge integrity protected bio into ditto rq
+        */
+       if (bio_integrity(bio) != blk_integrity_rq(rq))
+               return 0;
+
        if (!elv_iosched_allow_merge(rq, bio))
                return 0;
 
@@ -144,7 +150,7 @@ static struct elevator_type *elevator_get(const char *name)
                else
                        sprintf(elv, "%s-iosched", name);
 
-               request_module(elv);
+               request_module("%s", elv);
                spin_lock(&elv_list_lock);
                e = elevator_find(name);
        }
index b922d4801c87d0f6951f86f8deae3fc32bbd03d7..9074f384b0970535c9048432065ef043ff231923 100644 (file)
@@ -189,6 +189,7 @@ void add_disk(struct gendisk *disk)
                            disk->minors, NULL, exact_match, exact_lock, disk);
        register_disk(disk);
        blk_register_queue(disk);
+       blk_register_filter(disk);
 
        bdi = &disk->queue->backing_dev_info;
        bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor));
@@ -200,6 +201,7 @@ EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */
 
 void unlink_gendisk(struct gendisk *disk)
 {
+       blk_unregister_filter(disk);
        sysfs_remove_link(&disk->dev.kobj, "bdi");
        bdi_unregister(&disk->queue->backing_dev_info);
        blk_unregister_queue(disk);
@@ -400,6 +402,14 @@ static ssize_t disk_removable_show(struct device *dev,
                       (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0));
 }
 
+static ssize_t disk_ro_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct gendisk *disk = dev_to_disk(dev);
+
+       return sprintf(buf, "%d\n", disk->policy ? 1 : 0);
+}
+
 static ssize_t disk_size_show(struct device *dev,
                              struct device_attribute *attr, char *buf)
 {
@@ -472,6 +482,7 @@ static ssize_t disk_fail_store(struct device *dev,
 
 static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL);
 static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL);
+static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL);
 static DEVICE_ATTR(size, S_IRUGO, disk_size_show, NULL);
 static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL);
 static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL);
@@ -483,6 +494,7 @@ static struct device_attribute dev_attr_fail =
 static struct attribute *disk_attrs[] = {
        &dev_attr_range.attr,
        &dev_attr_removable.attr,
+       &dev_attr_ro.attr,
        &dev_attr_size.attr,
        &dev_attr_capability.attr,
        &dev_attr_stat.attr,
index 78199c08ec92fc7c23549ef41c7d5b0862cfb938..c5b9bcfc0a6d9c3629fa1aa1492fbcba1cb42e32 100644 (file)
@@ -105,120 +105,12 @@ static int sg_emulated_host(struct request_queue *q, int __user *p)
        return put_user(1, p);
 }
 
-#define CMD_READ_SAFE  0x01
-#define CMD_WRITE_SAFE 0x02
-#define CMD_WARNED     0x04
-#define safe_for_read(cmd)     [cmd] = CMD_READ_SAFE
-#define safe_for_write(cmd)    [cmd] = CMD_WRITE_SAFE
-
-int blk_verify_command(unsigned char *cmd, int has_write_perm)
-{
-       static unsigned char cmd_type[256] = {
-
-               /* Basic read-only commands */
-               safe_for_read(TEST_UNIT_READY),
-               safe_for_read(REQUEST_SENSE),
-               safe_for_read(READ_6),
-               safe_for_read(READ_10),
-               safe_for_read(READ_12),
-               safe_for_read(READ_16),
-               safe_for_read(READ_BUFFER),
-               safe_for_read(READ_DEFECT_DATA),
-               safe_for_read(READ_LONG),
-               safe_for_read(INQUIRY),
-               safe_for_read(MODE_SENSE),
-               safe_for_read(MODE_SENSE_10),
-               safe_for_read(LOG_SENSE),
-               safe_for_read(START_STOP),
-               safe_for_read(GPCMD_VERIFY_10),
-               safe_for_read(VERIFY_16),
-
-               /* Audio CD commands */
-               safe_for_read(GPCMD_PLAY_CD),
-               safe_for_read(GPCMD_PLAY_AUDIO_10),
-               safe_for_read(GPCMD_PLAY_AUDIO_MSF),
-               safe_for_read(GPCMD_PLAY_AUDIO_TI),
-               safe_for_read(GPCMD_PAUSE_RESUME),
-
-               /* CD/DVD data reading */
-               safe_for_read(GPCMD_READ_BUFFER_CAPACITY),
-               safe_for_read(GPCMD_READ_CD),
-               safe_for_read(GPCMD_READ_CD_MSF),
-               safe_for_read(GPCMD_READ_DISC_INFO),
-               safe_for_read(GPCMD_READ_CDVD_CAPACITY),
-               safe_for_read(GPCMD_READ_DVD_STRUCTURE),
-               safe_for_read(GPCMD_READ_HEADER),
-               safe_for_read(GPCMD_READ_TRACK_RZONE_INFO),
-               safe_for_read(GPCMD_READ_SUBCHANNEL),
-               safe_for_read(GPCMD_READ_TOC_PMA_ATIP),
-               safe_for_read(GPCMD_REPORT_KEY),
-               safe_for_read(GPCMD_SCAN),
-               safe_for_read(GPCMD_GET_CONFIGURATION),
-               safe_for_read(GPCMD_READ_FORMAT_CAPACITIES),
-               safe_for_read(GPCMD_GET_EVENT_STATUS_NOTIFICATION),
-               safe_for_read(GPCMD_GET_PERFORMANCE),
-               safe_for_read(GPCMD_SEEK),
-               safe_for_read(GPCMD_STOP_PLAY_SCAN),
-
-               /* Basic writing commands */
-               safe_for_write(WRITE_6),
-               safe_for_write(WRITE_10),
-               safe_for_write(WRITE_VERIFY),
-               safe_for_write(WRITE_12),
-               safe_for_write(WRITE_VERIFY_12),
-               safe_for_write(WRITE_16),
-               safe_for_write(WRITE_LONG),
-               safe_for_write(WRITE_LONG_2),
-               safe_for_write(ERASE),
-               safe_for_write(GPCMD_MODE_SELECT_10),
-               safe_for_write(MODE_SELECT),
-               safe_for_write(LOG_SELECT),
-               safe_for_write(GPCMD_BLANK),
-               safe_for_write(GPCMD_CLOSE_TRACK),
-               safe_for_write(GPCMD_FLUSH_CACHE),
-               safe_for_write(GPCMD_FORMAT_UNIT),
-               safe_for_write(GPCMD_REPAIR_RZONE_TRACK),
-               safe_for_write(GPCMD_RESERVE_RZONE_TRACK),
-               safe_for_write(GPCMD_SEND_DVD_STRUCTURE),
-               safe_for_write(GPCMD_SEND_EVENT),
-               safe_for_write(GPCMD_SEND_KEY),
-               safe_for_write(GPCMD_SEND_OPC),
-               safe_for_write(GPCMD_SEND_CUE_SHEET),
-               safe_for_write(GPCMD_SET_SPEED),
-               safe_for_write(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL),
-               safe_for_write(GPCMD_LOAD_UNLOAD),
-               safe_for_write(GPCMD_SET_STREAMING),
-       };
-       unsigned char type = cmd_type[cmd[0]];
-
-       /* Anybody who can open the device can do a read-safe command */
-       if (type & CMD_READ_SAFE)
-               return 0;
-
-       /* Write-safe commands just require a writable open.. */
-       if ((type & CMD_WRITE_SAFE) && has_write_perm)
-               return 0;
-
-       /* And root can do any command.. */
-       if (capable(CAP_SYS_RAWIO))
-               return 0;
-
-       if (!type) {
-               cmd_type[cmd[0]] = CMD_WARNED;
-               printk(KERN_WARNING "scsi: unknown opcode 0x%02x\n", cmd[0]);
-       }
-
-       /* Otherwise fail it with an "Operation not permitted" */
-       return -EPERM;
-}
-EXPORT_SYMBOL_GPL(blk_verify_command);
-
 static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
-                            struct sg_io_hdr *hdr, int has_write_perm)
+                            struct sg_io_hdr *hdr, struct file *file)
 {
        if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
                return -EFAULT;
-       if (blk_verify_command(rq->cmd, has_write_perm))
+       if (blk_verify_command(file, rq->cmd))
                return -EPERM;
 
        /*
@@ -287,7 +179,7 @@ static int sg_io(struct file *file, struct request_queue *q,
                struct gendisk *bd_disk, struct sg_io_hdr *hdr)
 {
        unsigned long start_time;
-       int writing = 0, ret = 0, has_write_perm = 0;
+       int writing = 0, ret = 0;
        struct request *rq;
        char sense[SCSI_SENSE_BUFFERSIZE];
        struct bio *bio;
@@ -316,10 +208,7 @@ static int sg_io(struct file *file, struct request_queue *q,
        if (!rq)
                return -ENOMEM;
 
-       if (file)
-               has_write_perm = file->f_mode & FMODE_WRITE;
-
-       if (blk_fill_sghdr_rq(q, rq, hdr, has_write_perm)) {
+       if (blk_fill_sghdr_rq(q, rq, hdr, file)) {
                blk_put_request(rq);
                return -EFAULT;
        }
@@ -451,7 +340,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q,
        if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
                goto error;
 
-       err = blk_verify_command(rq->cmd, file->f_mode & FMODE_WRITE);
+       err = blk_verify_command(file, rq->cmd);
        if (err)
                goto error;
 
index 6da3f577e4db1d6c81c95b1fc9bb3eb7a5424df4..9affadee32879c5114afab56d4bc82428c01dcf6 100644 (file)
@@ -117,6 +117,7 @@ static int chainiv_init(struct crypto_tfm *tfm)
 static int async_chainiv_schedule_work(struct async_chainiv_ctx *ctx)
 {
        int queued;
+       int err = ctx->err;
 
        if (!ctx->queue.qlen) {
                smp_mb__before_clear_bit();
@@ -131,7 +132,7 @@ static int async_chainiv_schedule_work(struct async_chainiv_ctx *ctx)
        BUG_ON(!queued);
 
 out:
-       return ctx->err;
+       return err;
 }
 
 static int async_chainiv_postpone_request(struct skcipher_givcrypt_request *req)
@@ -227,6 +228,7 @@ static void async_chainiv_do_postponed(struct work_struct *work)
                                                     postponed);
        struct skcipher_givcrypt_request *req;
        struct ablkcipher_request *subreq;
+       int err;
 
        /* Only handle one request at a time to avoid hogging keventd. */
        spin_lock_bh(&ctx->lock);
@@ -241,7 +243,11 @@ static void async_chainiv_do_postponed(struct work_struct *work)
        subreq = skcipher_givcrypt_reqctx(req);
        subreq->base.flags |= CRYPTO_TFM_REQ_MAY_SLEEP;
 
-       async_chainiv_givencrypt_tail(req);
+       err = async_chainiv_givencrypt_tail(req);
+
+       local_bh_disable();
+       skcipher_givcrypt_complete(req, err);
+       local_bh_enable();
 }
 
 static int async_chainiv_init(struct crypto_tfm *tfm)
index 6beabc5abd0747b0c2749d1d0c045c53e87e9856..e47f6e02133c155622d477567d88f890489f151f 100644 (file)
@@ -586,12 +586,6 @@ static void test_cipher(char *algo, int enc,
        j = 0;
        for (i = 0; i < tcount; i++) {
 
-               data = kzalloc(template[i].ilen, GFP_KERNEL);
-               if (!data)
-                       continue;
-
-               memcpy(data, template[i].input, template[i].ilen);
-
                if (template[i].iv)
                        memcpy(iv, template[i].iv, MAX_IVLEN);
                else
@@ -613,10 +607,8 @@ static void test_cipher(char *algo, int enc,
                                printk("setkey() failed flags=%x\n",
                                                crypto_ablkcipher_get_flags(tfm));
 
-                               if (!template[i].fail) {
-                                       kfree(data);
+                               if (!template[i].fail)
                                        goto out;
-                               }
                        }
 
                        temp = 0;
index f65deda72d6102636e47554c9864d529df27a258..fda44679dffc72ebb05f3241e8780eb86cf56b97 100644 (file)
@@ -10,6 +10,7 @@ obj-$(CONFIG_PCI)             += pci/
 obj-$(CONFIG_PARISC)           += parisc/
 obj-$(CONFIG_RAPIDIO)          += rapidio/
 obj-y                          += video/
+obj-y                          += gpu/
 obj-$(CONFIG_ACPI)             += acpi/
 # PnP must come after ACPI since it will eventually need to check if acpi
 # was used and do nothing if so
index 26038c2a2a71bb20026a0631e890b6d57705805e..61b6c5beb2d347d32d1fe1e3ee1ff8195e5f731d 100644 (file)
@@ -377,6 +377,9 @@ static int __init bay_init(void)
 
        INIT_LIST_HEAD(&drive_bays);
 
+       if (acpi_disabled)
+               return -ENODEV;
+
        /* look for dockable drive bays */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                ACPI_UINT32_MAX, find_bay, &bays, NULL);
index 96c542f7fded0c3abe8bfb3e07eec1a15a52ae41..bb7c51f712bd6cde630e4e8e5a771ca9d9e5fc55 100644 (file)
@@ -917,6 +917,9 @@ static int __init dock_init(void)
 
        dock_station = NULL;
 
+       if (acpi_disabled)
+               return 0;
+
        /* look for a dock station */
        acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                            ACPI_UINT32_MAX, find_dock, &num, NULL);
index 2808dc60fd670065a94ddf4c0be90876fd3fc20a..9b227d4dc9c9bbd43b7649b66b7ee311371f7eaf 100644 (file)
@@ -333,6 +333,9 @@ static int __init acpi_rtc_init(void)
 {
        struct device *dev = get_rtc_dev();
 
+       if (acpi_disabled)
+               return 0;
+
        if (dev) {
                rtc_wake_setup();
                rtc_info.wake_on = rtc_wake_on;
index c3b0cd88d09f22972342af30e02abfafe18fadcc..495c63a3e0afb1fce2e4fcb6801020ad2f8413ad 100644 (file)
@@ -36,9 +36,8 @@ static int acpi_sleep_prepare(u32 acpi_state)
                if (!acpi_wakeup_address) {
                        return -EFAULT;
                }
-               acpi_set_firmware_waking_vector((acpi_physical_address)
-                                               virt_to_phys((void *)
-                                                            acpi_wakeup_address));
+               acpi_set_firmware_waking_vector(
+                               (acpi_physical_address)acpi_wakeup_address);
 
        }
        ACPI_FLUSH_CPU_CACHE();
index 224c57c0338106e2d283f1b811de2bdd66b74b7f..4ebbba2b6b194f4f6c6532ad698d9a0582e2519f 100644 (file)
@@ -315,8 +315,11 @@ acpi_system_write_alarm(struct file *file,
                cmos_bcd_write(day, acpi_gbl_FADT.day_alarm, rtc_control);
        if (acpi_gbl_FADT.month_alarm)
                cmos_bcd_write(mo, acpi_gbl_FADT.month_alarm, rtc_control);
-       if (acpi_gbl_FADT.century)
+       if (acpi_gbl_FADT.century) {
+               if (adjust)
+                       yr += cmos_bcd_read(acpi_gbl_FADT.century, rtc_control) * 100;
                cmos_bcd_write(yr / 100, acpi_gbl_FADT.century, rtc_control);
+       }
        /* enable the rtc alarm interrupt */
        rtc_control |= RTC_AIE;
        CMOS_WRITE(rtc_control, RTC_CONTROL);
index 6a4a2a25d97a6bd258f1fee4c7cad287d7ef8c0d..5e6468a7ca4bd2a051b6ee9244297933a3ee7a60 100644 (file)
@@ -1777,7 +1777,7 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
        struct ahci_host_priv *hpriv;
        unsigned int i, handled = 0;
        void __iomem *mmio;
-       u32 irq_stat, irq_ack = 0;
+       u32 irq_stat, irq_masked;
 
        VPRINTK("ENTER\n");
 
@@ -1786,16 +1786,17 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
 
        /* sigh.  0xffffffff is a valid return from h/w */
        irq_stat = readl(mmio + HOST_IRQ_STAT);
-       irq_stat &= hpriv->port_map;
        if (!irq_stat)
                return IRQ_NONE;
 
+       irq_masked = irq_stat & hpriv->port_map;
+
        spin_lock(&host->lock);
 
        for (i = 0; i < host->n_ports; i++) {
                struct ata_port *ap;
 
-               if (!(irq_stat & (1 << i)))
+               if (!(irq_masked & (1 << i)))
                        continue;
 
                ap = host->ports[i];
@@ -1809,14 +1810,20 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
                                        "interrupt on disabled port %u\n", i);
                }
 
-               irq_ack |= (1 << i);
-       }
-
-       if (irq_ack) {
-               writel(irq_ack, mmio + HOST_IRQ_STAT);
                handled = 1;
        }
 
+       /* HOST_IRQ_STAT behaves as level triggered latch meaning that
+        * it should be cleared after all the port events are cleared;
+        * otherwise, it will raise a spurious interrupt after each
+        * valid one.  Please read section 10.6.2 of ahci 1.1 for more
+        * information.
+        *
+        * Also, use the unmasked value to clear interrupt as spurious
+        * pending event on a dummy port might cause screaming IRQ.
+        */
+       writel(irq_stat, mmio + HOST_IRQ_STAT);
+
        spin_unlock(&host->lock);
 
        VPRINTK("EXIT\n");
index 3ff8b14420d9bad5c2de548dd5edee8e730537e0..9330b7922f6281e758a795603d18e2550fb70da1 100644 (file)
 enum {
        ATA_ACPI_FILTER_SETXFER = 1 << 0,
        ATA_ACPI_FILTER_LOCK    = 1 << 1,
+       ATA_ACPI_FILTER_DIPM    = 1 << 2,
 
        ATA_ACPI_FILTER_DEFAULT = ATA_ACPI_FILTER_SETXFER |
-                                 ATA_ACPI_FILTER_LOCK,
+                                 ATA_ACPI_FILTER_LOCK |
+                                 ATA_ACPI_FILTER_DIPM,
 };
 
 static unsigned int ata_acpi_gtf_filter = ATA_ACPI_FILTER_DEFAULT;
 module_param_named(acpi_gtf_filter, ata_acpi_gtf_filter, int, 0644);
-MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock)");
+MODULE_PARM_DESC(acpi_gtf_filter, "filter mask for ACPI _GTF commands, set to filter out (0x1=set xfermode, 0x2=lock/freeze lock, 0x4=DIPM)");
 
 #define NO_PORT_MULT           0xffff
 #define SATA_ADR(root, pmp)    (((root) << 16) | (pmp))
@@ -195,6 +197,10 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
                /* This device does not support hotplug */
                return;
 
+       if (event == ACPI_NOTIFY_BUS_CHECK ||
+           event == ACPI_NOTIFY_DEVICE_CHECK)
+               status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+
        spin_lock_irqsave(ap->lock, flags);
 
        switch (event) {
@@ -202,7 +208,6 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
        case ACPI_NOTIFY_DEVICE_CHECK:
                ata_ehi_push_desc(ehi, "ACPI event");
 
-               status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
                if (ACPI_FAILURE(status)) {
                        ata_port_printk(ap, KERN_ERR,
                                "acpi: failed to determine bay status (0x%x)\n",
@@ -690,6 +695,14 @@ static int ata_acpi_filter_tf(const struct ata_taskfile *tf,
                        return 1;
        }
 
+       if (ata_acpi_gtf_filter & ATA_ACPI_FILTER_DIPM) {
+               /* inhibit enabling DIPM */
+               if (tf->command == ATA_CMD_SET_FEATURES &&
+                   tf->feature == SETFEATURES_SATA_ENABLE &&
+                   tf->nsect == SATA_DIPM)
+                       return 1;
+       }
+
        return 0;
 }
 
index 57a43649a4616bf0cdaeb9614d8489e3dbbb9758..499ccc628d81f3f80326ecd1340cd1fea4463e79 100644 (file)
@@ -885,7 +885,8 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
                /* set the min alignment and padding */
                blk_queue_update_dma_alignment(sdev->request_queue,
                                               ATA_DMA_PAD_SZ - 1);
-               blk_queue_dma_pad(sdev->request_queue, ATA_DMA_PAD_SZ - 1);
+               blk_queue_update_dma_pad(sdev->request_queue,
+                                        ATA_DMA_PAD_SZ - 1);
 
                /* configure draining */
                buf = kmalloc(ATAPI_MAX_DRAIN, q->bounce_gfp | GFP_KERNEL);
index 215d18672a5a9c62a00c43d5b3678b3bc5638242..c0908c225483bcd352508a1b9fc239a48b50f36c 100644 (file)
@@ -1094,6 +1094,7 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
 int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
                     u8 status, int in_wq)
 {
+       struct ata_eh_info *ehi = &ap->link.eh_info;
        unsigned long flags = 0;
        int poll_next;
 
@@ -1125,9 +1126,12 @@ fsm_start:
                        if (likely(status & (ATA_ERR | ATA_DF)))
                                /* device stops HSM for abort/error */
                                qc->err_mask |= AC_ERR_DEV;
-                       else
+                       else {
                                /* HSM violation. Let EH handle this */
+                               ata_ehi_push_desc(ehi,
+                                       "ST_FIRST: !(DRQ|ERR|DF)");
                                qc->err_mask |= AC_ERR_HSM;
+                       }
 
                        ap->hsm_task_state = HSM_ST_ERR;
                        goto fsm_start;
@@ -1146,9 +1150,9 @@ fsm_start:
                         * the CDB.
                         */
                        if (!(qc->dev->horkage & ATA_HORKAGE_STUCK_ERR)) {
-                               ata_port_printk(ap, KERN_WARNING,
-                                               "DRQ=1 with device error, "
-                                               "dev_stat 0x%X\n", status);
+                               ata_ehi_push_desc(ehi, "ST_FIRST: "
+                                       "DRQ=1 with device error, "
+                                       "dev_stat 0x%X", status);
                                qc->err_mask |= AC_ERR_HSM;
                                ap->hsm_task_state = HSM_ST_ERR;
                                goto fsm_start;
@@ -1205,9 +1209,9 @@ fsm_start:
                         * let the EH abort the command or reset the device.
                         */
                        if (unlikely(status & (ATA_ERR | ATA_DF))) {
-                               ata_port_printk(ap, KERN_WARNING, "DRQ=1 with "
-                                               "device error, dev_stat 0x%X\n",
-                                               status);
+                               ata_ehi_push_desc(ehi, "ST-ATAPI: "
+                                       "DRQ=1 with device error, "
+                                       "dev_stat 0x%X", status);
                                qc->err_mask |= AC_ERR_HSM;
                                ap->hsm_task_state = HSM_ST_ERR;
                                goto fsm_start;
@@ -1226,13 +1230,17 @@ fsm_start:
                                if (likely(status & (ATA_ERR | ATA_DF)))
                                        /* device stops HSM for abort/error */
                                        qc->err_mask |= AC_ERR_DEV;
-                               else
+                               else {
                                        /* HSM violation. Let EH handle this.
                                         * Phantom devices also trigger this
                                         * condition.  Mark hint.
                                         */
+                                       ata_ehi_push_desc(ehi, "ST-ATA: "
+                                               "DRQ=1 with device error, "
+                                               "dev_stat 0x%X", status);
                                        qc->err_mask |= AC_ERR_HSM |
                                                        AC_ERR_NODEV_HINT;
+                               }
 
                                ap->hsm_task_state = HSM_ST_ERR;
                                goto fsm_start;
@@ -1257,8 +1265,12 @@ fsm_start:
                                        status = ata_wait_idle(ap);
                                }
 
-                               if (status & (ATA_BUSY | ATA_DRQ))
+                               if (status & (ATA_BUSY | ATA_DRQ)) {
+                                       ata_ehi_push_desc(ehi, "ST-ATA: "
+                                               "BUSY|DRQ persists on ERR|DF, "
+                                               "dev_stat 0x%X", status);
                                        qc->err_mask |= AC_ERR_HSM;
+                               }
 
                                /* ata_pio_sectors() might change the
                                 * state to HSM_ST_LAST. so, the state
index e82c66e8d31bdd211568a5bdbc9e3ae719633c17..26345d7b531c76aaffe00231649c7fe9640c14e8 100644 (file)
@@ -56,6 +56,7 @@ static const struct sis_laptop sis_laptop[] = {
        { 0x5513, 0x1043, 0x1107 },     /* ASUS A6K */
        { 0x5513, 0x1734, 0x105F },     /* FSC Amilo A1630 */
        { 0x5513, 0x1071, 0x8640 },     /* EasyNote K5305 */
+       { 0x5513, 0x1039, 0x5513 },     /* Targa Visionary 1000 */
        /* end marker */
        { 0, }
 };
index 28092bc50146a04bf0298f48166550c8efa4320b..ad169ffbc4cb2a0ad8387c478b6a9540992f99b6 100644 (file)
@@ -1607,7 +1607,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
                 * Much of the time, this could just work regardless.
                 * So for now, just log the incident, and allow the attempt.
                 */
-               if (limit_warnings && (qc->nbytes / qc->sect_size) > 1) {
+               if (limit_warnings > 0 && (qc->nbytes / qc->sect_size) > 1) {
                        --limit_warnings;
                        ata_link_printk(qc->dev->link, KERN_WARNING, DRV_NAME
                                        ": attempting PIO w/multiple DRQ: "
index 8ee6b5b4ede7bca0940783b37756b8b5f4aba158..84ffcc26a74bec944506096c20e578a49c516bcf 100644 (file)
@@ -370,6 +370,7 @@ static const struct pci_device_id sil24_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x3124), BID_SIL3124 },
        { PCI_VDEVICE(CMD, 0x3132), BID_SIL3132 },
        { PCI_VDEVICE(CMD, 0x0242), BID_SIL3132 },
+       { PCI_VDEVICE(CMD, 0x0244), BID_SIL3132 },
        { PCI_VDEVICE(CMD, 0x3131), BID_SIL3131 },
        { PCI_VDEVICE(CMD, 0x3531), BID_SIL3131 },
 
index f277cea904ce89bc90adc909ca5fe0809a13c621..db529b8499482fc08c3f4b6de08fcc4d43a6f2cc 100644 (file)
@@ -83,6 +83,7 @@ static struct ata_port_operations uli_ops = {
        .inherits               = &ata_bmdma_port_ops,
        .scr_read               = uli_scr_read,
        .scr_write              = uli_scr_write,
+       .hardreset              = ATA_OP_NULL,
 };
 
 static const struct ata_port_info uli_port_info = {
index 043353bd0600fb4c8d517672cab3116047a3fd50..14b9d5f4c203d28d3bcc639e6f1f8580d77093f0 100644 (file)
@@ -64,7 +64,7 @@ config KS0108_DELAY
          Amount of time the ks0108 should wait between each control write
          to the parallel port.
 
-         If your driver seems to miss random writings, increment this.
+         If your LCD seems to miss random writings, increment this.
 
          If you don't know what I'm talking about, ignore it.
 
index 80bb061053877806bc7d6de0256e27b706a18977..683509f013abaabdc1711e3436dc94474cd1429c 100644 (file)
@@ -5,7 +5,7 @@
  *     License: GPLv2
  *     Depends: ks0108
  *
- *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
+ *      Author: Copyright (C) Miguel Ojeda Sandonis
  *        Date: 2006-10-31
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -398,5 +398,5 @@ module_init(cfag12864b_init);
 module_exit(cfag12864b_exit);
 
 MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>");
+MODULE_AUTHOR("Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>");
 MODULE_DESCRIPTION("cfag12864b LCD driver");
index 307c190699e04193815004207549a5f7d8706284..fe3a865be4e556c615fbac9fd49cae7bfcaf444d 100644 (file)
@@ -5,7 +5,7 @@
  *     License: GPLv2
  *     Depends: cfag12864b
  *
- *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
+ *      Author: Copyright (C) Miguel Ojeda Sandonis
  *        Date: 2006-10-31
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -186,5 +186,5 @@ module_init(cfag12864bfb_init);
 module_exit(cfag12864bfb_exit);
 
 MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>");
+MODULE_AUTHOR("Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>");
 MODULE_DESCRIPTION("cfag12864b LCD framebuffer driver");
index e6c3646ef18ce007c4446b6d96738202d0cf0874..5b93852392b8c342cc3c772979a346dedd261439 100644 (file)
@@ -5,7 +5,7 @@
  *     License: GPLv2
  *     Depends: parport
  *
- *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
+ *      Author: Copyright (C) Miguel Ojeda Sandonis
  *        Date: 2006-10-31
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -173,6 +173,6 @@ module_init(ks0108_init);
 module_exit(ks0108_exit);
 
 MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Miguel Ojeda Sandonis <maxextreme@gmail.com>");
+MODULE_AUTHOR("Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>");
 MODULE_DESCRIPTION("ks0108 LCD Controller driver");
 
index 39f3d1b3a21354aa112f5fb222b862d99daafb04..0f867a0833387fc7cfa5094450593c94f4905486 100644 (file)
@@ -84,8 +84,8 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
                       nid, K(i.totalram),
                       nid, K(i.freeram),
                       nid, K(i.totalram - i.freeram),
-                      nid, node_page_state(nid, NR_ACTIVE),
-                      nid, node_page_state(nid, NR_INACTIVE),
+                      nid, K(node_page_state(nid, NR_ACTIVE)),
+                      nid, K(node_page_state(nid, NR_INACTIVE)),
 #ifdef CONFIG_HIGHMEM
                       nid, K(i.totalhigh),
                       nid, K(i.freehigh),
index cd03473f35474d743f7d2d4c2406443a215ce85a..a002a381df921f466b1293574aafb7a4b52e2b6b 100644 (file)
@@ -6628,15 +6628,18 @@ static void DAC960_DestroyProcEntries(DAC960_Controller_T *Controller)
  * DAC960_gam_ioctl is the ioctl function for performing RAID operations.
 */
 
-static int DAC960_gam_ioctl(struct inode *inode, struct file *file,
-                           unsigned int Request, unsigned long Argument)
+static long DAC960_gam_ioctl(struct file *file, unsigned int Request,
+                                               unsigned long Argument)
 {
-  int ErrorCode = 0;
+  long ErrorCode = 0;
   if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+
+  lock_kernel();
   switch (Request)
     {
     case DAC960_IOCTL_GET_CONTROLLER_COUNT:
-      return DAC960_ControllerCount;
+      ErrorCode = DAC960_ControllerCount;
+      break;
     case DAC960_IOCTL_GET_CONTROLLER_INFO:
       {
        DAC960_ControllerInfo_T __user *UserSpaceControllerInfo =
@@ -6644,15 +6647,20 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file,
        DAC960_ControllerInfo_T ControllerInfo;
        DAC960_Controller_T *Controller;
        int ControllerNumber;
-       if (UserSpaceControllerInfo == NULL) return -EINVAL;
-       ErrorCode = get_user(ControllerNumber,
+       if (UserSpaceControllerInfo == NULL)
+               ErrorCode = -EINVAL;
+       else ErrorCode = get_user(ControllerNumber,
                             &UserSpaceControllerInfo->ControllerNumber);
-       if (ErrorCode != 0) return ErrorCode;
+       if (ErrorCode != 0)
+               break;;
+       ErrorCode = -ENXIO;
        if (ControllerNumber < 0 ||
-           ControllerNumber > DAC960_ControllerCount - 1)
-         return -ENXIO;
+           ControllerNumber > DAC960_ControllerCount - 1) {
+         break;
+       }
        Controller = DAC960_Controllers[ControllerNumber];
-       if (Controller == NULL) return -ENXIO;
+       if (Controller == NULL)
+               break;;
        memset(&ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T));
        ControllerInfo.ControllerNumber = ControllerNumber;
        ControllerInfo.FirmwareType = Controller->FirmwareType;
@@ -6665,8 +6673,9 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file,
        ControllerInfo.PCI_Address = Controller->PCI_Address;
        strcpy(ControllerInfo.ModelName, Controller->ModelName);
        strcpy(ControllerInfo.FirmwareVersion, Controller->FirmwareVersion);
-       return (copy_to_user(UserSpaceControllerInfo, &ControllerInfo,
+       ErrorCode = (copy_to_user(UserSpaceControllerInfo, &ControllerInfo,
                             sizeof(DAC960_ControllerInfo_T)) ? -EFAULT : 0);
+       break;
       }
     case DAC960_IOCTL_V1_EXECUTE_COMMAND:
       {
@@ -6684,30 +6693,39 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file,
        int ControllerNumber, DataTransferLength;
        unsigned char *DataTransferBuffer = NULL;
        dma_addr_t DataTransferBufferDMA;
-       if (UserSpaceUserCommand == NULL) return -EINVAL;
+       if (UserSpaceUserCommand == NULL) {
+               ErrorCode = -EINVAL;
+               break;
+       }
        if (copy_from_user(&UserCommand, UserSpaceUserCommand,
                                   sizeof(DAC960_V1_UserCommand_T))) {
                ErrorCode = -EFAULT;
-               goto Failure1a;
+               break;
        }
        ControllerNumber = UserCommand.ControllerNumber;
+       ErrorCode = -ENXIO;
        if (ControllerNumber < 0 ||
            ControllerNumber > DAC960_ControllerCount - 1)
-         return -ENXIO;
+               break;
        Controller = DAC960_Controllers[ControllerNumber];
-       if (Controller == NULL) return -ENXIO;
-       if (Controller->FirmwareType != DAC960_V1_Controller) return -EINVAL;
+       if (Controller == NULL)
+               break;
+       ErrorCode = -EINVAL;
+       if (Controller->FirmwareType != DAC960_V1_Controller)
+               break;
        CommandOpcode = UserCommand.CommandMailbox.Common.CommandOpcode;
        DataTransferLength = UserCommand.DataTransferLength;
-       if (CommandOpcode & 0x80) return -EINVAL;
+       if (CommandOpcode & 0x80)
+               break;
        if (CommandOpcode == DAC960_V1_DCDB)
          {
            if (copy_from_user(&DCDB, UserCommand.DCDB,
                               sizeof(DAC960_V1_DCDB_T))) {
                ErrorCode = -EFAULT;
-               goto Failure1a;
+               break;
            }
-           if (DCDB.Channel >= DAC960_V1_MaxChannels) return -EINVAL;
+           if (DCDB.Channel >= DAC960_V1_MaxChannels)
+                       break;
            if (!((DataTransferLength == 0 &&
                   DCDB.Direction
                   == DAC960_V1_DCDB_NoDataTransfer) ||
@@ -6717,38 +6735,37 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file,
                  (DataTransferLength < 0 &&
                   DCDB.Direction
                   == DAC960_V1_DCDB_DataTransferSystemToDevice)))
-             return -EINVAL;
+                       break;
            if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength)
                != abs(DataTransferLength))
-             return -EINVAL;
+                       break;
            DCDB_IOBUF = pci_alloc_consistent(Controller->PCIDevice,
                        sizeof(DAC960_V1_DCDB_T), &DCDB_IOBUFDMA);
-           if (DCDB_IOBUF == NULL)
-                       return -ENOMEM;
+           if (DCDB_IOBUF == NULL) {
+                       ErrorCode = -ENOMEM;
+                       break;
+               }
          }
+       ErrorCode = -ENOMEM;
        if (DataTransferLength > 0)
          {
            DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
                                DataTransferLength, &DataTransferBufferDMA);
-           if (DataTransferBuffer == NULL) {
-               ErrorCode = -ENOMEM;
-               goto Failure1;
-           }
+           if (DataTransferBuffer == NULL)
+               break;
            memset(DataTransferBuffer, 0, DataTransferLength);
          }
        else if (DataTransferLength < 0)
          {
            DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
                                -DataTransferLength, &DataTransferBufferDMA);
-           if (DataTransferBuffer == NULL) {
-               ErrorCode = -ENOMEM;
-               goto Failure1;
-           }
+           if (DataTransferBuffer == NULL)
+               break;
            if (copy_from_user(DataTransferBuffer,
                               UserCommand.DataTransferBuffer,
                               -DataTransferLength)) {
                ErrorCode = -EFAULT;
-               goto Failure1;
+               break;
            }
          }
        if (CommandOpcode == DAC960_V1_DCDB)
@@ -6825,8 +6842,7 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file,
        if (DCDB_IOBUF != NULL)
          pci_free_consistent(Controller->PCIDevice, sizeof(DAC960_V1_DCDB_T),
                        DCDB_IOBUF, DCDB_IOBUFDMA);
-      Failure1a:
-       return ErrorCode;
+       break;
       }
     case DAC960_IOCTL_V2_EXECUTE_COMMAND:
       {
@@ -6844,32 +6860,43 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file,
        dma_addr_t DataTransferBufferDMA;
        unsigned char *RequestSenseBuffer = NULL;
        dma_addr_t RequestSenseBufferDMA;
-       if (UserSpaceUserCommand == NULL) return -EINVAL;
+
+       ErrorCode = -EINVAL;
+       if (UserSpaceUserCommand == NULL)
+               break;
        if (copy_from_user(&UserCommand, UserSpaceUserCommand,
                           sizeof(DAC960_V2_UserCommand_T))) {
                ErrorCode = -EFAULT;
-               goto Failure2a;
+               break;
        }
+       ErrorCode = -ENXIO;
        ControllerNumber = UserCommand.ControllerNumber;
        if (ControllerNumber < 0 ||
            ControllerNumber > DAC960_ControllerCount - 1)
-         return -ENXIO;
+               break;
        Controller = DAC960_Controllers[ControllerNumber];
-       if (Controller == NULL) return -ENXIO;
-       if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL;
+       if (Controller == NULL)
+               break;
+       if (Controller->FirmwareType != DAC960_V2_Controller){
+               ErrorCode = -EINVAL;
+               break;
+       }
        DataTransferLength = UserCommand.DataTransferLength;
+       ErrorCode = -ENOMEM;
        if (DataTransferLength > 0)
          {
            DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
                                DataTransferLength, &DataTransferBufferDMA);
-           if (DataTransferBuffer == NULL) return -ENOMEM;
+           if (DataTransferBuffer == NULL)
+               break;
            memset(DataTransferBuffer, 0, DataTransferLength);
          }
        else if (DataTransferLength < 0)
          {
            DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
                                -DataTransferLength, &DataTransferBufferDMA);
-           if (DataTransferBuffer == NULL) return -ENOMEM;
+           if (DataTransferBuffer == NULL)
+               break;
            if (copy_from_user(DataTransferBuffer,
                               UserCommand.DataTransferBuffer,
                               -DataTransferLength)) {
@@ -6979,8 +7006,7 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file,
        if (RequestSenseBuffer != NULL)
          pci_free_consistent(Controller->PCIDevice, RequestSenseLength,
                RequestSenseBuffer, RequestSenseBufferDMA);
-      Failure2a:
-       return ErrorCode;
+        break;
       }
     case DAC960_IOCTL_V2_GET_HEALTH_STATUS:
       {
@@ -6990,21 +7016,33 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file,
        DAC960_V2_HealthStatusBuffer_T HealthStatusBuffer;
        DAC960_Controller_T *Controller;
        int ControllerNumber;
-       if (UserSpaceGetHealthStatus == NULL) return -EINVAL;
+       if (UserSpaceGetHealthStatus == NULL) {
+               ErrorCode = -EINVAL;
+               break;
+       }
        if (copy_from_user(&GetHealthStatus, UserSpaceGetHealthStatus,
-                          sizeof(DAC960_V2_GetHealthStatus_T)))
-               return -EFAULT;
+                          sizeof(DAC960_V2_GetHealthStatus_T))) {
+               ErrorCode = -EFAULT;
+               break;
+       }
+       ErrorCode = -ENXIO;
        ControllerNumber = GetHealthStatus.ControllerNumber;
        if (ControllerNumber < 0 ||
            ControllerNumber > DAC960_ControllerCount - 1)
-         return -ENXIO;
+                   break;
        Controller = DAC960_Controllers[ControllerNumber];
-       if (Controller == NULL) return -ENXIO;
-       if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL;
+       if (Controller == NULL)
+               break;
+       if (Controller->FirmwareType != DAC960_V2_Controller) {
+               ErrorCode = -EINVAL;
+               break;
+       }
        if (copy_from_user(&HealthStatusBuffer,
                           GetHealthStatus.HealthStatusBuffer,
-                          sizeof(DAC960_V2_HealthStatusBuffer_T)))
-               return -EFAULT;
+                          sizeof(DAC960_V2_HealthStatusBuffer_T))) {
+               ErrorCode = -EFAULT;
+               break;
+       }
        while (Controller->V2.HealthStatusBuffer->StatusChangeCounter
               == HealthStatusBuffer.StatusChangeCounter &&
               Controller->V2.HealthStatusBuffer->NextEventSequenceNumber
@@ -7012,21 +7050,28 @@ static int DAC960_gam_ioctl(struct inode *inode, struct file *file,
          {
            interruptible_sleep_on_timeout(&Controller->HealthStatusWaitQueue,
                                           DAC960_MonitoringTimerInterval);
-           if (signal_pending(current)) return -EINTR;
+           if (signal_pending(current)) {
+               ErrorCode = -EINTR;
+               break;
+           }
          }
        if (copy_to_user(GetHealthStatus.HealthStatusBuffer,
                         Controller->V2.HealthStatusBuffer,
                         sizeof(DAC960_V2_HealthStatusBuffer_T)))
-               return -EFAULT;
-       return 0;
+               ErrorCode = -EFAULT;
+       else
+               ErrorCode =  0;
       }
+      default:
+       ErrorCode = -ENOTTY;
     }
-  return -EINVAL;
+  unlock_kernel();
+  return ErrorCode;
 }
 
 static const struct file_operations DAC960_gam_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = DAC960_gam_ioctl
+       .unlocked_ioctl = DAC960_gam_ioctl
 };
 
 static struct miscdevice DAC960_gam_dev = {
index 41f818be2f7ec8c4c737acaa16ecfeddc94f42b4..2f1746295d06fc438ac4b1ba923c2aeb1d634dd8 100644 (file)
@@ -1003,7 +1003,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
         * Enough people have their dip switches set backwards to
         * warrant a loud message for this special case.
         */
-       aoemajor = be16_to_cpu(get_unaligned(&h->major));
+       aoemajor = get_unaligned_be16(&h->major);
        if (aoemajor == 0xfff) {
                printk(KERN_ERR "aoe: Warning: shelf address is all ones.  "
                        "Check shelf dip switches.\n");
index 5f1e1cc6165a91b5b5388dcabc8bac06d13db782..d81632cd7d062fd01bb2e2987dd8095b567c1e87 100644 (file)
@@ -106,35 +106,34 @@ MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
 /*  board_id = Subsystem Device ID & Vendor ID
  *  product = Marketing Name for the board
  *  access = Address of the struct of function pointers
- *  nr_cmds = Number of commands supported by controller
  */
 static struct board_type products[] = {
-       {0x40700E11, "Smart Array 5300", &SA5_access, 512},
-       {0x40800E11, "Smart Array 5i", &SA5B_access, 512},
-       {0x40820E11, "Smart Array 532", &SA5B_access, 512},
-       {0x40830E11, "Smart Array 5312", &SA5B_access, 512},
-       {0x409A0E11, "Smart Array 641", &SA5_access, 512},
-       {0x409B0E11, "Smart Array 642", &SA5_access, 512},
-       {0x409C0E11, "Smart Array 6400", &SA5_access, 512},
-       {0x409D0E11, "Smart Array 6400 EM", &SA5_access, 512},
-       {0x40910E11, "Smart Array 6i", &SA5_access, 512},
-       {0x3225103C, "Smart Array P600", &SA5_access, 512},
-       {0x3223103C, "Smart Array P800", &SA5_access, 512},
-       {0x3234103C, "Smart Array P400", &SA5_access, 512},
-       {0x3235103C, "Smart Array P400i", &SA5_access, 512},
-       {0x3211103C, "Smart Array E200i", &SA5_access, 120},
-       {0x3212103C, "Smart Array E200", &SA5_access, 120},
-       {0x3213103C, "Smart Array E200i", &SA5_access, 120},
-       {0x3214103C, "Smart Array E200i", &SA5_access, 120},
-       {0x3215103C, "Smart Array E200i", &SA5_access, 120},
-       {0x3237103C, "Smart Array E500", &SA5_access, 512},
-       {0x323D103C, "Smart Array P700m", &SA5_access, 512},
-       {0x3241103C, "Smart Array P212", &SA5_access, 384},
-       {0x3243103C, "Smart Array P410", &SA5_access, 384},
-       {0x3245103C, "Smart Array P410i", &SA5_access, 384},
-       {0x3247103C, "Smart Array P411", &SA5_access, 384},
-       {0x3249103C, "Smart Array P812", &SA5_access, 384},
-       {0xFFFF103C, "Unknown Smart Array", &SA5_access, 120},
+       {0x40700E11, "Smart Array 5300", &SA5_access},
+       {0x40800E11, "Smart Array 5i", &SA5B_access},
+       {0x40820E11, "Smart Array 532", &SA5B_access},
+       {0x40830E11, "Smart Array 5312", &SA5B_access},
+       {0x409A0E11, "Smart Array 641", &SA5_access},
+       {0x409B0E11, "Smart Array 642", &SA5_access},
+       {0x409C0E11, "Smart Array 6400", &SA5_access},
+       {0x409D0E11, "Smart Array 6400 EM", &SA5_access},
+       {0x40910E11, "Smart Array 6i", &SA5_access},
+       {0x3225103C, "Smart Array P600", &SA5_access},
+       {0x3223103C, "Smart Array P800", &SA5_access},
+       {0x3234103C, "Smart Array P400", &SA5_access},
+       {0x3235103C, "Smart Array P400i", &SA5_access},
+       {0x3211103C, "Smart Array E200i", &SA5_access},
+       {0x3212103C, "Smart Array E200", &SA5_access},
+       {0x3213103C, "Smart Array E200i", &SA5_access},
+       {0x3214103C, "Smart Array E200i", &SA5_access},
+       {0x3215103C, "Smart Array E200i", &SA5_access},
+       {0x3237103C, "Smart Array E500", &SA5_access},
+       {0x323D103C, "Smart Array P700m", &SA5_access},
+       {0x3241103C, "Smart Array P212", &SA5_access},
+       {0x3243103C, "Smart Array P410", &SA5_access},
+       {0x3245103C, "Smart Array P410i", &SA5_access},
+       {0x3247103C, "Smart Array P411", &SA5_access},
+       {0x3249103C, "Smart Array P812", &SA5_access},
+       {0xFFFF103C, "Unknown Smart Array", &SA5_access},
 };
 
 /* How long to wait (in milliseconds) for board to go into simple mode */
@@ -3086,11 +3085,20 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
        print_cfg_table(c->cfgtable);
 #endif                         /* CCISS_DEBUG */
 
+       /* Some controllers support Zero Memory Raid (ZMR).
+        * When configured in ZMR mode the number of supported
+        * commands drops to 64. So instead of just setting an
+        * arbitrary value we make the driver a little smarter.
+        * We read the config table to tell us how many commands
+        * are supported on the controller then subtract 4 to
+        * leave a little room for ioctl calls.
+        */
+       c->max_commands = readl(&(c->cfgtable->CmdsOutMax));
        for (i = 0; i < ARRAY_SIZE(products); i++) {
                if (board_id == products[i].board_id) {
                        c->product_name = products[i].product_name;
                        c->access = *(products[i].access);
-                       c->nr_cmds = products[i].nr_cmds;
+                       c->nr_cmds = c->max_commands - 4;
                        break;
                }
        }
@@ -3110,7 +3118,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
                if (subsystem_vendor_id == PCI_VENDOR_ID_HP) {
                        c->product_name = products[i-1].product_name;
                        c->access = *(products[i-1].access);
-                       c->nr_cmds = products[i-1].nr_cmds;
+                       c->nr_cmds = c->max_commands - 4;
                        printk(KERN_WARNING "cciss: This is an unknown "
                                "Smart Array controller.\n"
                                "cciss: Please update to the latest driver "
@@ -3546,6 +3554,10 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        for (j = 0; j <= hba[i]->highest_lun; j++)
                add_disk(hba[i]->gendisk[j]);
 
+       /* we must register the controller even if no disks exist */
+       if (hba[i]->highest_lun == -1)
+               add_disk(hba[i]->gendisk[0]);
+
        return 1;
 
       clean4:
index 8b9549ab4a4e6eafd21b2e38b835618448cf31d9..27455ee1e9da555f680c7a694cf5874e9198a31b 100644 (file)
@@ -146,6 +146,7 @@ static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
 #include <linux/mtio.h>
 #include <linux/device.h>
 #include <linux/sched.h>       /* current, TASK_*, schedule_timeout() */
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 
@@ -189,8 +190,7 @@ module_param_array(drive3, int, NULL, 0);
 #define ATAPI_LOG_SENSE                0x4d
 
 static int pt_open(struct inode *inode, struct file *file);
-static int pt_ioctl(struct inode *inode, struct file *file,
-                   unsigned int cmd, unsigned long arg);
+static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 static int pt_release(struct inode *inode, struct file *file);
 static ssize_t pt_read(struct file *filp, char __user *buf,
                       size_t count, loff_t * ppos);
@@ -236,7 +236,7 @@ static const struct file_operations pt_fops = {
        .owner = THIS_MODULE,
        .read = pt_read,
        .write = pt_write,
-       .ioctl = pt_ioctl,
+       .unlocked_ioctl = pt_ioctl,
        .open = pt_open,
        .release = pt_release,
 };
@@ -685,8 +685,7 @@ out:
        return err;
 }
 
-static int pt_ioctl(struct inode *inode, struct file *file,
-        unsigned int cmd, unsigned long arg)
+static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct pt_unit *tape = file->private_data;
        struct mtop __user *p = (void __user *)arg;
@@ -700,23 +699,26 @@ static int pt_ioctl(struct inode *inode, struct file *file,
                switch (mtop.mt_op) {
 
                case MTREW:
+                       lock_kernel();
                        pt_rewind(tape);
+                       unlock_kernel();
                        return 0;
 
                case MTWEOF:
+                       lock_kernel();
                        pt_write_fm(tape);
+                       unlock_kernel();
                        return 0;
 
                default:
-                       printk("%s: Unimplemented mt_op %d\n", tape->name,
+                       /* FIXME: rate limit ?? */
+                       printk(KERN_DEBUG "%s: Unimplemented mt_op %d\n", tape->name,
                               mtop.mt_op);
                        return -EINVAL;
                }
 
        default:
-               printk("%s: Unimplemented ioctl 0x%x\n", tape->name, cmd);
-               return -EINVAL;
-
+               return -ENOTTY;
        }
 }
 
index 3ba1df93e9e32e8fb3c8641f7f11b9a33a575cc2..45bee918c46a821e5a5c4ec3c2a74ad96b8d8e72 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
+#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/spinlock.h>
 #include <linux/file.h>
@@ -2079,7 +2080,6 @@ static noinline_for_stack int pkt_write_caching(struct pktcdvd_device *pd,
        unsigned char buf[64];
        int ret;
 
-       memset(buf, 0, sizeof(buf));
        init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
        cgc.sense = &sense;
        cgc.buflen = pd->mode_offset + 12;
@@ -2126,7 +2126,6 @@ static noinline_for_stack int pkt_get_max_speed(struct pktcdvd_device *pd,
        unsigned char *cap_buf;
        int ret, offset;
 
-       memset(buf, 0, sizeof(buf));
        cap_buf = &buf[sizeof(struct mode_page_header) + pd->mode_offset];
        init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_UNKNOWN);
        cgc.sense = &sense;
@@ -2633,11 +2632,12 @@ end_io:
 
 
 
-static int pkt_merge_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *bvec)
+static int pkt_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd,
+                         struct bio_vec *bvec)
 {
        struct pktcdvd_device *pd = q->queuedata;
-       sector_t zone = ZONE(bio->bi_sector, pd);
-       int used = ((bio->bi_sector - zone) << 9) + bio->bi_size;
+       sector_t zone = ZONE(bmd->bi_sector, pd);
+       int used = ((bmd->bi_sector - zone) << 9) + bmd->bi_size;
        int remaining = (pd->settings.size << 9) - used;
        int remaining2;
 
@@ -2645,7 +2645,7 @@ static int pkt_merge_bvec(struct request_queue *q, struct bio *bio, struct bio_v
         * A bio <= PAGE_SIZE must be allowed. If it crosses a packet
         * boundary, pkt_make_request() will split the bio.
         */
-       remaining2 = PAGE_SIZE - bio->bi_size;
+       remaining2 = PAGE_SIZE - bmd->bi_size;
        remaining = max(remaining, remaining2);
 
        BUG_ON(remaining < 0);
@@ -2796,9 +2796,14 @@ out_mem:
        return ret;
 }
 
-static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long pkt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data;
+       struct inode *inode = file->f_path.dentry->d_inode;
+       struct pktcdvd_device *pd;
+       long ret;
+
+       lock_kernel();
+       pd = inode->i_bdev->bd_disk->private_data;
 
        VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode));
 
@@ -2811,7 +2816,8 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
        case CDROM_LAST_WRITTEN:
        case CDROM_SEND_PACKET:
        case SCSI_IOCTL_SEND_COMMAND:
-               return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
+               ret = blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
+               break;
 
        case CDROMEJECT:
                /*
@@ -2820,14 +2826,15 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
                 */
                if (pd->refcnt == 1)
                        pkt_lock_door(pd, 0);
-               return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
+               ret = blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
+               break;
 
        default:
                VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd);
-               return -ENOTTY;
+               ret = -ENOTTY;
        }
-
-       return 0;
+       unlock_kernel();
+       return ret;
 }
 
 static int pkt_media_changed(struct gendisk *disk)
@@ -2849,7 +2856,7 @@ static struct block_device_operations pktcdvd_ops = {
        .owner =                THIS_MODULE,
        .open =                 pkt_open,
        .release =              pkt_close,
-       .ioctl =                pkt_ioctl,
+       .unlocked_ioctl =       pkt_ioctl,
        .media_changed =        pkt_media_changed,
 };
 
@@ -3014,7 +3021,8 @@ static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd)
        mutex_unlock(&ctl_mutex);
 }
 
-static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long pkt_ctl_ioctl(struct file *file, unsigned int cmd,
+                                               unsigned long arg)
 {
        void __user *argp = (void __user *)arg;
        struct pkt_ctrl_command ctrl_cmd;
@@ -3031,16 +3039,22 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm
        case PKT_CTRL_CMD_SETUP:
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
+               lock_kernel();
                ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev);
                ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev);
+               unlock_kernel();
                break;
        case PKT_CTRL_CMD_TEARDOWN:
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
+               lock_kernel();
                ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev));
+               unlock_kernel();
                break;
        case PKT_CTRL_CMD_STATUS:
+               lock_kernel();
                pkt_get_status(&ctrl_cmd);
+               unlock_kernel();
                break;
        default:
                return -ENOTTY;
@@ -3053,7 +3067,7 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm
 
 
 static const struct file_operations pkt_ctl_fops = {
-       .ioctl   = pkt_ctl_ioctl,
+       .unlocked_ioctl  = pkt_ctl_ioctl,
        .owner   = THIS_MODULE,
 };
 
index f2fff5799ddf0fe1b41909b64d606d747f9081f7..9ae05c5842344c56d06a187764dbd328ab5e4822 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/cdrom.h>
 #include <linux/module.h>
 
 #include <xen/xenbus.h>
@@ -153,6 +154,40 @@ static int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg)
        return 0;
 }
 
+int blkif_ioctl(struct inode *inode, struct file *filep,
+               unsigned command, unsigned long argument)
+{
+       struct blkfront_info *info =
+               inode->i_bdev->bd_disk->private_data;
+       int i;
+
+       dev_dbg(&info->xbdev->dev, "command: 0x%x, argument: 0x%lx\n",
+               command, (long)argument);
+
+       switch (command) {
+       case CDROMMULTISESSION:
+               dev_dbg(&info->xbdev->dev, "FIXME: support multisession CDs later\n");
+               for (i = 0; i < sizeof(struct cdrom_multisession); i++)
+                       if (put_user(0, (char __user *)(argument + i)))
+                               return -EFAULT;
+               return 0;
+
+       case CDROM_GET_CAPABILITY: {
+               struct gendisk *gd = info->gd;
+               if (gd->flags & GENHD_FL_CD)
+                       return 0;
+               return -EINVAL;
+       }
+
+       default:
+               /*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n",
+                 command);*/
+               return -EINVAL; /* same return as native Linux */
+       }
+
+       return 0;
+}
+
 /*
  * blkif_queue_request
  *
@@ -324,6 +359,9 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
        /* Make sure buffer addresses are sector-aligned. */
        blk_queue_dma_alignment(rq, 511);
 
+       /* Make sure we don't use bounce buffers. */
+       blk_queue_bounce_limit(rq, BLK_BOUNCE_ANY);
+
        gd->queue = rq;
 
        return 0;
@@ -546,7 +584,7 @@ static int setup_blkring(struct xenbus_device *dev,
 
        info->ring_ref = GRANT_INVALID_REF;
 
-       sring = (struct blkif_sring *)__get_free_page(GFP_KERNEL);
+       sring = (struct blkif_sring *)__get_free_page(GFP_NOIO | __GFP_HIGH);
        if (!sring) {
                xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
                return -ENOMEM;
@@ -703,7 +741,8 @@ static int blkif_recover(struct blkfront_info *info)
        int j;
 
        /* Stage 1: Make a safe copy of the shadow state. */
-       copy = kmalloc(sizeof(info->shadow), GFP_KERNEL);
+       copy = kmalloc(sizeof(info->shadow),
+                      GFP_NOIO | __GFP_REPEAT | __GFP_HIGH);
        if (!copy)
                return -ENOMEM;
        memcpy(copy, info->shadow, sizeof(info->shadow));
@@ -959,7 +998,7 @@ static int blkif_release(struct inode *inode, struct file *filep)
                struct xenbus_device *dev = info->xbdev;
                enum xenbus_state state = xenbus_read_driver_state(dev->otherend);
 
-               if (state == XenbusStateClosing)
+               if (state == XenbusStateClosing && info->is_ready)
                        blkfront_closing(dev);
        }
        return 0;
@@ -971,6 +1010,7 @@ static struct block_device_operations xlvbd_block_fops =
        .open = blkif_open,
        .release = blkif_release,
        .getgeo = blkif_getgeo,
+       .ioctl = blkif_ioctl,
 };
 
 
@@ -1006,7 +1046,7 @@ static int __init xlblk_init(void)
 module_init(xlblk_init);
 
 
-static void xlblk_exit(void)
+static void __exit xlblk_exit(void)
 {
        return xenbus_unregister_driver(&blkfront);
 }
index 69f26eb6415bdbb9824ed89ca1307134fe55b647..a5da356326515c637f7a66ff04c1cd018c828f31 100644 (file)
@@ -461,37 +461,27 @@ int cdrom_get_media_event(struct cdrom_device_info *cdi,
                          struct media_event_desc *med)
 {
        struct packet_command cgc;
-       unsigned char *buffer;
-       struct event_header *eh;
-       int ret = 1;
-
-       buffer = kmalloc(8, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
+       unsigned char buffer[8];
+       struct event_header *eh = (struct event_header *) buffer;
 
-       eh = (struct event_header *)buffer;
-
-       init_cdrom_command(&cgc, buffer, 8, CGC_DATA_READ);
+       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
        cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
        cgc.cmd[1] = 1;         /* IMMED */
        cgc.cmd[4] = 1 << 4;    /* media event */
-       cgc.cmd[8] = 8;
+       cgc.cmd[8] = sizeof(buffer);
        cgc.quiet = 1;
 
        if (cdi->ops->generic_packet(cdi, &cgc))
-               goto err;
+               return 1;
 
        if (be16_to_cpu(eh->data_len) < sizeof(*med))
-               goto err;
+               return 1;
 
        if (eh->nea || eh->notification_class != 0x4)
-               goto err;
+               return 1;
 
-       memcpy(med, buffer + sizeof(*eh), sizeof(*med));
-       ret = 0;
-err:
-       kfree(buffer);
-       return ret;
+       memcpy(med, &buffer[sizeof(*eh)], sizeof(*med));
+       return 0;
 }
 
 /*
@@ -501,82 +491,68 @@ err:
 static int cdrom_mrw_probe_pc(struct cdrom_device_info *cdi)
 {
        struct packet_command cgc;
-       char *buffer;
-       int ret = 1;
-
-       buffer = kmalloc(16, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
+       char buffer[16];
 
-       init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
 
        cgc.timeout = HZ;
        cgc.quiet = 1;
 
        if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC, 0)) {
                cdi->mrw_mode_page = MRW_MODE_PC;
-               ret = 0;
+               return 0;
        } else if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC_PRE1, 0)) {
                cdi->mrw_mode_page = MRW_MODE_PC_PRE1;
-               ret = 0;
+               return 0;
        }
-       kfree(buffer);
-       return ret;
+
+       return 1;
 }
 
 static int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write)
 {
        struct packet_command cgc;
        struct mrw_feature_desc *mfd;
-       unsigned char *buffer;
+       unsigned char buffer[16];
        int ret;
 
        *write = 0;
-       buffer = kmalloc(16, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
 
-       init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
 
        cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
        cgc.cmd[3] = CDF_MRW;
-       cgc.cmd[8] = 16;
+       cgc.cmd[8] = sizeof(buffer);
        cgc.quiet = 1;
 
        if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
-               goto err;
+               return ret;
 
        mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)];
-       if (be16_to_cpu(mfd->feature_code) != CDF_MRW) {
-               ret = 1;
-               goto err;
-       }
+       if (be16_to_cpu(mfd->feature_code) != CDF_MRW)
+               return 1;
        *write = mfd->write;
 
        if ((ret = cdrom_mrw_probe_pc(cdi))) {
                *write = 0;
+               return ret;
        }
-err:
-       kfree(buffer);
-       return ret;
+
+       return 0;
 }
 
 static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
 {
        struct packet_command cgc;
-       unsigned char *buffer;
+       unsigned char buffer[12];
        int ret;
 
        printk(KERN_INFO "cdrom: %sstarting format\n", cont ? "Re" : "");
 
-       buffer = kmalloc(12, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
        /*
         * FmtData bit set (bit 4), format type is 1
         */
-       init_cdrom_command(&cgc, buffer, 12, CGC_DATA_WRITE);
+       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_WRITE);
        cgc.cmd[0] = GPCMD_FORMAT_UNIT;
        cgc.cmd[1] = (1 << 4) | 1;
 
@@ -603,7 +579,6 @@ static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
        if (ret)
                printk(KERN_INFO "cdrom: bgformat failed\n");
 
-       kfree(buffer);
        return ret;
 }
 
@@ -663,17 +638,16 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
 {
        struct packet_command cgc;
        struct mode_page_header *mph;
-       char *buffer;
+       char buffer[16];
        int ret, offset, size;
 
-       buffer = kmalloc(16, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
+       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
 
-       init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+       cgc.buffer = buffer;
+       cgc.buflen = sizeof(buffer);
 
        if ((ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0)))
-               goto err;
+               return ret;
 
        mph = (struct mode_page_header *) buffer;
        offset = be16_to_cpu(mph->desc_length);
@@ -683,70 +657,55 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
        cgc.buflen = size;
 
        if ((ret = cdrom_mode_select(cdi, &cgc)))
-               goto err;
+               return ret;
 
        printk(KERN_INFO "cdrom: %s: mrw address space %s selected\n", cdi->name, mrw_address_space[space]);
-       ret = 0;
-err:
-       kfree(buffer);
-       return ret;
+       return 0;
 }
 
 static int cdrom_get_random_writable(struct cdrom_device_info *cdi,
                              struct rwrt_feature_desc *rfd)
 {
        struct packet_command cgc;
-       char *buffer;
+       char buffer[24];
        int ret;
 
-       buffer = kmalloc(24, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
-       init_cdrom_command(&cgc, buffer, 24, CGC_DATA_READ);
+       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
 
        cgc.cmd[0] = GPCMD_GET_CONFIGURATION;   /* often 0x46 */
        cgc.cmd[3] = CDF_RWRT;                  /* often 0x0020 */
-       cgc.cmd[8] = 24;                        /* often 0x18 */
+       cgc.cmd[8] = sizeof(buffer);            /* often 0x18 */
        cgc.quiet = 1;
 
        if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
-               goto err;
+               return ret;
 
        memcpy(rfd, &buffer[sizeof(struct feature_header)], sizeof (*rfd));
-       ret = 0;
-err:
-       kfree(buffer);
-       return ret;
+       return 0;
 }
 
 static int cdrom_has_defect_mgt(struct cdrom_device_info *cdi)
 {
        struct packet_command cgc;
-       char *buffer;
+       char buffer[16];
        __be16 *feature_code;
        int ret;
 
-       buffer = kmalloc(16, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
-       init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
+       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
 
        cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
        cgc.cmd[3] = CDF_HWDM;
-       cgc.cmd[8] = 16;
+       cgc.cmd[8] = sizeof(buffer);
        cgc.quiet = 1;
 
        if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
-               goto err;
+               return ret;
 
        feature_code = (__be16 *) &buffer[sizeof(struct feature_header)];
        if (be16_to_cpu(*feature_code) == CDF_HWDM)
-               ret = 0;
-err:
-       kfree(buffer);
-       return ret;
+               return 0;
+
+       return 1;
 }
 
 
@@ -837,14 +796,10 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi)
 static int mo_open_write(struct cdrom_device_info *cdi)
 {
        struct packet_command cgc;
-       char *buffer;
+       char buffer[255];
        int ret;
 
-       buffer = kmalloc(255, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
-       init_cdrom_command(&cgc, buffer, 4, CGC_DATA_READ);
+       init_cdrom_command(&cgc, &buffer, 4, CGC_DATA_READ);
        cgc.quiet = 1;
 
        /*
@@ -861,15 +816,10 @@ static int mo_open_write(struct cdrom_device_info *cdi)
        }
 
        /* drive gave us no info, let the user go ahead */
-       if (ret) {
-               ret = 0;
-               goto err;
-       }
+       if (ret)
+               return 0;
 
-       ret = buffer[3] & 0x80;
-err:
-       kfree(buffer);
-       return ret;
+       return buffer[3] & 0x80;
 }
 
 static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
@@ -892,19 +842,15 @@ static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
 static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
 {
        struct packet_command cgc;
-       char *buffer;
+       char buffer[32];
        int ret, mmc3_profile;
 
-       buffer = kmalloc(32, GFP_KERNEL);
-       if (!buffer)
-               return;
-
-       init_cdrom_command(&cgc, buffer, 32, CGC_DATA_READ);
+       init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
 
        cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
        cgc.cmd[1] = 0;
        cgc.cmd[2] = cgc.cmd[3] = 0;            /* Starting Feature Number */
-       cgc.cmd[8] = 32;                        /* Allocation Length */
+       cgc.cmd[8] = sizeof(buffer);            /* Allocation Length */
        cgc.quiet = 1;
 
        if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
@@ -913,7 +859,6 @@ static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
                mmc3_profile = (buffer[6] << 8) | buffer[7];
 
        cdi->mmc3_profile = mmc3_profile;
-       kfree(buffer);
 }
 
 static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi)
@@ -1628,15 +1573,12 @@ static void setup_send_key(struct packet_command *cgc, unsigned agid, unsigned t
 static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
 {
        int ret;
-       u_char *buf;
+       u_char buf[20];
        struct packet_command cgc;
        struct cdrom_device_ops *cdo = cdi->ops;
-       rpc_state_t *rpc_state;
-
-       buf = kzalloc(20, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
+       rpc_state_t rpc_state;
 
+       memset(buf, 0, sizeof(buf));
        init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ);
 
        switch (ai->type) {
@@ -1647,7 +1589,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                setup_report_key(&cgc, ai->lsa.agid, 0);
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       goto err;
+                       return ret;
 
                ai->lsa.agid = buf[7] >> 6;
                /* Returning data, let host change state */
@@ -1658,7 +1600,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                setup_report_key(&cgc, ai->lsk.agid, 2);
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       goto err;
+                       return ret;
 
                copy_key(ai->lsk.key, &buf[4]);
                /* Returning data, let host change state */
@@ -1669,7 +1611,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                setup_report_key(&cgc, ai->lsc.agid, 1);
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       goto err;
+                       return ret;
 
                copy_chal(ai->lsc.chal, &buf[4]);
                /* Returning data, let host change state */
@@ -1686,7 +1628,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                cgc.cmd[2] = ai->lstk.lba >> 24;
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       goto err;
+                       return ret;
 
                ai->lstk.cpm = (buf[4] >> 7) & 1;
                ai->lstk.cp_sec = (buf[4] >> 6) & 1;
@@ -1700,7 +1642,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                setup_report_key(&cgc, ai->lsasf.agid, 5);
                
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       goto err;
+                       return ret;
 
                ai->lsasf.asf = buf[7] & 1;
                break;
@@ -1713,7 +1655,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                copy_chal(&buf[4], ai->hsc.chal);
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       goto err;
+                       return ret;
 
                ai->type = DVD_LU_SEND_KEY1;
                break;
@@ -1726,7 +1668,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
 
                if ((ret = cdo->generic_packet(cdi, &cgc))) {
                        ai->type = DVD_AUTH_FAILURE;
-                       goto err;
+                       return ret;
                }
                ai->type = DVD_AUTH_ESTABLISHED;
                break;
@@ -1737,23 +1679,24 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n"); 
                setup_report_key(&cgc, ai->lsa.agid, 0x3f);
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       goto err;
+                       return ret;
                break;
 
        /* Get region settings */
        case DVD_LU_SEND_RPC_STATE:
                cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
                setup_report_key(&cgc, 0, 8);
+               memset(&rpc_state, 0, sizeof(rpc_state_t));
+               cgc.buffer = (char *) &rpc_state;
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       goto err;
+                       return ret;
 
-               rpc_state = (rpc_state_t *)buf;
-               ai->lrpcs.type = rpc_state->type_code;
-               ai->lrpcs.vra = rpc_state->vra;
-               ai->lrpcs.ucca = rpc_state->ucca;
-               ai->lrpcs.region_mask = rpc_state->region_mask;
-               ai->lrpcs.rpc_scheme = rpc_state->rpc_scheme;
+               ai->lrpcs.type = rpc_state.type_code;
+               ai->lrpcs.vra = rpc_state.vra;
+               ai->lrpcs.ucca = rpc_state.ucca;
+               ai->lrpcs.region_mask = rpc_state.region_mask;
+               ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme;
                break;
 
        /* Set region settings */
@@ -1764,23 +1707,20 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
                buf[4] = ai->hrpcs.pdrc;
 
                if ((ret = cdo->generic_packet(cdi, &cgc)))
-                       goto err;
+                       return ret;
                break;
 
        default:
                cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type);
-               ret = -ENOTTY;
-               goto err;
+               return -ENOTTY;
        }
-       ret = 0;
-err:
-       kfree(buf);
-       return ret;
+
+       return 0;
 }
 
 static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
 {
-       unsigned char *buf, *base;
+       unsigned char buf[21], *base;
        struct dvd_layer *layer;
        struct packet_command cgc;
        struct cdrom_device_ops *cdo = cdi->ops;
@@ -1789,11 +1729,7 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
        if (layer_num >= DVD_LAYERS)
                return -EINVAL;
 
-       buf = kmalloc(21, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       init_cdrom_command(&cgc, buf, 21, CGC_DATA_READ);
+       init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
        cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
        cgc.cmd[6] = layer_num;
        cgc.cmd[7] = s->type;
@@ -1805,7 +1741,7 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
        cgc.quiet = 1;
 
        if ((ret = cdo->generic_packet(cdi, &cgc)))
-               goto err;
+               return ret;
 
        base = &buf[4];
        layer = &s->physical.layer[layer_num];
@@ -1829,24 +1765,17 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
        layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];
        layer->bca = base[16] >> 7;
 
-       ret = 0;
-err:
-       kfree(buf);
-       return ret;
+       return 0;
 }
 
 static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
 {
        int ret;
-       u_char *buf;
+       u_char buf[8];
        struct packet_command cgc;
        struct cdrom_device_ops *cdo = cdi->ops;
 
-       buf = kmalloc(8, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       init_cdrom_command(&cgc, buf, 8, CGC_DATA_READ);
+       init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
        cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
        cgc.cmd[6] = s->copyright.layer_num;
        cgc.cmd[7] = s->type;
@@ -1854,15 +1783,12 @@ static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
        cgc.cmd[9] = cgc.buflen & 0xff;
 
        if ((ret = cdo->generic_packet(cdi, &cgc)))
-               goto err;
+               return ret;
 
        s->copyright.cpst = buf[4];
        s->copyright.rmi = buf[5];
 
-       ret = 0;
-err:
-       kfree(buf);
-       return ret;
+       return 0;
 }
 
 static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
@@ -1894,33 +1820,26 @@ static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
 static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s)
 {
        int ret;
-       u_char *buf;
+       u_char buf[4 + 188];
        struct packet_command cgc;
        struct cdrom_device_ops *cdo = cdi->ops;
 
-       buf = kmalloc(4 + 188, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       init_cdrom_command(&cgc, buf, 4 + 188, CGC_DATA_READ);
+       init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
        cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
        cgc.cmd[7] = s->type;
        cgc.cmd[9] = cgc.buflen & 0xff;
 
        if ((ret = cdo->generic_packet(cdi, &cgc)))
-               goto err;
+               return ret;
 
        s->bca.len = buf[0] << 8 | buf[1];
        if (s->bca.len < 12 || s->bca.len > 188) {
                cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len);
-               ret = -EIO;
-               goto err;
+               return -EIO;
        }
        memcpy(s->bca.value, &buf[4], s->bca.len);
-       ret = 0;
-err:
-       kfree(buf);
-       return ret;
+
+       return 0;
 }
 
 static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s)
@@ -2020,13 +1939,9 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
 {
        struct cdrom_device_ops *cdo = cdi->ops;
        struct packet_command cgc;
-       char *buffer;
+       char buffer[32];
        int ret;
 
-       buffer = kmalloc(32, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
        init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
        cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
        cgc.cmd[1] = 2;     /* MSF addressing */
@@ -2035,7 +1950,7 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
        cgc.cmd[8] = 16;
 
        if ((ret = cdo->generic_packet(cdi, &cgc)))
-               goto err;
+               return ret;
 
        subchnl->cdsc_audiostatus = cgc.buffer[1];
        subchnl->cdsc_format = CDROM_MSF;
@@ -2050,10 +1965,7 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
        subchnl->cdsc_absaddr.msf.second = cgc.buffer[10];
        subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11];
 
-       ret = 0;
-err:
-       kfree(buffer);
-       return ret;
+       return 0;
 }
 
 /*
index 4c1c584e9eb678d366e575a3cd983b287d4419e0..81630a68475cd7ad8859c650c20a6431fae60539 100644 (file)
@@ -101,7 +101,6 @@ obj-$(CONFIG_TELCLOCK)              += tlclk.o
 
 obj-$(CONFIG_MWAVE)            += mwave/
 obj-$(CONFIG_AGP)              += agp/
-obj-$(CONFIG_DRM)              += drm/
 obj-$(CONFIG_PCMCIA)           += pcmcia/
 obj-$(CONFIG_IPMI_HANDLER)     += ipmi/
 
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
deleted file mode 100644 (file)
index 610d6fd..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-#
-# Drm device configuration
-#
-# This driver provides support for the
-# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
-#
-menuconfig DRM
-       tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
-       depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG
-       help
-         Kernel-level support for the Direct Rendering Infrastructure (DRI)
-         introduced in XFree86 4.0. If you say Y here, you need to select
-         the module that's right for your graphics card from the list below.
-         These modules provide support for synchronization, security, and
-         DMA transfers. Please see <http://dri.sourceforge.net/> for more
-         details.  You should also select and configure AGP
-         (/dev/agpgart) support.
-
-config DRM_TDFX
-       tristate "3dfx Banshee/Voodoo3+"
-       depends on DRM && PCI
-       help
-         Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
-         graphics card.  If M is selected, the module will be called tdfx.
-
-config DRM_R128
-       tristate "ATI Rage 128"
-       depends on DRM && PCI
-       help
-         Choose this option if you have an ATI Rage 128 graphics card.  If M
-         is selected, the module will be called r128.  AGP support for
-         this card is strongly suggested (unless you have a PCI version).
-
-config DRM_RADEON
-       tristate "ATI Radeon"
-       depends on DRM && PCI
-       help
-         Choose this option if you have an ATI Radeon graphics card.  There
-         are both PCI and AGP versions.  You don't need to choose this to
-         run the Radeon in plain VGA mode.
-
-         If M is selected, the module will be called radeon.
-
-config DRM_I810
-       tristate "Intel I810"
-       depends on DRM && AGP && AGP_INTEL
-       help
-         Choose this option if you have an Intel I810 graphics card.  If M is
-         selected, the module will be called i810.  AGP support is required
-         for this driver to work.
-
-choice
-       prompt "Intel 830M, 845G, 852GM, 855GM, 865G"
-       depends on DRM && AGP && AGP_INTEL
-       optional
-
-config DRM_I830
-       tristate "i830 driver"
-       help
-         Choose this option if you have a system that has Intel 830M, 845G,
-         852GM, 855GM or 865G integrated graphics.  If M is selected, the
-         module will be called i830.  AGP support is required for this driver
-         to work. This driver is used by the older X releases X.org 6.7 and
-         XFree86 4.3. If unsure, build this and i915 as modules and the X server
-         will load the correct one.
-
-config DRM_I915
-       tristate "i915 driver"
-       help
-         Choose this option if you have a system that has Intel 830M, 845G,
-         852GM, 855GM 865G or 915G integrated graphics.  If M is selected, the
-         module will be called i915.  AGP support is required for this driver
-         to work. This driver is used by the Intel driver in X.org 6.8 and
-         XFree86 4.4 and above. If unsure, build this and i830 as modules and
-         the X server will load the correct one.
-
-endchoice
-
-config DRM_MGA
-       tristate "Matrox g200/g400"
-       depends on DRM
-       help
-         Choose this option if you have a Matrox G200, G400 or G450 graphics
-         card.  If M is selected, the module will be called mga.  AGP
-         support is required for this driver to work.
-
-config DRM_SIS
-       tristate "SiS video cards"
-       depends on DRM && AGP
-       help
-         Choose this option if you have a SiS 630 or compatible video
-          chipset. If M is selected the module will be called sis. AGP
-          support is required for this driver to work.
-
-config DRM_VIA
-       tristate "Via unichrome video cards"
-       depends on DRM
-       help
-         Choose this option if you have a Via unichrome or compatible video
-         chipset. If M is selected the module will be called via.
-
-config DRM_SAVAGE
-       tristate "Savage video cards"
-       depends on DRM
-       help
-         Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
-         chipset. If M is selected the module will be called savage.
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
deleted file mode 100644 (file)
index 1283ded..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Makefile for the drm device driver.  This driver provides support for the
-# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
-
-drm-objs    := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
-               drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \
-               drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
-               drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
-               drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o
-
-tdfx-objs   := tdfx_drv.o
-r128-objs   := r128_drv.o r128_cce.o r128_state.o r128_irq.o
-mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
-i810-objs   := i810_drv.o i810_dma.o
-i830-objs   := i830_drv.o i830_dma.o i830_irq.o
-i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
-radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o
-sis-objs    := sis_drv.o sis_mm.o
-savage-objs := savage_drv.o savage_bci.o savage_state.o
-via-objs    := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o
-
-ifeq ($(CONFIG_COMPAT),y)
-drm-objs    += drm_ioc32.o
-radeon-objs += radeon_ioc32.o
-mga-objs    += mga_ioc32.o
-r128-objs   += r128_ioc32.o
-i915-objs   += i915_ioc32.o
-endif
-
-obj-$(CONFIG_DRM)      += drm.o
-obj-$(CONFIG_DRM_TDFX) += tdfx.o
-obj-$(CONFIG_DRM_R128) += r128.o
-obj-$(CONFIG_DRM_RADEON)+= radeon.o
-obj-$(CONFIG_DRM_MGA)  += mga.o
-obj-$(CONFIG_DRM_I810) += i810.o
-obj-$(CONFIG_DRM_I830) += i830.o
-obj-$(CONFIG_DRM_I915)  += i915.o
-obj-$(CONFIG_DRM_SIS)   += sis.o
-obj-$(CONFIG_DRM_SAVAGE)+= savage.o
-obj-$(CONFIG_DRM_VIA)  +=via.o
diff --git a/drivers/char/drm/README.drm b/drivers/char/drm/README.drm
deleted file mode 100644 (file)
index b5b3327..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-************************************************************
-* For the very latest on DRI development, please see:      *
-*     http://dri.freedesktop.org/                          *
-************************************************************
-
-The Direct Rendering Manager (drm) is a device-independent kernel-level
-device driver that provides support for the XFree86 Direct Rendering
-Infrastructure (DRI).
-
-The DRM supports the Direct Rendering Infrastructure (DRI) in four major
-ways:
-
-    1. The DRM provides synchronized access to the graphics hardware via
-       the use of an optimized two-tiered lock.
-
-    2. The DRM enforces the DRI security policy for access to the graphics
-       hardware by only allowing authenticated X11 clients access to
-       restricted regions of memory.
-
-    3. The DRM provides a generic DMA engine, complete with multiple
-       queues and the ability to detect the need for an OpenGL context
-       switch.
-
-    4. The DRM is extensible via the use of small device-specific modules
-       that rely extensively on the API exported by the DRM module.
-
-
-Documentation on the DRI is available from:
-    http://dri.freedesktop.org/wiki/Documentation
-    http://sourceforge.net/project/showfiles.php?group_id=387
-    http://dri.sourceforge.net/doc/
-
-For specific information about kernel-level support, see:
-
-    The Direct Rendering Manager, Kernel Support for the Direct Rendering
-    Infrastructure
-    http://dri.sourceforge.net/doc/drm_low_level.html
-
-    Hardware Locking for the Direct Rendering Infrastructure
-    http://dri.sourceforge.net/doc/hardware_locking_low_level.html
-
-    A Security Analysis of the Direct Rendering Infrastructure
-    http://dri.sourceforge.net/doc/security_low_level.html
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
deleted file mode 100644 (file)
index c533d0c..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/**
- * \file ati_pcigart.c
- * ATI PCI GART support
- *
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
- *
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-# define ATI_PCIGART_PAGE_SIZE         4096    /**< PCI GART page size */
-
-static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
-                                      struct drm_ati_pcigart_info *gart_info)
-{
-       gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size,
-                                               PAGE_SIZE,
-                                               gart_info->table_mask);
-       if (gart_info->table_handle == NULL)
-               return -ENOMEM;
-
-       return 0;
-}
-
-static void drm_ati_free_pcigart_table(struct drm_device *dev,
-                                      struct drm_ati_pcigart_info *gart_info)
-{
-       drm_pci_free(dev, gart_info->table_handle);
-       gart_info->table_handle = NULL;
-}
-
-int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
-{
-       struct drm_sg_mem *entry = dev->sg;
-       unsigned long pages;
-       int i;
-       int max_pages;
-
-       /* we need to support large memory configurations */
-       if (!entry) {
-               DRM_ERROR("no scatter/gather memory!\n");
-               return 0;
-       }
-
-       if (gart_info->bus_addr) {
-
-               max_pages = (gart_info->table_size / sizeof(u32));
-               pages = (entry->pages <= max_pages)
-                 ? entry->pages : max_pages;
-
-               for (i = 0; i < pages; i++) {
-                       if (!entry->busaddr[i])
-                               break;
-                       pci_unmap_page(dev->pdev, entry->busaddr[i],
-                                        PAGE_SIZE, PCI_DMA_TODEVICE);
-               }
-
-               if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
-                       gart_info->bus_addr = 0;
-       }
-
-       if (gart_info->gart_table_location == DRM_ATI_GART_MAIN &&
-           gart_info->table_handle) {
-               drm_ati_free_pcigart_table(dev, gart_info);
-       }
-
-       return 1;
-}
-EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
-
-int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
-{
-       struct drm_sg_mem *entry = dev->sg;
-       void *address = NULL;
-       unsigned long pages;
-       u32 *pci_gart, page_base;
-       dma_addr_t bus_address = 0;
-       int i, j, ret = 0;
-       int max_pages;
-
-       if (!entry) {
-               DRM_ERROR("no scatter/gather memory!\n");
-               goto done;
-       }
-
-       if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
-               DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
-
-               ret = drm_ati_alloc_pcigart_table(dev, gart_info);
-               if (ret) {
-                       DRM_ERROR("cannot allocate PCI GART page!\n");
-                       goto done;
-               }
-
-               address = gart_info->table_handle->vaddr;
-               bus_address = gart_info->table_handle->busaddr;
-       } else {
-               address = gart_info->addr;
-               bus_address = gart_info->bus_addr;
-               DRM_DEBUG("PCI: Gart Table: VRAM %08LX mapped at %08lX\n",
-                         (unsigned long long)bus_address,
-                         (unsigned long)address);
-       }
-
-       pci_gart = (u32 *) address;
-
-       max_pages = (gart_info->table_size / sizeof(u32));
-       pages = (entry->pages <= max_pages)
-           ? entry->pages : max_pages;
-
-       memset(pci_gart, 0, max_pages * sizeof(u32));
-
-       for (i = 0; i < pages; i++) {
-               /* we need to support large memory configurations */
-               entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i],
-                                                0, PAGE_SIZE, PCI_DMA_TODEVICE);
-               if (entry->busaddr[i] == 0) {
-                       DRM_ERROR("unable to map PCIGART pages!\n");
-                       drm_ati_pcigart_cleanup(dev, gart_info);
-                       address = NULL;
-                       bus_address = 0;
-                       goto done;
-               }
-               page_base = (u32) entry->busaddr[i];
-
-               for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
-                       switch(gart_info->gart_reg_if) {
-                       case DRM_ATI_GART_IGP:
-                               *pci_gart = cpu_to_le32((page_base) | 0xc);
-                               break;
-                       case DRM_ATI_GART_PCIE:
-                               *pci_gart = cpu_to_le32((page_base >> 8) | 0xc);
-                               break;
-                       default:
-                       case DRM_ATI_GART_PCI:
-                               *pci_gart = cpu_to_le32(page_base);
-                               break;
-                       }
-                       pci_gart++;
-                       page_base += ATI_PCIGART_PAGE_SIZE;
-               }
-       }
-       ret = 1;
-
-#if defined(__i386__) || defined(__x86_64__)
-       wbinvd();
-#else
-       mb();
-#endif
-
-      done:
-       gart_info->addr = address;
-       gart_info->bus_addr = bus_address;
-       return ret;
-}
-EXPORT_SYMBOL(drm_ati_pcigart_init);
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
deleted file mode 100644 (file)
index 38d3c6b..0000000
+++ /dev/null
@@ -1,694 +0,0 @@
-/**
- * \file drm.h
- * Header for the Direct Rendering Manager
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- *
- * \par Acknowledgments:
- * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic \c cmpxchg.
- */
-
-/*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _DRM_H_
-#define _DRM_H_
-
-#if defined(__linux__)
-#if defined(__KERNEL__)
-#endif
-#include <asm/ioctl.h>         /* For _IO* macros */
-#define DRM_IOCTL_NR(n)                _IOC_NR(n)
-#define DRM_IOC_VOID           _IOC_NONE
-#define DRM_IOC_READ           _IOC_READ
-#define DRM_IOC_WRITE          _IOC_WRITE
-#define DRM_IOC_READWRITE      _IOC_READ|_IOC_WRITE
-#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
-#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
-#if defined(__FreeBSD__) && defined(IN_MODULE)
-/* Prevent name collision when including sys/ioccom.h */
-#undef ioctl
-#include <sys/ioccom.h>
-#define ioctl(a,b,c)           xf86ioctl(a,b,c)
-#else
-#include <sys/ioccom.h>
-#endif                         /* __FreeBSD__ && xf86ioctl */
-#define DRM_IOCTL_NR(n)                ((n) & 0xff)
-#define DRM_IOC_VOID           IOC_VOID
-#define DRM_IOC_READ           IOC_OUT
-#define DRM_IOC_WRITE          IOC_IN
-#define DRM_IOC_READWRITE      IOC_INOUT
-#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
-#endif
-
-#define DRM_MAJOR       226
-#define DRM_MAX_MINOR   15
-
-#define DRM_NAME       "drm"     /**< Name in kernel, /dev, and /proc */
-#define DRM_MIN_ORDER  5         /**< At least 2^5 bytes = 32 bytes */
-#define DRM_MAX_ORDER  22        /**< Up to 2^22 bytes = 4MB */
-#define DRM_RAM_PERCENT 10       /**< How much system ram can we lock? */
-
-#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */
-#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */
-#define _DRM_LOCK_IS_HELD(lock)           ((lock) & _DRM_LOCK_HELD)
-#define _DRM_LOCK_IS_CONT(lock)           ((lock) & _DRM_LOCK_CONT)
-#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
-
-typedef unsigned int drm_handle_t;
-typedef unsigned int drm_context_t;
-typedef unsigned int drm_drawable_t;
-typedef unsigned int drm_magic_t;
-
-/**
- * Cliprect.
- *
- * \warning: If you change this structure, make sure you change
- * XF86DRIClipRectRec in the server as well
- *
- * \note KW: Actually it's illegal to change either for
- * backwards-compatibility reasons.
- */
-struct drm_clip_rect {
-       unsigned short x1;
-       unsigned short y1;
-       unsigned short x2;
-       unsigned short y2;
-};
-
-/**
- * Drawable information.
- */
-struct drm_drawable_info {
-       unsigned int num_rects;
-       struct drm_clip_rect *rects;
-};
-
-/**
- * Texture region,
- */
-struct drm_tex_region {
-       unsigned char next;
-       unsigned char prev;
-       unsigned char in_use;
-       unsigned char padding;
-       unsigned int age;
-};
-
-/**
- * Hardware lock.
- *
- * The lock structure is a simple cache-line aligned integer.  To avoid
- * processor bus contention on a multiprocessor system, there should not be any
- * other data stored in the same cache line.
- */
-struct drm_hw_lock {
-       __volatile__ unsigned int lock;         /**< lock variable */
-       char padding[60];                       /**< Pad to cache line */
-};
-
-/**
- * DRM_IOCTL_VERSION ioctl argument type.
- *
- * \sa drmGetVersion().
- */
-struct drm_version {
-       int version_major;        /**< Major version */
-       int version_minor;        /**< Minor version */
-       int version_patchlevel;   /**< Patch level */
-       size_t name_len;          /**< Length of name buffer */
-       char __user *name;        /**< Name of driver */
-       size_t date_len;          /**< Length of date buffer */
-       char __user *date;        /**< User-space buffer to hold date */
-       size_t desc_len;          /**< Length of desc buffer */
-       char __user *desc;        /**< User-space buffer to hold desc */
-};
-
-/**
- * DRM_IOCTL_GET_UNIQUE ioctl argument type.
- *
- * \sa drmGetBusid() and drmSetBusId().
- */
-struct drm_unique {
-       size_t unique_len;        /**< Length of unique */
-       char __user *unique;      /**< Unique name for driver instantiation */
-};
-
-struct drm_list {
-       int count;                /**< Length of user-space structures */
-       struct drm_version __user *version;
-};
-
-struct drm_block {
-       int unused;
-};
-
-/**
- * DRM_IOCTL_CONTROL ioctl argument type.
- *
- * \sa drmCtlInstHandler() and drmCtlUninstHandler().
- */
-struct drm_control {
-       enum {
-               DRM_ADD_COMMAND,
-               DRM_RM_COMMAND,
-               DRM_INST_HANDLER,
-               DRM_UNINST_HANDLER
-       } func;
-       int irq;
-};
-
-/**
- * Type of memory to map.
- */
-enum drm_map_type {
-       _DRM_FRAME_BUFFER = 0,    /**< WC (no caching), no core dump */
-       _DRM_REGISTERS = 1,       /**< no caching, no core dump */
-       _DRM_SHM = 2,             /**< shared, cached */
-       _DRM_AGP = 3,             /**< AGP/GART */
-       _DRM_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
-       _DRM_CONSISTENT = 5,      /**< Consistent memory for PCI DMA */
-};
-
-/**
- * Memory mapping flags.
- */
-enum drm_map_flags {
-       _DRM_RESTRICTED = 0x01,      /**< Cannot be mapped to user-virtual */
-       _DRM_READ_ONLY = 0x02,
-       _DRM_LOCKED = 0x04,          /**< shared, cached, locked */
-       _DRM_KERNEL = 0x08,          /**< kernel requires access */
-       _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
-       _DRM_CONTAINS_LOCK = 0x20,   /**< SHM page that contains lock */
-       _DRM_REMOVABLE = 0x40,       /**< Removable mapping */
-       _DRM_DRIVER = 0x80           /**< Managed by driver */
-};
-
-struct drm_ctx_priv_map {
-       unsigned int ctx_id;     /**< Context requesting private mapping */
-       void *handle;            /**< Handle of map */
-};
-
-/**
- * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
- * argument type.
- *
- * \sa drmAddMap().
- */
-struct drm_map {
-       unsigned long offset;    /**< Requested physical address (0 for SAREA)*/
-       unsigned long size;      /**< Requested physical size (bytes) */
-       enum drm_map_type type;  /**< Type of memory to map */
-       enum drm_map_flags flags;        /**< Flags */
-       void *handle;            /**< User-space: "Handle" to pass to mmap() */
-                                /**< Kernel-space: kernel-virtual address */
-       int mtrr;                /**< MTRR slot used */
-       /*   Private data */
-};
-
-/**
- * DRM_IOCTL_GET_CLIENT ioctl argument type.
- */
-struct drm_client {
-       int idx;                /**< Which client desired? */
-       int auth;               /**< Is client authenticated? */
-       unsigned long pid;      /**< Process ID */
-       unsigned long uid;      /**< User ID */
-       unsigned long magic;    /**< Magic */
-       unsigned long iocs;     /**< Ioctl count */
-};
-
-enum drm_stat_type {
-       _DRM_STAT_LOCK,
-       _DRM_STAT_OPENS,
-       _DRM_STAT_CLOSES,
-       _DRM_STAT_IOCTLS,
-       _DRM_STAT_LOCKS,
-       _DRM_STAT_UNLOCKS,
-       _DRM_STAT_VALUE,        /**< Generic value */
-       _DRM_STAT_BYTE,         /**< Generic byte counter (1024bytes/K) */
-       _DRM_STAT_COUNT,        /**< Generic non-byte counter (1000/k) */
-
-       _DRM_STAT_IRQ,          /**< IRQ */
-       _DRM_STAT_PRIMARY,      /**< Primary DMA bytes */
-       _DRM_STAT_SECONDARY,    /**< Secondary DMA bytes */
-       _DRM_STAT_DMA,          /**< DMA */
-       _DRM_STAT_SPECIAL,      /**< Special DMA (e.g., priority or polled) */
-       _DRM_STAT_MISSED        /**< Missed DMA opportunity */
-           /* Add to the *END* of the list */
-};
-
-/**
- * DRM_IOCTL_GET_STATS ioctl argument type.
- */
-struct drm_stats {
-       unsigned long count;
-       struct {
-               unsigned long value;
-               enum drm_stat_type type;
-       } data[15];
-};
-
-/**
- * Hardware locking flags.
- */
-enum drm_lock_flags {
-       _DRM_LOCK_READY = 0x01,      /**< Wait until hardware is ready for DMA */
-       _DRM_LOCK_QUIESCENT = 0x02,  /**< Wait until hardware quiescent */
-       _DRM_LOCK_FLUSH = 0x04,      /**< Flush this context's DMA queue first */
-       _DRM_LOCK_FLUSH_ALL = 0x08,  /**< Flush all DMA queues first */
-       /* These *HALT* flags aren't supported yet
-          -- they will be used to support the
-          full-screen DGA-like mode. */
-       _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
-       _DRM_HALT_CUR_QUEUES = 0x20  /**< Halt all current queues */
-};
-
-/**
- * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
- *
- * \sa drmGetLock() and drmUnlock().
- */
-struct drm_lock {
-       int context;
-       enum drm_lock_flags flags;
-};
-
-/**
- * DMA flags
- *
- * \warning
- * These values \e must match xf86drm.h.
- *
- * \sa drm_dma.
- */
-enum drm_dma_flags {
-       /* Flags for DMA buffer dispatch */
-       _DRM_DMA_BLOCK = 0x01,        /**<
-                                      * Block until buffer dispatched.
-                                      *
-                                      * \note The buffer may not yet have
-                                      * been processed by the hardware --
-                                      * getting a hardware lock with the
-                                      * hardware quiescent will ensure
-                                      * that the buffer has been
-                                      * processed.
-                                      */
-       _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
-       _DRM_DMA_PRIORITY = 0x04,     /**< High priority dispatch */
-
-       /* Flags for DMA buffer request */
-       _DRM_DMA_WAIT = 0x10,         /**< Wait for free buffers */
-       _DRM_DMA_SMALLER_OK = 0x20,   /**< Smaller-than-requested buffers OK */
-       _DRM_DMA_LARGER_OK = 0x40     /**< Larger-than-requested buffers OK */
-};
-
-/**
- * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
- *
- * \sa drmAddBufs().
- */
-struct drm_buf_desc {
-       int count;               /**< Number of buffers of this size */
-       int size;                /**< Size in bytes */
-       int low_mark;            /**< Low water mark */
-       int high_mark;           /**< High water mark */
-       enum {
-               _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
-               _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
-               _DRM_SG_BUFFER = 0x04,  /**< Scatter/gather memory buffer */
-               _DRM_FB_BUFFER = 0x08,  /**< Buffer is in frame buffer */
-               _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */
-       } flags;
-       unsigned long agp_start; /**<
-                                 * Start address of where the AGP buffers are
-                                 * in the AGP aperture
-                                 */
-};
-
-/**
- * DRM_IOCTL_INFO_BUFS ioctl argument type.
- */
-struct drm_buf_info {
-       int count;              /**< Entries in list */
-       struct drm_buf_desc __user *list;
-};
-
-/**
- * DRM_IOCTL_FREE_BUFS ioctl argument type.
- */
-struct drm_buf_free {
-       int count;
-       int __user *list;
-};
-
-/**
- * Buffer information
- *
- * \sa drm_buf_map.
- */
-struct drm_buf_pub {
-       int idx;                       /**< Index into the master buffer list */
-       int total;                     /**< Buffer size */
-       int used;                      /**< Amount of buffer in use (for DMA) */
-       void __user *address;          /**< Address of buffer */
-};
-
-/**
- * DRM_IOCTL_MAP_BUFS ioctl argument type.
- */
-struct drm_buf_map {
-       int count;              /**< Length of the buffer list */
-       void __user *virtual;           /**< Mmap'd area in user-virtual */
-       struct drm_buf_pub __user *list;        /**< Buffer information */
-};
-
-/**
- * DRM_IOCTL_DMA ioctl argument type.
- *
- * Indices here refer to the offset into the buffer list in drm_buf_get.
- *
- * \sa drmDMA().
- */
-struct drm_dma {
-       int context;                      /**< Context handle */
-       int send_count;                   /**< Number of buffers to send */
-       int __user *send_indices;         /**< List of handles to buffers */
-       int __user *send_sizes;           /**< Lengths of data to send */
-       enum drm_dma_flags flags;         /**< Flags */
-       int request_count;                /**< Number of buffers requested */
-       int request_size;                 /**< Desired size for buffers */
-       int __user *request_indices;      /**< Buffer information */
-       int __user *request_sizes;
-       int granted_count;                /**< Number of buffers granted */
-};
-
-enum drm_ctx_flags {
-       _DRM_CONTEXT_PRESERVED = 0x01,
-       _DRM_CONTEXT_2DONLY = 0x02
-};
-
-/**
- * DRM_IOCTL_ADD_CTX ioctl argument type.
- *
- * \sa drmCreateContext() and drmDestroyContext().
- */
-struct drm_ctx {
-       drm_context_t handle;
-       enum drm_ctx_flags flags;
-};
-
-/**
- * DRM_IOCTL_RES_CTX ioctl argument type.
- */
-struct drm_ctx_res {
-       int count;
-       struct drm_ctx __user *contexts;
-};
-
-/**
- * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
- */
-struct drm_draw {
-       drm_drawable_t handle;
-};
-
-/**
- * DRM_IOCTL_UPDATE_DRAW ioctl argument type.
- */
-typedef enum {
-       DRM_DRAWABLE_CLIPRECTS,
-} drm_drawable_info_type_t;
-
-struct drm_update_draw {
-       drm_drawable_t handle;
-       unsigned int type;
-       unsigned int num;
-       unsigned long long data;
-};
-
-/**
- * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
- */
-struct drm_auth {
-       drm_magic_t magic;
-};
-
-/**
- * DRM_IOCTL_IRQ_BUSID ioctl argument type.
- *
- * \sa drmGetInterruptFromBusID().
- */
-struct drm_irq_busid {
-       int irq;        /**< IRQ number */
-       int busnum;     /**< bus number */
-       int devnum;     /**< device number */
-       int funcnum;    /**< function number */
-};
-
-enum drm_vblank_seq_type {
-       _DRM_VBLANK_ABSOLUTE = 0x0,     /**< Wait for specific vblank sequence number */
-       _DRM_VBLANK_RELATIVE = 0x1,     /**< Wait for given number of vblanks */
-       _DRM_VBLANK_NEXTONMISS = 0x10000000,    /**< If missed, wait for next vblank */
-       _DRM_VBLANK_SECONDARY = 0x20000000,     /**< Secondary display controller */
-       _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
-};
-
-#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
-#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \
-                               _DRM_VBLANK_NEXTONMISS)
-
-struct drm_wait_vblank_request {
-       enum drm_vblank_seq_type type;
-       unsigned int sequence;
-       unsigned long signal;
-};
-
-struct drm_wait_vblank_reply {
-       enum drm_vblank_seq_type type;
-       unsigned int sequence;
-       long tval_sec;
-       long tval_usec;
-};
-
-/**
- * DRM_IOCTL_WAIT_VBLANK ioctl argument type.
- *
- * \sa drmWaitVBlank().
- */
-union drm_wait_vblank {
-       struct drm_wait_vblank_request request;
-       struct drm_wait_vblank_reply reply;
-};
-
-/**
- * DRM_IOCTL_AGP_ENABLE ioctl argument type.
- *
- * \sa drmAgpEnable().
- */
-struct drm_agp_mode {
-       unsigned long mode;     /**< AGP mode */
-};
-
-/**
- * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
- *
- * \sa drmAgpAlloc() and drmAgpFree().
- */
-struct drm_agp_buffer {
-       unsigned long size;     /**< In bytes -- will round to page boundary */
-       unsigned long handle;   /**< Used for binding / unbinding */
-       unsigned long type;     /**< Type of memory to allocate */
-       unsigned long physical; /**< Physical used by i810 */
-};
-
-/**
- * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
- *
- * \sa drmAgpBind() and drmAgpUnbind().
- */
-struct drm_agp_binding {
-       unsigned long handle;   /**< From drm_agp_buffer */
-       unsigned long offset;   /**< In bytes -- will round to page boundary */
-};
-
-/**
- * DRM_IOCTL_AGP_INFO ioctl argument type.
- *
- * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(),
- * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
- * drmAgpVendorId() and drmAgpDeviceId().
- */
-struct drm_agp_info {
-       int agp_version_major;
-       int agp_version_minor;
-       unsigned long mode;
-       unsigned long aperture_base;    /* physical address */
-       unsigned long aperture_size;    /* bytes */
-       unsigned long memory_allowed;   /* bytes */
-       unsigned long memory_used;
-
-       /* PCI information */
-       unsigned short id_vendor;
-       unsigned short id_device;
-};
-
-/**
- * DRM_IOCTL_SG_ALLOC ioctl argument type.
- */
-struct drm_scatter_gather {
-       unsigned long size;     /**< In bytes -- will round to page boundary */
-       unsigned long handle;   /**< Used for mapping / unmapping */
-};
-
-/**
- * DRM_IOCTL_SET_VERSION ioctl argument type.
- */
-struct drm_set_version {
-       int drm_di_major;
-       int drm_di_minor;
-       int drm_dd_major;
-       int drm_dd_minor;
-};
-
-#define DRM_IOCTL_BASE                 'd'
-#define DRM_IO(nr)                     _IO(DRM_IOCTL_BASE,nr)
-#define DRM_IOR(nr,type)               _IOR(DRM_IOCTL_BASE,nr,type)
-#define DRM_IOW(nr,type)               _IOW(DRM_IOCTL_BASE,nr,type)
-#define DRM_IOWR(nr,type)              _IOWR(DRM_IOCTL_BASE,nr,type)
-
-#define DRM_IOCTL_VERSION              DRM_IOWR(0x00, struct drm_version)
-#define DRM_IOCTL_GET_UNIQUE           DRM_IOWR(0x01, struct drm_unique)
-#define DRM_IOCTL_GET_MAGIC            DRM_IOR( 0x02, struct drm_auth)
-#define DRM_IOCTL_IRQ_BUSID            DRM_IOWR(0x03, struct drm_irq_busid)
-#define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, struct drm_map)
-#define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
-#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
-#define DRM_IOCTL_SET_VERSION          DRM_IOWR(0x07, struct drm_set_version)
-
-#define DRM_IOCTL_SET_UNIQUE           DRM_IOW( 0x10, struct drm_unique)
-#define DRM_IOCTL_AUTH_MAGIC           DRM_IOW( 0x11, struct drm_auth)
-#define DRM_IOCTL_BLOCK                        DRM_IOWR(0x12, struct drm_block)
-#define DRM_IOCTL_UNBLOCK              DRM_IOWR(0x13, struct drm_block)
-#define DRM_IOCTL_CONTROL              DRM_IOW( 0x14, struct drm_control)
-#define DRM_IOCTL_ADD_MAP              DRM_IOWR(0x15, struct drm_map)
-#define DRM_IOCTL_ADD_BUFS             DRM_IOWR(0x16, struct drm_buf_desc)
-#define DRM_IOCTL_MARK_BUFS            DRM_IOW( 0x17, struct drm_buf_desc)
-#define DRM_IOCTL_INFO_BUFS            DRM_IOWR(0x18, struct drm_buf_info)
-#define DRM_IOCTL_MAP_BUFS             DRM_IOWR(0x19, struct drm_buf_map)
-#define DRM_IOCTL_FREE_BUFS            DRM_IOW( 0x1a, struct drm_buf_free)
-
-#define DRM_IOCTL_RM_MAP               DRM_IOW( 0x1b, struct drm_map)
-
-#define DRM_IOCTL_SET_SAREA_CTX                DRM_IOW( 0x1c, struct drm_ctx_priv_map)
-#define DRM_IOCTL_GET_SAREA_CTX        DRM_IOWR(0x1d, struct drm_ctx_priv_map)
-
-#define DRM_IOCTL_ADD_CTX              DRM_IOWR(0x20, struct drm_ctx)
-#define DRM_IOCTL_RM_CTX               DRM_IOWR(0x21, struct drm_ctx)
-#define DRM_IOCTL_MOD_CTX              DRM_IOW( 0x22, struct drm_ctx)
-#define DRM_IOCTL_GET_CTX              DRM_IOWR(0x23, struct drm_ctx)
-#define DRM_IOCTL_SWITCH_CTX           DRM_IOW( 0x24, struct drm_ctx)
-#define DRM_IOCTL_NEW_CTX              DRM_IOW( 0x25, struct drm_ctx)
-#define DRM_IOCTL_RES_CTX              DRM_IOWR(0x26, struct drm_ctx_res)
-#define DRM_IOCTL_ADD_DRAW             DRM_IOWR(0x27, struct drm_draw)
-#define DRM_IOCTL_RM_DRAW              DRM_IOWR(0x28, struct drm_draw)
-#define DRM_IOCTL_DMA                  DRM_IOWR(0x29, struct drm_dma)
-#define DRM_IOCTL_LOCK                 DRM_IOW( 0x2a, struct drm_lock)
-#define DRM_IOCTL_UNLOCK               DRM_IOW( 0x2b, struct drm_lock)
-#define DRM_IOCTL_FINISH               DRM_IOW( 0x2c, struct drm_lock)
-
-#define DRM_IOCTL_AGP_ACQUIRE          DRM_IO(  0x30)
-#define DRM_IOCTL_AGP_RELEASE          DRM_IO(  0x31)
-#define DRM_IOCTL_AGP_ENABLE           DRM_IOW( 0x32, struct drm_agp_mode)
-#define DRM_IOCTL_AGP_INFO             DRM_IOR( 0x33, struct drm_agp_info)
-#define DRM_IOCTL_AGP_ALLOC            DRM_IOWR(0x34, struct drm_agp_buffer)
-#define DRM_IOCTL_AGP_FREE             DRM_IOW( 0x35, struct drm_agp_buffer)
-#define DRM_IOCTL_AGP_BIND             DRM_IOW( 0x36, struct drm_agp_binding)
-#define DRM_IOCTL_AGP_UNBIND           DRM_IOW( 0x37, struct drm_agp_binding)
-
-#define DRM_IOCTL_SG_ALLOC             DRM_IOWR(0x38, struct drm_scatter_gather)
-#define DRM_IOCTL_SG_FREE              DRM_IOW( 0x39, struct drm_scatter_gather)
-
-#define DRM_IOCTL_WAIT_VBLANK          DRM_IOWR(0x3a, union drm_wait_vblank)
-
-#define DRM_IOCTL_UPDATE_DRAW          DRM_IOW(0x3f, struct drm_update_draw)
-
-/**
- * Device specific ioctls should only be in their respective headers
- * The device specific ioctl range is from 0x40 to 0x99.
- * Generic IOCTLS restart at 0xA0.
- *
- * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
- * drmCommandReadWrite().
- */
-#define DRM_COMMAND_BASE                0x40
-#define DRM_COMMAND_END                        0xA0
-
-/* typedef area */
-#ifndef __KERNEL__
-typedef struct drm_clip_rect drm_clip_rect_t;
-typedef struct drm_drawable_info drm_drawable_info_t;
-typedef struct drm_tex_region drm_tex_region_t;
-typedef struct drm_hw_lock drm_hw_lock_t;
-typedef struct drm_version drm_version_t;
-typedef struct drm_unique drm_unique_t;
-typedef struct drm_list drm_list_t;
-typedef struct drm_block drm_block_t;
-typedef struct drm_control drm_control_t;
-typedef enum drm_map_type drm_map_type_t;
-typedef enum drm_map_flags drm_map_flags_t;
-typedef struct drm_ctx_priv_map drm_ctx_priv_map_t;
-typedef struct drm_map drm_map_t;
-typedef struct drm_client drm_client_t;
-typedef enum drm_stat_type drm_stat_type_t;
-typedef struct drm_stats drm_stats_t;
-typedef enum drm_lock_flags drm_lock_flags_t;
-typedef struct drm_lock drm_lock_t;
-typedef enum drm_dma_flags drm_dma_flags_t;
-typedef struct drm_buf_desc drm_buf_desc_t;
-typedef struct drm_buf_info drm_buf_info_t;
-typedef struct drm_buf_free drm_buf_free_t;
-typedef struct drm_buf_pub drm_buf_pub_t;
-typedef struct drm_buf_map drm_buf_map_t;
-typedef struct drm_dma drm_dma_t;
-typedef union drm_wait_vblank drm_wait_vblank_t;
-typedef struct drm_agp_mode drm_agp_mode_t;
-typedef enum drm_ctx_flags drm_ctx_flags_t;
-typedef struct drm_ctx drm_ctx_t;
-typedef struct drm_ctx_res drm_ctx_res_t;
-typedef struct drm_draw drm_draw_t;
-typedef struct drm_update_draw drm_update_draw_t;
-typedef struct drm_auth drm_auth_t;
-typedef struct drm_irq_busid drm_irq_busid_t;
-typedef enum drm_vblank_seq_type drm_vblank_seq_type_t;
-
-typedef struct drm_agp_buffer drm_agp_buffer_t;
-typedef struct drm_agp_binding drm_agp_binding_t;
-typedef struct drm_agp_info drm_agp_info_t;
-typedef struct drm_scatter_gather drm_scatter_gather_t;
-typedef struct drm_set_version drm_set_version_t;
-#endif
-
-#endif
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
deleted file mode 100644 (file)
index 0764b66..0000000
+++ /dev/null
@@ -1,1153 +0,0 @@
-/**
- * \file drmP.h
- * Private header for Direct Rendering Manager
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _DRM_P_H_
-#define _DRM_P_H_
-
-/* If you want the memory alloc debug functionality, change define below */
-/* #define DEBUG_MEMORY */
-
-#ifdef __KERNEL__
-#ifdef __alpha__
-/* add include of current.h so that "current" is defined
- * before static inline funcs in wait.h. Doing this so we
- * can build the DRM (part of PI DRI). 4/21/2000 S + B */
-#include <asm/current.h>
-#endif                         /* __alpha__ */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-#include <linux/file.h>
-#include <linux/pci.h>
-#include <linux/jiffies.h>
-#include <linux/smp_lock.h>    /* For (un)lock_kernel */
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/cdev.h>
-#include <linux/mutex.h>
-#if defined(__alpha__) || defined(__powerpc__)
-#include <asm/pgtable.h>       /* For pte_wrprotect */
-#endif
-#include <asm/io.h>
-#include <asm/mman.h>
-#include <asm/uaccess.h>
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
-#include <linux/types.h>
-#include <linux/agp_backend.h>
-#endif
-#include <linux/workqueue.h>
-#include <linux/poll.h>
-#include <asm/pgalloc.h>
-#include "drm.h"
-
-#include <linux/idr.h>
-
-#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
-#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
-
-struct drm_file;
-struct drm_device;
-
-#include "drm_os_linux.h"
-#include "drm_hashtab.h"
-
-/***********************************************************************/
-/** \name DRM template customization defaults */
-/*@{*/
-
-/* driver capabilities and requirements mask */
-#define DRIVER_USE_AGP     0x1
-#define DRIVER_REQUIRE_AGP 0x2
-#define DRIVER_USE_MTRR    0x4
-#define DRIVER_PCI_DMA     0x8
-#define DRIVER_SG          0x10
-#define DRIVER_HAVE_DMA    0x20
-#define DRIVER_HAVE_IRQ    0x40
-#define DRIVER_IRQ_SHARED  0x80
-#define DRIVER_IRQ_VBL     0x100
-#define DRIVER_DMA_QUEUE   0x200
-#define DRIVER_FB_DMA      0x400
-#define DRIVER_IRQ_VBL2    0x800
-
-/***********************************************************************/
-/** \name Begin the DRM... */
-/*@{*/
-
-#define DRM_DEBUG_CODE 2         /**< Include debugging code if > 1, then
-                                    also include looping detection. */
-
-#define DRM_MAGIC_HASH_ORDER  4  /**< Size of key hash table. Must be power of 2. */
-#define DRM_KERNEL_CONTEXT    0         /**< Change drm_resctx if changed */
-#define DRM_RESERVED_CONTEXTS 1         /**< Change drm_resctx if changed */
-#define DRM_LOOPING_LIMIT     5000000
-#define DRM_TIME_SLICE       (HZ/20)  /**< Time slice for GLXContexts */
-#define DRM_LOCK_SLICE       1 /**< Time slice for lock, in jiffies */
-
-#define DRM_FLAG_DEBUG   0x01
-
-#define DRM_MEM_DMA       0
-#define DRM_MEM_SAREA     1
-#define DRM_MEM_DRIVER    2
-#define DRM_MEM_MAGIC     3
-#define DRM_MEM_IOCTLS    4
-#define DRM_MEM_MAPS      5
-#define DRM_MEM_VMAS      6
-#define DRM_MEM_BUFS      7
-#define DRM_MEM_SEGS      8
-#define DRM_MEM_PAGES     9
-#define DRM_MEM_FILES    10
-#define DRM_MEM_QUEUES   11
-#define DRM_MEM_CMDS     12
-#define DRM_MEM_MAPPINGS  13
-#define DRM_MEM_BUFLISTS  14
-#define DRM_MEM_AGPLISTS  15
-#define DRM_MEM_TOTALAGP  16
-#define DRM_MEM_BOUNDAGP  17
-#define DRM_MEM_CTXBITMAP 18
-#define DRM_MEM_STUB      19
-#define DRM_MEM_SGLISTS   20
-#define DRM_MEM_CTXLIST   21
-#define DRM_MEM_MM        22
-#define DRM_MEM_HASHTAB   23
-
-#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
-#define DRM_MAP_HASH_OFFSET 0x10000000
-
-/*@}*/
-
-/***********************************************************************/
-/** \name Macros to make printk easier */
-/*@{*/
-
-/**
- * Error output.
- *
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#define DRM_ERROR(fmt, arg...) \
-       printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __func__ , ##arg)
-
-/**
- * Memory error output.
- *
- * \param area memory area where the error occurred.
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#define DRM_MEM_ERROR(area, fmt, arg...) \
-       printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __func__, \
-              drm_mem_stats[area].name , ##arg)
-
-#define DRM_INFO(fmt, arg...)  printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
-
-/**
- * Debug output.
- *
- * \param fmt printf() like format string.
- * \param arg arguments
- */
-#if DRM_DEBUG_CODE
-#define DRM_DEBUG(fmt, arg...)                                         \
-       do {                                                            \
-               if ( drm_debug )                        \
-                       printk(KERN_DEBUG                               \
-                              "[" DRM_NAME ":%s] " fmt ,       \
-                              __func__ , ##arg);                       \
-       } while (0)
-#else
-#define DRM_DEBUG(fmt, arg...)          do { } while (0)
-#endif
-
-#define DRM_PROC_LIMIT (PAGE_SIZE-80)
-
-#define DRM_PROC_PRINT(fmt, arg...)                                    \
-   len += sprintf(&buf[len], fmt , ##arg);                             \
-   if (len > DRM_PROC_LIMIT) { *eof = 1; return len - offset; }
-
-#define DRM_PROC_PRINT_RET(ret, fmt, arg...)                           \
-   len += sprintf(&buf[len], fmt , ##arg);                             \
-   if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }
-
-/*@}*/
-
-/***********************************************************************/
-/** \name Internal types and structures */
-/*@{*/
-
-#define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x)
-
-#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
-#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
-#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
-
-#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
-/**
- * Get the private SAREA mapping.
- *
- * \param _dev DRM device.
- * \param _ctx context number.
- * \param _map output mapping.
- */
-#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do {      \
-       (_map) = (_dev)->context_sareas[_ctx];          \
-} while(0)
-
-/**
- * Test that the hardware lock is held by the caller, returning otherwise.
- *
- * \param dev DRM device.
- * \param filp file pointer of the caller.
- */
-#define LOCK_TEST_WITH_RETURN( dev, file_priv )                                \
-do {                                                                   \
-       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||           \
-            dev->lock.file_priv != file_priv ) {                       \
-               DRM_ERROR( "%s called without lock held, held  %d owner %p %p\n",\
-                          __func__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\
-                          dev->lock.file_priv, file_priv );            \
-               return -EINVAL;                                         \
-       }                                                               \
-} while (0)
-
-/**
- * Copy and IOCTL return string to user space
- */
-#define DRM_COPY( name, value )                                                \
-       len = strlen( value );                                          \
-       if ( len > name##_len ) len = name##_len;                       \
-       name##_len = strlen( value );                                   \
-       if ( len && name ) {                                            \
-               if ( copy_to_user( name, value, len ) )                 \
-                       return -EFAULT;                                 \
-       }
-
-/**
- * Ioctl function type.
- *
- * \param inode device inode.
- * \param file_priv DRM file private pointer.
- * \param cmd command.
- * \param arg argument.
- */
-typedef int drm_ioctl_t(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-
-typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
-                              unsigned long arg);
-
-#define DRM_AUTH       0x1
-#define        DRM_MASTER      0x2
-#define DRM_ROOT_ONLY  0x4
-
-struct drm_ioctl_desc {
-       unsigned int cmd;
-       drm_ioctl_t *func;
-       int flags;
-};
-
-/**
- * Creates a driver or general drm_ioctl_desc array entry for the given
- * ioctl, for use by drm_ioctl().
- */
-#define DRM_IOCTL_DEF(ioctl, func, flags) \
-       [DRM_IOCTL_NR(ioctl)] = {ioctl, func, flags}
-
-struct drm_magic_entry {
-       struct list_head head;
-       struct drm_hash_item hash_item;
-       struct drm_file *priv;
-};
-
-struct drm_vma_entry {
-       struct list_head head;
-       struct vm_area_struct *vma;
-       pid_t pid;
-};
-
-/**
- * DMA buffer.
- */
-struct drm_buf {
-       int idx;                       /**< Index into master buflist */
-       int total;                     /**< Buffer size */
-       int order;                     /**< log-base-2(total) */
-       int used;                      /**< Amount of buffer in use (for DMA) */
-       unsigned long offset;          /**< Byte offset (used internally) */
-       void *address;                 /**< Address of buffer */
-       unsigned long bus_address;     /**< Bus address of buffer */
-       struct drm_buf *next;          /**< Kernel-only: used for free list */
-       __volatile__ int waiting;      /**< On kernel DMA queue */
-       __volatile__ int pending;      /**< On hardware DMA queue */
-       wait_queue_head_t dma_wait;    /**< Processes waiting */
-       struct drm_file *file_priv;    /**< Private of holding file descr */
-       int context;                   /**< Kernel queue for this buffer */
-       int while_locked;              /**< Dispatch this buffer while locked */
-       enum {
-               DRM_LIST_NONE = 0,
-               DRM_LIST_FREE = 1,
-               DRM_LIST_WAIT = 2,
-               DRM_LIST_PEND = 3,
-               DRM_LIST_PRIO = 4,
-               DRM_LIST_RECLAIM = 5
-       } list;                        /**< Which list we're on */
-
-       int dev_priv_size;               /**< Size of buffer private storage */
-       void *dev_private;               /**< Per-buffer private storage */
-};
-
-/** bufs is one longer than it has to be */
-struct drm_waitlist {
-       int count;                      /**< Number of possible buffers */
-       struct drm_buf **bufs;          /**< List of pointers to buffers */
-       struct drm_buf **rp;                    /**< Read pointer */
-       struct drm_buf **wp;                    /**< Write pointer */
-       struct drm_buf **end;           /**< End pointer */
-       spinlock_t read_lock;
-       spinlock_t write_lock;
-};
-
-struct drm_freelist {
-       int initialized;               /**< Freelist in use */
-       atomic_t count;                /**< Number of free buffers */
-       struct drm_buf *next;          /**< End pointer */
-
-       wait_queue_head_t waiting;     /**< Processes waiting on free bufs */
-       int low_mark;                  /**< Low water mark */
-       int high_mark;                 /**< High water mark */
-       atomic_t wfh;                  /**< If waiting for high mark */
-       spinlock_t lock;
-};
-
-typedef struct drm_dma_handle {
-       dma_addr_t busaddr;
-       void *vaddr;
-       size_t size;
-} drm_dma_handle_t;
-
-/**
- * Buffer entry.  There is one of this for each buffer size order.
- */
-struct drm_buf_entry {
-       int buf_size;                   /**< size */
-       int buf_count;                  /**< number of buffers */
-       struct drm_buf *buflist;                /**< buffer list */
-       int seg_count;
-       int page_order;
-       struct drm_dma_handle **seglist;
-
-       struct drm_freelist freelist;
-};
-
-/** File private data */
-struct drm_file {
-       int authenticated;
-       int master;
-       pid_t pid;
-       uid_t uid;
-       drm_magic_t magic;
-       unsigned long ioctl_count;
-       struct list_head lhead;
-       struct drm_minor *minor;
-       int remove_auth_on_close;
-       unsigned long lock_count;
-       struct file *filp;
-       void *driver_priv;
-};
-
-/** Wait queue */
-struct drm_queue {
-       atomic_t use_count;             /**< Outstanding uses (+1) */
-       atomic_t finalization;          /**< Finalization in progress */
-       atomic_t block_count;           /**< Count of processes waiting */
-       atomic_t block_read;            /**< Queue blocked for reads */
-       wait_queue_head_t read_queue;   /**< Processes waiting on block_read */
-       atomic_t block_write;           /**< Queue blocked for writes */
-       wait_queue_head_t write_queue;  /**< Processes waiting on block_write */
-       atomic_t total_queued;          /**< Total queued statistic */
-       atomic_t total_flushed;         /**< Total flushes statistic */
-       atomic_t total_locks;           /**< Total locks statistics */
-       enum drm_ctx_flags flags;       /**< Context preserving and 2D-only */
-       struct drm_waitlist waitlist;   /**< Pending buffers */
-       wait_queue_head_t flush_queue;  /**< Processes waiting until flush */
-};
-
-/**
- * Lock data.
- */
-struct drm_lock_data {
-       struct drm_hw_lock *hw_lock;    /**< Hardware lock */
-       /** Private of lock holder's file (NULL=kernel) */
-       struct drm_file *file_priv;
-       wait_queue_head_t lock_queue;   /**< Queue of blocked processes */
-       unsigned long lock_time;        /**< Time of last lock in jiffies */
-       spinlock_t spinlock;
-       uint32_t kernel_waiters;
-       uint32_t user_waiters;
-       int idle_has_lock;
-};
-
-/**
- * DMA data.
- */
-struct drm_device_dma {
-
-       struct drm_buf_entry bufs[DRM_MAX_ORDER + 1];   /**< buffers, grouped by their size order */
-       int buf_count;                  /**< total number of buffers */
-       struct drm_buf **buflist;               /**< Vector of pointers into drm_device_dma::bufs */
-       int seg_count;
-       int page_count;                 /**< number of pages */
-       unsigned long *pagelist;        /**< page list */
-       unsigned long byte_count;
-       enum {
-               _DRM_DMA_USE_AGP = 0x01,
-               _DRM_DMA_USE_SG = 0x02,
-               _DRM_DMA_USE_FB = 0x04,
-               _DRM_DMA_USE_PCI_RO = 0x08
-       } flags;
-
-};
-
-/**
- * AGP memory entry.  Stored as a doubly linked list.
- */
-struct drm_agp_mem {
-       unsigned long handle;           /**< handle */
-       DRM_AGP_MEM *memory;
-       unsigned long bound;            /**< address */
-       int pages;
-       struct list_head head;
-};
-
-/**
- * AGP data.
- *
- * \sa drm_agp_init() and drm_device::agp.
- */
-struct drm_agp_head {
-       DRM_AGP_KERN agp_info;          /**< AGP device information */
-       struct list_head memory;
-       unsigned long mode;             /**< AGP mode */
-       struct agp_bridge_data *bridge;
-       int enabled;                    /**< whether the AGP bus as been enabled */
-       int acquired;                   /**< whether the AGP device has been acquired */
-       unsigned long base;
-       int agp_mtrr;
-       int cant_use_aperture;
-       unsigned long page_mask;
-};
-
-/**
- * Scatter-gather memory.
- */
-struct drm_sg_mem {
-       unsigned long handle;
-       void *virtual;
-       int pages;
-       struct page **pagelist;
-       dma_addr_t *busaddr;
-};
-
-struct drm_sigdata {
-       int context;
-       struct drm_hw_lock *lock;
-};
-
-
-/*
- * Generic memory manager structs
- */
-
-struct drm_mm_node {
-       struct list_head fl_entry;
-       struct list_head ml_entry;
-       int free;
-       unsigned long start;
-       unsigned long size;
-       struct drm_mm *mm;
-       void *private;
-};
-
-struct drm_mm {
-       struct list_head fl_entry;
-       struct list_head ml_entry;
-};
-
-
-/**
- * Mappings list
- */
-struct drm_map_list {
-       struct list_head head;          /**< list head */
-       struct drm_hash_item hash;
-       struct drm_map *map;                    /**< mapping */
-       uint64_t user_token;
-};
-
-typedef struct drm_map drm_local_map_t;
-
-/**
- * Context handle list
- */
-struct drm_ctx_list {
-       struct list_head head;          /**< list head */
-       drm_context_t handle;           /**< context handle */
-       struct drm_file *tag;           /**< associated fd private data */
-};
-
-struct drm_vbl_sig {
-       struct list_head head;
-       unsigned int sequence;
-       struct siginfo info;
-       struct task_struct *task;
-};
-
-/* location of GART table */
-#define DRM_ATI_GART_MAIN 1
-#define DRM_ATI_GART_FB   2
-
-#define DRM_ATI_GART_PCI 1
-#define DRM_ATI_GART_PCIE 2
-#define DRM_ATI_GART_IGP 3
-
-struct drm_ati_pcigart_info {
-       int gart_table_location;
-       int gart_reg_if;
-       void *addr;
-       dma_addr_t bus_addr;
-       dma_addr_t table_mask;
-       struct drm_dma_handle *table_handle;
-       drm_local_map_t mapping;
-       int table_size;
-};
-
-/**
- * DRM driver structure. This structure represent the common code for
- * a family of cards. There will one drm_device for each card present
- * in this family
- */
-struct drm_driver {
-       int (*load) (struct drm_device *, unsigned long flags);
-       int (*firstopen) (struct drm_device *);
-       int (*open) (struct drm_device *, struct drm_file *);
-       void (*preclose) (struct drm_device *, struct drm_file *file_priv);
-       void (*postclose) (struct drm_device *, struct drm_file *);
-       void (*lastclose) (struct drm_device *);
-       int (*unload) (struct drm_device *);
-       int (*suspend) (struct drm_device *, pm_message_t state);
-       int (*resume) (struct drm_device *);
-       int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
-       void (*dma_ready) (struct drm_device *);
-       int (*dma_quiescent) (struct drm_device *);
-       int (*context_ctor) (struct drm_device *dev, int context);
-       int (*context_dtor) (struct drm_device *dev, int context);
-       int (*kernel_context_switch) (struct drm_device *dev, int old,
-                                     int new);
-       void (*kernel_context_switch_unlock) (struct drm_device *dev);
-       int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
-       int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
-       int (*dri_library_name) (struct drm_device *dev, char *buf);
-
-       /**
-        * Called by \c drm_device_is_agp.  Typically used to determine if a
-        * card is really attached to AGP or not.
-        *
-        * \param dev  DRM device handle
-        *
-        * \returns
-        * One of three values is returned depending on whether or not the
-        * card is absolutely \b not AGP (return of 0), absolutely \b is AGP
-        * (return of 1), or may or may not be AGP (return of 2).
-        */
-       int (*device_is_agp) (struct drm_device *dev);
-
-       /* these have to be filled in */
-
-       irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
-       void (*irq_preinstall) (struct drm_device *dev);
-       void (*irq_postinstall) (struct drm_device *dev);
-       void (*irq_uninstall) (struct drm_device *dev);
-       void (*reclaim_buffers) (struct drm_device *dev,
-                                struct drm_file * file_priv);
-       void (*reclaim_buffers_locked) (struct drm_device *dev,
-                                       struct drm_file *file_priv);
-       void (*reclaim_buffers_idlelocked) (struct drm_device *dev,
-                                           struct drm_file *file_priv);
-       unsigned long (*get_map_ofs) (struct drm_map * map);
-       unsigned long (*get_reg_ofs) (struct drm_device *dev);
-       void (*set_version) (struct drm_device *dev,
-                            struct drm_set_version *sv);
-
-       int major;
-       int minor;
-       int patchlevel;
-       char *name;
-       char *desc;
-       char *date;
-
-       u32 driver_features;
-       int dev_priv_size;
-       struct drm_ioctl_desc *ioctls;
-       int num_ioctls;
-       struct file_operations fops;
-       struct pci_driver pci_driver;
-};
-
-#define DRM_MINOR_UNASSIGNED 0
-#define DRM_MINOR_LEGACY 1
-
-/**
- * DRM minor structure. This structure represents a drm minor number.
- */
-struct drm_minor {
-       int index;                      /**< Minor device number */
-       int type;                       /**< Control or render */
-       dev_t device;                   /**< Device number for mknod */
-       struct device kdev;             /**< Linux device */
-       struct drm_device *dev;
-       struct proc_dir_entry *dev_root;  /**< proc directory entry */
-};
-
-/**
- * DRM device structure. This structure represent a complete card that
- * may contain multiple heads.
- */
-struct drm_device {
-       char *unique;                   /**< Unique identifier: e.g., busid */
-       int unique_len;                 /**< Length of unique field */
-       char *devname;                  /**< For /proc/interrupts */
-       int if_version;                 /**< Highest interface version set */
-
-       int blocked;                    /**< Blocked due to VC switch? */
-
-       /** \name Locks */
-       /*@{ */
-       spinlock_t count_lock;          /**< For inuse, drm_device::open_count, drm_device::buf_use */
-       struct mutex struct_mutex;      /**< For others */
-       /*@} */
-
-       /** \name Usage Counters */
-       /*@{ */
-       int open_count;                 /**< Outstanding files open */
-       atomic_t ioctl_count;           /**< Outstanding IOCTLs pending */
-       atomic_t vma_count;             /**< Outstanding vma areas open */
-       int buf_use;                    /**< Buffers in use -- cannot alloc */
-       atomic_t buf_alloc;             /**< Buffer allocation in progress */
-       /*@} */
-
-       /** \name Performance counters */
-       /*@{ */
-       unsigned long counters;
-       enum drm_stat_type types[15];
-       atomic_t counts[15];
-       /*@} */
-
-       /** \name Authentication */
-       /*@{ */
-       struct list_head filelist;
-       struct drm_open_hash magiclist; /**< magic hash table */
-       struct list_head magicfree;
-       /*@} */
-
-       /** \name Memory management */
-       /*@{ */
-       struct list_head maplist;       /**< Linked list of regions */
-       int map_count;                  /**< Number of mappable regions */
-       struct drm_open_hash map_hash;  /**< User token hash table for maps */
-
-       /** \name Context handle management */
-       /*@{ */
-       struct list_head ctxlist;       /**< Linked list of context handles */
-       int ctx_count;                  /**< Number of context handles */
-       struct mutex ctxlist_mutex;     /**< For ctxlist */
-
-       struct idr ctx_idr;
-
-       struct list_head vmalist;       /**< List of vmas (for debugging) */
-       struct drm_lock_data lock;      /**< Information on hardware lock */
-       /*@} */
-
-       /** \name DMA queues (contexts) */
-       /*@{ */
-       int queue_count;                /**< Number of active DMA queues */
-       int queue_reserved;               /**< Number of reserved DMA queues */
-       int queue_slots;                /**< Actual length of queuelist */
-       struct drm_queue **queuelist;   /**< Vector of pointers to DMA queues */
-       struct drm_device_dma *dma;             /**< Optional pointer for DMA support */
-       /*@} */
-
-       /** \name Context support */
-       /*@{ */
-       int irq;                        /**< Interrupt used by board */
-       int irq_enabled;                /**< True if irq handler is enabled */
-       __volatile__ long context_flag; /**< Context swapping flag */
-       __volatile__ long interrupt_flag; /**< Interruption handler flag */
-       __volatile__ long dma_flag;     /**< DMA dispatch flag */
-       struct timer_list timer;        /**< Timer for delaying ctx switch */
-       wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
-       int last_checked;               /**< Last context checked for DMA */
-       int last_context;               /**< Last current context */
-       unsigned long last_switch;      /**< jiffies at last context switch */
-       /*@} */
-
-       struct work_struct work;
-       /** \name VBLANK IRQ support */
-       /*@{ */
-
-       wait_queue_head_t vbl_queue;    /**< VBLANK wait queue */
-       atomic_t vbl_received;
-       atomic_t vbl_received2;         /**< number of secondary VBLANK interrupts */
-       spinlock_t vbl_lock;
-       struct list_head vbl_sigs;              /**< signal list to send on VBLANK */
-       struct list_head vbl_sigs2;     /**< signals to send on secondary VBLANK */
-       unsigned int vbl_pending;
-       spinlock_t tasklet_lock;        /**< For drm_locked_tasklet */
-       void (*locked_tasklet_func)(struct drm_device *dev);
-
-       /*@} */
-       cycles_t ctx_start;
-       cycles_t lck_start;
-
-       struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
-       wait_queue_head_t buf_readers;  /**< Processes waiting to read */
-       wait_queue_head_t buf_writers;  /**< Processes waiting to ctx switch */
-
-       struct drm_agp_head *agp;       /**< AGP data */
-
-       struct pci_dev *pdev;           /**< PCI device structure */
-       int pci_vendor;                 /**< PCI vendor id */
-       int pci_device;                 /**< PCI device id */
-#ifdef __alpha__
-       struct pci_controller *hose;
-#endif
-       struct drm_sg_mem *sg;  /**< Scatter gather memory */
-       void *dev_private;              /**< device private data */
-       struct drm_sigdata sigdata;        /**< For block_all_signals */
-       sigset_t sigmask;
-
-       struct drm_driver *driver;
-       drm_local_map_t *agp_buffer_map;
-       unsigned int agp_buffer_token;
-       struct drm_minor *primary;              /**< render type primary screen head */
-
-       /** \name Drawable information */
-       /*@{ */
-       spinlock_t drw_lock;
-       struct idr drw_idr;
-       /*@} */
-};
-
-static __inline__ int drm_core_check_feature(struct drm_device *dev,
-                                            int feature)
-{
-       return ((dev->driver->driver_features & feature) ? 1 : 0);
-}
-
-#ifdef __alpha__
-#define drm_get_pci_domain(dev) dev->hose->index
-#else
-#define drm_get_pci_domain(dev) 0
-#endif
-
-#if __OS_HAS_AGP
-static inline int drm_core_has_AGP(struct drm_device *dev)
-{
-       return drm_core_check_feature(dev, DRIVER_USE_AGP);
-}
-#else
-#define drm_core_has_AGP(dev) (0)
-#endif
-
-#if __OS_HAS_MTRR
-static inline int drm_core_has_MTRR(struct drm_device *dev)
-{
-       return drm_core_check_feature(dev, DRIVER_USE_MTRR);
-}
-
-#define DRM_MTRR_WC            MTRR_TYPE_WRCOMB
-
-static inline int drm_mtrr_add(unsigned long offset, unsigned long size,
-                              unsigned int flags)
-{
-       return mtrr_add(offset, size, flags, 1);
-}
-
-static inline int drm_mtrr_del(int handle, unsigned long offset,
-                              unsigned long size, unsigned int flags)
-{
-       return mtrr_del(handle, offset, size);
-}
-
-#else
-#define drm_core_has_MTRR(dev) (0)
-
-#define DRM_MTRR_WC            0
-
-static inline int drm_mtrr_add(unsigned long offset, unsigned long size,
-                              unsigned int flags)
-{
-       return 0;
-}
-
-static inline int drm_mtrr_del(int handle, unsigned long offset,
-                              unsigned long size, unsigned int flags)
-{
-       return 0;
-}
-#endif
-
-/******************************************************************/
-/** \name Internal function definitions */
-/*@{*/
-
-                               /* Driver support (drm_drv.h) */
-extern int drm_init(struct drm_driver *driver);
-extern void drm_exit(struct drm_driver *driver);
-extern int drm_ioctl(struct inode *inode, struct file *filp,
-                    unsigned int cmd, unsigned long arg);
-extern long drm_compat_ioctl(struct file *filp,
-                            unsigned int cmd, unsigned long arg);
-extern int drm_lastclose(struct drm_device *dev);
-
-                               /* Device support (drm_fops.h) */
-extern int drm_open(struct inode *inode, struct file *filp);
-extern int drm_stub_open(struct inode *inode, struct file *filp);
-extern int drm_fasync(int fd, struct file *filp, int on);
-extern int drm_release(struct inode *inode, struct file *filp);
-
-                               /* Mapping support (drm_vm.h) */
-extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
-extern unsigned long drm_core_get_map_ofs(struct drm_map * map);
-extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
-extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
-
-                               /* Memory management support (drm_memory.h) */
-#include "drm_memory.h"
-extern void drm_mem_init(void);
-extern int drm_mem_info(char *buf, char **start, off_t offset,
-                       int request, int *eof, void *data);
-extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
-
-extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type);
-extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
-extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
-extern int drm_unbind_agp(DRM_AGP_MEM * handle);
-
-                               /* Misc. IOCTL support (drm_ioctl.h) */
-extern int drm_irq_by_busid(struct drm_device *dev, void *data,
-                           struct drm_file *file_priv);
-extern int drm_getunique(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-extern int drm_setunique(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-extern int drm_getmap(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
-extern int drm_getclient(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-extern int drm_getstats(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-extern int drm_setversion(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv);
-extern int drm_noop(struct drm_device *dev, void *data,
-                   struct drm_file *file_priv);
-
-                               /* Context IOCTL support (drm_context.h) */
-extern int drm_resctx(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
-extern int drm_addctx(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
-extern int drm_modctx(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
-extern int drm_getctx(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
-extern int drm_switchctx(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-extern int drm_newctx(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
-extern int drm_rmctx(struct drm_device *dev, void *data,
-                    struct drm_file *file_priv);
-
-extern int drm_ctxbitmap_init(struct drm_device *dev);
-extern void drm_ctxbitmap_cleanup(struct drm_device *dev);
-extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
-
-extern int drm_setsareactx(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv);
-extern int drm_getsareactx(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv);
-
-                               /* Drawable IOCTL support (drm_drawable.h) */
-extern int drm_adddraw(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv);
-extern int drm_rmdraw(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
-extern int drm_update_drawable_info(struct drm_device *dev, void *data,
-                                   struct drm_file *file_priv);
-extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev,
-                                                 drm_drawable_t id);
-extern void drm_drawable_free_all(struct drm_device *dev);
-
-                               /* Authentication IOCTL support (drm_auth.h) */
-extern int drm_getmagic(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-extern int drm_authmagic(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-
-                               /* Locking IOCTL support (drm_lock.h) */
-extern int drm_lock(struct drm_device *dev, void *data,
-                   struct drm_file *file_priv);
-extern int drm_unlock(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv);
-extern int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
-extern int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context);
-extern void drm_idlelock_take(struct drm_lock_data *lock_data);
-extern void drm_idlelock_release(struct drm_lock_data *lock_data);
-
-/*
- * These are exported to drivers so that they can implement fencing using
- * DMA quiscent + idle. DMA quiescent usually requires the hardware lock.
- */
-
-extern int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv);
-
-                               /* Buffer management support (drm_bufs.h) */
-extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request);
-extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request);
-extern int drm_addmap(struct drm_device *dev, unsigned int offset,
-                     unsigned int size, enum drm_map_type type,
-                     enum drm_map_flags flags, drm_local_map_t ** map_ptr);
-extern int drm_addmap_ioctl(struct drm_device *dev, void *data,
-                           struct drm_file *file_priv);
-extern int drm_rmmap(struct drm_device *dev, drm_local_map_t *map);
-extern int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map);
-extern int drm_rmmap_ioctl(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv);
-extern int drm_addbufs(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv);
-extern int drm_infobufs(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-extern int drm_markbufs(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-extern int drm_freebufs(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-extern int drm_mapbufs(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv);
-extern int drm_order(unsigned long size);
-extern unsigned long drm_get_resource_start(struct drm_device *dev,
-                                           unsigned int resource);
-extern unsigned long drm_get_resource_len(struct drm_device *dev,
-                                         unsigned int resource);
-
-                               /* DMA support (drm_dma.h) */
-extern int drm_dma_setup(struct drm_device *dev);
-extern void drm_dma_takedown(struct drm_device *dev);
-extern void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf);
-extern void drm_core_reclaim_buffers(struct drm_device *dev,
-                                    struct drm_file *filp);
-
-                               /* IRQ support (drm_irq.h) */
-extern int drm_control(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv);
-extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
-extern int drm_irq_uninstall(struct drm_device *dev);
-extern void drm_driver_irq_preinstall(struct drm_device *dev);
-extern void drm_driver_irq_postinstall(struct drm_device *dev);
-extern void drm_driver_irq_uninstall(struct drm_device *dev);
-
-extern int drm_wait_vblank(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv);
-extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
-extern void drm_vbl_send_signals(struct drm_device *dev);
-extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
-
-                               /* AGP/GART support (drm_agpsupport.h) */
-extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
-extern int drm_agp_acquire(struct drm_device *dev);
-extern int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
-                                struct drm_file *file_priv);
-extern int drm_agp_release(struct drm_device *dev);
-extern int drm_agp_release_ioctl(struct drm_device *dev, void *data,
-                                struct drm_file *file_priv);
-extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode);
-extern int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv);
-extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info);
-extern int drm_agp_info_ioctl(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
-extern int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
-extern int drm_agp_free_ioctl(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
-extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv);
-extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
-extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type);
-extern int drm_agp_free_memory(DRM_AGP_MEM * handle);
-extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);
-extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
-
-                               /* Stub support (drm_stub.h) */
-extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
-                      struct drm_driver *driver);
-extern int drm_put_dev(struct drm_device *dev);
-extern int drm_put_minor(struct drm_minor **minor);
-extern unsigned int drm_debug;
-
-extern struct class *drm_class;
-extern struct proc_dir_entry *drm_proc_root;
-
-extern struct idr drm_minors_idr;
-
-extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
-
-                               /* Proc support (drm_proc.h) */
-extern int drm_proc_init(struct drm_minor *minor, int minor_id,
-                        struct proc_dir_entry *root);
-extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root);
-
-                               /* Scatter Gather Support (drm_scatter.h) */
-extern void drm_sg_cleanup(struct drm_sg_mem * entry);
-extern int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-extern int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request);
-extern int drm_sg_free(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv);
-
-                              /* ATI PCIGART support (ati_pcigart.h) */
-extern int drm_ati_pcigart_init(struct drm_device *dev,
-                               struct drm_ati_pcigart_info * gart_info);
-extern int drm_ati_pcigart_cleanup(struct drm_device *dev,
-                                  struct drm_ati_pcigart_info * gart_info);
-
-extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size,
-                                      size_t align, dma_addr_t maxaddr);
-extern void __drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
-extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
-
-                              /* sysfs support (drm_sysfs.c) */
-struct drm_sysfs_class;
-extern struct class *drm_sysfs_create(struct module *owner, char *name);
-extern void drm_sysfs_destroy(void);
-extern int drm_sysfs_device_add(struct drm_minor *minor);
-extern void drm_sysfs_device_remove(struct drm_minor *minor);
-
-/*
- * Basic memory manager support (drm_mm.c)
- */
-extern struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
-                                      unsigned long size,
-                                      unsigned alignment);
-extern void drm_mm_put_block(struct drm_mm_node * cur);
-extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, unsigned long size,
-                                        unsigned alignment, int best_match);
-extern int drm_mm_init(struct drm_mm *mm, unsigned long start, unsigned long size);
-extern void drm_mm_takedown(struct drm_mm *mm);
-extern int drm_mm_clean(struct drm_mm *mm);
-extern unsigned long drm_mm_tail_space(struct drm_mm *mm);
-extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size);
-extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size);
-
-extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
-extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
-
-static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev,
-                                                  unsigned int token)
-{
-       struct drm_map_list *_entry;
-       list_for_each_entry(_entry, &dev->maplist, head)
-           if (_entry->user_token == token)
-               return _entry->map;
-       return NULL;
-}
-
-static __inline__ int drm_device_is_agp(struct drm_device *dev)
-{
-       if (dev->driver->device_is_agp != NULL) {
-               int err = (*dev->driver->device_is_agp) (dev);
-
-               if (err != 2) {
-                       return err;
-               }
-       }
-
-       return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
-}
-
-static __inline__ int drm_device_is_pcie(struct drm_device *dev)
-{
-       return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
-}
-
-static __inline__ void drm_core_dropmap(struct drm_map *map)
-{
-}
-
-#ifndef DEBUG_MEMORY
-/** Wrapper around kmalloc() */
-static __inline__ void *drm_alloc(size_t size, int area)
-{
-       return kmalloc(size, GFP_KERNEL);
-}
-
-/** Wrapper around kfree() */
-static __inline__ void drm_free(void *pt, size_t size, int area)
-{
-       kfree(pt);
-}
-
-/** Wrapper around kcalloc() */
-static __inline__ void *drm_calloc(size_t nmemb, size_t size, int area)
-{
-       return kcalloc(nmemb, size, GFP_KERNEL);
-}
-#else
-extern void *drm_alloc(size_t size, int area);
-extern void drm_free(void *pt, size_t size, int area);
-extern void *drm_calloc(size_t nmemb, size_t size, int area);
-#endif
-
-/*@}*/
-
-#endif                         /* __KERNEL__ */
-#endif
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
deleted file mode 100644 (file)
index aefa5ac..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-/**
- * \file drm_agpsupport.c
- * DRM support for AGP/GART backend
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include <linux/module.h>
-
-#if __OS_HAS_AGP
-
-/**
- * Get AGP information.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a (output) drm_agp_info structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device has been initialized and acquired and fills in the
- * drm_agp_info structure with the information in drm_agp_head::agp_info.
- */
-int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
-{
-       DRM_AGP_KERN *kern;
-
-       if (!dev->agp || !dev->agp->acquired)
-               return -EINVAL;
-
-       kern = &dev->agp->agp_info;
-       info->agp_version_major = kern->version.major;
-       info->agp_version_minor = kern->version.minor;
-       info->mode = kern->mode;
-       info->aperture_base = kern->aper_base;
-       info->aperture_size = kern->aper_size * 1024 * 1024;
-       info->memory_allowed = kern->max_memory << PAGE_SHIFT;
-       info->memory_used = kern->current_memory << PAGE_SHIFT;
-       info->id_vendor = kern->device->vendor;
-       info->id_device = kern->device->device;
-
-       return 0;
-}
-
-EXPORT_SYMBOL(drm_agp_info);
-
-int drm_agp_info_ioctl(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       struct drm_agp_info *info = data;
-       int err;
-
-       err = drm_agp_info(dev, info);
-       if (err)
-               return err;
-
-       return 0;
-}
-
-/**
- * Acquire the AGP device.
- *
- * \param dev DRM device that is to acquire AGP.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device hasn't been acquired before and calls
- * \c agp_backend_acquire.
- */
-int drm_agp_acquire(struct drm_device * dev)
-{
-       if (!dev->agp)
-               return -ENODEV;
-       if (dev->agp->acquired)
-               return -EBUSY;
-       if (!(dev->agp->bridge = agp_backend_acquire(dev->pdev)))
-               return -ENODEV;
-       dev->agp->acquired = 1;
-       return 0;
-}
-
-EXPORT_SYMBOL(drm_agp_acquire);
-
-/**
- * Acquire the AGP device (ioctl).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device hasn't been acquired before and calls
- * \c agp_backend_acquire.
- */
-int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv)
-{
-       return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
-}
-
-/**
- * Release the AGP device.
- *
- * \param dev DRM device that is to release AGP.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device has been acquired and calls \c agp_backend_release.
- */
-int drm_agp_release(struct drm_device * dev)
-{
-       if (!dev->agp || !dev->agp->acquired)
-               return -EINVAL;
-       agp_backend_release(dev->agp->bridge);
-       dev->agp->acquired = 0;
-       return 0;
-}
-EXPORT_SYMBOL(drm_agp_release);
-
-int drm_agp_release_ioctl(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv)
-{
-       return drm_agp_release(dev);
-}
-
-/**
- * Enable the AGP bus.
- *
- * \param dev DRM device that has previously acquired AGP.
- * \param mode Requested AGP mode.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device has been acquired but not enabled, and calls
- * \c agp_enable.
- */
-int drm_agp_enable(struct drm_device * dev, struct drm_agp_mode mode)
-{
-       if (!dev->agp || !dev->agp->acquired)
-               return -EINVAL;
-
-       dev->agp->mode = mode.mode;
-       agp_enable(dev->agp->bridge, mode.mode);
-       dev->agp->enabled = 1;
-       return 0;
-}
-
-EXPORT_SYMBOL(drm_agp_enable);
-
-int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       struct drm_agp_mode *mode = data;
-
-       return drm_agp_enable(dev, *mode);
-}
-
-/**
- * Allocate AGP memory.
- *
- * \param inode device inode.
- * \param file_priv file private pointer.
- * \param cmd command.
- * \param arg pointer to a drm_agp_buffer structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device is present and has been acquired, allocates the
- * memory via alloc_agp() and creates a drm_agp_mem entry for it.
- */
-int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
-{
-       struct drm_agp_mem *entry;
-       DRM_AGP_MEM *memory;
-       unsigned long pages;
-       u32 type;
-
-       if (!dev->agp || !dev->agp->acquired)
-               return -EINVAL;
-       if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
-               return -ENOMEM;
-
-       memset(entry, 0, sizeof(*entry));
-
-       pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
-       type = (u32) request->type;
-       if (!(memory = drm_alloc_agp(dev, pages, type))) {
-               drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
-               return -ENOMEM;
-       }
-
-       entry->handle = (unsigned long)memory->key + 1;
-       entry->memory = memory;
-       entry->bound = 0;
-       entry->pages = pages;
-       list_add(&entry->head, &dev->agp->memory);
-
-       request->handle = entry->handle;
-       request->physical = memory->physical;
-
-       return 0;
-}
-EXPORT_SYMBOL(drm_agp_alloc);
-
-
-int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv)
-{
-       struct drm_agp_buffer *request = data;
-
-       return drm_agp_alloc(dev, request);
-}
-
-/**
- * Search for the AGP memory entry associated with a handle.
- *
- * \param dev DRM device structure.
- * \param handle AGP memory handle.
- * \return pointer to the drm_agp_mem structure associated with \p handle.
- *
- * Walks through drm_agp_head::memory until finding a matching handle.
- */
-static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev,
-                                          unsigned long handle)
-{
-       struct drm_agp_mem *entry;
-
-       list_for_each_entry(entry, &dev->agp->memory, head) {
-               if (entry->handle == handle)
-                       return entry;
-       }
-       return NULL;
-}
-
-/**
- * Unbind AGP memory from the GATT (ioctl).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_agp_binding structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device is present and acquired, looks-up the AGP memory
- * entry and passes it to the unbind_agp() function.
- */
-int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
-{
-       struct drm_agp_mem *entry;
-       int ret;
-
-       if (!dev->agp || !dev->agp->acquired)
-               return -EINVAL;
-       if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
-               return -EINVAL;
-       if (!entry->bound)
-               return -EINVAL;
-       ret = drm_unbind_agp(entry->memory);
-       if (ret == 0)
-               entry->bound = 0;
-       return ret;
-}
-EXPORT_SYMBOL(drm_agp_unbind);
-
-
-int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       struct drm_agp_binding *request = data;
-
-       return drm_agp_unbind(dev, request);
-}
-
-/**
- * Bind AGP memory into the GATT (ioctl)
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_agp_binding structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device is present and has been acquired and that no memory
- * is currently bound into the GATT. Looks-up the AGP memory entry and passes
- * it to bind_agp() function.
- */
-int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
-{
-       struct drm_agp_mem *entry;
-       int retcode;
-       int page;
-
-       if (!dev->agp || !dev->agp->acquired)
-               return -EINVAL;
-       if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
-               return -EINVAL;
-       if (entry->bound)
-               return -EINVAL;
-       page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
-       if ((retcode = drm_bind_agp(entry->memory, page)))
-               return retcode;
-       entry->bound = dev->agp->base + (page << PAGE_SHIFT);
-       DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
-                 dev->agp->base, entry->bound);
-       return 0;
-}
-EXPORT_SYMBOL(drm_agp_bind);
-
-
-int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       struct drm_agp_binding *request = data;
-
-       return drm_agp_bind(dev, request);
-}
-
-/**
- * Free AGP memory (ioctl).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_agp_buffer structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the AGP device is present and has been acquired and looks up the
- * AGP memory entry. If the memory it's currently bound, unbind it via
- * unbind_agp(). Frees it via free_agp() as well as the entry itself
- * and unlinks from the doubly linked list it's inserted in.
- */
-int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
-{
-       struct drm_agp_mem *entry;
-
-       if (!dev->agp || !dev->agp->acquired)
-               return -EINVAL;
-       if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
-               return -EINVAL;
-       if (entry->bound)
-               drm_unbind_agp(entry->memory);
-
-       list_del(&entry->head);
-
-       drm_free_agp(entry->memory, entry->pages);
-       drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
-       return 0;
-}
-EXPORT_SYMBOL(drm_agp_free);
-
-
-
-int drm_agp_free_ioctl(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       struct drm_agp_buffer *request = data;
-
-       return drm_agp_free(dev, request);
-}
-
-/**
- * Initialize the AGP resources.
- *
- * \return pointer to a drm_agp_head structure.
- *
- * Gets the drm_agp_t structure which is made available by the agpgart module
- * via the inter_module_* functions. Creates and initializes a drm_agp_head
- * structure.
- */
-struct drm_agp_head *drm_agp_init(struct drm_device *dev)
-{
-       struct drm_agp_head *head = NULL;
-
-       if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
-               return NULL;
-       memset((void *)head, 0, sizeof(*head));
-       head->bridge = agp_find_bridge(dev->pdev);
-       if (!head->bridge) {
-               if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
-                       drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
-                       return NULL;
-               }
-               agp_copy_info(head->bridge, &head->agp_info);
-               agp_backend_release(head->bridge);
-       } else {
-               agp_copy_info(head->bridge, &head->agp_info);
-       }
-       if (head->agp_info.chipset == NOT_SUPPORTED) {
-               drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
-               return NULL;
-       }
-       INIT_LIST_HEAD(&head->memory);
-       head->cant_use_aperture = head->agp_info.cant_use_aperture;
-       head->page_mask = head->agp_info.page_mask;
-       head->base = head->agp_info.aper_base;
-       return head;
-}
-
-/** Calls agp_allocate_memory() */
-DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data * bridge,
-                                    size_t pages, u32 type)
-{
-       return agp_allocate_memory(bridge, pages, type);
-}
-
-/** Calls agp_free_memory() */
-int drm_agp_free_memory(DRM_AGP_MEM * handle)
-{
-       if (!handle)
-               return 0;
-       agp_free_memory(handle);
-       return 1;
-}
-
-/** Calls agp_bind_memory() */
-int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start)
-{
-       if (!handle)
-               return -EINVAL;
-       return agp_bind_memory(handle, start);
-}
-
-/** Calls agp_unbind_memory() */
-int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
-{
-       if (!handle)
-               return -EINVAL;
-       return agp_unbind_memory(handle);
-}
-
-#endif                         /* __OS_HAS_AGP */
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
deleted file mode 100644 (file)
index a734627..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/**
- * \file drm_auth.c
- * IOCTLs for authentication
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-/**
- * Find the file with the given magic number.
- *
- * \param dev DRM device.
- * \param magic magic number.
- *
- * Searches in drm_device::magiclist within all files with the same hash key
- * the one with matching magic number, while holding the drm_device::struct_mutex
- * lock.
- */
-static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic)
-{
-       struct drm_file *retval = NULL;
-       struct drm_magic_entry *pt;
-       struct drm_hash_item *hash;
-
-       mutex_lock(&dev->struct_mutex);
-       if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
-               pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
-               retval = pt->priv;
-       }
-       mutex_unlock(&dev->struct_mutex);
-       return retval;
-}
-
-/**
- * Adds a magic number.
- *
- * \param dev DRM device.
- * \param priv file private data.
- * \param magic magic number.
- *
- * Creates a drm_magic_entry structure and appends to the linked list
- * associated the magic number hash key in drm_device::magiclist, while holding
- * the drm_device::struct_mutex lock.
- */
-static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
-                        drm_magic_t magic)
-{
-       struct drm_magic_entry *entry;
-
-       DRM_DEBUG("%d\n", magic);
-
-       entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
-       if (!entry)
-               return -ENOMEM;
-       memset(entry, 0, sizeof(*entry));
-       entry->priv = priv;
-
-       entry->hash_item.key = (unsigned long)magic;
-       mutex_lock(&dev->struct_mutex);
-       drm_ht_insert_item(&dev->magiclist, &entry->hash_item);
-       list_add_tail(&entry->head, &dev->magicfree);
-       mutex_unlock(&dev->struct_mutex);
-
-       return 0;
-}
-
-/**
- * Remove a magic number.
- *
- * \param dev DRM device.
- * \param magic magic number.
- *
- * Searches and unlinks the entry in drm_device::magiclist with the magic
- * number hash key, while holding the drm_device::struct_mutex lock.
- */
-static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic)
-{
-       struct drm_magic_entry *pt;
-       struct drm_hash_item *hash;
-
-       DRM_DEBUG("%d\n", magic);
-
-       mutex_lock(&dev->struct_mutex);
-       if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
-               mutex_unlock(&dev->struct_mutex);
-               return -EINVAL;
-       }
-       pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
-       drm_ht_remove_item(&dev->magiclist, hash);
-       list_del(&pt->head);
-       mutex_unlock(&dev->struct_mutex);
-
-       drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
-
-       return 0;
-}
-
-/**
- * Get a unique magic number (ioctl).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a resulting drm_auth structure.
- * \return zero on success, or a negative number on failure.
- *
- * If there is a magic number in drm_file::magic then use it, otherwise
- * searches an unique non-zero magic number and add it associating it with \p
- * file_priv.
- */
-int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       static drm_magic_t sequence = 0;
-       static DEFINE_SPINLOCK(lock);
-       struct drm_auth *auth = data;
-
-       /* Find unique magic */
-       if (file_priv->magic) {
-               auth->magic = file_priv->magic;
-       } else {
-               do {
-                       spin_lock(&lock);
-                       if (!sequence)
-                               ++sequence;     /* reserve 0 */
-                       auth->magic = sequence++;
-                       spin_unlock(&lock);
-               } while (drm_find_file(dev, auth->magic));
-               file_priv->magic = auth->magic;
-               drm_add_magic(dev, file_priv, auth->magic);
-       }
-
-       DRM_DEBUG("%u\n", auth->magic);
-
-       return 0;
-}
-
-/**
- * Authenticate with a magic.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_auth structure.
- * \return zero if authentication successed, or a negative number otherwise.
- *
- * Checks if \p file_priv is associated with the magic number passed in \arg.
- */
-int drm_authmagic(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
-{
-       struct drm_auth *auth = data;
-       struct drm_file *file;
-
-       DRM_DEBUG("%u\n", auth->magic);
-       if ((file = drm_find_file(dev, auth->magic))) {
-               file->authenticated = 1;
-               drm_remove_magic(dev, auth->magic);
-               return 0;
-       }
-       return -EINVAL;
-}
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
deleted file mode 100644 (file)
index bde64b8..0000000
+++ /dev/null
@@ -1,1601 +0,0 @@
-/**
- * \file drm_bufs.c
- * Generic buffer template
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/vmalloc.h>
-#include "drmP.h"
-
-unsigned long drm_get_resource_start(struct drm_device *dev, unsigned int resource)
-{
-       return pci_resource_start(dev->pdev, resource);
-}
-EXPORT_SYMBOL(drm_get_resource_start);
-
-unsigned long drm_get_resource_len(struct drm_device *dev, unsigned int resource)
-{
-       return pci_resource_len(dev->pdev, resource);
-}
-
-EXPORT_SYMBOL(drm_get_resource_len);
-
-static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
-                                            drm_local_map_t *map)
-{
-       struct drm_map_list *entry;
-       list_for_each_entry(entry, &dev->maplist, head) {
-               if (entry->map && map->type == entry->map->type &&
-                   ((entry->map->offset == map->offset) ||
-                    (map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) {
-                       return entry;
-               }
-       }
-
-       return NULL;
-}
-
-static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
-                         unsigned long user_token, int hashed_handle)
-{
-       int use_hashed_handle;
-#if (BITS_PER_LONG == 64)
-       use_hashed_handle = ((user_token & 0xFFFFFFFF00000000UL) || hashed_handle);
-#elif (BITS_PER_LONG == 32)
-       use_hashed_handle = hashed_handle;
-#else
-#error Unsupported long size. Neither 64 nor 32 bits.
-#endif
-
-       if (!use_hashed_handle) {
-               int ret;
-               hash->key = user_token >> PAGE_SHIFT;
-               ret = drm_ht_insert_item(&dev->map_hash, hash);
-               if (ret != -EINVAL)
-                       return ret;
-       }
-       return drm_ht_just_insert_please(&dev->map_hash, hash,
-                                        user_token, 32 - PAGE_SHIFT - 3,
-                                        0, DRM_MAP_HASH_OFFSET >> PAGE_SHIFT);
-}
-
-/**
- * Ioctl to specify a range of memory that is available for mapping by a non-root process.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_map structure.
- * \return zero on success or a negative value on error.
- *
- * Adjusts the memory offset to its absolute value according to the mapping
- * type.  Adds the map to the map list drm_device::maplist. Adds MTRR's where
- * applicable and if supported by the kernel.
- */
-static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
-                          unsigned int size, enum drm_map_type type,
-                          enum drm_map_flags flags,
-                          struct drm_map_list ** maplist)
-{
-       struct drm_map *map;
-       struct drm_map_list *list;
-       drm_dma_handle_t *dmah;
-       unsigned long user_token;
-       int ret;
-
-       map = drm_alloc(sizeof(*map), DRM_MEM_MAPS);
-       if (!map)
-               return -ENOMEM;
-
-       map->offset = offset;
-       map->size = size;
-       map->flags = flags;
-       map->type = type;
-
-       /* Only allow shared memory to be removable since we only keep enough
-        * book keeping information about shared memory to allow for removal
-        * when processes fork.
-        */
-       if ((map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM) {
-               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-               return -EINVAL;
-       }
-       DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n",
-                 map->offset, map->size, map->type);
-       if ((map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
-               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-               return -EINVAL;
-       }
-       map->mtrr = -1;
-       map->handle = NULL;
-
-       switch (map->type) {
-       case _DRM_REGISTERS:
-       case _DRM_FRAME_BUFFER:
-#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
-               if (map->offset + (map->size-1) < map->offset ||
-                   map->offset < virt_to_phys(high_memory)) {
-                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-                       return -EINVAL;
-               }
-#endif
-#ifdef __alpha__
-               map->offset += dev->hose->mem_space->start;
-#endif
-               /* Some drivers preinitialize some maps, without the X Server
-                * needing to be aware of it.  Therefore, we just return success
-                * when the server tries to create a duplicate map.
-                */
-               list = drm_find_matching_map(dev, map);
-               if (list != NULL) {
-                       if (list->map->size != map->size) {
-                               DRM_DEBUG("Matching maps of type %d with "
-                                         "mismatched sizes, (%ld vs %ld)\n",
-                                         map->type, map->size,
-                                         list->map->size);
-                               list->map->size = map->size;
-                       }
-
-                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-                       *maplist = list;
-                       return 0;
-               }
-
-               if (drm_core_has_MTRR(dev)) {
-                       if (map->type == _DRM_FRAME_BUFFER ||
-                           (map->flags & _DRM_WRITE_COMBINING)) {
-                               map->mtrr = mtrr_add(map->offset, map->size,
-                                                    MTRR_TYPE_WRCOMB, 1);
-                       }
-               }
-               if (map->type == _DRM_REGISTERS) {
-                       map->handle = ioremap(map->offset, map->size);
-                       if (!map->handle) {
-                               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-                               return -ENOMEM;
-                       }
-               }
-
-               break;
-       case _DRM_SHM:
-               list = drm_find_matching_map(dev, map);
-               if (list != NULL) {
-                       if(list->map->size != map->size) {
-                               DRM_DEBUG("Matching maps of type %d with "
-                                         "mismatched sizes, (%ld vs %ld)\n",
-                                         map->type, map->size, list->map->size);
-                               list->map->size = map->size;
-                       }
-
-                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-                       *maplist = list;
-                       return 0;
-               }
-               map->handle = vmalloc_user(map->size);
-               DRM_DEBUG("%lu %d %p\n",
-                         map->size, drm_order(map->size), map->handle);
-               if (!map->handle) {
-                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-                       return -ENOMEM;
-               }
-               map->offset = (unsigned long)map->handle;
-               if (map->flags & _DRM_CONTAINS_LOCK) {
-                       /* Prevent a 2nd X Server from creating a 2nd lock */
-                       if (dev->lock.hw_lock != NULL) {
-                               vfree(map->handle);
-                               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-                               return -EBUSY;
-                       }
-                       dev->sigdata.lock = dev->lock.hw_lock = map->handle;    /* Pointer to lock */
-               }
-               break;
-       case _DRM_AGP: {
-               struct drm_agp_mem *entry;
-               int valid = 0;
-
-               if (!drm_core_has_AGP(dev)) {
-                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-                       return -EINVAL;
-               }
-#ifdef __alpha__
-               map->offset += dev->hose->mem_space->start;
-#endif
-               /* In some cases (i810 driver), user space may have already
-                * added the AGP base itself, because dev->agp->base previously
-                * only got set during AGP enable.  So, only add the base
-                * address if the map's offset isn't already within the
-                * aperture.
-                */
-               if (map->offset < dev->agp->base ||
-                   map->offset > dev->agp->base +
-                   dev->agp->agp_info.aper_size * 1024 * 1024 - 1) {
-                       map->offset += dev->agp->base;
-               }
-               map->mtrr = dev->agp->agp_mtrr; /* for getmap */
-
-               /* This assumes the DRM is in total control of AGP space.
-                * It's not always the case as AGP can be in the control
-                * of user space (i.e. i810 driver). So this loop will get
-                * skipped and we double check that dev->agp->memory is
-                * actually set as well as being invalid before EPERM'ing
-                */
-               list_for_each_entry(entry, &dev->agp->memory, head) {
-                       if ((map->offset >= entry->bound) &&
-                           (map->offset + map->size <= entry->bound + entry->pages * PAGE_SIZE)) {
-                               valid = 1;
-                               break;
-                       }
-               }
-               if (!list_empty(&dev->agp->memory) && !valid) {
-                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-                       return -EPERM;
-               }
-               DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n", map->offset, map->size);
-
-               break;
-       }
-       case _DRM_SCATTER_GATHER:
-               if (!dev->sg) {
-                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-                       return -EINVAL;
-               }
-               map->offset += (unsigned long)dev->sg->virtual;
-               break;
-       case _DRM_CONSISTENT:
-               /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
-                * As we're limiting the address to 2^32-1 (or less),
-                * casting it down to 32 bits is no problem, but we
-                * need to point to a 64bit variable first. */
-               dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL);
-               if (!dmah) {
-                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-                       return -ENOMEM;
-               }
-               map->handle = dmah->vaddr;
-               map->offset = (unsigned long)dmah->busaddr;
-               kfree(dmah);
-               break;
-       default:
-               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-               return -EINVAL;
-       }
-
-       list = drm_alloc(sizeof(*list), DRM_MEM_MAPS);
-       if (!list) {
-               if (map->type == _DRM_REGISTERS)
-                       iounmap(map->handle);
-               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-               return -EINVAL;
-       }
-       memset(list, 0, sizeof(*list));
-       list->map = map;
-
-       mutex_lock(&dev->struct_mutex);
-       list_add(&list->head, &dev->maplist);
-
-       /* Assign a 32-bit handle */
-       /* We do it here so that dev->struct_mutex protects the increment */
-       user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle :
-               map->offset;
-       ret = drm_map_handle(dev, &list->hash, user_token, 0);
-       if (ret) {
-               if (map->type == _DRM_REGISTERS)
-                       iounmap(map->handle);
-               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-               drm_free(list, sizeof(*list), DRM_MEM_MAPS);
-               mutex_unlock(&dev->struct_mutex);
-               return ret;
-       }
-
-       list->user_token = list->hash.key << PAGE_SHIFT;
-       mutex_unlock(&dev->struct_mutex);
-
-       *maplist = list;
-       return 0;
-       }
-
-int drm_addmap(struct drm_device * dev, unsigned int offset,
-              unsigned int size, enum drm_map_type type,
-              enum drm_map_flags flags, drm_local_map_t ** map_ptr)
-{
-       struct drm_map_list *list;
-       int rc;
-
-       rc = drm_addmap_core(dev, offset, size, type, flags, &list);
-       if (!rc)
-               *map_ptr = list->map;
-       return rc;
-}
-
-EXPORT_SYMBOL(drm_addmap);
-
-int drm_addmap_ioctl(struct drm_device *dev, void *data,
-                    struct drm_file *file_priv)
-{
-       struct drm_map *map = data;
-       struct drm_map_list *maplist;
-       int err;
-
-       if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP))
-               return -EPERM;
-
-       err = drm_addmap_core(dev, map->offset, map->size, map->type,
-                             map->flags, &maplist);
-
-       if (err)
-               return err;
-
-       /* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
-       map->handle = (void *)(unsigned long)maplist->user_token;
-       return 0;
-}
-
-/**
- * Remove a map private from list and deallocate resources if the mapping
- * isn't in use.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a struct drm_map structure.
- * \return zero on success or a negative value on error.
- *
- * Searches the map on drm_device::maplist, removes it from the list, see if
- * its being used, and free any associate resource (such as MTRR's) if it's not
- * being on use.
- *
- * \sa drm_addmap
- */
-int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
-{
-       struct drm_map_list *r_list = NULL, *list_t;
-       drm_dma_handle_t dmah;
-       int found = 0;
-
-       /* Find the list entry for the map and remove it */
-       list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
-               if (r_list->map == map) {
-                       list_del(&r_list->head);
-                       drm_ht_remove_key(&dev->map_hash,
-                                         r_list->user_token >> PAGE_SHIFT);
-                       drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (!found)
-               return -EINVAL;
-
-       switch (map->type) {
-       case _DRM_REGISTERS:
-               iounmap(map->handle);
-               /* FALLTHROUGH */
-       case _DRM_FRAME_BUFFER:
-               if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
-                       int retcode;
-                       retcode = mtrr_del(map->mtrr, map->offset, map->size);
-                       DRM_DEBUG("mtrr_del=%d\n", retcode);
-               }
-               break;
-       case _DRM_SHM:
-               vfree(map->handle);
-               break;
-       case _DRM_AGP:
-       case _DRM_SCATTER_GATHER:
-               break;
-       case _DRM_CONSISTENT:
-               dmah.vaddr = map->handle;
-               dmah.busaddr = map->offset;
-               dmah.size = map->size;
-               __drm_pci_free(dev, &dmah);
-               break;
-       }
-       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-
-       return 0;
-}
-
-int drm_rmmap(struct drm_device *dev, drm_local_map_t *map)
-{
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-       ret = drm_rmmap_locked(dev, map);
-       mutex_unlock(&dev->struct_mutex);
-
-       return ret;
-}
-EXPORT_SYMBOL(drm_rmmap);
-
-/* The rmmap ioctl appears to be unnecessary.  All mappings are torn down on
- * the last close of the device, and this is necessary for cleanup when things
- * exit uncleanly.  Therefore, having userland manually remove mappings seems
- * like a pointless exercise since they're going away anyway.
- *
- * One use case might be after addmap is allowed for normal users for SHM and
- * gets used by drivers that the server doesn't need to care about.  This seems
- * unlikely.
- */
-int drm_rmmap_ioctl(struct drm_device *dev, void *data,
-                   struct drm_file *file_priv)
-{
-       struct drm_map *request = data;
-       drm_local_map_t *map = NULL;
-       struct drm_map_list *r_list;
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-       list_for_each_entry(r_list, &dev->maplist, head) {
-               if (r_list->map &&
-                   r_list->user_token == (unsigned long)request->handle &&
-                   r_list->map->flags & _DRM_REMOVABLE) {
-                       map = r_list->map;
-                       break;
-               }
-       }
-
-       /* List has wrapped around to the head pointer, or its empty we didn't
-        * find anything.
-        */
-       if (list_empty(&dev->maplist) || !map) {
-               mutex_unlock(&dev->struct_mutex);
-               return -EINVAL;
-       }
-
-       /* Register and framebuffer maps are permanent */
-       if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
-               mutex_unlock(&dev->struct_mutex);
-               return 0;
-       }
-
-       ret = drm_rmmap_locked(dev, map);
-
-       mutex_unlock(&dev->struct_mutex);
-
-       return ret;
-}
-
-/**
- * Cleanup after an error on one of the addbufs() functions.
- *
- * \param dev DRM device.
- * \param entry buffer entry where the error occurred.
- *
- * Frees any pages and buffers associated with the given entry.
- */
-static void drm_cleanup_buf_error(struct drm_device * dev,
-                                 struct drm_buf_entry * entry)
-{
-       int i;
-
-       if (entry->seg_count) {
-               for (i = 0; i < entry->seg_count; i++) {
-                       if (entry->seglist[i]) {
-                               drm_pci_free(dev, entry->seglist[i]);
-                       }
-               }
-               drm_free(entry->seglist,
-                        entry->seg_count *
-                        sizeof(*entry->seglist), DRM_MEM_SEGS);
-
-               entry->seg_count = 0;
-       }
-
-       if (entry->buf_count) {
-               for (i = 0; i < entry->buf_count; i++) {
-                       if (entry->buflist[i].dev_private) {
-                               drm_free(entry->buflist[i].dev_private,
-                                        entry->buflist[i].dev_priv_size,
-                                        DRM_MEM_BUFS);
-                       }
-               }
-               drm_free(entry->buflist,
-                        entry->buf_count *
-                        sizeof(*entry->buflist), DRM_MEM_BUFS);
-
-               entry->buf_count = 0;
-       }
-}
-
-#if __OS_HAS_AGP
-/**
- * Add AGP buffers for DMA transfers.
- *
- * \param dev struct drm_device to which the buffers are to be added.
- * \param request pointer to a struct drm_buf_desc describing the request.
- * \return zero on success or a negative number on failure.
- *
- * After some sanity checks creates a drm_buf structure for each buffer and
- * reallocates the buffer list of the same size order to accommodate the new
- * buffers.
- */
-int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
-{
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf_entry *entry;
-       struct drm_agp_mem *agp_entry;
-       struct drm_buf *buf;
-       unsigned long offset;
-       unsigned long agp_offset;
-       int count;
-       int order;
-       int size;
-       int alignment;
-       int page_order;
-       int total;
-       int byte_count;
-       int i, valid;
-       struct drm_buf **temp_buflist;
-
-       if (!dma)
-               return -EINVAL;
-
-       count = request->count;
-       order = drm_order(request->size);
-       size = 1 << order;
-
-       alignment = (request->flags & _DRM_PAGE_ALIGN)
-           ? PAGE_ALIGN(size) : size;
-       page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
-       total = PAGE_SIZE << page_order;
-
-       byte_count = 0;
-       agp_offset = dev->agp->base + request->agp_start;
-
-       DRM_DEBUG("count:      %d\n", count);
-       DRM_DEBUG("order:      %d\n", order);
-       DRM_DEBUG("size:       %d\n", size);
-       DRM_DEBUG("agp_offset: %lx\n", agp_offset);
-       DRM_DEBUG("alignment:  %d\n", alignment);
-       DRM_DEBUG("page_order: %d\n", page_order);
-       DRM_DEBUG("total:      %d\n", total);
-
-       if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
-               return -EINVAL;
-       if (dev->queue_count)
-               return -EBUSY;  /* Not while in use */
-
-       /* Make sure buffers are located in AGP memory that we own */
-       valid = 0;
-       list_for_each_entry(agp_entry, &dev->agp->memory, head) {
-               if ((agp_offset >= agp_entry->bound) &&
-                   (agp_offset + total * count <= agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
-                       valid = 1;
-                       break;
-               }
-       }
-       if (!list_empty(&dev->agp->memory) && !valid) {
-               DRM_DEBUG("zone invalid\n");
-               return -EINVAL;
-       }
-       spin_lock(&dev->count_lock);
-       if (dev->buf_use) {
-               spin_unlock(&dev->count_lock);
-               return -EBUSY;
-       }
-       atomic_inc(&dev->buf_alloc);
-       spin_unlock(&dev->count_lock);
-
-       mutex_lock(&dev->struct_mutex);
-       entry = &dma->bufs[order];
-       if (entry->buf_count) {
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM; /* May only call once for each order */
-       }
-
-       if (count < 0 || count > 4096) {
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -EINVAL;
-       }
-
-       entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-                                  DRM_MEM_BUFS);
-       if (!entry->buflist) {
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM;
-       }
-       memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-
-       entry->buf_size = size;
-       entry->page_order = page_order;
-
-       offset = 0;
-
-       while (entry->buf_count < count) {
-               buf = &entry->buflist[entry->buf_count];
-               buf->idx = dma->buf_count + entry->buf_count;
-               buf->total = alignment;
-               buf->order = order;
-               buf->used = 0;
-
-               buf->offset = (dma->byte_count + offset);
-               buf->bus_address = agp_offset + offset;
-               buf->address = (void *)(agp_offset + offset);
-               buf->next = NULL;
-               buf->waiting = 0;
-               buf->pending = 0;
-               init_waitqueue_head(&buf->dma_wait);
-               buf->file_priv = NULL;
-
-               buf->dev_priv_size = dev->driver->dev_priv_size;
-               buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
-               if (!buf->dev_private) {
-                       /* Set count correctly so we free the proper amount. */
-                       entry->buf_count = count;
-                       drm_cleanup_buf_error(dev, entry);
-                       mutex_unlock(&dev->struct_mutex);
-                       atomic_dec(&dev->buf_alloc);
-                       return -ENOMEM;
-               }
-               memset(buf->dev_private, 0, buf->dev_priv_size);
-
-               DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
-
-               offset += alignment;
-               entry->buf_count++;
-               byte_count += PAGE_SIZE << page_order;
-       }
-
-       DRM_DEBUG("byte_count: %d\n", byte_count);
-
-       temp_buflist = drm_realloc(dma->buflist,
-                                  dma->buf_count * sizeof(*dma->buflist),
-                                  (dma->buf_count + entry->buf_count)
-                                  * sizeof(*dma->buflist), DRM_MEM_BUFS);
-       if (!temp_buflist) {
-               /* Free the entry because it isn't valid */
-               drm_cleanup_buf_error(dev, entry);
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM;
-       }
-       dma->buflist = temp_buflist;
-
-       for (i = 0; i < entry->buf_count; i++) {
-               dma->buflist[i + dma->buf_count] = &entry->buflist[i];
-       }
-
-       dma->buf_count += entry->buf_count;
-       dma->seg_count += entry->seg_count;
-       dma->page_count += byte_count >> PAGE_SHIFT;
-       dma->byte_count += byte_count;
-
-       DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
-       DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
-
-       mutex_unlock(&dev->struct_mutex);
-
-       request->count = entry->buf_count;
-       request->size = size;
-
-       dma->flags = _DRM_DMA_USE_AGP;
-
-       atomic_dec(&dev->buf_alloc);
-       return 0;
-}
-EXPORT_SYMBOL(drm_addbufs_agp);
-#endif                         /* __OS_HAS_AGP */
-
-int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int count;
-       int order;
-       int size;
-       int total;
-       int page_order;
-       struct drm_buf_entry *entry;
-       drm_dma_handle_t *dmah;
-       struct drm_buf *buf;
-       int alignment;
-       unsigned long offset;
-       int i;
-       int byte_count;
-       int page_count;
-       unsigned long *temp_pagelist;
-       struct drm_buf **temp_buflist;
-
-       if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
-               return -EINVAL;
-
-       if (!dma)
-               return -EINVAL;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       count = request->count;
-       order = drm_order(request->size);
-       size = 1 << order;
-
-       DRM_DEBUG("count=%d, size=%d (%d), order=%d, queue_count=%d\n",
-                 request->count, request->size, size, order, dev->queue_count);
-
-       if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
-               return -EINVAL;
-       if (dev->queue_count)
-               return -EBUSY;  /* Not while in use */
-
-       alignment = (request->flags & _DRM_PAGE_ALIGN)
-           ? PAGE_ALIGN(size) : size;
-       page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
-       total = PAGE_SIZE << page_order;
-
-       spin_lock(&dev->count_lock);
-       if (dev->buf_use) {
-               spin_unlock(&dev->count_lock);
-               return -EBUSY;
-       }
-       atomic_inc(&dev->buf_alloc);
-       spin_unlock(&dev->count_lock);
-
-       mutex_lock(&dev->struct_mutex);
-       entry = &dma->bufs[order];
-       if (entry->buf_count) {
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM; /* May only call once for each order */
-       }
-
-       if (count < 0 || count > 4096) {
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -EINVAL;
-       }
-
-       entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-                                  DRM_MEM_BUFS);
-       if (!entry->buflist) {
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM;
-       }
-       memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-
-       entry->seglist = drm_alloc(count * sizeof(*entry->seglist),
-                                  DRM_MEM_SEGS);
-       if (!entry->seglist) {
-               drm_free(entry->buflist,
-                        count * sizeof(*entry->buflist), DRM_MEM_BUFS);
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM;
-       }
-       memset(entry->seglist, 0, count * sizeof(*entry->seglist));
-
-       /* Keep the original pagelist until we know all the allocations
-        * have succeeded
-        */
-       temp_pagelist = drm_alloc((dma->page_count + (count << page_order))
-                                 * sizeof(*dma->pagelist), DRM_MEM_PAGES);
-       if (!temp_pagelist) {
-               drm_free(entry->buflist,
-                        count * sizeof(*entry->buflist), DRM_MEM_BUFS);
-               drm_free(entry->seglist,
-                        count * sizeof(*entry->seglist), DRM_MEM_SEGS);
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM;
-       }
-       memcpy(temp_pagelist,
-              dma->pagelist, dma->page_count * sizeof(*dma->pagelist));
-       DRM_DEBUG("pagelist: %d entries\n",
-                 dma->page_count + (count << page_order));
-
-       entry->buf_size = size;
-       entry->page_order = page_order;
-       byte_count = 0;
-       page_count = 0;
-
-       while (entry->buf_count < count) {
-
-               dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful);
-
-               if (!dmah) {
-                       /* Set count correctly so we free the proper amount. */
-                       entry->buf_count = count;
-                       entry->seg_count = count;
-                       drm_cleanup_buf_error(dev, entry);
-                       drm_free(temp_pagelist,
-                                (dma->page_count + (count << page_order))
-                                * sizeof(*dma->pagelist), DRM_MEM_PAGES);
-                       mutex_unlock(&dev->struct_mutex);
-                       atomic_dec(&dev->buf_alloc);
-                       return -ENOMEM;
-               }
-               entry->seglist[entry->seg_count++] = dmah;
-               for (i = 0; i < (1 << page_order); i++) {
-                       DRM_DEBUG("page %d @ 0x%08lx\n",
-                                 dma->page_count + page_count,
-                                 (unsigned long)dmah->vaddr + PAGE_SIZE * i);
-                       temp_pagelist[dma->page_count + page_count++]
-                               = (unsigned long)dmah->vaddr + PAGE_SIZE * i;
-               }
-               for (offset = 0;
-                    offset + size <= total && entry->buf_count < count;
-                    offset += alignment, ++entry->buf_count) {
-                       buf = &entry->buflist[entry->buf_count];
-                       buf->idx = dma->buf_count + entry->buf_count;
-                       buf->total = alignment;
-                       buf->order = order;
-                       buf->used = 0;
-                       buf->offset = (dma->byte_count + byte_count + offset);
-                       buf->address = (void *)(dmah->vaddr + offset);
-                       buf->bus_address = dmah->busaddr + offset;
-                       buf->next = NULL;
-                       buf->waiting = 0;
-                       buf->pending = 0;
-                       init_waitqueue_head(&buf->dma_wait);
-                       buf->file_priv = NULL;
-
-                       buf->dev_priv_size = dev->driver->dev_priv_size;
-                       buf->dev_private = drm_alloc(buf->dev_priv_size,
-                                                    DRM_MEM_BUFS);
-                       if (!buf->dev_private) {
-                               /* Set count correctly so we free the proper amount. */
-                               entry->buf_count = count;
-                               entry->seg_count = count;
-                               drm_cleanup_buf_error(dev, entry);
-                               drm_free(temp_pagelist,
-                                        (dma->page_count +
-                                         (count << page_order))
-                                        * sizeof(*dma->pagelist),
-                                        DRM_MEM_PAGES);
-                               mutex_unlock(&dev->struct_mutex);
-                               atomic_dec(&dev->buf_alloc);
-                               return -ENOMEM;
-                       }
-                       memset(buf->dev_private, 0, buf->dev_priv_size);
-
-                       DRM_DEBUG("buffer %d @ %p\n",
-                                 entry->buf_count, buf->address);
-               }
-               byte_count += PAGE_SIZE << page_order;
-       }
-
-       temp_buflist = drm_realloc(dma->buflist,
-                                  dma->buf_count * sizeof(*dma->buflist),
-                                  (dma->buf_count + entry->buf_count)
-                                  * sizeof(*dma->buflist), DRM_MEM_BUFS);
-       if (!temp_buflist) {
-               /* Free the entry because it isn't valid */
-               drm_cleanup_buf_error(dev, entry);
-               drm_free(temp_pagelist,
-                        (dma->page_count + (count << page_order))
-                        * sizeof(*dma->pagelist), DRM_MEM_PAGES);
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM;
-       }
-       dma->buflist = temp_buflist;
-
-       for (i = 0; i < entry->buf_count; i++) {
-               dma->buflist[i + dma->buf_count] = &entry->buflist[i];
-       }
-
-       /* No allocations failed, so now we can replace the orginal pagelist
-        * with the new one.
-        */
-       if (dma->page_count) {
-               drm_free(dma->pagelist,
-                        dma->page_count * sizeof(*dma->pagelist),
-                        DRM_MEM_PAGES);
-       }
-       dma->pagelist = temp_pagelist;
-
-       dma->buf_count += entry->buf_count;
-       dma->seg_count += entry->seg_count;
-       dma->page_count += entry->seg_count << page_order;
-       dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
-
-       mutex_unlock(&dev->struct_mutex);
-
-       request->count = entry->buf_count;
-       request->size = size;
-
-       if (request->flags & _DRM_PCI_BUFFER_RO)
-               dma->flags = _DRM_DMA_USE_PCI_RO;
-
-       atomic_dec(&dev->buf_alloc);
-       return 0;
-
-}
-EXPORT_SYMBOL(drm_addbufs_pci);
-
-static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request)
-{
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf_entry *entry;
-       struct drm_buf *buf;
-       unsigned long offset;
-       unsigned long agp_offset;
-       int count;
-       int order;
-       int size;
-       int alignment;
-       int page_order;
-       int total;
-       int byte_count;
-       int i;
-       struct drm_buf **temp_buflist;
-
-       if (!drm_core_check_feature(dev, DRIVER_SG))
-               return -EINVAL;
-
-       if (!dma)
-               return -EINVAL;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       count = request->count;
-       order = drm_order(request->size);
-       size = 1 << order;
-
-       alignment = (request->flags & _DRM_PAGE_ALIGN)
-           ? PAGE_ALIGN(size) : size;
-       page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
-       total = PAGE_SIZE << page_order;
-
-       byte_count = 0;
-       agp_offset = request->agp_start;
-
-       DRM_DEBUG("count:      %d\n", count);
-       DRM_DEBUG("order:      %d\n", order);
-       DRM_DEBUG("size:       %d\n", size);
-       DRM_DEBUG("agp_offset: %lu\n", agp_offset);
-       DRM_DEBUG("alignment:  %d\n", alignment);
-       DRM_DEBUG("page_order: %d\n", page_order);
-       DRM_DEBUG("total:      %d\n", total);
-
-       if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
-               return -EINVAL;
-       if (dev->queue_count)
-               return -EBUSY;  /* Not while in use */
-
-       spin_lock(&dev->count_lock);
-       if (dev->buf_use) {
-               spin_unlock(&dev->count_lock);
-               return -EBUSY;
-       }
-       atomic_inc(&dev->buf_alloc);
-       spin_unlock(&dev->count_lock);
-
-       mutex_lock(&dev->struct_mutex);
-       entry = &dma->bufs[order];
-       if (entry->buf_count) {
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM; /* May only call once for each order */
-       }
-
-       if (count < 0 || count > 4096) {
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -EINVAL;
-       }
-
-       entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-                                  DRM_MEM_BUFS);
-       if (!entry->buflist) {
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM;
-       }
-       memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-
-       entry->buf_size = size;
-       entry->page_order = page_order;
-
-       offset = 0;
-
-       while (entry->buf_count < count) {
-               buf = &entry->buflist[entry->buf_count];
-               buf->idx = dma->buf_count + entry->buf_count;
-               buf->total = alignment;
-               buf->order = order;
-               buf->used = 0;
-
-               buf->offset = (dma->byte_count + offset);
-               buf->bus_address = agp_offset + offset;
-               buf->address = (void *)(agp_offset + offset
-                                       + (unsigned long)dev->sg->virtual);
-               buf->next = NULL;
-               buf->waiting = 0;
-               buf->pending = 0;
-               init_waitqueue_head(&buf->dma_wait);
-               buf->file_priv = NULL;
-
-               buf->dev_priv_size = dev->driver->dev_priv_size;
-               buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
-               if (!buf->dev_private) {
-                       /* Set count correctly so we free the proper amount. */
-                       entry->buf_count = count;
-                       drm_cleanup_buf_error(dev, entry);
-                       mutex_unlock(&dev->struct_mutex);
-                       atomic_dec(&dev->buf_alloc);
-                       return -ENOMEM;
-               }
-
-               memset(buf->dev_private, 0, buf->dev_priv_size);
-
-               DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
-
-               offset += alignment;
-               entry->buf_count++;
-               byte_count += PAGE_SIZE << page_order;
-       }
-
-       DRM_DEBUG("byte_count: %d\n", byte_count);
-
-       temp_buflist = drm_realloc(dma->buflist,
-                                  dma->buf_count * sizeof(*dma->buflist),
-                                  (dma->buf_count + entry->buf_count)
-                                  * sizeof(*dma->buflist), DRM_MEM_BUFS);
-       if (!temp_buflist) {
-               /* Free the entry because it isn't valid */
-               drm_cleanup_buf_error(dev, entry);
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM;
-       }
-       dma->buflist = temp_buflist;
-
-       for (i = 0; i < entry->buf_count; i++) {
-               dma->buflist[i + dma->buf_count] = &entry->buflist[i];
-       }
-
-       dma->buf_count += entry->buf_count;
-       dma->seg_count += entry->seg_count;
-       dma->page_count += byte_count >> PAGE_SHIFT;
-       dma->byte_count += byte_count;
-
-       DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
-       DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
-
-       mutex_unlock(&dev->struct_mutex);
-
-       request->count = entry->buf_count;
-       request->size = size;
-
-       dma->flags = _DRM_DMA_USE_SG;
-
-       atomic_dec(&dev->buf_alloc);
-       return 0;
-}
-
-static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request)
-{
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf_entry *entry;
-       struct drm_buf *buf;
-       unsigned long offset;
-       unsigned long agp_offset;
-       int count;
-       int order;
-       int size;
-       int alignment;
-       int page_order;
-       int total;
-       int byte_count;
-       int i;
-       struct drm_buf **temp_buflist;
-
-       if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
-               return -EINVAL;
-
-       if (!dma)
-               return -EINVAL;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       count = request->count;
-       order = drm_order(request->size);
-       size = 1 << order;
-
-       alignment = (request->flags & _DRM_PAGE_ALIGN)
-           ? PAGE_ALIGN(size) : size;
-       page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
-       total = PAGE_SIZE << page_order;
-
-       byte_count = 0;
-       agp_offset = request->agp_start;
-
-       DRM_DEBUG("count:      %d\n", count);
-       DRM_DEBUG("order:      %d\n", order);
-       DRM_DEBUG("size:       %d\n", size);
-       DRM_DEBUG("agp_offset: %lu\n", agp_offset);
-       DRM_DEBUG("alignment:  %d\n", alignment);
-       DRM_DEBUG("page_order: %d\n", page_order);
-       DRM_DEBUG("total:      %d\n", total);
-
-       if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
-               return -EINVAL;
-       if (dev->queue_count)
-               return -EBUSY;  /* Not while in use */
-
-       spin_lock(&dev->count_lock);
-       if (dev->buf_use) {
-               spin_unlock(&dev->count_lock);
-               return -EBUSY;
-       }
-       atomic_inc(&dev->buf_alloc);
-       spin_unlock(&dev->count_lock);
-
-       mutex_lock(&dev->struct_mutex);
-       entry = &dma->bufs[order];
-       if (entry->buf_count) {
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM; /* May only call once for each order */
-       }
-
-       if (count < 0 || count > 4096) {
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -EINVAL;
-       }
-
-       entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
-                                  DRM_MEM_BUFS);
-       if (!entry->buflist) {
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM;
-       }
-       memset(entry->buflist, 0, count * sizeof(*entry->buflist));
-
-       entry->buf_size = size;
-       entry->page_order = page_order;
-
-       offset = 0;
-
-       while (entry->buf_count < count) {
-               buf = &entry->buflist[entry->buf_count];
-               buf->idx = dma->buf_count + entry->buf_count;
-               buf->total = alignment;
-               buf->order = order;
-               buf->used = 0;
-
-               buf->offset = (dma->byte_count + offset);
-               buf->bus_address = agp_offset + offset;
-               buf->address = (void *)(agp_offset + offset);
-               buf->next = NULL;
-               buf->waiting = 0;
-               buf->pending = 0;
-               init_waitqueue_head(&buf->dma_wait);
-               buf->file_priv = NULL;
-
-               buf->dev_priv_size = dev->driver->dev_priv_size;
-               buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
-               if (!buf->dev_private) {
-                       /* Set count correctly so we free the proper amount. */
-                       entry->buf_count = count;
-                       drm_cleanup_buf_error(dev, entry);
-                       mutex_unlock(&dev->struct_mutex);
-                       atomic_dec(&dev->buf_alloc);
-                       return -ENOMEM;
-               }
-               memset(buf->dev_private, 0, buf->dev_priv_size);
-
-               DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
-
-               offset += alignment;
-               entry->buf_count++;
-               byte_count += PAGE_SIZE << page_order;
-       }
-
-       DRM_DEBUG("byte_count: %d\n", byte_count);
-
-       temp_buflist = drm_realloc(dma->buflist,
-                                  dma->buf_count * sizeof(*dma->buflist),
-                                  (dma->buf_count + entry->buf_count)
-                                  * sizeof(*dma->buflist), DRM_MEM_BUFS);
-       if (!temp_buflist) {
-               /* Free the entry because it isn't valid */
-               drm_cleanup_buf_error(dev, entry);
-               mutex_unlock(&dev->struct_mutex);
-               atomic_dec(&dev->buf_alloc);
-               return -ENOMEM;
-       }
-       dma->buflist = temp_buflist;
-
-       for (i = 0; i < entry->buf_count; i++) {
-               dma->buflist[i + dma->buf_count] = &entry->buflist[i];
-       }
-
-       dma->buf_count += entry->buf_count;
-       dma->seg_count += entry->seg_count;
-       dma->page_count += byte_count >> PAGE_SHIFT;
-       dma->byte_count += byte_count;
-
-       DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
-       DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
-
-       mutex_unlock(&dev->struct_mutex);
-
-       request->count = entry->buf_count;
-       request->size = size;
-
-       dma->flags = _DRM_DMA_USE_FB;
-
-       atomic_dec(&dev->buf_alloc);
-       return 0;
-}
-
-
-/**
- * Add buffers for DMA transfers (ioctl).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a struct drm_buf_desc request.
- * \return zero on success or a negative number on failure.
- *
- * According with the memory type specified in drm_buf_desc::flags and the
- * build options, it dispatches the call either to addbufs_agp(),
- * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
- * PCI memory respectively.
- */
-int drm_addbufs(struct drm_device *dev, void *data,
-               struct drm_file *file_priv)
-{
-       struct drm_buf_desc *request = data;
-       int ret;
-
-       if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
-               return -EINVAL;
-
-#if __OS_HAS_AGP
-       if (request->flags & _DRM_AGP_BUFFER)
-               ret = drm_addbufs_agp(dev, request);
-       else
-#endif
-       if (request->flags & _DRM_SG_BUFFER)
-               ret = drm_addbufs_sg(dev, request);
-       else if (request->flags & _DRM_FB_BUFFER)
-               ret = drm_addbufs_fb(dev, request);
-       else
-               ret = drm_addbufs_pci(dev, request);
-
-       return ret;
-}
-
-/**
- * Get information about the buffer mappings.
- *
- * This was originally mean for debugging purposes, or by a sophisticated
- * client library to determine how best to use the available buffers (e.g.,
- * large buffers can be used for image transfer).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_buf_info structure.
- * \return zero on success or a negative number on failure.
- *
- * Increments drm_device::buf_use while holding the drm_device::count_lock
- * lock, preventing of allocating more buffers after this call. Information
- * about each requested buffer is then copied into user space.
- */
-int drm_infobufs(struct drm_device *dev, void *data,
-                struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf_info *request = data;
-       int i;
-       int count;
-
-       if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
-               return -EINVAL;
-
-       if (!dma)
-               return -EINVAL;
-
-       spin_lock(&dev->count_lock);
-       if (atomic_read(&dev->buf_alloc)) {
-               spin_unlock(&dev->count_lock);
-               return -EBUSY;
-       }
-       ++dev->buf_use;         /* Can't allocate more after this call */
-       spin_unlock(&dev->count_lock);
-
-       for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
-               if (dma->bufs[i].buf_count)
-                       ++count;
-       }
-
-       DRM_DEBUG("count = %d\n", count);
-
-       if (request->count >= count) {
-               for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
-                       if (dma->bufs[i].buf_count) {
-                               struct drm_buf_desc __user *to =
-                                   &request->list[count];
-                               struct drm_buf_entry *from = &dma->bufs[i];
-                               struct drm_freelist *list = &dma->bufs[i].freelist;
-                               if (copy_to_user(&to->count,
-                                                &from->buf_count,
-                                                sizeof(from->buf_count)) ||
-                                   copy_to_user(&to->size,
-                                                &from->buf_size,
-                                                sizeof(from->buf_size)) ||
-                                   copy_to_user(&to->low_mark,
-                                                &list->low_mark,
-                                                sizeof(list->low_mark)) ||
-                                   copy_to_user(&to->high_mark,
-                                                &list->high_mark,
-                                                sizeof(list->high_mark)))
-                                       return -EFAULT;
-
-                               DRM_DEBUG("%d %d %d %d %d\n",
-                                         i,
-                                         dma->bufs[i].buf_count,
-                                         dma->bufs[i].buf_size,
-                                         dma->bufs[i].freelist.low_mark,
-                                         dma->bufs[i].freelist.high_mark);
-                               ++count;
-                       }
-               }
-       }
-       request->count = count;
-
-       return 0;
-}
-
-/**
- * Specifies a low and high water mark for buffer allocation
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg a pointer to a drm_buf_desc structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies that the size order is bounded between the admissible orders and
- * updates the respective drm_device_dma::bufs entry low and high water mark.
- *
- * \note This ioctl is deprecated and mostly never used.
- */
-int drm_markbufs(struct drm_device *dev, void *data,
-                struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf_desc *request = data;
-       int order;
-       struct drm_buf_entry *entry;
-
-       if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
-               return -EINVAL;
-
-       if (!dma)
-               return -EINVAL;
-
-       DRM_DEBUG("%d, %d, %d\n",
-                 request->size, request->low_mark, request->high_mark);
-       order = drm_order(request->size);
-       if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
-               return -EINVAL;
-       entry = &dma->bufs[order];
-
-       if (request->low_mark < 0 || request->low_mark > entry->buf_count)
-               return -EINVAL;
-       if (request->high_mark < 0 || request->high_mark > entry->buf_count)
-               return -EINVAL;
-
-       entry->freelist.low_mark = request->low_mark;
-       entry->freelist.high_mark = request->high_mark;
-
-       return 0;
-}
-
-/**
- * Unreserve the buffers in list, previously reserved using drmDMA.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_buf_free structure.
- * \return zero on success or a negative number on failure.
- *
- * Calls free_buffer() for each used buffer.
- * This function is primarily used for debugging.
- */
-int drm_freebufs(struct drm_device *dev, void *data,
-                struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf_free *request = data;
-       int i;
-       int idx;
-       struct drm_buf *buf;
-
-       if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
-               return -EINVAL;
-
-       if (!dma)
-               return -EINVAL;
-
-       DRM_DEBUG("%d\n", request->count);
-       for (i = 0; i < request->count; i++) {
-               if (copy_from_user(&idx, &request->list[i], sizeof(idx)))
-                       return -EFAULT;
-               if (idx < 0 || idx >= dma->buf_count) {
-                       DRM_ERROR("Index %d (of %d max)\n",
-                                 idx, dma->buf_count - 1);
-                       return -EINVAL;
-               }
-               buf = dma->buflist[idx];
-               if (buf->file_priv != file_priv) {
-                       DRM_ERROR("Process %d freeing buffer not owned\n",
-                                 task_pid_nr(current));
-                       return -EINVAL;
-               }
-               drm_free_buffer(dev, buf);
-       }
-
-       return 0;
-}
-
-/**
- * Maps all of the DMA buffers into client-virtual space (ioctl).
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg pointer to a drm_buf_map structure.
- * \return zero on success or a negative number on failure.
- *
- * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information
- * about each buffer into user space. For PCI buffers, it calls do_mmap() with
- * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
- * drm_mmap_dma().
- */
-int drm_mapbufs(struct drm_device *dev, void *data,
-               struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int retcode = 0;
-       const int zero = 0;
-       unsigned long virtual;
-       unsigned long address;
-       struct drm_buf_map *request = data;
-       int i;
-
-       if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
-               return -EINVAL;
-
-       if (!dma)
-               return -EINVAL;
-
-       spin_lock(&dev->count_lock);
-       if (atomic_read(&dev->buf_alloc)) {
-               spin_unlock(&dev->count_lock);
-               return -EBUSY;
-       }
-       dev->buf_use++;         /* Can't allocate more after this call */
-       spin_unlock(&dev->count_lock);
-
-       if (request->count >= dma->buf_count) {
-               if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP))
-                   || (drm_core_check_feature(dev, DRIVER_SG)
-                       && (dma->flags & _DRM_DMA_USE_SG))
-                   || (drm_core_check_feature(dev, DRIVER_FB_DMA)
-                       && (dma->flags & _DRM_DMA_USE_FB))) {
-                       struct drm_map *map = dev->agp_buffer_map;
-                       unsigned long token = dev->agp_buffer_token;
-
-                       if (!map) {
-                               retcode = -EINVAL;
-                               goto done;
-                       }
-                       down_write(&current->mm->mmap_sem);
-                       virtual = do_mmap(file_priv->filp, 0, map->size,
-                                         PROT_READ | PROT_WRITE,
-                                         MAP_SHARED,
-                                         token);
-                       up_write(&current->mm->mmap_sem);
-               } else {
-                       down_write(&current->mm->mmap_sem);
-                       virtual = do_mmap(file_priv->filp, 0, dma->byte_count,
-                                         PROT_READ | PROT_WRITE,
-                                         MAP_SHARED, 0);
-                       up_write(&current->mm->mmap_sem);
-               }
-               if (virtual > -1024UL) {
-                       /* Real error */
-                       retcode = (signed long)virtual;
-                       goto done;
-               }
-               request->virtual = (void __user *)virtual;
-
-               for (i = 0; i < dma->buf_count; i++) {
-                       if (copy_to_user(&request->list[i].idx,
-                                        &dma->buflist[i]->idx,
-                                        sizeof(request->list[0].idx))) {
-                               retcode = -EFAULT;
-                               goto done;
-                       }
-                       if (copy_to_user(&request->list[i].total,
-                                        &dma->buflist[i]->total,
-                                        sizeof(request->list[0].total))) {
-                               retcode = -EFAULT;
-                               goto done;
-                       }
-                       if (copy_to_user(&request->list[i].used,
-                                        &zero, sizeof(zero))) {
-                               retcode = -EFAULT;
-                               goto done;
-                       }
-                       address = virtual + dma->buflist[i]->offset;    /* *** */
-                       if (copy_to_user(&request->list[i].address,
-                                        &address, sizeof(address))) {
-                               retcode = -EFAULT;
-                               goto done;
-                       }
-               }
-       }
-      done:
-       request->count = dma->buf_count;
-       DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode);
-
-       return retcode;
-}
-
-/**
- * Compute size order.  Returns the exponent of the smaller power of two which
- * is greater or equal to given number.
- *
- * \param size size.
- * \return order.
- *
- * \todo Can be made faster.
- */
-int drm_order(unsigned long size)
-{
-       int order;
-       unsigned long tmp;
-
-       for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
-
-       if (size & (size - 1))
-               ++order;
-
-       return order;
-}
-EXPORT_SYMBOL(drm_order);
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
deleted file mode 100644 (file)
index d505f69..0000000
+++ /dev/null
@@ -1,471 +0,0 @@
-/**
- * \file drm_context.c
- * IOCTLs for generic contexts
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * ChangeLog:
- *  2001-11-16 Torsten Duwe <duwe@caldera.de>
- *             added context constructor/destructor hooks,
- *             needed by SiS driver's memory management.
- */
-
-#include "drmP.h"
-
-/******************************************************************/
-/** \name Context bitmap support */
-/*@{*/
-
-/**
- * Free a handle from the context bitmap.
- *
- * \param dev DRM device.
- * \param ctx_handle context handle.
- *
- * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
- * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
- * lock.
- */
-void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
-{
-       mutex_lock(&dev->struct_mutex);
-       idr_remove(&dev->ctx_idr, ctx_handle);
-       mutex_unlock(&dev->struct_mutex);
-}
-
-/**
- * Context bitmap allocation.
- *
- * \param dev DRM device.
- * \return (non-negative) context handle on success or a negative number on failure.
- *
- * Allocate a new idr from drm_device::ctx_idr while holding the
- * drm_device::struct_mutex lock.
- */
-static int drm_ctxbitmap_next(struct drm_device * dev)
-{
-       int new_id;
-       int ret;
-
-again:
-       if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
-               DRM_ERROR("Out of memory expanding drawable idr\n");
-               return -ENOMEM;
-       }
-       mutex_lock(&dev->struct_mutex);
-       ret = idr_get_new_above(&dev->ctx_idr, NULL,
-                               DRM_RESERVED_CONTEXTS, &new_id);
-       if (ret == -EAGAIN) {
-               mutex_unlock(&dev->struct_mutex);
-               goto again;
-       }
-       mutex_unlock(&dev->struct_mutex);
-       return new_id;
-}
-
-/**
- * Context bitmap initialization.
- *
- * \param dev DRM device.
- *
- * Initialise the drm_device::ctx_idr
- */
-int drm_ctxbitmap_init(struct drm_device * dev)
-{
-       idr_init(&dev->ctx_idr);
-       return 0;
-}
-
-/**
- * Context bitmap cleanup.
- *
- * \param dev DRM device.
- *
- * Free all idr members using drm_ctx_sarea_free helper function
- * while holding the drm_device::struct_mutex lock.
- */
-void drm_ctxbitmap_cleanup(struct drm_device * dev)
-{
-       mutex_lock(&dev->struct_mutex);
-       idr_remove_all(&dev->ctx_idr);
-       mutex_unlock(&dev->struct_mutex);
-}
-
-/*@}*/
-
-/******************************************************************/
-/** \name Per Context SAREA Support */
-/*@{*/
-
-/**
- * Get per-context SAREA.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx_priv_map structure.
- * \return zero on success or a negative number on failure.
- *
- * Gets the map from drm_device::ctx_idr with the handle specified and
- * returns its handle.
- */
-int drm_getsareactx(struct drm_device *dev, void *data,
-                   struct drm_file *file_priv)
-{
-       struct drm_ctx_priv_map *request = data;
-       struct drm_map *map;
-       struct drm_map_list *_entry;
-
-       mutex_lock(&dev->struct_mutex);
-
-       map = idr_find(&dev->ctx_idr, request->ctx_id);
-       if (!map) {
-               mutex_unlock(&dev->struct_mutex);
-               return -EINVAL;
-       }
-
-       mutex_unlock(&dev->struct_mutex);
-
-       request->handle = NULL;
-       list_for_each_entry(_entry, &dev->maplist, head) {
-               if (_entry->map == map) {
-                       request->handle =
-                           (void *)(unsigned long)_entry->user_token;
-                       break;
-               }
-       }
-       if (request->handle == NULL)
-               return -EINVAL;
-
-       return 0;
-}
-
-/**
- * Set per-context SAREA.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx_priv_map structure.
- * \return zero on success or a negative number on failure.
- *
- * Searches the mapping specified in \p arg and update the entry in
- * drm_device::ctx_idr with it.
- */
-int drm_setsareactx(struct drm_device *dev, void *data,
-                   struct drm_file *file_priv)
-{
-       struct drm_ctx_priv_map *request = data;
-       struct drm_map *map = NULL;
-       struct drm_map_list *r_list = NULL;
-
-       mutex_lock(&dev->struct_mutex);
-       list_for_each_entry(r_list, &dev->maplist, head) {
-               if (r_list->map
-                   && r_list->user_token == (unsigned long) request->handle)
-                       goto found;
-       }
-      bad:
-       mutex_unlock(&dev->struct_mutex);
-       return -EINVAL;
-
-      found:
-       map = r_list->map;
-       if (!map)
-               goto bad;
-
-       if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id)))
-               goto bad;
-
-       mutex_unlock(&dev->struct_mutex);
-
-       return 0;
-}
-
-/*@}*/
-
-/******************************************************************/
-/** \name The actual DRM context handling routines */
-/*@{*/
-
-/**
- * Switch context.
- *
- * \param dev DRM device.
- * \param old old context handle.
- * \param new new context handle.
- * \return zero on success or a negative number on failure.
- *
- * Attempt to set drm_device::context_flag.
- */
-static int drm_context_switch(struct drm_device * dev, int old, int new)
-{
-       if (test_and_set_bit(0, &dev->context_flag)) {
-               DRM_ERROR("Reentering -- FIXME\n");
-               return -EBUSY;
-       }
-
-       DRM_DEBUG("Context switch from %d to %d\n", old, new);
-
-       if (new == dev->last_context) {
-               clear_bit(0, &dev->context_flag);
-               return 0;
-       }
-
-       return 0;
-}
-
-/**
- * Complete context switch.
- *
- * \param dev DRM device.
- * \param new new context handle.
- * \return zero on success or a negative number on failure.
- *
- * Updates drm_device::last_context and drm_device::last_switch. Verifies the
- * hardware lock is held, clears the drm_device::context_flag and wakes up
- * drm_device::context_wait.
- */
-static int drm_context_switch_complete(struct drm_device * dev, int new)
-{
-       dev->last_context = new;        /* PRE/POST: This is the _only_ writer. */
-       dev->last_switch = jiffies;
-
-       if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
-               DRM_ERROR("Lock isn't held after context switch\n");
-       }
-
-       /* If a context switch is ever initiated
-          when the kernel holds the lock, release
-          that lock here. */
-       clear_bit(0, &dev->context_flag);
-       wake_up(&dev->context_wait);
-
-       return 0;
-}
-
-/**
- * Reserve contexts.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx_res structure.
- * \return zero on success or a negative number on failure.
- */
-int drm_resctx(struct drm_device *dev, void *data,
-              struct drm_file *file_priv)
-{
-       struct drm_ctx_res *res = data;
-       struct drm_ctx ctx;
-       int i;
-
-       if (res->count >= DRM_RESERVED_CONTEXTS) {
-               memset(&ctx, 0, sizeof(ctx));
-               for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
-                       ctx.handle = i;
-                       if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx)))
-                               return -EFAULT;
-               }
-       }
-       res->count = DRM_RESERVED_CONTEXTS;
-
-       return 0;
-}
-
-/**
- * Add context.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx structure.
- * \return zero on success or a negative number on failure.
- *
- * Get a new handle for the context and copy to userspace.
- */
-int drm_addctx(struct drm_device *dev, void *data,
-              struct drm_file *file_priv)
-{
-       struct drm_ctx_list *ctx_entry;
-       struct drm_ctx *ctx = data;
-
-       ctx->handle = drm_ctxbitmap_next(dev);
-       if (ctx->handle == DRM_KERNEL_CONTEXT) {
-               /* Skip kernel's context and get a new one. */
-               ctx->handle = drm_ctxbitmap_next(dev);
-       }
-       DRM_DEBUG("%d\n", ctx->handle);
-       if (ctx->handle == -1) {
-               DRM_DEBUG("Not enough free contexts.\n");
-               /* Should this return -EBUSY instead? */
-               return -ENOMEM;
-       }
-
-       if (ctx->handle != DRM_KERNEL_CONTEXT) {
-               if (dev->driver->context_ctor)
-                       if (!dev->driver->context_ctor(dev, ctx->handle)) {
-                               DRM_DEBUG("Running out of ctxs or memory.\n");
-                               return -ENOMEM;
-                       }
-       }
-
-       ctx_entry = drm_alloc(sizeof(*ctx_entry), DRM_MEM_CTXLIST);
-       if (!ctx_entry) {
-               DRM_DEBUG("out of memory\n");
-               return -ENOMEM;
-       }
-
-       INIT_LIST_HEAD(&ctx_entry->head);
-       ctx_entry->handle = ctx->handle;
-       ctx_entry->tag = file_priv;
-
-       mutex_lock(&dev->ctxlist_mutex);
-       list_add(&ctx_entry->head, &dev->ctxlist);
-       ++dev->ctx_count;
-       mutex_unlock(&dev->ctxlist_mutex);
-
-       return 0;
-}
-
-int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       /* This does nothing */
-       return 0;
-}
-
-/**
- * Get context.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx structure.
- * \return zero on success or a negative number on failure.
- */
-int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       struct drm_ctx *ctx = data;
-
-       /* This is 0, because we don't handle any context flags */
-       ctx->flags = 0;
-
-       return 0;
-}
-
-/**
- * Switch context.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx structure.
- * \return zero on success or a negative number on failure.
- *
- * Calls context_switch().
- */
-int drm_switchctx(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
-{
-       struct drm_ctx *ctx = data;
-
-       DRM_DEBUG("%d\n", ctx->handle);
-       return drm_context_switch(dev, dev->last_context, ctx->handle);
-}
-
-/**
- * New context.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx structure.
- * \return zero on success or a negative number on failure.
- *
- * Calls context_switch_complete().
- */
-int drm_newctx(struct drm_device *dev, void *data,
-              struct drm_file *file_priv)
-{
-       struct drm_ctx *ctx = data;
-
-       DRM_DEBUG("%d\n", ctx->handle);
-       drm_context_switch_complete(dev, ctx->handle);
-
-       return 0;
-}
-
-/**
- * Remove context.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument pointing to a drm_ctx structure.
- * \return zero on success or a negative number on failure.
- *
- * If not the special kernel context, calls ctxbitmap_free() to free the specified context.
- */
-int drm_rmctx(struct drm_device *dev, void *data,
-             struct drm_file *file_priv)
-{
-       struct drm_ctx *ctx = data;
-
-       DRM_DEBUG("%d\n", ctx->handle);
-       if (ctx->handle == DRM_KERNEL_CONTEXT + 1) {
-               file_priv->remove_auth_on_close = 1;
-       }
-       if (ctx->handle != DRM_KERNEL_CONTEXT) {
-               if (dev->driver->context_dtor)
-                       dev->driver->context_dtor(dev, ctx->handle);
-               drm_ctxbitmap_free(dev, ctx->handle);
-       }
-
-       mutex_lock(&dev->ctxlist_mutex);
-       if (!list_empty(&dev->ctxlist)) {
-               struct drm_ctx_list *pos, *n;
-
-               list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
-                       if (pos->handle == ctx->handle) {
-                               list_del(&pos->head);
-                               drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
-                               --dev->ctx_count;
-                       }
-               }
-       }
-       mutex_unlock(&dev->ctxlist_mutex);
-
-       return 0;
-}
-
-/*@}*/
diff --git a/drivers/char/drm/drm_core.h b/drivers/char/drm/drm_core.h
deleted file mode 100644 (file)
index 3167390..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2004 Jon Smirl <jonsmirl@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#define CORE_AUTHOR            "Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl"
-
-#define CORE_NAME              "drm"
-#define CORE_DESC              "DRM shared core routines"
-#define CORE_DATE              "20060810"
-
-#define DRM_IF_MAJOR   1
-#define DRM_IF_MINOR   3
-
-#define CORE_MAJOR     1
-#define CORE_MINOR     1
-#define CORE_PATCHLEVEL 0
diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c
deleted file mode 100644 (file)
index 7a8e2fb..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- * \file drm_dma.c
- * DMA IOCTL and function support
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-/**
- * Initialize the DMA data.
- *
- * \param dev DRM device.
- * \return zero on success or a negative value on failure.
- *
- * Allocate and initialize a drm_device_dma structure.
- */
-int drm_dma_setup(struct drm_device *dev)
-{
-       int i;
-
-       dev->dma = drm_alloc(sizeof(*dev->dma), DRM_MEM_DRIVER);
-       if (!dev->dma)
-               return -ENOMEM;
-
-       memset(dev->dma, 0, sizeof(*dev->dma));
-
-       for (i = 0; i <= DRM_MAX_ORDER; i++)
-               memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
-
-       return 0;
-}
-
-/**
- * Cleanup the DMA resources.
- *
- * \param dev DRM device.
- *
- * Free all pages associated with DMA buffers, the buffers and pages lists, and
- * finally the drm_device::dma structure itself.
- */
-void drm_dma_takedown(struct drm_device *dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int i, j;
-
-       if (!dma)
-               return;
-
-       /* Clear dma buffers */
-       for (i = 0; i <= DRM_MAX_ORDER; i++) {
-               if (dma->bufs[i].seg_count) {
-                       DRM_DEBUG("order %d: buf_count = %d,"
-                                 " seg_count = %d\n",
-                                 i,
-                                 dma->bufs[i].buf_count,
-                                 dma->bufs[i].seg_count);
-                       for (j = 0; j < dma->bufs[i].seg_count; j++) {
-                               if (dma->bufs[i].seglist[j]) {
-                                       drm_pci_free(dev, dma->bufs[i].seglist[j]);
-                               }
-                       }
-                       drm_free(dma->bufs[i].seglist,
-                                dma->bufs[i].seg_count
-                                * sizeof(*dma->bufs[0].seglist), DRM_MEM_SEGS);
-               }
-               if (dma->bufs[i].buf_count) {
-                       for (j = 0; j < dma->bufs[i].buf_count; j++) {
-                               if (dma->bufs[i].buflist[j].dev_private) {
-                                       drm_free(dma->bufs[i].buflist[j].
-                                                dev_private,
-                                                dma->bufs[i].buflist[j].
-                                                dev_priv_size, DRM_MEM_BUFS);
-                               }
-                       }
-                       drm_free(dma->bufs[i].buflist,
-                                dma->bufs[i].buf_count *
-                                sizeof(*dma->bufs[0].buflist), DRM_MEM_BUFS);
-               }
-       }
-
-       if (dma->buflist) {
-               drm_free(dma->buflist,
-                        dma->buf_count * sizeof(*dma->buflist), DRM_MEM_BUFS);
-       }
-
-       if (dma->pagelist) {
-               drm_free(dma->pagelist,
-                        dma->page_count * sizeof(*dma->pagelist),
-                        DRM_MEM_PAGES);
-       }
-       drm_free(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
-       dev->dma = NULL;
-}
-
-/**
- * Free a buffer.
- *
- * \param dev DRM device.
- * \param buf buffer to free.
- *
- * Resets the fields of \p buf.
- */
-void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf)
-{
-       if (!buf)
-               return;
-
-       buf->waiting = 0;
-       buf->pending = 0;
-       buf->file_priv = NULL;
-       buf->used = 0;
-
-       if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)
-           && waitqueue_active(&buf->dma_wait)) {
-               wake_up_interruptible(&buf->dma_wait);
-       }
-}
-
-/**
- * Reclaim the buffers.
- *
- * \param file_priv DRM file private.
- *
- * Frees each buffer associated with \p file_priv not already on the hardware.
- */
-void drm_core_reclaim_buffers(struct drm_device *dev,
-                             struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int i;
-
-       if (!dma)
-               return;
-       for (i = 0; i < dma->buf_count; i++) {
-               if (dma->buflist[i]->file_priv == file_priv) {
-                       switch (dma->buflist[i]->list) {
-                       case DRM_LIST_NONE:
-                               drm_free_buffer(dev, dma->buflist[i]);
-                               break;
-                       case DRM_LIST_WAIT:
-                               dma->buflist[i]->list = DRM_LIST_RECLAIM;
-                               break;
-                       default:
-                               /* Buffer already on hardware. */
-                               break;
-                       }
-               }
-       }
-}
-
-EXPORT_SYMBOL(drm_core_reclaim_buffers);
diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c
deleted file mode 100644 (file)
index 1839c57..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/**
- * \file drm_drawable.c
- * IOCTLs for drawables
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- * \author Michel Dänzer <michel@tungstengraphics.com>
- */
-
-/*
- * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck, North Dakota.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-/**
- * Allocate drawable ID and memory to store information about it.
- */
-int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       unsigned long irqflags;
-       struct drm_draw *draw = data;
-       int new_id = 0;
-       int ret;
-
-again:
-       if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) {
-               DRM_ERROR("Out of memory expanding drawable idr\n");
-               return -ENOMEM;
-       }
-
-       spin_lock_irqsave(&dev->drw_lock, irqflags);
-       ret = idr_get_new_above(&dev->drw_idr, NULL, 1, &new_id);
-       if (ret == -EAGAIN) {
-               spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-               goto again;
-       }
-
-       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-
-       draw->handle = new_id;
-
-       DRM_DEBUG("%d\n", draw->handle);
-
-       return 0;
-}
-
-/**
- * Free drawable ID and memory to store information about it.
- */
-int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       struct drm_draw *draw = data;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev->drw_lock, irqflags);
-
-       drm_free(drm_get_drawable_info(dev, draw->handle),
-                sizeof(struct drm_drawable_info), DRM_MEM_BUFS);
-
-       idr_remove(&dev->drw_idr, draw->handle);
-
-       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-       DRM_DEBUG("%d\n", draw->handle);
-       return 0;
-}
-
-int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       struct drm_update_draw *update = data;
-       unsigned long irqflags;
-       struct drm_clip_rect *rects;
-       struct drm_drawable_info *info;
-       int err;
-
-       info = idr_find(&dev->drw_idr, update->handle);
-       if (!info) {
-               info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS);
-               if (!info)
-                       return -ENOMEM;
-               if (IS_ERR(idr_replace(&dev->drw_idr, info, update->handle))) {
-                       DRM_ERROR("No such drawable %d\n", update->handle);
-                       drm_free(info, sizeof(*info), DRM_MEM_BUFS);
-                       return -EINVAL;
-               }
-       }
-
-       switch (update->type) {
-       case DRM_DRAWABLE_CLIPRECTS:
-               if (update->num != info->num_rects) {
-                       rects = drm_alloc(update->num * sizeof(struct drm_clip_rect),
-                                        DRM_MEM_BUFS);
-               } else
-                       rects = info->rects;
-
-               if (update->num && !rects) {
-                       DRM_ERROR("Failed to allocate cliprect memory\n");
-                       err = -ENOMEM;
-                       goto error;
-               }
-
-               if (update->num && DRM_COPY_FROM_USER(rects,
-                                                    (struct drm_clip_rect __user *)
-                                                    (unsigned long)update->data,
-                                                    update->num *
-                                                    sizeof(*rects))) {
-                       DRM_ERROR("Failed to copy cliprects from userspace\n");
-                       err = -EFAULT;
-                       goto error;
-               }
-
-               spin_lock_irqsave(&dev->drw_lock, irqflags);
-
-               if (rects != info->rects) {
-                       drm_free(info->rects, info->num_rects *
-                                sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
-               }
-
-               info->rects = rects;
-               info->num_rects = update->num;
-
-               spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-
-               DRM_DEBUG("Updated %d cliprects for drawable %d\n",
-                         info->num_rects, update->handle);
-               break;
-       default:
-               DRM_ERROR("Invalid update type %d\n", update->type);
-               return -EINVAL;
-       }
-
-       return 0;
-
-error:
-       if (rects != info->rects)
-               drm_free(rects, update->num * sizeof(struct drm_clip_rect),
-                        DRM_MEM_BUFS);
-
-       return err;
-}
-
-/**
- * Caller must hold the drawable spinlock!
- */
-struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id)
-{
-       return idr_find(&dev->drw_idr, id);
-}
-EXPORT_SYMBOL(drm_get_drawable_info);
-
-static int drm_drawable_free(int idr, void *p, void *data)
-{
-       struct drm_drawable_info *info = p;
-
-       if (info) {
-               drm_free(info->rects, info->num_rects *
-                        sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
-               drm_free(info, sizeof(*info), DRM_MEM_BUFS);
-       }
-
-       return 0;
-}
-
-void drm_drawable_free_all(struct drm_device *dev)
-{
-       idr_for_each(&dev->drw_idr, drm_drawable_free, NULL);
-       idr_remove_all(&dev->drw_idr);
-}
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
deleted file mode 100644 (file)
index 5641387..0000000
+++ /dev/null
@@ -1,540 +0,0 @@
-/**
- * \file drm_drv.c
- * Generic driver template
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- *
- * To use this template, you must at least define the following (samples
- * given for the MGA driver):
- *
- * \code
- * #define DRIVER_AUTHOR       "VA Linux Systems, Inc."
- *
- * #define DRIVER_NAME         "mga"
- * #define DRIVER_DESC         "Matrox G200/G400"
- * #define DRIVER_DATE         "20001127"
- *
- * #define drm_x               mga_##x
- * \endcode
- */
-
-/*
- * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm_core.h"
-
-static int drm_version(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv);
-
-/** Ioctl table */
-static struct drm_ioctl_desc drm_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
-       DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
-       DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
-       /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
-       DRM_IOCTL_DEF(DRM_IOCTL_DMA, NULL, DRM_AUTH),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
-#if __OS_HAS_AGP
-       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-#endif
-
-       DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
-
-       DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-};
-
-#define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
-
-/**
- * Take down the DRM device.
- *
- * \param dev DRM device structure.
- *
- * Frees every resource in \p dev.
- *
- * \sa drm_device
- */
-int drm_lastclose(struct drm_device * dev)
-{
-       struct drm_magic_entry *pt, *next;
-       struct drm_map_list *r_list, *list_t;
-       struct drm_vma_entry *vma, *vma_temp;
-       int i;
-
-       DRM_DEBUG("\n");
-
-       if (dev->driver->lastclose)
-               dev->driver->lastclose(dev);
-       DRM_DEBUG("driver lastclose completed\n");
-
-       if (dev->unique) {
-               drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
-               dev->unique = NULL;
-               dev->unique_len = 0;
-       }
-
-       if (dev->irq_enabled)
-               drm_irq_uninstall(dev);
-
-       mutex_lock(&dev->struct_mutex);
-
-       /* Free drawable information memory */
-       drm_drawable_free_all(dev);
-       del_timer(&dev->timer);
-
-       /* Clear pid list */
-       if (dev->magicfree.next) {
-               list_for_each_entry_safe(pt, next, &dev->magicfree, head) {
-                       list_del(&pt->head);
-                       drm_ht_remove_item(&dev->magiclist, &pt->hash_item);
-                       drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
-               }
-               drm_ht_remove(&dev->magiclist);
-       }
-
-       /* Clear AGP information */
-       if (drm_core_has_AGP(dev) && dev->agp) {
-               struct drm_agp_mem *entry, *tempe;
-
-               /* Remove AGP resources, but leave dev->agp
-                  intact until drv_cleanup is called. */
-               list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
-                       if (entry->bound)
-                               drm_unbind_agp(entry->memory);
-                       drm_free_agp(entry->memory, entry->pages);
-                       drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
-               }
-               INIT_LIST_HEAD(&dev->agp->memory);
-
-               if (dev->agp->acquired)
-                       drm_agp_release(dev);
-
-               dev->agp->acquired = 0;
-               dev->agp->enabled = 0;
-       }
-       if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
-               drm_sg_cleanup(dev->sg);
-               dev->sg = NULL;
-       }
-
-       /* Clear vma list (only built for debugging) */
-       list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
-               list_del(&vma->head);
-               drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
-       }
-
-       list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
-               if (!(r_list->map->flags & _DRM_DRIVER)) {
-                       drm_rmmap_locked(dev, r_list->map);
-                       r_list = NULL;
-               }
-       }
-
-       if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
-               for (i = 0; i < dev->queue_count; i++) {
-                       if (dev->queuelist[i]) {
-                               drm_free(dev->queuelist[i],
-                                        sizeof(*dev->queuelist[0]),
-                                        DRM_MEM_QUEUES);
-                               dev->queuelist[i] = NULL;
-                       }
-               }
-               drm_free(dev->queuelist,
-                        dev->queue_slots * sizeof(*dev->queuelist),
-                        DRM_MEM_QUEUES);
-               dev->queuelist = NULL;
-       }
-       dev->queue_count = 0;
-
-       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
-               drm_dma_takedown(dev);
-
-       if (dev->lock.hw_lock) {
-               dev->sigdata.lock = dev->lock.hw_lock = NULL;   /* SHM removed */
-               dev->lock.file_priv = NULL;
-               wake_up_interruptible(&dev->lock.lock_queue);
-       }
-       mutex_unlock(&dev->struct_mutex);
-
-       DRM_DEBUG("lastclose completed\n");
-       return 0;
-}
-
-/**
- * Module initialization. Called via init_module at module load time, or via
- * linux/init/main.c (this is not currently supported).
- *
- * \return zero on success or a negative number on failure.
- *
- * Initializes an array of drm_device structures, and attempts to
- * initialize all available devices, using consecutive minors, registering the
- * stubs and initializing the AGP device.
- *
- * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
- * after the initialization for driver customization.
- */
-int drm_init(struct drm_driver *driver)
-{
-       struct pci_dev *pdev = NULL;
-       struct pci_device_id *pid;
-       int i;
-
-       DRM_DEBUG("\n");
-
-       for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
-               pid = (struct pci_device_id *)&driver->pci_driver.id_table[i];
-
-               pdev = NULL;
-               /* pass back in pdev to account for multiple identical cards */
-               while ((pdev =
-                       pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
-                                      pid->subdevice, pdev)) != NULL) {
-                       /* stealth mode requires a manual probe */
-                       pci_dev_get(pdev);
-                       drm_get_dev(pdev, pid, driver);
-               }
-       }
-       return 0;
-}
-
-EXPORT_SYMBOL(drm_init);
-
-/**
- * Called via cleanup_module() at module unload time.
- *
- * Cleans up all DRM device, calling drm_lastclose().
- *
- * \sa drm_init
- */
-static void drm_cleanup(struct drm_device * dev)
-{
-       DRM_DEBUG("\n");
-
-       if (!dev) {
-               DRM_ERROR("cleanup called no dev\n");
-               return;
-       }
-
-       drm_lastclose(dev);
-
-       if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
-           dev->agp && dev->agp->agp_mtrr >= 0) {
-               int retval;
-               retval = mtrr_del(dev->agp->agp_mtrr,
-                                 dev->agp->agp_info.aper_base,
-                                 dev->agp->agp_info.aper_size * 1024 * 1024);
-               DRM_DEBUG("mtrr_del=%d\n", retval);
-       }
-
-       if (drm_core_has_AGP(dev) && dev->agp) {
-               drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
-               dev->agp = NULL;
-       }
-
-       if (dev->driver->unload)
-               dev->driver->unload(dev);
-
-       drm_ht_remove(&dev->map_hash);
-       drm_ctxbitmap_cleanup(dev);
-
-       drm_put_minor(&dev->primary);
-       if (drm_put_dev(dev))
-               DRM_ERROR("Cannot unload module\n");
-}
-
-int drm_minors_cleanup(int id, void *ptr, void *data)
-{
-       struct drm_minor *minor = ptr;
-       struct drm_device *dev;
-       struct drm_driver *driver = data;
-
-       dev = minor->dev;
-       if (minor->dev->driver != driver)
-               return 0;
-
-       if (minor->type != DRM_MINOR_LEGACY)
-               return 0;
-
-       if (dev)
-               pci_dev_put(dev->pdev);
-       drm_cleanup(dev);
-       return 1;
-}
-
-void drm_exit(struct drm_driver *driver)
-{
-       DRM_DEBUG("\n");
-
-       idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver);
-
-       DRM_INFO("Module unloaded\n");
-}
-
-EXPORT_SYMBOL(drm_exit);
-
-/** File operations structure */
-static const struct file_operations drm_stub_fops = {
-       .owner = THIS_MODULE,
-       .open = drm_stub_open
-};
-
-static int __init drm_core_init(void)
-{
-       int ret = -ENOMEM;
-
-       idr_init(&drm_minors_idr);
-
-       if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
-               goto err_p1;
-
-       drm_class = drm_sysfs_create(THIS_MODULE, "drm");
-       if (IS_ERR(drm_class)) {
-               printk(KERN_ERR "DRM: Error creating drm class.\n");
-               ret = PTR_ERR(drm_class);
-               goto err_p2;
-       }
-
-       drm_proc_root = proc_mkdir("dri", NULL);
-       if (!drm_proc_root) {
-               DRM_ERROR("Cannot create /proc/dri\n");
-               ret = -1;
-               goto err_p3;
-       }
-
-       drm_mem_init();
-
-       DRM_INFO("Initialized %s %d.%d.%d %s\n",
-                CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
-       return 0;
-err_p3:
-       drm_sysfs_destroy();
-err_p2:
-       unregister_chrdev(DRM_MAJOR, "drm");
-
-       idr_destroy(&drm_minors_idr);
-err_p1:
-       return ret;
-}
-
-static void __exit drm_core_exit(void)
-{
-       remove_proc_entry("dri", NULL);
-       drm_sysfs_destroy();
-
-       unregister_chrdev(DRM_MAJOR, "drm");
-
-       idr_destroy(&drm_minors_idr);
-}
-
-module_init(drm_core_init);
-module_exit(drm_core_exit);
-
-/**
- * Get version information
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_version structure.
- * \return zero on success or negative number on failure.
- *
- * Fills in the version information in \p arg.
- */
-static int drm_version(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       struct drm_version *version = data;
-       int len;
-
-       version->version_major = dev->driver->major;
-       version->version_minor = dev->driver->minor;
-       version->version_patchlevel = dev->driver->patchlevel;
-       DRM_COPY(version->name, dev->driver->name);
-       DRM_COPY(version->date, dev->driver->date);
-       DRM_COPY(version->desc, dev->driver->desc);
-
-       return 0;
-}
-
-/**
- * Called whenever a process performs an ioctl on /dev/drm.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
- *
- * Looks up the ioctl function in the ::ioctls table, checking for root
- * previleges if so required, and dispatches to the respective function.
- */
-int drm_ioctl(struct inode *inode, struct file *filp,
-             unsigned int cmd, unsigned long arg)
-{
-       struct drm_file *file_priv = filp->private_data;
-       struct drm_device *dev = file_priv->minor->dev;
-       struct drm_ioctl_desc *ioctl;
-       drm_ioctl_t *func;
-       unsigned int nr = DRM_IOCTL_NR(cmd);
-       int retcode = -EINVAL;
-       char *kdata = NULL;
-
-       atomic_inc(&dev->ioctl_count);
-       atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
-       ++file_priv->ioctl_count;
-
-       DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
-                 task_pid_nr(current), cmd, nr,
-                 (long)old_encode_dev(file_priv->minor->device),
-                 file_priv->authenticated);
-
-       if ((nr >= DRM_CORE_IOCTL_COUNT) &&
-           ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
-               goto err_i1;
-       if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
-           (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
-               ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
-       else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
-               ioctl = &drm_ioctls[nr];
-               cmd = ioctl->cmd;
-       } else
-               goto err_i1;
-
-       /* Do not trust userspace, use our own definition */
-       func = ioctl->func;
-       /* is there a local override? */
-       if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
-               func = dev->driver->dma_ioctl;
-
-       if (!func) {
-               DRM_DEBUG("no function\n");
-               retcode = -EINVAL;
-       } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
-                  ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
-                  ((ioctl->flags & DRM_MASTER) && !file_priv->master)) {
-               retcode = -EACCES;
-       } else {
-               if (cmd & (IOC_IN | IOC_OUT)) {
-                       kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
-                       if (!kdata) {
-                               retcode = -ENOMEM;
-                               goto err_i1;
-                       }
-               }
-
-               if (cmd & IOC_IN) {
-                       if (copy_from_user(kdata, (void __user *)arg,
-                                          _IOC_SIZE(cmd)) != 0) {
-                               retcode = -EFAULT;
-                               goto err_i1;
-                       }
-               }
-               retcode = func(dev, kdata, file_priv);
-
-               if ((retcode == 0) && (cmd & IOC_OUT)) {
-                       if (copy_to_user((void __user *)arg, kdata,
-                                        _IOC_SIZE(cmd)) != 0)
-                               retcode = -EFAULT;
-               }
-       }
-
-      err_i1:
-       if (kdata)
-               kfree(kdata);
-       atomic_dec(&dev->ioctl_count);
-       if (retcode)
-               DRM_DEBUG("ret = %x\n", retcode);
-       return retcode;
-}
-
-EXPORT_SYMBOL(drm_ioctl);
-
-drm_local_map_t *drm_getsarea(struct drm_device *dev)
-{
-       struct drm_map_list *entry;
-
-       list_for_each_entry(entry, &dev->maplist, head) {
-               if (entry->map && entry->map->type == _DRM_SHM &&
-                   (entry->map->flags & _DRM_CONTAINS_LOCK)) {
-                       return entry->map;
-               }
-       }
-       return NULL;
-}
-EXPORT_SYMBOL(drm_getsarea);
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
deleted file mode 100644 (file)
index d2e6da8..0000000
+++ /dev/null
@@ -1,466 +0,0 @@
-/**
- * \file drm_fops.c
- * File operations for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Daryll Strauss <daryll@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm_sarea.h"
-#include <linux/poll.h>
-
-static int drm_open_helper(struct inode *inode, struct file *filp,
-                          struct drm_device * dev);
-
-static int drm_setup(struct drm_device * dev)
-{
-       drm_local_map_t *map;
-       int i;
-       int ret;
-       u32 sareapage;
-
-       if (dev->driver->firstopen) {
-               ret = dev->driver->firstopen(dev);
-               if (ret != 0)
-                       return ret;
-       }
-
-       dev->magicfree.next = NULL;
-
-       /* prebuild the SAREA */
-       sareapage = max_t(unsigned, SAREA_MAX, PAGE_SIZE);
-       i = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
-       if (i != 0)
-               return i;
-
-       atomic_set(&dev->ioctl_count, 0);
-       atomic_set(&dev->vma_count, 0);
-       dev->buf_use = 0;
-       atomic_set(&dev->buf_alloc, 0);
-
-       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) {
-               i = drm_dma_setup(dev);
-               if (i < 0)
-                       return i;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
-               atomic_set(&dev->counts[i], 0);
-
-       drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
-       INIT_LIST_HEAD(&dev->magicfree);
-
-       dev->sigdata.lock = NULL;
-       init_waitqueue_head(&dev->lock.lock_queue);
-       dev->queue_count = 0;
-       dev->queue_reserved = 0;
-       dev->queue_slots = 0;
-       dev->queuelist = NULL;
-       dev->irq_enabled = 0;
-       dev->context_flag = 0;
-       dev->interrupt_flag = 0;
-       dev->dma_flag = 0;
-       dev->last_context = 0;
-       dev->last_switch = 0;
-       dev->last_checked = 0;
-       init_waitqueue_head(&dev->context_wait);
-       dev->if_version = 0;
-
-       dev->ctx_start = 0;
-       dev->lck_start = 0;
-
-       dev->buf_async = NULL;
-       init_waitqueue_head(&dev->buf_readers);
-       init_waitqueue_head(&dev->buf_writers);
-
-       DRM_DEBUG("\n");
-
-       /*
-        * The kernel's context could be created here, but is now created
-        * in drm_dma_enqueue.  This is more resource-efficient for
-        * hardware that does not do DMA, but may mean that
-        * drm_select_queue fails between the time the interrupt is
-        * initialized and the time the queues are initialized.
-        */
-
-       return 0;
-}
-
-/**
- * Open file.
- *
- * \param inode device inode
- * \param filp file pointer.
- * \return zero on success or a negative number on failure.
- *
- * Searches the DRM device with the same minor number, calls open_helper(), and
- * increments the device open count. If the open count was previous at zero,
- * i.e., it's the first that the device is open, then calls setup().
- */
-int drm_open(struct inode *inode, struct file *filp)
-{
-       struct drm_device *dev = NULL;
-       int minor_id = iminor(inode);
-       struct drm_minor *minor;
-       int retcode = 0;
-
-       minor = idr_find(&drm_minors_idr, minor_id);
-       if (!minor)
-               return -ENODEV;
-
-       if (!(dev = minor->dev))
-               return -ENODEV;
-
-       retcode = drm_open_helper(inode, filp, dev);
-       if (!retcode) {
-               atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
-               spin_lock(&dev->count_lock);
-               if (!dev->open_count++) {
-                       spin_unlock(&dev->count_lock);
-                       return drm_setup(dev);
-               }
-               spin_unlock(&dev->count_lock);
-       }
-
-       return retcode;
-}
-EXPORT_SYMBOL(drm_open);
-
-/**
- * File \c open operation.
- *
- * \param inode device inode.
- * \param filp file pointer.
- *
- * Puts the dev->fops corresponding to the device minor number into
- * \p filp, call the \c open method, and restore the file operations.
- */
-int drm_stub_open(struct inode *inode, struct file *filp)
-{
-       struct drm_device *dev = NULL;
-       struct drm_minor *minor;
-       int minor_id = iminor(inode);
-       int err = -ENODEV;
-       const struct file_operations *old_fops;
-
-       DRM_DEBUG("\n");
-
-       minor = idr_find(&drm_minors_idr, minor_id);
-       if (!minor)
-               return -ENODEV;
-
-       if (!(dev = minor->dev))
-               return -ENODEV;
-
-       old_fops = filp->f_op;
-       filp->f_op = fops_get(&dev->driver->fops);
-       if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
-               fops_put(filp->f_op);
-               filp->f_op = fops_get(old_fops);
-       }
-       fops_put(old_fops);
-
-       return err;
-}
-
-/**
- * Check whether DRI will run on this CPU.
- *
- * \return non-zero if the DRI will run on this CPU, or zero otherwise.
- */
-static int drm_cpu_valid(void)
-{
-#if defined(__i386__)
-       if (boot_cpu_data.x86 == 3)
-               return 0;       /* No cmpxchg on a 386 */
-#endif
-#if defined(__sparc__) && !defined(__sparc_v9__)
-       return 0;               /* No cmpxchg before v9 sparc. */
-#endif
-       return 1;
-}
-
-/**
- * Called whenever a process opens /dev/drm.
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param dev device.
- * \return zero on success or a negative number on failure.
- *
- * Creates and initializes a drm_file structure for the file private data in \p
- * filp and add it into the double linked list in \p dev.
- */
-static int drm_open_helper(struct inode *inode, struct file *filp,
-                          struct drm_device * dev)
-{
-       int minor_id = iminor(inode);
-       struct drm_file *priv;
-       int ret;
-
-       if (filp->f_flags & O_EXCL)
-               return -EBUSY;  /* No exclusive opens */
-       if (!drm_cpu_valid())
-               return -EINVAL;
-
-       DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
-
-       priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
-       if (!priv)
-               return -ENOMEM;
-
-       memset(priv, 0, sizeof(*priv));
-       filp->private_data = priv;
-       priv->filp = filp;
-       priv->uid = current->euid;
-       priv->pid = task_pid_nr(current);
-       priv->minor = idr_find(&drm_minors_idr, minor_id);
-       priv->ioctl_count = 0;
-       /* for compatibility root is always authenticated */
-       priv->authenticated = capable(CAP_SYS_ADMIN);
-       priv->lock_count = 0;
-
-       INIT_LIST_HEAD(&priv->lhead);
-
-       if (dev->driver->open) {
-               ret = dev->driver->open(dev, priv);
-               if (ret < 0)
-                       goto out_free;
-       }
-
-       mutex_lock(&dev->struct_mutex);
-       if (list_empty(&dev->filelist))
-               priv->master = 1;
-
-       list_add(&priv->lhead, &dev->filelist);
-       mutex_unlock(&dev->struct_mutex);
-
-#ifdef __alpha__
-       /*
-        * Default the hose
-        */
-       if (!dev->hose) {
-               struct pci_dev *pci_dev;
-               pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
-               if (pci_dev) {
-                       dev->hose = pci_dev->sysdata;
-                       pci_dev_put(pci_dev);
-               }
-               if (!dev->hose) {
-                       struct pci_bus *b = pci_bus_b(pci_root_buses.next);
-                       if (b)
-                               dev->hose = b->sysdata;
-               }
-       }
-#endif
-
-       return 0;
-      out_free:
-       drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
-       filp->private_data = NULL;
-       return ret;
-}
-
-/** No-op. */
-int drm_fasync(int fd, struct file *filp, int on)
-{
-       struct drm_file *priv = filp->private_data;
-       struct drm_device *dev = priv->minor->dev;
-       int retcode;
-
-       DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
-                 (long)old_encode_dev(priv->minor->device));
-       retcode = fasync_helper(fd, filp, on, &dev->buf_async);
-       if (retcode < 0)
-               return retcode;
-       return 0;
-}
-EXPORT_SYMBOL(drm_fasync);
-
-/**
- * Release file.
- *
- * \param inode device inode
- * \param file_priv DRM file private.
- * \return zero on success or a negative number on failure.
- *
- * If the hardware lock is held then free it, and take it again for the kernel
- * context since it's necessary to reclaim buffers. Unlink the file private
- * data from its list and free it. Decreases the open count and if it reaches
- * zero calls drm_lastclose().
- */
-int drm_release(struct inode *inode, struct file *filp)
-{
-       struct drm_file *file_priv = filp->private_data;
-       struct drm_device *dev = file_priv->minor->dev;
-       int retcode = 0;
-
-       lock_kernel();
-
-       DRM_DEBUG("open_count = %d\n", dev->open_count);
-
-       if (dev->driver->preclose)
-               dev->driver->preclose(dev, file_priv);
-
-       /* ========================================================
-        * Begin inline drm_release
-        */
-
-       DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
-                 task_pid_nr(current),
-                 (long)old_encode_dev(file_priv->minor->device),
-                 dev->open_count);
-
-       if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
-               if (drm_i_have_hw_lock(dev, file_priv)) {
-                       dev->driver->reclaim_buffers_locked(dev, file_priv);
-               } else {
-                       unsigned long endtime = jiffies + 3 * DRM_HZ;
-                       int locked = 0;
-
-                       drm_idlelock_take(&dev->lock);
-
-                       /*
-                        * Wait for a while.
-                        */
-
-                       do{
-                               spin_lock_bh(&dev->lock.spinlock);
-                               locked = dev->lock.idle_has_lock;
-                               spin_unlock_bh(&dev->lock.spinlock);
-                               if (locked)
-                                       break;
-                               schedule();
-                       } while (!time_after_eq(jiffies, endtime));
-
-                       if (!locked) {
-                               DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n"
-                                         "\tdriver to use reclaim_buffers_idlelocked() instead.\n"
-                                         "\tI will go on reclaiming the buffers anyway.\n");
-                       }
-
-                       dev->driver->reclaim_buffers_locked(dev, file_priv);
-                       drm_idlelock_release(&dev->lock);
-               }
-       }
-
-       if (dev->driver->reclaim_buffers_idlelocked && dev->lock.hw_lock) {
-
-               drm_idlelock_take(&dev->lock);
-               dev->driver->reclaim_buffers_idlelocked(dev, file_priv);
-               drm_idlelock_release(&dev->lock);
-
-       }
-
-       if (drm_i_have_hw_lock(dev, file_priv)) {
-               DRM_DEBUG("File %p released, freeing lock for context %d\n",
-                         filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-
-               drm_lock_free(&dev->lock,
-                             _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
-       }
-
-
-       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
-           !dev->driver->reclaim_buffers_locked) {
-               dev->driver->reclaim_buffers(dev, file_priv);
-       }
-
-       drm_fasync(-1, filp, 0);
-
-       mutex_lock(&dev->ctxlist_mutex);
-       if (!list_empty(&dev->ctxlist)) {
-               struct drm_ctx_list *pos, *n;
-
-               list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
-                       if (pos->tag == file_priv &&
-                           pos->handle != DRM_KERNEL_CONTEXT) {
-                               if (dev->driver->context_dtor)
-                                       dev->driver->context_dtor(dev,
-                                                                 pos->handle);
-
-                               drm_ctxbitmap_free(dev, pos->handle);
-
-                               list_del(&pos->head);
-                               drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
-                               --dev->ctx_count;
-                       }
-               }
-       }
-       mutex_unlock(&dev->ctxlist_mutex);
-
-       mutex_lock(&dev->struct_mutex);
-       if (file_priv->remove_auth_on_close == 1) {
-               struct drm_file *temp;
-
-               list_for_each_entry(temp, &dev->filelist, lhead)
-                       temp->authenticated = 0;
-       }
-       list_del(&file_priv->lhead);
-       mutex_unlock(&dev->struct_mutex);
-
-       if (dev->driver->postclose)
-               dev->driver->postclose(dev, file_priv);
-       drm_free(file_priv, sizeof(*file_priv), DRM_MEM_FILES);
-
-       /* ========================================================
-        * End inline drm_release
-        */
-
-       atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
-       spin_lock(&dev->count_lock);
-       if (!--dev->open_count) {
-               if (atomic_read(&dev->ioctl_count) || dev->blocked) {
-                       DRM_ERROR("Device busy: %d %d\n",
-                                 atomic_read(&dev->ioctl_count), dev->blocked);
-                       spin_unlock(&dev->count_lock);
-                       unlock_kernel();
-                       return -EBUSY;
-               }
-               spin_unlock(&dev->count_lock);
-               unlock_kernel();
-               return drm_lastclose(dev);
-       }
-       spin_unlock(&dev->count_lock);
-
-       unlock_kernel();
-
-       return retcode;
-}
-EXPORT_SYMBOL(drm_release);
-
-/** No-op. */
-unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
-{
-       return 0;
-}
-EXPORT_SYMBOL(drm_poll);
diff --git a/drivers/char/drm/drm_hashtab.c b/drivers/char/drm/drm_hashtab.c
deleted file mode 100644 (file)
index 3316067..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- **************************************************************************/
-/*
- * Simple open hash tab implementation.
- *
- * Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#include "drmP.h"
-#include "drm_hashtab.h"
-#include <linux/hash.h>
-
-int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
-{
-       unsigned int i;
-
-       ht->size = 1 << order;
-       ht->order = order;
-       ht->fill = 0;
-       ht->table = NULL;
-       ht->use_vmalloc = ((ht->size * sizeof(*ht->table)) > PAGE_SIZE);
-       if (!ht->use_vmalloc) {
-               ht->table = drm_calloc(ht->size, sizeof(*ht->table),
-                                      DRM_MEM_HASHTAB);
-       }
-       if (!ht->table) {
-               ht->use_vmalloc = 1;
-               ht->table = vmalloc(ht->size*sizeof(*ht->table));
-       }
-       if (!ht->table) {
-               DRM_ERROR("Out of memory for hash table\n");
-               return -ENOMEM;
-       }
-       for (i=0; i< ht->size; ++i) {
-               INIT_HLIST_HEAD(&ht->table[i]);
-       }
-       return 0;
-}
-
-void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
-{
-       struct drm_hash_item *entry;
-       struct hlist_head *h_list;
-       struct hlist_node *list;
-       unsigned int hashed_key;
-       int count = 0;
-
-       hashed_key = hash_long(key, ht->order);
-       DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
-       h_list = &ht->table[hashed_key];
-       hlist_for_each(list, h_list) {
-               entry = hlist_entry(list, struct drm_hash_item, head);
-               DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
-       }
-}
-
-static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
-                                         unsigned long key)
-{
-       struct drm_hash_item *entry;
-       struct hlist_head *h_list;
-       struct hlist_node *list;
-       unsigned int hashed_key;
-
-       hashed_key = hash_long(key, ht->order);
-       h_list = &ht->table[hashed_key];
-       hlist_for_each(list, h_list) {
-               entry = hlist_entry(list, struct drm_hash_item, head);
-               if (entry->key == key)
-                       return list;
-               if (entry->key > key)
-                       break;
-       }
-       return NULL;
-}
-
-
-int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
-{
-       struct drm_hash_item *entry;
-       struct hlist_head *h_list;
-       struct hlist_node *list, *parent;
-       unsigned int hashed_key;
-       unsigned long key = item->key;
-
-       hashed_key = hash_long(key, ht->order);
-       h_list = &ht->table[hashed_key];
-       parent = NULL;
-       hlist_for_each(list, h_list) {
-               entry = hlist_entry(list, struct drm_hash_item, head);
-               if (entry->key == key)
-                       return -EINVAL;
-               if (entry->key > key)
-                       break;
-               parent = list;
-       }
-       if (parent) {
-               hlist_add_after(parent, &item->head);
-       } else {
-               hlist_add_head(&item->head, h_list);
-       }
-       return 0;
-}
-
-/*
- * Just insert an item and return any "bits" bit key that hasn't been
- * used before.
- */
-int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
-                             unsigned long seed, int bits, int shift,
-                             unsigned long add)
-{
-       int ret;
-       unsigned long mask = (1 << bits) - 1;
-       unsigned long first, unshifted_key;
-
-       unshifted_key = hash_long(seed, bits);
-       first = unshifted_key;
-       do {
-               item->key = (unshifted_key << shift) + add;
-               ret = drm_ht_insert_item(ht, item);
-               if (ret)
-                       unshifted_key = (unshifted_key + 1) & mask;
-       } while(ret && (unshifted_key != first));
-
-       if (ret) {
-               DRM_ERROR("Available key bit space exhausted\n");
-               return -EINVAL;
-       }
-       return 0;
-}
-
-int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
-                    struct drm_hash_item **item)
-{
-       struct hlist_node *list;
-
-       list = drm_ht_find_key(ht, key);
-       if (!list)
-               return -EINVAL;
-
-       *item = hlist_entry(list, struct drm_hash_item, head);
-       return 0;
-}
-
-int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
-{
-       struct hlist_node *list;
-
-       list = drm_ht_find_key(ht, key);
-       if (list) {
-               hlist_del_init(list);
-               ht->fill--;
-               return 0;
-       }
-       return -EINVAL;
-}
-
-int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
-{
-       hlist_del_init(&item->head);
-       ht->fill--;
-       return 0;
-}
-
-void drm_ht_remove(struct drm_open_hash *ht)
-{
-       if (ht->table) {
-               if (ht->use_vmalloc)
-                       vfree(ht->table);
-               else
-                       drm_free(ht->table, ht->size * sizeof(*ht->table),
-                                DRM_MEM_HASHTAB);
-               ht->table = NULL;
-       }
-}
diff --git a/drivers/char/drm/drm_hashtab.h b/drivers/char/drm/drm_hashtab.h
deleted file mode 100644 (file)
index cd2b189..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismack, ND. USA.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- **************************************************************************/
-/*
- * Simple open hash tab implementation.
- *
- * Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#ifndef DRM_HASHTAB_H
-#define DRM_HASHTAB_H
-
-#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
-
-struct drm_hash_item {
-       struct hlist_node head;
-       unsigned long key;
-};
-
-struct drm_open_hash {
-       unsigned int size;
-       unsigned int order;
-       unsigned int fill;
-       struct hlist_head *table;
-       int use_vmalloc;
-};
-
-
-extern int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
-extern int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
-extern int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
-                                    unsigned long seed, int bits, int shift,
-                                    unsigned long add);
-extern int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item);
-
-extern void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key);
-extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
-extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
-extern void drm_ht_remove(struct drm_open_hash *ht);
-
-
-#endif
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
deleted file mode 100644 (file)
index 90f5a8d..0000000
+++ /dev/null
@@ -1,1073 +0,0 @@
-/**
- * \file drm_ioc32.c
- *
- * 32-bit ioctl compatibility routines for the DRM.
- *
- * \author Paul Mackerras <paulus@samba.org>
- *
- * Copyright (C) Paul Mackerras 2005.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <linux/compat.h>
-
-#include "drmP.h"
-#include "drm_core.h"
-
-#define DRM_IOCTL_VERSION32            DRM_IOWR(0x00, drm_version32_t)
-#define DRM_IOCTL_GET_UNIQUE32         DRM_IOWR(0x01, drm_unique32_t)
-#define DRM_IOCTL_GET_MAP32            DRM_IOWR(0x04, drm_map32_t)
-#define DRM_IOCTL_GET_CLIENT32         DRM_IOWR(0x05, drm_client32_t)
-#define DRM_IOCTL_GET_STATS32          DRM_IOR( 0x06, drm_stats32_t)
-
-#define DRM_IOCTL_SET_UNIQUE32         DRM_IOW( 0x10, drm_unique32_t)
-#define DRM_IOCTL_ADD_MAP32            DRM_IOWR(0x15, drm_map32_t)
-#define DRM_IOCTL_ADD_BUFS32           DRM_IOWR(0x16, drm_buf_desc32_t)
-#define DRM_IOCTL_MARK_BUFS32          DRM_IOW( 0x17, drm_buf_desc32_t)
-#define DRM_IOCTL_INFO_BUFS32          DRM_IOWR(0x18, drm_buf_info32_t)
-#define DRM_IOCTL_MAP_BUFS32           DRM_IOWR(0x19, drm_buf_map32_t)
-#define DRM_IOCTL_FREE_BUFS32          DRM_IOW( 0x1a, drm_buf_free32_t)
-
-#define DRM_IOCTL_RM_MAP32             DRM_IOW( 0x1b, drm_map32_t)
-
-#define DRM_IOCTL_SET_SAREA_CTX32      DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
-#define DRM_IOCTL_GET_SAREA_CTX32      DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
-
-#define DRM_IOCTL_RES_CTX32            DRM_IOWR(0x26, drm_ctx_res32_t)
-#define DRM_IOCTL_DMA32                        DRM_IOWR(0x29, drm_dma32_t)
-
-#define DRM_IOCTL_AGP_ENABLE32         DRM_IOW( 0x32, drm_agp_mode32_t)
-#define DRM_IOCTL_AGP_INFO32           DRM_IOR( 0x33, drm_agp_info32_t)
-#define DRM_IOCTL_AGP_ALLOC32          DRM_IOWR(0x34, drm_agp_buffer32_t)
-#define DRM_IOCTL_AGP_FREE32           DRM_IOW( 0x35, drm_agp_buffer32_t)
-#define DRM_IOCTL_AGP_BIND32           DRM_IOW( 0x36, drm_agp_binding32_t)
-#define DRM_IOCTL_AGP_UNBIND32         DRM_IOW( 0x37, drm_agp_binding32_t)
-
-#define DRM_IOCTL_SG_ALLOC32           DRM_IOW( 0x38, drm_scatter_gather32_t)
-#define DRM_IOCTL_SG_FREE32            DRM_IOW( 0x39, drm_scatter_gather32_t)
-
-#define DRM_IOCTL_WAIT_VBLANK32                DRM_IOWR(0x3a, drm_wait_vblank32_t)
-
-typedef struct drm_version_32 {
-       int version_major;        /**< Major version */
-       int version_minor;        /**< Minor version */
-       int version_patchlevel;    /**< Patch level */
-       u32 name_len;             /**< Length of name buffer */
-       u32 name;                 /**< Name of driver */
-       u32 date_len;             /**< Length of date buffer */
-       u32 date;                 /**< User-space buffer to hold date */
-       u32 desc_len;             /**< Length of desc buffer */
-       u32 desc;                 /**< User-space buffer to hold desc */
-} drm_version32_t;
-
-static int compat_drm_version(struct file *file, unsigned int cmd,
-                             unsigned long arg)
-{
-       drm_version32_t v32;
-       struct drm_version __user *version;
-       int err;
-
-       if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
-               return -EFAULT;
-
-       version = compat_alloc_user_space(sizeof(*version));
-       if (!access_ok(VERIFY_WRITE, version, sizeof(*version)))
-               return -EFAULT;
-       if (__put_user(v32.name_len, &version->name_len)
-           || __put_user((void __user *)(unsigned long)v32.name,
-                         &version->name)
-           || __put_user(v32.date_len, &version->date_len)
-           || __put_user((void __user *)(unsigned long)v32.date,
-                         &version->date)
-           || __put_user(v32.desc_len, &version->desc_len)
-           || __put_user((void __user *)(unsigned long)v32.desc,
-                         &version->desc))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_VERSION, (unsigned long)version);
-       if (err)
-               return err;
-
-       if (__get_user(v32.version_major, &version->version_major)
-           || __get_user(v32.version_minor, &version->version_minor)
-           || __get_user(v32.version_patchlevel, &version->version_patchlevel)
-           || __get_user(v32.name_len, &version->name_len)
-           || __get_user(v32.date_len, &version->date_len)
-           || __get_user(v32.desc_len, &version->desc_len))
-               return -EFAULT;
-
-       if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
-               return -EFAULT;
-       return 0;
-}
-
-typedef struct drm_unique32 {
-       u32 unique_len; /**< Length of unique */
-       u32 unique;     /**< Unique name for driver instantiation */
-} drm_unique32_t;
-
-static int compat_drm_getunique(struct file *file, unsigned int cmd,
-                               unsigned long arg)
-{
-       drm_unique32_t uq32;
-       struct drm_unique __user *u;
-       int err;
-
-       if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
-               return -EFAULT;
-
-       u = compat_alloc_user_space(sizeof(*u));
-       if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
-               return -EFAULT;
-       if (__put_user(uq32.unique_len, &u->unique_len)
-           || __put_user((void __user *)(unsigned long)uq32.unique,
-                         &u->unique))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
-       if (err)
-               return err;
-
-       if (__get_user(uq32.unique_len, &u->unique_len))
-               return -EFAULT;
-       if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
-               return -EFAULT;
-       return 0;
-}
-
-static int compat_drm_setunique(struct file *file, unsigned int cmd,
-                               unsigned long arg)
-{
-       drm_unique32_t uq32;
-       struct drm_unique __user *u;
-
-       if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
-               return -EFAULT;
-
-       u = compat_alloc_user_space(sizeof(*u));
-       if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
-               return -EFAULT;
-       if (__put_user(uq32.unique_len, &u->unique_len)
-           || __put_user((void __user *)(unsigned long)uq32.unique,
-                         &u->unique))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
-}
-
-typedef struct drm_map32 {
-       u32 offset;             /**< Requested physical address (0 for SAREA)*/
-       u32 size;               /**< Requested physical size (bytes) */
-       enum drm_map_type type; /**< Type of memory to map */
-       enum drm_map_flags flags;       /**< Flags */
-       u32 handle;             /**< User-space: "Handle" to pass to mmap() */
-       int mtrr;               /**< MTRR slot used */
-} drm_map32_t;
-
-static int compat_drm_getmap(struct file *file, unsigned int cmd,
-                            unsigned long arg)
-{
-       drm_map32_t __user *argp = (void __user *)arg;
-       drm_map32_t m32;
-       struct drm_map __user *map;
-       int idx, err;
-       void *handle;
-
-       if (get_user(idx, &argp->offset))
-               return -EFAULT;
-
-       map = compat_alloc_user_space(sizeof(*map));
-       if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
-               return -EFAULT;
-       if (__put_user(idx, &map->offset))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_GET_MAP, (unsigned long)map);
-       if (err)
-               return err;
-
-       if (__get_user(m32.offset, &map->offset)
-           || __get_user(m32.size, &map->size)
-           || __get_user(m32.type, &map->type)
-           || __get_user(m32.flags, &map->flags)
-           || __get_user(handle, &map->handle)
-           || __get_user(m32.mtrr, &map->mtrr))
-               return -EFAULT;
-
-       m32.handle = (unsigned long)handle;
-       if (copy_to_user(argp, &m32, sizeof(m32)))
-               return -EFAULT;
-       return 0;
-
-}
-
-static int compat_drm_addmap(struct file *file, unsigned int cmd,
-                            unsigned long arg)
-{
-       drm_map32_t __user *argp = (void __user *)arg;
-       drm_map32_t m32;
-       struct drm_map __user *map;
-       int err;
-       void *handle;
-
-       if (copy_from_user(&m32, argp, sizeof(m32)))
-               return -EFAULT;
-
-       map = compat_alloc_user_space(sizeof(*map));
-       if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
-               return -EFAULT;
-       if (__put_user(m32.offset, &map->offset)
-           || __put_user(m32.size, &map->size)
-           || __put_user(m32.type, &map->type)
-           || __put_user(m32.flags, &map->flags))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_ADD_MAP, (unsigned long)map);
-       if (err)
-               return err;
-
-       if (__get_user(m32.offset, &map->offset)
-           || __get_user(m32.mtrr, &map->mtrr)
-           || __get_user(handle, &map->handle))
-               return -EFAULT;
-
-       m32.handle = (unsigned long)handle;
-       if (m32.handle != (unsigned long)handle && printk_ratelimit())
-               printk(KERN_ERR "compat_drm_addmap truncated handle"
-                      " %p for type %d offset %x\n",
-                      handle, m32.type, m32.offset);
-
-       if (copy_to_user(argp, &m32, sizeof(m32)))
-               return -EFAULT;
-
-       return 0;
-}
-
-static int compat_drm_rmmap(struct file *file, unsigned int cmd,
-                           unsigned long arg)
-{
-       drm_map32_t __user *argp = (void __user *)arg;
-       struct drm_map __user *map;
-       u32 handle;
-
-       if (get_user(handle, &argp->handle))
-               return -EFAULT;
-
-       map = compat_alloc_user_space(sizeof(*map));
-       if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
-               return -EFAULT;
-       if (__put_user((void *)(unsigned long)handle, &map->handle))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RM_MAP, (unsigned long)map);
-}
-
-typedef struct drm_client32 {
-       int idx;        /**< Which client desired? */
-       int auth;       /**< Is client authenticated? */
-       u32 pid;        /**< Process ID */
-       u32 uid;        /**< User ID */
-       u32 magic;      /**< Magic */
-       u32 iocs;       /**< Ioctl count */
-} drm_client32_t;
-
-static int compat_drm_getclient(struct file *file, unsigned int cmd,
-                               unsigned long arg)
-{
-       drm_client32_t c32;
-       drm_client32_t __user *argp = (void __user *)arg;
-       struct drm_client __user *client;
-       int idx, err;
-
-       if (get_user(idx, &argp->idx))
-               return -EFAULT;
-
-       client = compat_alloc_user_space(sizeof(*client));
-       if (!access_ok(VERIFY_WRITE, client, sizeof(*client)))
-               return -EFAULT;
-       if (__put_user(idx, &client->idx))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_GET_CLIENT, (unsigned long)client);
-       if (err)
-               return err;
-
-       if (__get_user(c32.auth, &client->auth)
-           || __get_user(c32.pid, &client->pid)
-           || __get_user(c32.uid, &client->uid)
-           || __get_user(c32.magic, &client->magic)
-           || __get_user(c32.iocs, &client->iocs))
-               return -EFAULT;
-
-       if (copy_to_user(argp, &c32, sizeof(c32)))
-               return -EFAULT;
-       return 0;
-}
-
-typedef struct drm_stats32 {
-       u32 count;
-       struct {
-               u32 value;
-               enum drm_stat_type type;
-       } data[15];
-} drm_stats32_t;
-
-static int compat_drm_getstats(struct file *file, unsigned int cmd,
-                              unsigned long arg)
-{
-       drm_stats32_t s32;
-       drm_stats32_t __user *argp = (void __user *)arg;
-       struct drm_stats __user *stats;
-       int i, err;
-
-       stats = compat_alloc_user_space(sizeof(*stats));
-       if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_GET_STATS, (unsigned long)stats);
-       if (err)
-               return err;
-
-       if (__get_user(s32.count, &stats->count))
-               return -EFAULT;
-       for (i = 0; i < 15; ++i)
-               if (__get_user(s32.data[i].value, &stats->data[i].value)
-                   || __get_user(s32.data[i].type, &stats->data[i].type))
-                       return -EFAULT;
-
-       if (copy_to_user(argp, &s32, sizeof(s32)))
-               return -EFAULT;
-       return 0;
-}
-
-typedef struct drm_buf_desc32 {
-       int count;               /**< Number of buffers of this size */
-       int size;                /**< Size in bytes */
-       int low_mark;            /**< Low water mark */
-       int high_mark;           /**< High water mark */
-       int flags;
-       u32 agp_start;           /**< Start address in the AGP aperture */
-} drm_buf_desc32_t;
-
-static int compat_drm_addbufs(struct file *file, unsigned int cmd,
-                             unsigned long arg)
-{
-       drm_buf_desc32_t __user *argp = (void __user *)arg;
-       struct drm_buf_desc __user *buf;
-       int err;
-       unsigned long agp_start;
-
-       buf = compat_alloc_user_space(sizeof(*buf));
-       if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf))
-           || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)))
-               return -EFAULT;
-
-       if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start))
-           || __get_user(agp_start, &argp->agp_start)
-           || __put_user(agp_start, &buf->agp_start))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
-       if (err)
-               return err;
-
-       if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start))
-           || __get_user(agp_start, &buf->agp_start)
-           || __put_user(agp_start, &argp->agp_start))
-               return -EFAULT;
-
-       return 0;
-}
-
-static int compat_drm_markbufs(struct file *file, unsigned int cmd,
-                              unsigned long arg)
-{
-       drm_buf_desc32_t b32;
-       drm_buf_desc32_t __user *argp = (void __user *)arg;
-       struct drm_buf_desc __user *buf;
-
-       if (copy_from_user(&b32, argp, sizeof(b32)))
-               return -EFAULT;
-
-       buf = compat_alloc_user_space(sizeof(*buf));
-       if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)))
-               return -EFAULT;
-
-       if (__put_user(b32.size, &buf->size)
-           || __put_user(b32.low_mark, &buf->low_mark)
-           || __put_user(b32.high_mark, &buf->high_mark))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
-}
-
-typedef struct drm_buf_info32 {
-       int count;              /**< Entries in list */
-       u32 list;
-} drm_buf_info32_t;
-
-static int compat_drm_infobufs(struct file *file, unsigned int cmd,
-                              unsigned long arg)
-{
-       drm_buf_info32_t req32;
-       drm_buf_info32_t __user *argp = (void __user *)arg;
-       drm_buf_desc32_t __user *to;
-       struct drm_buf_info __user *request;
-       struct drm_buf_desc __user *list;
-       size_t nbytes;
-       int i, err;
-       int count, actual;
-
-       if (copy_from_user(&req32, argp, sizeof(req32)))
-               return -EFAULT;
-
-       count = req32.count;
-       to = (drm_buf_desc32_t __user *) (unsigned long)req32.list;
-       if (count < 0)
-               count = 0;
-       if (count > 0
-           && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
-               return -EFAULT;
-
-       nbytes = sizeof(*request) + count * sizeof(struct drm_buf_desc);
-       request = compat_alloc_user_space(nbytes);
-       if (!access_ok(VERIFY_WRITE, request, nbytes))
-               return -EFAULT;
-       list = (struct drm_buf_desc *) (request + 1);
-
-       if (__put_user(count, &request->count)
-           || __put_user(list, &request->list))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_INFO_BUFS, (unsigned long)request);
-       if (err)
-               return err;
-
-       if (__get_user(actual, &request->count))
-               return -EFAULT;
-       if (count >= actual)
-               for (i = 0; i < actual; ++i)
-                       if (__copy_in_user(&to[i], &list[i],
-                                          offsetof(struct drm_buf_desc, flags)))
-                               return -EFAULT;
-
-       if (__put_user(actual, &argp->count))
-               return -EFAULT;
-
-       return 0;
-}
-
-typedef struct drm_buf_pub32 {
-       int idx;                /**< Index into the master buffer list */
-       int total;              /**< Buffer size */
-       int used;               /**< Amount of buffer in use (for DMA) */
-       u32 address;            /**< Address of buffer */
-} drm_buf_pub32_t;
-
-typedef struct drm_buf_map32 {
-       int count;              /**< Length of the buffer list */
-       u32 virtual;            /**< Mmap'd area in user-virtual */
-       u32 list;               /**< Buffer information */
-} drm_buf_map32_t;
-
-static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
-                             unsigned long arg)
-{
-       drm_buf_map32_t __user *argp = (void __user *)arg;
-       drm_buf_map32_t req32;
-       drm_buf_pub32_t __user *list32;
-       struct drm_buf_map __user *request;
-       struct drm_buf_pub __user *list;
-       int i, err;
-       int count, actual;
-       size_t nbytes;
-       void __user *addr;
-
-       if (copy_from_user(&req32, argp, sizeof(req32)))
-               return -EFAULT;
-       count = req32.count;
-       list32 = (void __user *)(unsigned long)req32.list;
-
-       if (count < 0)
-               return -EINVAL;
-       nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub);
-       request = compat_alloc_user_space(nbytes);
-       if (!access_ok(VERIFY_WRITE, request, nbytes))
-               return -EFAULT;
-       list = (struct drm_buf_pub *) (request + 1);
-
-       if (__put_user(count, &request->count)
-           || __put_user(list, &request->list))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_MAP_BUFS, (unsigned long)request);
-       if (err)
-               return err;
-
-       if (__get_user(actual, &request->count))
-               return -EFAULT;
-       if (count >= actual)
-               for (i = 0; i < actual; ++i)
-                       if (__copy_in_user(&list32[i], &list[i],
-                                          offsetof(struct drm_buf_pub, address))
-                           || __get_user(addr, &list[i].address)
-                           || __put_user((unsigned long)addr,
-                                         &list32[i].address))
-                               return -EFAULT;
-
-       if (__put_user(actual, &argp->count)
-           || __get_user(addr, &request->virtual)
-           || __put_user((unsigned long)addr, &argp->virtual))
-               return -EFAULT;
-
-       return 0;
-}
-
-typedef struct drm_buf_free32 {
-       int count;
-       u32 list;
-} drm_buf_free32_t;
-
-static int compat_drm_freebufs(struct file *file, unsigned int cmd,
-                              unsigned long arg)
-{
-       drm_buf_free32_t req32;
-       struct drm_buf_free __user *request;
-       drm_buf_free32_t __user *argp = (void __user *)arg;
-
-       if (copy_from_user(&req32, argp, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
-               return -EFAULT;
-       if (__put_user(req32.count, &request->count)
-           || __put_user((int __user *)(unsigned long)req32.list,
-                         &request->list))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_FREE_BUFS, (unsigned long)request);
-}
-
-typedef struct drm_ctx_priv_map32 {
-       unsigned int ctx_id;     /**< Context requesting private mapping */
-       u32 handle;             /**< Handle of map */
-} drm_ctx_priv_map32_t;
-
-static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
-                                 unsigned long arg)
-{
-       drm_ctx_priv_map32_t req32;
-       struct drm_ctx_priv_map __user *request;
-       drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
-
-       if (copy_from_user(&req32, argp, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
-               return -EFAULT;
-       if (__put_user(req32.ctx_id, &request->ctx_id)
-           || __put_user((void *)(unsigned long)req32.handle,
-                         &request->handle))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
-}
-
-static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
-                                 unsigned long arg)
-{
-       struct drm_ctx_priv_map __user *request;
-       drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
-       int err;
-       unsigned int ctx_id;
-       void *handle;
-
-       if (!access_ok(VERIFY_WRITE, argp, sizeof(*argp))
-           || __get_user(ctx_id, &argp->ctx_id))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
-               return -EFAULT;
-       if (__put_user(ctx_id, &request->ctx_id))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
-       if (err)
-               return err;
-
-       if (__get_user(handle, &request->handle)
-           || __put_user((unsigned long)handle, &argp->handle))
-               return -EFAULT;
-
-       return 0;
-}
-
-typedef struct drm_ctx_res32 {
-       int count;
-       u32 contexts;
-} drm_ctx_res32_t;
-
-static int compat_drm_resctx(struct file *file, unsigned int cmd,
-                            unsigned long arg)
-{
-       drm_ctx_res32_t __user *argp = (void __user *)arg;
-       drm_ctx_res32_t res32;
-       struct drm_ctx_res __user *res;
-       int err;
-
-       if (copy_from_user(&res32, argp, sizeof(res32)))
-               return -EFAULT;
-
-       res = compat_alloc_user_space(sizeof(*res));
-       if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
-               return -EFAULT;
-       if (__put_user(res32.count, &res->count)
-           || __put_user((struct drm_ctx __user *) (unsigned long)res32.contexts,
-                         &res->contexts))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_RES_CTX, (unsigned long)res);
-       if (err)
-               return err;
-
-       if (__get_user(res32.count, &res->count)
-           || __put_user(res32.count, &argp->count))
-               return -EFAULT;
-
-       return 0;
-}
-
-typedef struct drm_dma32 {
-       int context;              /**< Context handle */
-       int send_count;           /**< Number of buffers to send */
-       u32 send_indices;         /**< List of handles to buffers */
-       u32 send_sizes;           /**< Lengths of data to send */
-       enum drm_dma_flags flags;                 /**< Flags */
-       int request_count;        /**< Number of buffers requested */
-       int request_size;         /**< Desired size for buffers */
-       u32 request_indices;      /**< Buffer information */
-       u32 request_sizes;
-       int granted_count;        /**< Number of buffers granted */
-} drm_dma32_t;
-
-static int compat_drm_dma(struct file *file, unsigned int cmd,
-                         unsigned long arg)
-{
-       drm_dma32_t d32;
-       drm_dma32_t __user *argp = (void __user *)arg;
-       struct drm_dma __user *d;
-       int err;
-
-       if (copy_from_user(&d32, argp, sizeof(d32)))
-               return -EFAULT;
-
-       d = compat_alloc_user_space(sizeof(*d));
-       if (!access_ok(VERIFY_WRITE, d, sizeof(*d)))
-               return -EFAULT;
-
-       if (__put_user(d32.context, &d->context)
-           || __put_user(d32.send_count, &d->send_count)
-           || __put_user((int __user *)(unsigned long)d32.send_indices,
-                         &d->send_indices)
-           || __put_user((int __user *)(unsigned long)d32.send_sizes,
-                         &d->send_sizes)
-           || __put_user(d32.flags, &d->flags)
-           || __put_user(d32.request_count, &d->request_count)
-           || __put_user((int __user *)(unsigned long)d32.request_indices,
-                         &d->request_indices)
-           || __put_user((int __user *)(unsigned long)d32.request_sizes,
-                         &d->request_sizes))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_DMA, (unsigned long)d);
-       if (err)
-               return err;
-
-       if (__get_user(d32.request_size, &d->request_size)
-           || __get_user(d32.granted_count, &d->granted_count)
-           || __put_user(d32.request_size, &argp->request_size)
-           || __put_user(d32.granted_count, &argp->granted_count))
-               return -EFAULT;
-
-       return 0;
-}
-
-#if __OS_HAS_AGP
-typedef struct drm_agp_mode32 {
-       u32 mode;       /**< AGP mode */
-} drm_agp_mode32_t;
-
-static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
-                                unsigned long arg)
-{
-       drm_agp_mode32_t __user *argp = (void __user *)arg;
-       drm_agp_mode32_t m32;
-       struct drm_agp_mode __user *mode;
-
-       if (get_user(m32.mode, &argp->mode))
-               return -EFAULT;
-
-       mode = compat_alloc_user_space(sizeof(*mode));
-       if (put_user(m32.mode, &mode->mode))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
-}
-
-typedef struct drm_agp_info32 {
-       int agp_version_major;
-       int agp_version_minor;
-       u32 mode;
-       u32 aperture_base;      /* physical address */
-       u32 aperture_size;      /* bytes */
-       u32 memory_allowed;     /* bytes */
-       u32 memory_used;
-
-       /* PCI information */
-       unsigned short id_vendor;
-       unsigned short id_device;
-} drm_agp_info32_t;
-
-static int compat_drm_agp_info(struct file *file, unsigned int cmd,
-                              unsigned long arg)
-{
-       drm_agp_info32_t __user *argp = (void __user *)arg;
-       drm_agp_info32_t i32;
-       struct drm_agp_info __user *info;
-       int err;
-
-       info = compat_alloc_user_space(sizeof(*info));
-       if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_AGP_INFO, (unsigned long)info);
-       if (err)
-               return err;
-
-       if (__get_user(i32.agp_version_major, &info->agp_version_major)
-           || __get_user(i32.agp_version_minor, &info->agp_version_minor)
-           || __get_user(i32.mode, &info->mode)
-           || __get_user(i32.aperture_base, &info->aperture_base)
-           || __get_user(i32.aperture_size, &info->aperture_size)
-           || __get_user(i32.memory_allowed, &info->memory_allowed)
-           || __get_user(i32.memory_used, &info->memory_used)
-           || __get_user(i32.id_vendor, &info->id_vendor)
-           || __get_user(i32.id_device, &info->id_device))
-               return -EFAULT;
-
-       if (copy_to_user(argp, &i32, sizeof(i32)))
-               return -EFAULT;
-
-       return 0;
-}
-
-typedef struct drm_agp_buffer32 {
-       u32 size;       /**< In bytes -- will round to page boundary */
-       u32 handle;     /**< Used for binding / unbinding */
-       u32 type;       /**< Type of memory to allocate */
-       u32 physical;   /**< Physical used by i810 */
-} drm_agp_buffer32_t;
-
-static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
-                               unsigned long arg)
-{
-       drm_agp_buffer32_t __user *argp = (void __user *)arg;
-       drm_agp_buffer32_t req32;
-       struct drm_agp_buffer __user *request;
-       int err;
-
-       if (copy_from_user(&req32, argp, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user(req32.size, &request->size)
-           || __put_user(req32.type, &request->type))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
-       if (err)
-               return err;
-
-       if (__get_user(req32.handle, &request->handle)
-           || __get_user(req32.physical, &request->physical)
-           || copy_to_user(argp, &req32, sizeof(req32))) {
-               drm_ioctl(file->f_path.dentry->d_inode, file,
-                         DRM_IOCTL_AGP_FREE, (unsigned long)request);
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-static int compat_drm_agp_free(struct file *file, unsigned int cmd,
-                              unsigned long arg)
-{
-       drm_agp_buffer32_t __user *argp = (void __user *)arg;
-       struct drm_agp_buffer __user *request;
-       u32 handle;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || get_user(handle, &argp->handle)
-           || __put_user(handle, &request->handle))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_AGP_FREE, (unsigned long)request);
-}
-
-typedef struct drm_agp_binding32 {
-       u32 handle;     /**< From drm_agp_buffer */
-       u32 offset;     /**< In bytes -- will round to page boundary */
-} drm_agp_binding32_t;
-
-static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
-                              unsigned long arg)
-{
-       drm_agp_binding32_t __user *argp = (void __user *)arg;
-       drm_agp_binding32_t req32;
-       struct drm_agp_binding __user *request;
-
-       if (copy_from_user(&req32, argp, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user(req32.handle, &request->handle)
-           || __put_user(req32.offset, &request->offset))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_AGP_BIND, (unsigned long)request);
-}
-
-static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
-                                unsigned long arg)
-{
-       drm_agp_binding32_t __user *argp = (void __user *)arg;
-       struct drm_agp_binding __user *request;
-       u32 handle;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || get_user(handle, &argp->handle)
-           || __put_user(handle, &request->handle))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
-}
-#endif                         /* __OS_HAS_AGP */
-
-typedef struct drm_scatter_gather32 {
-       u32 size;       /**< In bytes -- will round to page boundary */
-       u32 handle;     /**< Used for mapping / unmapping */
-} drm_scatter_gather32_t;
-
-static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
-                              unsigned long arg)
-{
-       drm_scatter_gather32_t __user *argp = (void __user *)arg;
-       struct drm_scatter_gather __user *request;
-       int err;
-       unsigned long x;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
-           || __get_user(x, &argp->size)
-           || __put_user(x, &request->size))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_SG_ALLOC, (unsigned long)request);
-       if (err)
-               return err;
-
-       /* XXX not sure about the handle conversion here... */
-       if (__get_user(x, &request->handle)
-           || __put_user(x >> PAGE_SHIFT, &argp->handle))
-               return -EFAULT;
-
-       return 0;
-}
-
-static int compat_drm_sg_free(struct file *file, unsigned int cmd,
-                             unsigned long arg)
-{
-       drm_scatter_gather32_t __user *argp = (void __user *)arg;
-       struct drm_scatter_gather __user *request;
-       unsigned long x;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
-           || __get_user(x, &argp->handle)
-           || __put_user(x << PAGE_SHIFT, &request->handle))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_SG_FREE, (unsigned long)request);
-}
-
-struct drm_wait_vblank_request32 {
-       enum drm_vblank_seq_type type;
-       unsigned int sequence;
-       u32 signal;
-};
-
-struct drm_wait_vblank_reply32 {
-       enum drm_vblank_seq_type type;
-       unsigned int sequence;
-       s32 tval_sec;
-       s32 tval_usec;
-};
-
-typedef union drm_wait_vblank32 {
-       struct drm_wait_vblank_request32 request;
-       struct drm_wait_vblank_reply32 reply;
-} drm_wait_vblank32_t;
-
-static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
-                                 unsigned long arg)
-{
-       drm_wait_vblank32_t __user *argp = (void __user *)arg;
-       drm_wait_vblank32_t req32;
-       union drm_wait_vblank __user *request;
-       int err;
-
-       if (copy_from_user(&req32, argp, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user(req32.request.type, &request->request.type)
-           || __put_user(req32.request.sequence, &request->request.sequence)
-           || __put_user(req32.request.signal, &request->request.signal))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
-       if (err)
-               return err;
-
-       if (__get_user(req32.reply.type, &request->reply.type)
-           || __get_user(req32.reply.sequence, &request->reply.sequence)
-           || __get_user(req32.reply.tval_sec, &request->reply.tval_sec)
-           || __get_user(req32.reply.tval_usec, &request->reply.tval_usec))
-               return -EFAULT;
-
-       if (copy_to_user(argp, &req32, sizeof(req32)))
-               return -EFAULT;
-
-       return 0;
-}
-
-drm_ioctl_compat_t *drm_compat_ioctls[] = {
-       [DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version,
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique,
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap,
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT32)] = compat_drm_getclient,
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS32)] = compat_drm_getstats,
-       [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE32)] = compat_drm_setunique,
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP32)] = compat_drm_addmap,
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS32)] = compat_drm_addbufs,
-       [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS32)] = compat_drm_markbufs,
-       [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS32)] = compat_drm_infobufs,
-       [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS32)] = compat_drm_mapbufs,
-       [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS32)] = compat_drm_freebufs,
-       [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP32)] = compat_drm_rmmap,
-       [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX32)] = compat_drm_setsareactx,
-       [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX32)] = compat_drm_getsareactx,
-       [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX32)] = compat_drm_resctx,
-       [DRM_IOCTL_NR(DRM_IOCTL_DMA32)] = compat_drm_dma,
-#if __OS_HAS_AGP
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE32)] = compat_drm_agp_enable,
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO32)] = compat_drm_agp_info,
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC32)] = compat_drm_agp_alloc,
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE32)] = compat_drm_agp_free,
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND32)] = compat_drm_agp_bind,
-       [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND32)] = compat_drm_agp_unbind,
-#endif
-       [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc,
-       [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free,
-       [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
-};
-
-/**
- * Called whenever a 32-bit process running under a 64-bit kernel
- * performs an ioctl on /dev/drm.
- *
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
- */
-long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       unsigned int nr = DRM_IOCTL_NR(cmd);
-       drm_ioctl_compat_t *fn;
-       int ret;
-
-       /* Assume that ioctls without an explicit compat routine will just
-        * work.  This may not always be a good assumption, but it's better
-        * than always failing.
-        */
-       if (nr >= ARRAY_SIZE(drm_compat_ioctls))
-               return drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
-
-       fn = drm_compat_ioctls[nr];
-
-       lock_kernel();          /* XXX for now */
-       if (fn != NULL)
-               ret = (*fn) (filp, cmd, arg);
-       else
-               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
-
-       return ret;
-}
-
-EXPORT_SYMBOL(drm_compat_ioctl);
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
deleted file mode 100644 (file)
index 16829fb..0000000
+++ /dev/null
@@ -1,352 +0,0 @@
-/**
- * \file drm_ioctl.c
- * IOCTL processing for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Fri Jan  8 09:01:26 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm_core.h"
-
-#include "linux/pci.h"
-
-/**
- * Get the bus id.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_unique structure.
- * \return zero on success or a negative number on failure.
- *
- * Copies the bus id from drm_device::unique into user space.
- */
-int drm_getunique(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
-{
-       struct drm_unique *u = data;
-
-       if (u->unique_len >= dev->unique_len) {
-               if (copy_to_user(u->unique, dev->unique, dev->unique_len))
-                       return -EFAULT;
-       }
-       u->unique_len = dev->unique_len;
-
-       return 0;
-}
-
-/**
- * Set the bus id.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_unique structure.
- * \return zero on success or a negative number on failure.
- *
- * Copies the bus id from userspace into drm_device::unique, and verifies that
- * it matches the device this DRM is attached to (EINVAL otherwise).  Deprecated
- * in interface version 1.1 and will return EBUSY when setversion has requested
- * version 1.1 or greater.
- */
-int drm_setunique(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
-{
-       struct drm_unique *u = data;
-       int domain, bus, slot, func, ret;
-
-       if (dev->unique_len || dev->unique)
-               return -EBUSY;
-
-       if (!u->unique_len || u->unique_len > 1024)
-               return -EINVAL;
-
-       dev->unique_len = u->unique_len;
-       dev->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER);
-       if (!dev->unique)
-               return -ENOMEM;
-       if (copy_from_user(dev->unique, u->unique, dev->unique_len))
-               return -EFAULT;
-
-       dev->unique[dev->unique_len] = '\0';
-
-       dev->devname =
-           drm_alloc(strlen(dev->driver->pci_driver.name) +
-                     strlen(dev->unique) + 2, DRM_MEM_DRIVER);
-       if (!dev->devname)
-               return -ENOMEM;
-
-       sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
-               dev->unique);
-
-       /* Return error if the busid submitted doesn't match the device's actual
-        * busid.
-        */
-       ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
-       if (ret != 3)
-               return -EINVAL;
-       domain = bus >> 8;
-       bus &= 0xff;
-
-       if ((domain != drm_get_pci_domain(dev)) ||
-           (bus != dev->pdev->bus->number) ||
-           (slot != PCI_SLOT(dev->pdev->devfn)) ||
-           (func != PCI_FUNC(dev->pdev->devfn)))
-               return -EINVAL;
-
-       return 0;
-}
-
-static int drm_set_busid(struct drm_device * dev)
-{
-       int len;
-
-       if (dev->unique != NULL)
-               return 0;
-
-       dev->unique_len = 40;
-       dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER);
-       if (dev->unique == NULL)
-               return -ENOMEM;
-
-       len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
-                      drm_get_pci_domain(dev), dev->pdev->bus->number,
-                      PCI_SLOT(dev->pdev->devfn),
-                      PCI_FUNC(dev->pdev->devfn));
-
-       if (len > dev->unique_len)
-               DRM_ERROR("Unique buffer overflowed\n");
-
-       dev->devname =
-           drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len +
-                     2, DRM_MEM_DRIVER);
-       if (dev->devname == NULL)
-               return -ENOMEM;
-
-       sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
-               dev->unique);
-
-       return 0;
-}
-
-/**
- * Get a mapping information.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_map structure.
- *
- * \return zero on success or a negative number on failure.
- *
- * Searches for the mapping with the specified offset and copies its information
- * into userspace
- */
-int drm_getmap(struct drm_device *dev, void *data,
-              struct drm_file *file_priv)
-{
-       struct drm_map *map = data;
-       struct drm_map_list *r_list = NULL;
-       struct list_head *list;
-       int idx;
-       int i;
-
-       idx = map->offset;
-
-       mutex_lock(&dev->struct_mutex);
-       if (idx < 0) {
-               mutex_unlock(&dev->struct_mutex);
-               return -EINVAL;
-       }
-
-       i = 0;
-       list_for_each(list, &dev->maplist) {
-               if (i == idx) {
-                       r_list = list_entry(list, struct drm_map_list, head);
-                       break;
-               }
-               i++;
-       }
-       if (!r_list || !r_list->map) {
-               mutex_unlock(&dev->struct_mutex);
-               return -EINVAL;
-       }
-
-       map->offset = r_list->map->offset;
-       map->size = r_list->map->size;
-       map->type = r_list->map->type;
-       map->flags = r_list->map->flags;
-       map->handle = (void *)(unsigned long) r_list->user_token;
-       map->mtrr = r_list->map->mtrr;
-       mutex_unlock(&dev->struct_mutex);
-
-       return 0;
-}
-
-/**
- * Get client information.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_client structure.
- *
- * \return zero on success or a negative number on failure.
- *
- * Searches for the client with the specified index and copies its information
- * into userspace
- */
-int drm_getclient(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
-{
-       struct drm_client *client = data;
-       struct drm_file *pt;
-       int idx;
-       int i;
-
-       idx = client->idx;
-       mutex_lock(&dev->struct_mutex);
-
-       i = 0;
-       list_for_each_entry(pt, &dev->filelist, lhead) {
-               if (i++ >= idx) {
-                       client->auth = pt->authenticated;
-                       client->pid = pt->pid;
-                       client->uid = pt->uid;
-                       client->magic = pt->magic;
-                       client->iocs = pt->ioctl_count;
-                       mutex_unlock(&dev->struct_mutex);
-
-                       return 0;
-               }
-       }
-       mutex_unlock(&dev->struct_mutex);
-
-       return -EINVAL;
-}
-
-/**
- * Get statistics information.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_stats structure.
- *
- * \return zero on success or a negative number on failure.
- */
-int drm_getstats(struct drm_device *dev, void *data,
-                struct drm_file *file_priv)
-{
-       struct drm_stats *stats = data;
-       int i;
-
-       memset(stats, 0, sizeof(*stats));
-
-       mutex_lock(&dev->struct_mutex);
-
-       for (i = 0; i < dev->counters; i++) {
-               if (dev->types[i] == _DRM_STAT_LOCK)
-                       stats->data[i].value =
-                           (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0);
-               else
-                       stats->data[i].value = atomic_read(&dev->counts[i]);
-               stats->data[i].type = dev->types[i];
-       }
-
-       stats->count = dev->counters;
-
-       mutex_unlock(&dev->struct_mutex);
-
-       return 0;
-}
-
-/**
- * Setversion ioctl.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_lock structure.
- * \return zero on success or negative number on failure.
- *
- * Sets the requested interface version
- */
-int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       struct drm_set_version *sv = data;
-       int if_version, retcode = 0;
-
-       if (sv->drm_di_major != -1) {
-               if (sv->drm_di_major != DRM_IF_MAJOR ||
-                   sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) {
-                       retcode = -EINVAL;
-                       goto done;
-               }
-               if_version = DRM_IF_VERSION(sv->drm_di_major,
-                                           sv->drm_di_minor);
-               dev->if_version = max(if_version, dev->if_version);
-               if (sv->drm_di_minor >= 1) {
-                       /*
-                        * Version 1.1 includes tying of DRM to specific device
-                        */
-                       drm_set_busid(dev);
-               }
-       }
-
-       if (sv->drm_dd_major != -1) {
-               if (sv->drm_dd_major != dev->driver->major ||
-                   sv->drm_dd_minor < 0 || sv->drm_dd_minor >
-                   dev->driver->minor) {
-                       retcode = -EINVAL;
-                       goto done;
-               }
-
-               if (dev->driver->set_version)
-                       dev->driver->set_version(dev, sv);
-       }
-
-done:
-       sv->drm_di_major = DRM_IF_MAJOR;
-       sv->drm_di_minor = DRM_IF_MINOR;
-       sv->drm_dd_major = dev->driver->major;
-       sv->drm_dd_minor = dev->driver->minor;
-
-       return retcode;
-}
-
-/** No-op ioctl. */
-int drm_noop(struct drm_device *dev, void *data,
-            struct drm_file *file_priv)
-{
-       DRM_DEBUG("\n");
-       return 0;
-}
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
deleted file mode 100644 (file)
index 089c015..0000000
+++ /dev/null
@@ -1,462 +0,0 @@
-/**
- * \file drm_irq.c
- * IRQ support
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
- *
- * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-#include <linux/interrupt.h>   /* For task queue support */
-
-/**
- * Get interrupt from bus id.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_irq_busid structure.
- * \return zero on success or a negative number on failure.
- *
- * Finds the PCI device with the specified bus id and gets its IRQ number.
- * This IOCTL is deprecated, and will now return EINVAL for any busid not equal
- * to that of the device that this DRM instance attached to.
- */
-int drm_irq_by_busid(struct drm_device *dev, void *data,
-                    struct drm_file *file_priv)
-{
-       struct drm_irq_busid *p = data;
-
-       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
-               return -EINVAL;
-
-       if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
-           (p->busnum & 0xff) != dev->pdev->bus->number ||
-           p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
-               return -EINVAL;
-
-       p->irq = dev->irq;
-
-       DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
-                 p->irq);
-
-       return 0;
-}
-
-/**
- * Install IRQ handler.
- *
- * \param dev DRM device.
- * \param irq IRQ number.
- *
- * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
- * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
- * before and after the installation.
- */
-static int drm_irq_install(struct drm_device * dev)
-{
-       int ret;
-       unsigned long sh_flags = 0;
-
-       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
-               return -EINVAL;
-
-       if (dev->irq == 0)
-               return -EINVAL;
-
-       mutex_lock(&dev->struct_mutex);
-
-       /* Driver must have been initialized */
-       if (!dev->dev_private) {
-               mutex_unlock(&dev->struct_mutex);
-               return -EINVAL;
-       }
-
-       if (dev->irq_enabled) {
-               mutex_unlock(&dev->struct_mutex);
-               return -EBUSY;
-       }
-       dev->irq_enabled = 1;
-       mutex_unlock(&dev->struct_mutex);
-
-       DRM_DEBUG("irq=%d\n", dev->irq);
-
-       if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
-               init_waitqueue_head(&dev->vbl_queue);
-
-               spin_lock_init(&dev->vbl_lock);
-
-               INIT_LIST_HEAD(&dev->vbl_sigs);
-               INIT_LIST_HEAD(&dev->vbl_sigs2);
-
-               dev->vbl_pending = 0;
-       }
-
-       /* Before installing handler */
-       dev->driver->irq_preinstall(dev);
-
-       /* Install handler */
-       if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
-               sh_flags = IRQF_SHARED;
-
-       ret = request_irq(dev->irq, dev->driver->irq_handler,
-                         sh_flags, dev->devname, dev);
-       if (ret < 0) {
-               mutex_lock(&dev->struct_mutex);
-               dev->irq_enabled = 0;
-               mutex_unlock(&dev->struct_mutex);
-               return ret;
-       }
-
-       /* After installing handler */
-       dev->driver->irq_postinstall(dev);
-
-       return 0;
-}
-
-/**
- * Uninstall the IRQ handler.
- *
- * \param dev DRM device.
- *
- * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
- */
-int drm_irq_uninstall(struct drm_device * dev)
-{
-       int irq_enabled;
-
-       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
-               return -EINVAL;
-
-       mutex_lock(&dev->struct_mutex);
-       irq_enabled = dev->irq_enabled;
-       dev->irq_enabled = 0;
-       mutex_unlock(&dev->struct_mutex);
-
-       if (!irq_enabled)
-               return -EINVAL;
-
-       DRM_DEBUG("irq=%d\n", dev->irq);
-
-       dev->driver->irq_uninstall(dev);
-
-       free_irq(dev->irq, dev);
-
-       dev->locked_tasklet_func = NULL;
-
-       return 0;
-}
-
-EXPORT_SYMBOL(drm_irq_uninstall);
-
-/**
- * IRQ control ioctl.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_control structure.
- * \return zero on success or a negative number on failure.
- *
- * Calls irq_install() or irq_uninstall() according to \p arg.
- */
-int drm_control(struct drm_device *dev, void *data,
-               struct drm_file *file_priv)
-{
-       struct drm_control *ctl = data;
-
-       /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
-
-
-       switch (ctl->func) {
-       case DRM_INST_HANDLER:
-               if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
-                       return 0;
-               if (dev->if_version < DRM_IF_VERSION(1, 2) &&
-                   ctl->irq != dev->irq)
-                       return -EINVAL;
-               return drm_irq_install(dev);
-       case DRM_UNINST_HANDLER:
-               if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
-                       return 0;
-               return drm_irq_uninstall(dev);
-       default:
-               return -EINVAL;
-       }
-}
-
-/**
- * Wait for VBLANK.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param data user argument, pointing to a drm_wait_vblank structure.
- * \return zero on success or a negative number on failure.
- *
- * Verifies the IRQ is installed.
- *
- * If a signal is requested checks if this task has already scheduled the same signal
- * for the same vblank sequence number - nothing to be done in
- * that case. If the number of tasks waiting for the interrupt exceeds 100 the
- * function fails. Otherwise adds a new entry to drm_device::vbl_sigs for this
- * task.
- *
- * If a signal is not requested, then calls vblank_wait().
- */
-int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       union drm_wait_vblank *vblwait = data;
-       struct timeval now;
-       int ret = 0;
-       unsigned int flags, seq;
-
-       if ((!dev->irq) || (!dev->irq_enabled))
-               return -EINVAL;
-
-       if (vblwait->request.type &
-           ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
-               DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
-                         vblwait->request.type,
-                         (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
-               return -EINVAL;
-       }
-
-       flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
-
-       if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
-                                   DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
-               return -EINVAL;
-
-       seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
-                         : &dev->vbl_received);
-
-       switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
-       case _DRM_VBLANK_RELATIVE:
-               vblwait->request.sequence += seq;
-               vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
-       case _DRM_VBLANK_ABSOLUTE:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if ((flags & _DRM_VBLANK_NEXTONMISS) &&
-           (seq - vblwait->request.sequence) <= (1<<23)) {
-               vblwait->request.sequence = seq + 1;
-       }
-
-       if (flags & _DRM_VBLANK_SIGNAL) {
-               unsigned long irqflags;
-               struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
-                                     ? &dev->vbl_sigs2 : &dev->vbl_sigs;
-               struct drm_vbl_sig *vbl_sig;
-
-               spin_lock_irqsave(&dev->vbl_lock, irqflags);
-
-               /* Check if this task has already scheduled the same signal
-                * for the same vblank sequence number; nothing to be done in
-                * that case
-                */
-               list_for_each_entry(vbl_sig, vbl_sigs, head) {
-                       if (vbl_sig->sequence == vblwait->request.sequence
-                           && vbl_sig->info.si_signo ==
-                           vblwait->request.signal
-                           && vbl_sig->task == current) {
-                               spin_unlock_irqrestore(&dev->vbl_lock,
-                                                      irqflags);
-                               vblwait->reply.sequence = seq;
-                               goto done;
-                       }
-               }
-
-               if (dev->vbl_pending >= 100) {
-                       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-                       return -EBUSY;
-               }
-
-               dev->vbl_pending++;
-
-               spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-
-               if (!
-                   (vbl_sig =
-                    drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
-                       return -ENOMEM;
-               }
-
-               memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
-
-               vbl_sig->sequence = vblwait->request.sequence;
-               vbl_sig->info.si_signo = vblwait->request.signal;
-               vbl_sig->task = current;
-
-               spin_lock_irqsave(&dev->vbl_lock, irqflags);
-
-               list_add_tail(&vbl_sig->head, vbl_sigs);
-
-               spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-
-               vblwait->reply.sequence = seq;
-       } else {
-               if (flags & _DRM_VBLANK_SECONDARY) {
-                       if (dev->driver->vblank_wait2)
-                               ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
-               } else if (dev->driver->vblank_wait)
-                       ret =
-                           dev->driver->vblank_wait(dev,
-                                                    &vblwait->request.sequence);
-
-               do_gettimeofday(&now);
-               vblwait->reply.tval_sec = now.tv_sec;
-               vblwait->reply.tval_usec = now.tv_usec;
-       }
-
-      done:
-       return ret;
-}
-
-/**
- * Send the VBLANK signals.
- *
- * \param dev DRM device.
- *
- * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
- *
- * If a signal is not requested, then calls vblank_wait().
- */
-void drm_vbl_send_signals(struct drm_device * dev)
-{
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&dev->vbl_lock, flags);
-
-       for (i = 0; i < 2; i++) {
-               struct drm_vbl_sig *vbl_sig, *tmp;
-               struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
-               unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
-                                                  &dev->vbl_received);
-
-               list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
-                       if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
-                               vbl_sig->info.si_code = vbl_seq;
-                               send_sig_info(vbl_sig->info.si_signo,
-                                             &vbl_sig->info, vbl_sig->task);
-
-                               list_del(&vbl_sig->head);
-
-                               drm_free(vbl_sig, sizeof(*vbl_sig),
-                                        DRM_MEM_DRIVER);
-
-                               dev->vbl_pending--;
-                       }
-               }
-       }
-
-       spin_unlock_irqrestore(&dev->vbl_lock, flags);
-}
-
-EXPORT_SYMBOL(drm_vbl_send_signals);
-
-/**
- * Tasklet wrapper function.
- *
- * \param data DRM device in disguise.
- *
- * Attempts to grab the HW lock and calls the driver callback on success. On
- * failure, leave the lock marked as contended so the callback can be called
- * from drm_unlock().
- */
-static void drm_locked_tasklet_func(unsigned long data)
-{
-       struct drm_device *dev = (struct drm_device *)data;
-       unsigned long irqflags;
-
-       spin_lock_irqsave(&dev->tasklet_lock, irqflags);
-
-       if (!dev->locked_tasklet_func ||
-           !drm_lock_take(&dev->lock,
-                          DRM_KERNEL_CONTEXT)) {
-               spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
-               return;
-       }
-
-       dev->lock.lock_time = jiffies;
-       atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
-
-       dev->locked_tasklet_func(dev);
-
-       drm_lock_free(&dev->lock,
-                     DRM_KERNEL_CONTEXT);
-
-       dev->locked_tasklet_func = NULL;
-
-       spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
-}
-
-/**
- * Schedule a tasklet to call back a driver hook with the HW lock held.
- *
- * \param dev DRM device.
- * \param func Driver callback.
- *
- * This is intended for triggering actions that require the HW lock from an
- * interrupt handler. The lock will be grabbed ASAP after the interrupt handler
- * completes. Note that the callback may be called from interrupt or process
- * context, it must not make any assumptions about this. Also, the HW lock will
- * be held with the kernel context or any client context.
- */
-void drm_locked_tasklet(struct drm_device *dev, void (*func)(struct drm_device *))
-{
-       unsigned long irqflags;
-       static DECLARE_TASKLET(drm_tasklet, drm_locked_tasklet_func, 0);
-
-       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ) ||
-           test_bit(TASKLET_STATE_SCHED, &drm_tasklet.state))
-               return;
-
-       spin_lock_irqsave(&dev->tasklet_lock, irqflags);
-
-       if (dev->locked_tasklet_func) {
-               spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
-               return;
-       }
-
-       dev->locked_tasklet_func = func;
-
-       spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
-
-       drm_tasklet.data = (unsigned long)dev;
-
-       tasklet_hi_schedule(&drm_tasklet);
-}
-EXPORT_SYMBOL(drm_locked_tasklet);
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
deleted file mode 100644 (file)
index 0998723..0000000
+++ /dev/null
@@ -1,391 +0,0 @@
-/**
- * \file drm_lock.c
- * IOCTLs for locking
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-static int drm_notifier(void *priv);
-
-/**
- * Lock ioctl.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_lock structure.
- * \return zero on success or negative number on failure.
- *
- * Add the current task to the lock wait queue, and attempt to take to lock.
- */
-int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       DECLARE_WAITQUEUE(entry, current);
-       struct drm_lock *lock = data;
-       int ret = 0;
-
-       ++file_priv->lock_count;
-
-       if (lock->context == DRM_KERNEL_CONTEXT) {
-               DRM_ERROR("Process %d using kernel context %d\n",
-                         task_pid_nr(current), lock->context);
-               return -EINVAL;
-       }
-
-       DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
-                 lock->context, task_pid_nr(current),
-                 dev->lock.hw_lock->lock, lock->flags);
-
-       if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
-               if (lock->context < 0)
-                       return -EINVAL;
-
-       add_wait_queue(&dev->lock.lock_queue, &entry);
-       spin_lock_bh(&dev->lock.spinlock);
-       dev->lock.user_waiters++;
-       spin_unlock_bh(&dev->lock.spinlock);
-       for (;;) {
-               __set_current_state(TASK_INTERRUPTIBLE);
-               if (!dev->lock.hw_lock) {
-                       /* Device has been unregistered */
-                       ret = -EINTR;
-                       break;
-               }
-               if (drm_lock_take(&dev->lock, lock->context)) {
-                       dev->lock.file_priv = file_priv;
-                       dev->lock.lock_time = jiffies;
-                       atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
-                       break;  /* Got lock */
-               }
-
-               /* Contention */
-               schedule();
-               if (signal_pending(current)) {
-                       ret = -ERESTARTSYS;
-                       break;
-               }
-       }
-       spin_lock_bh(&dev->lock.spinlock);
-       dev->lock.user_waiters--;
-       spin_unlock_bh(&dev->lock.spinlock);
-       __set_current_state(TASK_RUNNING);
-       remove_wait_queue(&dev->lock.lock_queue, &entry);
-
-       DRM_DEBUG("%d %s\n", lock->context,
-                 ret ? "interrupted" : "has lock");
-       if (ret) return ret;
-
-       sigemptyset(&dev->sigmask);
-       sigaddset(&dev->sigmask, SIGSTOP);
-       sigaddset(&dev->sigmask, SIGTSTP);
-       sigaddset(&dev->sigmask, SIGTTIN);
-       sigaddset(&dev->sigmask, SIGTTOU);
-       dev->sigdata.context = lock->context;
-       dev->sigdata.lock = dev->lock.hw_lock;
-       block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
-
-       if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY))
-               dev->driver->dma_ready(dev);
-
-       if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT))
-       {
-               if (dev->driver->dma_quiescent(dev)) {
-                       DRM_DEBUG("%d waiting for DMA quiescent\n",
-                                 lock->context);
-                       return -EBUSY;
-               }
-       }
-
-       if (dev->driver->kernel_context_switch &&
-           dev->last_context != lock->context) {
-               dev->driver->kernel_context_switch(dev, dev->last_context,
-                                                  lock->context);
-       }
-
-       return 0;
-}
-
-/**
- * Unlock ioctl.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_lock structure.
- * \return zero on success or negative number on failure.
- *
- * Transfer and free the lock.
- */
-int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       struct drm_lock *lock = data;
-       unsigned long irqflags;
-
-       if (lock->context == DRM_KERNEL_CONTEXT) {
-               DRM_ERROR("Process %d using kernel context %d\n",
-                         task_pid_nr(current), lock->context);
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&dev->tasklet_lock, irqflags);
-
-       if (dev->locked_tasklet_func) {
-               dev->locked_tasklet_func(dev);
-
-               dev->locked_tasklet_func = NULL;
-       }
-
-       spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
-
-       atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
-
-       /* kernel_context_switch isn't used by any of the x86 drm
-        * modules but is required by the Sparc driver.
-        */
-       if (dev->driver->kernel_context_switch_unlock)
-               dev->driver->kernel_context_switch_unlock(dev);
-       else {
-               if (drm_lock_free(&dev->lock,lock->context)) {
-                       /* FIXME: Should really bail out here. */
-               }
-       }
-
-       unblock_all_signals();
-       return 0;
-}
-
-/**
- * Take the heavyweight lock.
- *
- * \param lock lock pointer.
- * \param context locking context.
- * \return one if the lock is held, or zero otherwise.
- *
- * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction.
- */
-int drm_lock_take(struct drm_lock_data *lock_data,
-                 unsigned int context)
-{
-       unsigned int old, new, prev;
-       volatile unsigned int *lock = &lock_data->hw_lock->lock;
-
-       spin_lock_bh(&lock_data->spinlock);
-       do {
-               old = *lock;
-               if (old & _DRM_LOCK_HELD)
-                       new = old | _DRM_LOCK_CONT;
-               else {
-                       new = context | _DRM_LOCK_HELD |
-                               ((lock_data->user_waiters + lock_data->kernel_waiters > 1) ?
-                                _DRM_LOCK_CONT : 0);
-               }
-               prev = cmpxchg(lock, old, new);
-       } while (prev != old);
-       spin_unlock_bh(&lock_data->spinlock);
-
-       if (_DRM_LOCKING_CONTEXT(old) == context) {
-               if (old & _DRM_LOCK_HELD) {
-                       if (context != DRM_KERNEL_CONTEXT) {
-                               DRM_ERROR("%d holds heavyweight lock\n",
-                                         context);
-                       }
-                       return 0;
-               }
-       }
-
-       if ((_DRM_LOCKING_CONTEXT(new)) == context && (new & _DRM_LOCK_HELD)) {
-               /* Have lock */
-               return 1;
-       }
-       return 0;
-}
-
-/**
- * This takes a lock forcibly and hands it to context. Should ONLY be used
- * inside *_unlock to give lock to kernel before calling *_dma_schedule.
- *
- * \param dev DRM device.
- * \param lock lock pointer.
- * \param context locking context.
- * \return always one.
- *
- * Resets the lock file pointer.
- * Marks the lock as held by the given context, via the \p cmpxchg instruction.
- */
-static int drm_lock_transfer(struct drm_lock_data *lock_data,
-                            unsigned int context)
-{
-       unsigned int old, new, prev;
-       volatile unsigned int *lock = &lock_data->hw_lock->lock;
-
-       lock_data->file_priv = NULL;
-       do {
-               old = *lock;
-               new = context | _DRM_LOCK_HELD;
-               prev = cmpxchg(lock, old, new);
-       } while (prev != old);
-       return 1;
-}
-
-/**
- * Free lock.
- *
- * \param dev DRM device.
- * \param lock lock.
- * \param context context.
- *
- * Resets the lock file pointer.
- * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
- * waiting on the lock queue.
- */
-int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
-{
-       unsigned int old, new, prev;
-       volatile unsigned int *lock = &lock_data->hw_lock->lock;
-
-       spin_lock_bh(&lock_data->spinlock);
-       if (lock_data->kernel_waiters != 0) {
-               drm_lock_transfer(lock_data, 0);
-               lock_data->idle_has_lock = 1;
-               spin_unlock_bh(&lock_data->spinlock);
-               return 1;
-       }
-       spin_unlock_bh(&lock_data->spinlock);
-
-       do {
-               old = *lock;
-               new = _DRM_LOCKING_CONTEXT(old);
-               prev = cmpxchg(lock, old, new);
-       } while (prev != old);
-
-       if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
-               DRM_ERROR("%d freed heavyweight lock held by %d\n",
-                         context, _DRM_LOCKING_CONTEXT(old));
-               return 1;
-       }
-       wake_up_interruptible(&lock_data->lock_queue);
-       return 0;
-}
-
-/**
- * If we get here, it means that the process has called DRM_IOCTL_LOCK
- * without calling DRM_IOCTL_UNLOCK.
- *
- * If the lock is not held, then let the signal proceed as usual.  If the lock
- * is held, then set the contended flag and keep the signal blocked.
- *
- * \param priv pointer to a drm_sigdata structure.
- * \return one if the signal should be delivered normally, or zero if the
- * signal should be blocked.
- */
-static int drm_notifier(void *priv)
-{
-       struct drm_sigdata *s = (struct drm_sigdata *) priv;
-       unsigned int old, new, prev;
-
-       /* Allow signal delivery if lock isn't held */
-       if (!s->lock || !_DRM_LOCK_IS_HELD(s->lock->lock)
-           || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context)
-               return 1;
-
-       /* Otherwise, set flag to force call to
-          drmUnlock */
-       do {
-               old = s->lock->lock;
-               new = old | _DRM_LOCK_CONT;
-               prev = cmpxchg(&s->lock->lock, old, new);
-       } while (prev != old);
-       return 0;
-}
-
-/**
- * This function returns immediately and takes the hw lock
- * with the kernel context if it is free, otherwise it gets the highest priority when and if
- * it is eventually released.
- *
- * This guarantees that the kernel will _eventually_ have the lock _unless_ it is held
- * by a blocked process. (In the latter case an explicit wait for the hardware lock would cause
- * a deadlock, which is why the "idlelock" was invented).
- *
- * This should be sufficient to wait for GPU idle without
- * having to worry about starvation.
- */
-
-void drm_idlelock_take(struct drm_lock_data *lock_data)
-{
-       int ret = 0;
-
-       spin_lock_bh(&lock_data->spinlock);
-       lock_data->kernel_waiters++;
-       if (!lock_data->idle_has_lock) {
-
-               spin_unlock_bh(&lock_data->spinlock);
-               ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT);
-               spin_lock_bh(&lock_data->spinlock);
-
-               if (ret == 1)
-                       lock_data->idle_has_lock = 1;
-       }
-       spin_unlock_bh(&lock_data->spinlock);
-}
-EXPORT_SYMBOL(drm_idlelock_take);
-
-void drm_idlelock_release(struct drm_lock_data *lock_data)
-{
-       unsigned int old, prev;
-       volatile unsigned int *lock = &lock_data->hw_lock->lock;
-
-       spin_lock_bh(&lock_data->spinlock);
-       if (--lock_data->kernel_waiters == 0) {
-               if (lock_data->idle_has_lock) {
-                       do {
-                               old = *lock;
-                               prev = cmpxchg(lock, old, DRM_KERNEL_CONTEXT);
-                       } while (prev != old);
-                       wake_up_interruptible(&lock_data->lock_queue);
-                       lock_data->idle_has_lock = 0;
-               }
-       }
-       spin_unlock_bh(&lock_data->spinlock);
-}
-EXPORT_SYMBOL(drm_idlelock_release);
-
-
-int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv)
-{
-       return (file_priv->lock_count && dev->lock.hw_lock &&
-               _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
-               dev->lock.file_priv == file_priv);
-}
-
-EXPORT_SYMBOL(drm_i_have_hw_lock);
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
deleted file mode 100644 (file)
index 845081b..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/**
- * \file drm_memory.c
- * Memory management wrappers for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Thu Feb  4 14:00:34 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/highmem.h>
-#include "drmP.h"
-
-#ifdef DEBUG_MEMORY
-#include "drm_memory_debug.h"
-#else
-
-/** No-op. */
-void drm_mem_init(void)
-{
-}
-
-/**
- * Called when "/proc/dri/%dev%/mem" is read.
- *
- * \param buf output buffer.
- * \param start start of output data.
- * \param offset requested start offset.
- * \param len requested number of bytes.
- * \param eof whether there is no more data to return.
- * \param data private data.
- * \return number of written bytes.
- *
- * No-op.
- */
-int drm_mem_info(char *buf, char **start, off_t offset,
-                int len, int *eof, void *data)
-{
-       return 0;
-}
-
-/** Wrapper around kmalloc() and kfree() */
-void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
-{
-       void *pt;
-
-       if (!(pt = kmalloc(size, GFP_KERNEL)))
-               return NULL;
-       if (oldpt && oldsize) {
-               memcpy(pt, oldpt, oldsize);
-               kfree(oldpt);
-       }
-       return pt;
-}
-
-#if __OS_HAS_AGP
-static void *agp_remap(unsigned long offset, unsigned long size,
-                      struct drm_device * dev)
-{
-       unsigned long *phys_addr_map, i, num_pages =
-           PAGE_ALIGN(size) / PAGE_SIZE;
-       struct drm_agp_mem *agpmem;
-       struct page **page_map;
-       void *addr;
-
-       size = PAGE_ALIGN(size);
-
-#ifdef __alpha__
-       offset -= dev->hose->mem_space->start;
-#endif
-
-       list_for_each_entry(agpmem, &dev->agp->memory, head)
-               if (agpmem->bound <= offset
-                   && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
-                   (offset + size))
-                       break;
-       if (!agpmem)
-               return NULL;
-
-       /*
-        * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
-        * the CPU do not get remapped by the GART.  We fix this by using the kernel's
-        * page-table instead (that's probably faster anyhow...).
-        */
-       /* note: use vmalloc() because num_pages could be large... */
-       page_map = vmalloc(num_pages * sizeof(struct page *));
-       if (!page_map)
-               return NULL;
-
-       phys_addr_map =
-           agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
-       for (i = 0; i < num_pages; ++i)
-               page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
-       addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
-       vfree(page_map);
-
-       return addr;
-}
-
-/** Wrapper around agp_allocate_memory() */
-DRM_AGP_MEM *drm_alloc_agp(struct drm_device * dev, int pages, u32 type)
-{
-       return drm_agp_allocate_memory(dev->agp->bridge, pages, type);
-}
-
-/** Wrapper around agp_free_memory() */
-int drm_free_agp(DRM_AGP_MEM * handle, int pages)
-{
-       return drm_agp_free_memory(handle) ? 0 : -EINVAL;
-}
-
-/** Wrapper around agp_bind_memory() */
-int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
-{
-       return drm_agp_bind_memory(handle, start);
-}
-
-/** Wrapper around agp_unbind_memory() */
-int drm_unbind_agp(DRM_AGP_MEM * handle)
-{
-       return drm_agp_unbind_memory(handle);
-}
-
-#else  /*  __OS_HAS_AGP  */
-static inline void *agp_remap(unsigned long offset, unsigned long size,
-                             struct drm_device * dev)
-{
-       return NULL;
-}
-
-#endif                         /* agp */
-
-#endif                         /* debug_memory */
-
-void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
-{
-       if (drm_core_has_AGP(dev) &&
-           dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
-               map->handle = agp_remap(map->offset, map->size, dev);
-       else
-               map->handle = ioremap(map->offset, map->size);
-}
-EXPORT_SYMBOL(drm_core_ioremap);
-
-void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
-{
-       if (!map->handle || !map->size)
-               return;
-
-       if (drm_core_has_AGP(dev) &&
-           dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
-               vunmap(map->handle);
-       else
-               iounmap(map->handle);
-}
-EXPORT_SYMBOL(drm_core_ioremapfree);
diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h
deleted file mode 100644 (file)
index 63e425b..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * \file drm_memory.h
- * Memory management wrappers for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Thu Feb  4 14:00:34 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/highmem.h>
-#include <linux/vmalloc.h>
-#include "drmP.h"
-
-/**
- * Cut down version of drm_memory_debug.h, which used to be called
- * drm_memory.h.
- */
-
-#if __OS_HAS_AGP
-
-#include <linux/vmalloc.h>
-
-#ifdef HAVE_PAGE_AGP
-#include <asm/agp.h>
-#else
-# ifdef __powerpc__
-#  define PAGE_AGP     __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
-# else
-#  define PAGE_AGP     PAGE_KERNEL
-# endif
-#endif
-
-#else                          /* __OS_HAS_AGP */
-
-#endif
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
deleted file mode 100644 (file)
index 6463271..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-/**
- * \file drm_memory_debug.h
- * Memory management wrappers for DRM.
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-typedef struct drm_mem_stats {
-       const char *name;
-       int succeed_count;
-       int free_count;
-       int fail_count;
-       unsigned long bytes_allocated;
-       unsigned long bytes_freed;
-} drm_mem_stats_t;
-
-static DEFINE_SPINLOCK(drm_mem_lock);
-static unsigned long drm_ram_available = 0;    /* In pages */
-static unsigned long drm_ram_used = 0;
-static drm_mem_stats_t drm_mem_stats[] =
-{
-       [DRM_MEM_DMA] = {"dmabufs"},
-       [DRM_MEM_SAREA] = {"sareas"},
-       [DRM_MEM_DRIVER] = {"driver"},
-       [DRM_MEM_MAGIC] = {"magic"},
-       [DRM_MEM_IOCTLS] = {"ioctltab"},
-       [DRM_MEM_MAPS] = {"maplist"},
-       [DRM_MEM_VMAS] = {"vmalist"},
-       [DRM_MEM_BUFS] = {"buflist"},
-       [DRM_MEM_SEGS] = {"seglist"},
-       [DRM_MEM_PAGES] = {"pagelist"},
-       [DRM_MEM_FILES] = {"files"},
-       [DRM_MEM_QUEUES] = {"queues"},
-       [DRM_MEM_CMDS] = {"commands"},
-       [DRM_MEM_MAPPINGS] = {"mappings"},
-       [DRM_MEM_BUFLISTS] = {"buflists"},
-       [DRM_MEM_AGPLISTS] = {"agplist"},
-       [DRM_MEM_SGLISTS] = {"sglist"},
-       [DRM_MEM_TOTALAGP] = {"totalagp"},
-       [DRM_MEM_BOUNDAGP] = {"boundagp"},
-       [DRM_MEM_CTXBITMAP] = {"ctxbitmap"},
-       [DRM_MEM_CTXLIST] = {"ctxlist"},
-       [DRM_MEM_STUB] = {"stub"},
-       {NULL, 0,}              /* Last entry must be null */
-};
-
-void drm_mem_init (void) {
-       drm_mem_stats_t *mem;
-       struct sysinfo si;
-
-       for (mem = drm_mem_stats; mem->name; ++mem) {
-               mem->succeed_count = 0;
-               mem->free_count = 0;
-               mem->fail_count = 0;
-               mem->bytes_allocated = 0;
-               mem->bytes_freed = 0;
-       }
-
-       si_meminfo(&si);
-       drm_ram_available = si.totalram;
-       drm_ram_used = 0;
-}
-
-/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
-
-static int drm__mem_info (char *buf, char **start, off_t offset,
-                          int request, int *eof, void *data) {
-       drm_mem_stats_t *pt;
-       int len = 0;
-
-       if (offset > DRM_PROC_LIMIT) {
-               *eof = 1;
-               return 0;
-       }
-
-       *eof = 0;
-       *start = &buf[offset];
-
-       DRM_PROC_PRINT("                  total counts                  "
-                      " |    outstanding  \n");
-       DRM_PROC_PRINT("type       alloc freed fail     bytes      freed"
-                      " | allocs      bytes\n\n");
-       DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB         |\n",
-                      "system", 0, 0, 0,
-                      drm_ram_available << (PAGE_SHIFT - 10));
-       DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB         |\n",
-                      "locked", 0, 0, 0, drm_ram_used >> 10);
-       DRM_PROC_PRINT("\n");
-       for (pt = drm_mem_stats; pt->name; pt++) {
-               DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
-                              pt->name,
-                              pt->succeed_count,
-                              pt->free_count,
-                              pt->fail_count,
-                              pt->bytes_allocated,
-                              pt->bytes_freed,
-                              pt->succeed_count - pt->free_count,
-                              (long)pt->bytes_allocated
-                              - (long)pt->bytes_freed);
-       }
-
-       if (len > request + offset)
-               return request;
-       *eof = 1;
-       return len - offset;
-}
-
-int drm_mem_info (char *buf, char **start, off_t offset,
-                  int len, int *eof, void *data) {
-       int ret;
-
-       spin_lock(&drm_mem_lock);
-       ret = drm__mem_info (buf, start, offset, len, eof, data);
-       spin_unlock(&drm_mem_lock);
-       return ret;
-}
-
-void *drm_alloc (size_t size, int area) {
-       void *pt;
-
-       if (!size) {
-               DRM_MEM_ERROR(area, "Allocating 0 bytes\n");
-               return NULL;
-       }
-
-       if (!(pt = kmalloc(size, GFP_KERNEL))) {
-               spin_lock(&drm_mem_lock);
-               ++drm_mem_stats[area].fail_count;
-               spin_unlock(&drm_mem_lock);
-               return NULL;
-       }
-       spin_lock(&drm_mem_lock);
-       ++drm_mem_stats[area].succeed_count;
-       drm_mem_stats[area].bytes_allocated += size;
-       spin_unlock(&drm_mem_lock);
-       return pt;
-}
-
-void *drm_calloc (size_t nmemb, size_t size, int area) {
-       void *addr;
-
-       addr = drm_alloc (nmemb * size, area);
-       if (addr != NULL)
-               memset((void *)addr, 0, size * nmemb);
-
-       return addr;
-}
-
-void *drm_realloc (void *oldpt, size_t oldsize, size_t size, int area) {
-       void *pt;
-
-       if (!(pt = drm_alloc (size, area)))
-               return NULL;
-       if (oldpt && oldsize) {
-               memcpy(pt, oldpt, oldsize);
-               drm_free (oldpt, oldsize, area);
-       }
-       return pt;
-}
-
-void drm_free (void *pt, size_t size, int area) {
-       int alloc_count;
-       int free_count;
-
-       if (!pt)
-               DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
-       else
-               kfree(pt);
-       spin_lock(&drm_mem_lock);
-       drm_mem_stats[area].bytes_freed += size;
-       free_count = ++drm_mem_stats[area].free_count;
-       alloc_count = drm_mem_stats[area].succeed_count;
-       spin_unlock(&drm_mem_lock);
-       if (free_count > alloc_count) {
-               DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
-                             free_count, alloc_count);
-       }
-}
-
-#if __OS_HAS_AGP
-
-DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) {
-       DRM_AGP_MEM *handle;
-
-       if (!pages) {
-               DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n");
-               return NULL;
-       }
-
-       if ((handle = drm_agp_allocate_memory (pages, type))) {
-               spin_lock(&drm_mem_lock);
-               ++drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count;
-               drm_mem_stats[DRM_MEM_TOTALAGP].bytes_allocated
-                   += pages << PAGE_SHIFT;
-               spin_unlock(&drm_mem_lock);
-               return handle;
-       }
-       spin_lock(&drm_mem_lock);
-       ++drm_mem_stats[DRM_MEM_TOTALAGP].fail_count;
-       spin_unlock(&drm_mem_lock);
-       return NULL;
-}
-
-int drm_free_agp (DRM_AGP_MEM * handle, int pages) {
-       int alloc_count;
-       int free_count;
-       int retval = -EINVAL;
-
-       if (!handle) {
-               DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
-                             "Attempt to free NULL AGP handle\n");
-               return retval;
-       }
-
-       if (drm_agp_free_memory (handle)) {
-               spin_lock(&drm_mem_lock);
-               free_count = ++drm_mem_stats[DRM_MEM_TOTALAGP].free_count;
-               alloc_count = drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count;
-               drm_mem_stats[DRM_MEM_TOTALAGP].bytes_freed
-                   += pages << PAGE_SHIFT;
-               spin_unlock(&drm_mem_lock);
-               if (free_count > alloc_count) {
-                       DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
-                                     "Excess frees: %d frees, %d allocs\n",
-                                     free_count, alloc_count);
-               }
-               return 0;
-       }
-       return retval;
-}
-
-int drm_bind_agp (DRM_AGP_MEM * handle, unsigned int start) {
-       int retcode = -EINVAL;
-
-       if (!handle) {
-               DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
-                             "Attempt to bind NULL AGP handle\n");
-               return retcode;
-       }
-
-       if (!(retcode = drm_agp_bind_memory (handle, start))) {
-               spin_lock(&drm_mem_lock);
-               ++drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;
-               drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_allocated
-                   += handle->page_count << PAGE_SHIFT;
-               spin_unlock(&drm_mem_lock);
-               return retcode;
-       }
-       spin_lock(&drm_mem_lock);
-       ++drm_mem_stats[DRM_MEM_BOUNDAGP].fail_count;
-       spin_unlock(&drm_mem_lock);
-       return retcode;
-}
-
-int drm_unbind_agp (DRM_AGP_MEM * handle) {
-       int alloc_count;
-       int free_count;
-       int retcode = -EINVAL;
-
-       if (!handle) {
-               DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
-                             "Attempt to unbind NULL AGP handle\n");
-               return retcode;
-       }
-
-       if ((retcode = drm_agp_unbind_memory (handle)))
-               return retcode;
-       spin_lock(&drm_mem_lock);
-       free_count = ++drm_mem_stats[DRM_MEM_BOUNDAGP].free_count;
-       alloc_count = drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;
-       drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_freed
-           += handle->page_count << PAGE_SHIFT;
-       spin_unlock(&drm_mem_lock);
-       if (free_count > alloc_count) {
-               DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
-                             "Excess frees: %d frees, %d allocs\n",
-                             free_count, alloc_count);
-       }
-       return retcode;
-}
-#endif
diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c
deleted file mode 100644 (file)
index dcff9e9..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- **************************************************************************/
-
-/*
- * Generic simple memory manager implementation. Intended to be used as a base
- * class implementation for more advanced memory managers.
- *
- * Note that the algorithm used is quite simple and there might be substantial
- * performance gains if a smarter free list is implemented. Currently it is just an
- * unordered stack of free regions. This could easily be improved if an RB-tree
- * is used instead. At least if we expect heavy fragmentation.
- *
- * Aligned allocations can also see improvement.
- *
- * Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#include "drmP.h"
-#include <linux/slab.h>
-
-unsigned long drm_mm_tail_space(struct drm_mm *mm)
-{
-       struct list_head *tail_node;
-       struct drm_mm_node *entry;
-
-       tail_node = mm->ml_entry.prev;
-       entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
-       if (!entry->free)
-               return 0;
-
-       return entry->size;
-}
-
-int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size)
-{
-       struct list_head *tail_node;
-       struct drm_mm_node *entry;
-
-       tail_node = mm->ml_entry.prev;
-       entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
-       if (!entry->free)
-               return -ENOMEM;
-
-       if (entry->size <= size)
-               return -ENOMEM;
-
-       entry->size -= size;
-       return 0;
-}
-
-
-static int drm_mm_create_tail_node(struct drm_mm *mm,
-                           unsigned long start,
-                           unsigned long size)
-{
-       struct drm_mm_node *child;
-
-       child = (struct drm_mm_node *)
-               drm_alloc(sizeof(*child), DRM_MEM_MM);
-       if (!child)
-               return -ENOMEM;
-
-       child->free = 1;
-       child->size = size;
-       child->start = start;
-       child->mm = mm;
-
-       list_add_tail(&child->ml_entry, &mm->ml_entry);
-       list_add_tail(&child->fl_entry, &mm->fl_entry);
-
-       return 0;
-}
-
-
-int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size)
-{
-       struct list_head *tail_node;
-       struct drm_mm_node *entry;
-
-       tail_node = mm->ml_entry.prev;
-       entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
-       if (!entry->free) {
-               return drm_mm_create_tail_node(mm, entry->start + entry->size, size);
-       }
-       entry->size += size;
-       return 0;
-}
-
-static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
-                                           unsigned long size)
-{
-       struct drm_mm_node *child;
-
-       child = (struct drm_mm_node *)
-               drm_alloc(sizeof(*child), DRM_MEM_MM);
-       if (!child)
-               return NULL;
-
-       INIT_LIST_HEAD(&child->fl_entry);
-
-       child->free = 0;
-       child->size = size;
-       child->start = parent->start;
-       child->mm = parent->mm;
-
-       list_add_tail(&child->ml_entry, &parent->ml_entry);
-       INIT_LIST_HEAD(&child->fl_entry);
-
-       parent->size -= size;
-       parent->start += size;
-       return child;
-}
-
-
-
-struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
-                               unsigned long size, unsigned alignment)
-{
-
-       struct drm_mm_node *align_splitoff = NULL;
-       struct drm_mm_node *child;
-       unsigned tmp = 0;
-
-       if (alignment)
-               tmp = parent->start % alignment;
-
-       if (tmp) {
-               align_splitoff = drm_mm_split_at_start(parent, alignment - tmp);
-               if (!align_splitoff)
-                       return NULL;
-       }
-
-       if (parent->size == size) {
-               list_del_init(&parent->fl_entry);
-               parent->free = 0;
-               return parent;
-       } else {
-               child = drm_mm_split_at_start(parent, size);
-       }
-
-       if (align_splitoff)
-               drm_mm_put_block(align_splitoff);
-
-       return child;
-}
-
-/*
- * Put a block. Merge with the previous and / or next block if they are free.
- * Otherwise add to the free stack.
- */
-
-void drm_mm_put_block(struct drm_mm_node * cur)
-{
-
-       struct drm_mm *mm = cur->mm;
-       struct list_head *cur_head = &cur->ml_entry;
-       struct list_head *root_head = &mm->ml_entry;
-       struct drm_mm_node *prev_node = NULL;
-       struct drm_mm_node *next_node;
-
-       int merged = 0;
-
-       if (cur_head->prev != root_head) {
-               prev_node = list_entry(cur_head->prev, struct drm_mm_node, ml_entry);
-               if (prev_node->free) {
-                       prev_node->size += cur->size;
-                       merged = 1;
-               }
-       }
-       if (cur_head->next != root_head) {
-               next_node = list_entry(cur_head->next, struct drm_mm_node, ml_entry);
-               if (next_node->free) {
-                       if (merged) {
-                               prev_node->size += next_node->size;
-                               list_del(&next_node->ml_entry);
-                               list_del(&next_node->fl_entry);
-                               drm_free(next_node, sizeof(*next_node),
-                                        DRM_MEM_MM);
-                       } else {
-                               next_node->size += cur->size;
-                               next_node->start = cur->start;
-                               merged = 1;
-                       }
-               }
-       }
-       if (!merged) {
-               cur->free = 1;
-               list_add(&cur->fl_entry, &mm->fl_entry);
-       } else {
-               list_del(&cur->ml_entry);
-               drm_free(cur, sizeof(*cur), DRM_MEM_MM);
-       }
-}
-
-struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
-                                 unsigned long size,
-                                 unsigned alignment, int best_match)
-{
-       struct list_head *list;
-       const struct list_head *free_stack = &mm->fl_entry;
-       struct drm_mm_node *entry;
-       struct drm_mm_node *best;
-       unsigned long best_size;
-       unsigned wasted;
-
-       best = NULL;
-       best_size = ~0UL;
-
-       list_for_each(list, free_stack) {
-               entry = list_entry(list, struct drm_mm_node, fl_entry);
-               wasted = 0;
-
-               if (entry->size < size)
-                       continue;
-
-               if (alignment) {
-                       register unsigned tmp = entry->start % alignment;
-                       if (tmp)
-                               wasted += alignment - tmp;
-               }
-
-
-               if (entry->size >= size + wasted) {
-                       if (!best_match)
-                               return entry;
-                       if (size < best_size) {
-                               best = entry;
-                               best_size = entry->size;
-                       }
-               }
-       }
-
-       return best;
-}
-
-int drm_mm_clean(struct drm_mm * mm)
-{
-       struct list_head *head = &mm->ml_entry;
-
-       return (head->next->next == head);
-}
-
-int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
-{
-       INIT_LIST_HEAD(&mm->ml_entry);
-       INIT_LIST_HEAD(&mm->fl_entry);
-
-       return drm_mm_create_tail_node(mm, start, size);
-}
-
-
-void drm_mm_takedown(struct drm_mm * mm)
-{
-       struct list_head *bnode = mm->fl_entry.next;
-       struct drm_mm_node *entry;
-
-       entry = list_entry(bnode, struct drm_mm_node, fl_entry);
-
-       if (entry->ml_entry.next != &mm->ml_entry ||
-           entry->fl_entry.next != &mm->fl_entry) {
-               DRM_ERROR("Memory manager not clean. Delaying takedown\n");
-               return;
-       }
-
-       list_del(&entry->fl_entry);
-       list_del(&entry->ml_entry);
-
-       drm_free(entry, sizeof(*entry), DRM_MEM_MM);
-}
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
deleted file mode 100644 (file)
index 8dbd257..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * \file drm_os_linux.h
- * OS abstraction macros.
- */
-
-#include <linux/interrupt.h>   /* For task queue support */
-#include <linux/delay.h>
-
-/** Current process ID */
-#define DRM_CURRENTPID                 task_pid_nr(current)
-#define DRM_SUSER(p)                   capable(CAP_SYS_ADMIN)
-#define DRM_UDELAY(d)                  udelay(d)
-/** Read a byte from a MMIO region */
-#define DRM_READ8(map, offset)         readb(((void __iomem *)(map)->handle) + (offset))
-/** Read a word from a MMIO region */
-#define DRM_READ16(map, offset)         readw(((void __iomem *)(map)->handle) + (offset))
-/** Read a dword from a MMIO region */
-#define DRM_READ32(map, offset)                readl(((void __iomem *)(map)->handle) + (offset))
-/** Write a byte into a MMIO region */
-#define DRM_WRITE8(map, offset, val)   writeb(val, ((void __iomem *)(map)->handle) + (offset))
-/** Write a word into a MMIO region */
-#define DRM_WRITE16(map, offset, val)   writew(val, ((void __iomem *)(map)->handle) + (offset))
-/** Write a dword into a MMIO region */
-#define DRM_WRITE32(map, offset, val)  writel(val, ((void __iomem *)(map)->handle) + (offset))
-/** Read memory barrier */
-#define DRM_READMEMORYBARRIER()                rmb()
-/** Write memory barrier */
-#define DRM_WRITEMEMORYBARRIER()       wmb()
-/** Read/write memory barrier */
-#define DRM_MEMORYBARRIER()            mb()
-
-/** IRQ handler arguments and return type and values */
-#define DRM_IRQ_ARGS           int irq, void *arg
-
-/** AGP types */
-#if __OS_HAS_AGP
-#define DRM_AGP_MEM            struct agp_memory
-#define DRM_AGP_KERN           struct agp_kern_info
-#else
-/* define some dummy types for non AGP supporting kernels */
-struct no_agp_kern {
-       unsigned long aper_base;
-       unsigned long aper_size;
-};
-#define DRM_AGP_MEM             int
-#define DRM_AGP_KERN            struct no_agp_kern
-#endif
-
-#if !(__OS_HAS_MTRR)
-static __inline__ int mtrr_add(unsigned long base, unsigned long size,
-                              unsigned int type, char increment)
-{
-       return -ENODEV;
-}
-
-static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
-{
-       return -ENODEV;
-}
-
-#define MTRR_TYPE_WRCOMB     1
-
-#endif
-
-/** Other copying of data to kernel space */
-#define DRM_COPY_FROM_USER(arg1, arg2, arg3)           \
-       copy_from_user(arg1, arg2, arg3)
-/** Other copying of data from kernel space */
-#define DRM_COPY_TO_USER(arg1, arg2, arg3)             \
-       copy_to_user(arg1, arg2, arg3)
-/* Macros for copyfrom user, but checking readability only once */
-#define DRM_VERIFYAREA_READ( uaddr, size )             \
-       (access_ok( VERIFY_READ, uaddr, size ) ? 0 : -EFAULT)
-#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \
-       __copy_from_user(arg1, arg2, arg3)
-#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3)   \
-       __copy_to_user(arg1, arg2, arg3)
-#define DRM_GET_USER_UNCHECKED(val, uaddr)             \
-       __get_user(val, uaddr)
-
-#define DRM_HZ HZ
-
-#define DRM_WAIT_ON( ret, queue, timeout, condition )          \
-do {                                                           \
-       DECLARE_WAITQUEUE(entry, current);                      \
-       unsigned long end = jiffies + (timeout);                \
-       add_wait_queue(&(queue), &entry);                       \
-                                                               \
-       for (;;) {                                              \
-               __set_current_state(TASK_INTERRUPTIBLE);        \
-               if (condition)                                  \
-                       break;                                  \
-               if (time_after_eq(jiffies, end)) {              \
-                       ret = -EBUSY;                           \
-                       break;                                  \
-               }                                               \
-               schedule_timeout((HZ/100 > 1) ? HZ/100 : 1);    \
-               if (signal_pending(current)) {                  \
-                       ret = -EINTR;                           \
-                       break;                                  \
-               }                                               \
-       }                                                       \
-       __set_current_state(TASK_RUNNING);                      \
-       remove_wait_queue(&(queue), &entry);                    \
-} while (0)
-
-#define DRM_WAKEUP( queue ) wake_up_interruptible( queue )
-#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c
deleted file mode 100644 (file)
index b55d5bc..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/* drm_pci.h -- PCI DMA memory management wrappers for DRM -*- linux-c -*- */
-/**
- * \file drm_pci.c
- * \brief Functions and ioctls to manage PCI memory
- *
- * \warning These interfaces aren't stable yet.
- *
- * \todo Implement the remaining ioctl's for the PCI pools.
- * \todo The wrappers here are so thin that they would be better off inlined..
- *
- * \author José Fonseca <jrfonseca@tungstengraphics.com>
- * \author Leif Delgass <ldelgass@retinalburn.net>
- */
-
-/*
- * Copyright 2003 José Fonseca.
- * Copyright 2003 Leif Delgass.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
- * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include "drmP.h"
-
-/**********************************************************************/
-/** \name PCI memory */
-/*@{*/
-
-/**
- * \brief Allocate a PCI consistent memory block, for DMA.
- */
-drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align,
-                               dma_addr_t maxaddr)
-{
-       drm_dma_handle_t *dmah;
-#if 1
-       unsigned long addr;
-       size_t sz;
-#endif
-#ifdef DRM_DEBUG_MEMORY
-       int area = DRM_MEM_DMA;
-
-       spin_lock(&drm_mem_lock);
-       if ((drm_ram_used >> PAGE_SHIFT)
-           > (DRM_RAM_PERCENT * drm_ram_available) / 100) {
-               spin_unlock(&drm_mem_lock);
-               return 0;
-       }
-       spin_unlock(&drm_mem_lock);
-#endif
-
-       /* pci_alloc_consistent only guarantees alignment to the smallest
-        * PAGE_SIZE order which is greater than or equal to the requested size.
-        * Return NULL here for now to make sure nobody tries for larger alignment
-        */
-       if (align > size)
-               return NULL;
-
-       if (pci_set_dma_mask(dev->pdev, maxaddr) != 0) {
-               DRM_ERROR("Setting pci dma mask failed\n");
-               return NULL;
-       }
-
-       dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
-       if (!dmah)
-               return NULL;
-
-       dmah->size = size;
-       dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP);
-
-#ifdef DRM_DEBUG_MEMORY
-       if (dmah->vaddr == NULL) {
-               spin_lock(&drm_mem_lock);
-               ++drm_mem_stats[area].fail_count;
-               spin_unlock(&drm_mem_lock);
-               kfree(dmah);
-               return NULL;
-       }
-
-       spin_lock(&drm_mem_lock);
-       ++drm_mem_stats[area].succeed_count;
-       drm_mem_stats[area].bytes_allocated += size;
-       drm_ram_used += size;
-       spin_unlock(&drm_mem_lock);
-#else
-       if (dmah->vaddr == NULL) {
-               kfree(dmah);
-               return NULL;
-       }
-#endif
-
-       memset(dmah->vaddr, 0, size);
-
-       /* XXX - Is virt_to_page() legal for consistent mem? */
-       /* Reserve */
-       for (addr = (unsigned long)dmah->vaddr, sz = size;
-            sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
-               SetPageReserved(virt_to_page(addr));
-       }
-
-       return dmah;
-}
-
-EXPORT_SYMBOL(drm_pci_alloc);
-
-/**
- * \brief Free a PCI consistent memory block without freeing its descriptor.
- *
- * This function is for internal use in the Linux-specific DRM core code.
- */
-void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
-{
-#if 1
-       unsigned long addr;
-       size_t sz;
-#endif
-#ifdef DRM_DEBUG_MEMORY
-       int area = DRM_MEM_DMA;
-       int alloc_count;
-       int free_count;
-#endif
-
-       if (!dmah->vaddr) {
-#ifdef DRM_DEBUG_MEMORY
-               DRM_MEM_ERROR(area, "Attempt to free address 0\n");
-#endif
-       } else {
-               /* XXX - Is virt_to_page() legal for consistent mem? */
-               /* Unreserve */
-               for (addr = (unsigned long)dmah->vaddr, sz = dmah->size;
-                    sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
-                       ClearPageReserved(virt_to_page(addr));
-               }
-               dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
-                                 dmah->busaddr);
-       }
-
-#ifdef DRM_DEBUG_MEMORY
-       spin_lock(&drm_mem_lock);
-       free_count = ++drm_mem_stats[area].free_count;
-       alloc_count = drm_mem_stats[area].succeed_count;
-       drm_mem_stats[area].bytes_freed += size;
-       drm_ram_used -= size;
-       spin_unlock(&drm_mem_lock);
-       if (free_count > alloc_count) {
-               DRM_MEM_ERROR(area,
-                             "Excess frees: %d frees, %d allocs\n",
-                             free_count, alloc_count);
-       }
-#endif
-
-}
-
-/**
- * \brief Free a PCI consistent memory block
- */
-void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
-{
-       __drm_pci_free(dev, dmah);
-       kfree(dmah);
-}
-
-EXPORT_SYMBOL(drm_pci_free);
-
-/*@}*/
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
deleted file mode 100644 (file)
index 135bd19..0000000
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
-   This file is auto-generated from the drm_pciids.txt in the DRM CVS
-   Please contact dri-devel@lists.sf.net to add new cards to this list
-*/
-#define radeon_PCI_IDS \
-       {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP}, \
-       {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \
-       {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-       {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-       {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-       {0x1002, 0x4147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-       {0x1002, 0x4148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-       {0x1002, 0x4149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-       {0x1002, 0x414A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-       {0x1002, 0x414B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-       {0x1002, 0x4150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-       {0x1002, 0x4151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-       {0x1002, 0x4152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-       {0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-       {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-       {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-       {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
-       {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \
-       {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-       {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-       {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
-       {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
-       {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-       {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-       {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-       {0x1002, 0x4E47, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
-       {0x1002, 0x4E48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-       {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-       {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-       {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
-       {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
-       {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
-       {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
-       {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
-       {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-       {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-       {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
-       {0x1002, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
-       {0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
-       {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
-       {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
-       {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
-       {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
-       {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x5954, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-       {0x1002, 0x5955, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-       {0x1002, 0x5974, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-       {0x1002, 0x5975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-       {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-       {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-       {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-       {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-       {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-       {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
-       {0x1002, 0x5a61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-       {0x1002, 0x5a62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
-       {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
-       {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x710A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x710B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x710C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x710E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x710F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7140, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7141, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7142, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7143, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x714A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x714B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x714C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x714D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x714E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x714F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x715E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x715F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7183, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7186, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7187, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7188, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x718A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x718B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x718C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x718D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x718F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7193, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7196, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x719B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x719F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71C0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71C2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71C3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71C4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71C5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71C6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71C7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71CD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71CE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71D2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71D4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71D5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71D6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x71DE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7244, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7245, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7246, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7247, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7248, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x724A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x724B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x724C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x724D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x724E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x724F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7280, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7281, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7283, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7284, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7287, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7289, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x728B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x728C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7290, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7291, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7293, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7297, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x791e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
-       {0x1002, 0x791f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
-       {0, 0, 0}
-
-#define r128_PCI_IDS \
-       {0x1002, 0x4c45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4c46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4d46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5041, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5042, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5044, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5045, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5046, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5047, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5048, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5049, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x504A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x504B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x504C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x504D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x504E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x504F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5245, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5246, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5247, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x524b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x524c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x534d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x544C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x5452, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0, 0, 0}
-
-#define mga_PCI_IDS \
-       {0x102b, 0x0520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \
-       {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \
-       {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G400}, \
-       {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G550}, \
-       {0, 0, 0}
-
-#define mach64_PCI_IDS \
-       {0x1002, 0x4749, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4742, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4744, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4c49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4c50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4c51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4c42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4c44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x474c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x474f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4752, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4753, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x474d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x474e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4c52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4c53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4c4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1002, 0x4c4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0, 0, 0}
-
-#define sisdrv_PCI_IDS \
-       {0x1039, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1039, 0x5300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1039, 0x6330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
-       {0x1039, 0x6351, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x18CA, 0x0040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
-       {0x18CA, 0x0042, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
-       {0, 0, 0}
-
-#define tdfx_PCI_IDS \
-       {0x121a, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x121a, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x121a, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x121a, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x121a, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x121a, 0x000b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0, 0, 0}
-
-#define viadrv_PCI_IDS \
-       {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \
-       {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1106, 0x3343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \
-       {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \
-       {0, 0, 0}
-
-#define i810_PCI_IDS \
-       {0x8086, 0x7121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x7123, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x7125, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x1132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0, 0, 0}
-
-#define i830_PCI_IDS \
-       {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0, 0, 0}
-
-#define gamma_PCI_IDS \
-       {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0, 0, 0}
-
-#define savage_PCI_IDS \
-       {0x5333, 0x8a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
-       {0x5333, 0x8a21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
-       {0x5333, 0x8a22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE4}, \
-       {0x5333, 0x8a23, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE4}, \
-       {0x5333, 0x8c10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
-       {0x5333, 0x8c11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
-       {0x5333, 0x8c12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
-       {0x5333, 0x8c13, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
-       {0x5333, 0x8c22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
-       {0x5333, 0x8c24, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
-       {0x5333, 0x8c26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
-       {0x5333, 0x8c2a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
-       {0x5333, 0x8c2b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
-       {0x5333, 0x8c2c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
-       {0x5333, 0x8c2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
-       {0x5333, 0x8c2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
-       {0x5333, 0x8c2f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
-       {0x5333, 0x8a25, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGE}, \
-       {0x5333, 0x8a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGE}, \
-       {0x5333, 0x8d01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_TWISTER}, \
-       {0x5333, 0x8d02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_TWISTER}, \
-       {0x5333, 0x8d03, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGEDDR}, \
-       {0x5333, 0x8d04, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGEDDR}, \
-       {0, 0, 0}
-
-#define ffb_PCI_IDS \
-       {0, 0, 0}
-
-#define i915_PCI_IDS \
-       {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x258a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x27ae, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2972, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x29b2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x29c2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x29d2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2a02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2a12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2a42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2e02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2e12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0x8086, 0x2e22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
-       {0, 0, 0}
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
deleted file mode 100644 (file)
index 93b1e04..0000000
+++ /dev/null
@@ -1,557 +0,0 @@
-/**
- * \file drm_proc.c
- * /proc support for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- *
- * \par Acknowledgements:
- *    Matthew J Sottek <matthew.j.sottek@intel.com> sent in a patch to fix
- *    the problem with the proc files not outputting all their information.
- */
-
-/*
- * Created: Mon Jan 11 09:48:47 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-
-static int drm_name_info(char *buf, char **start, off_t offset,
-                        int request, int *eof, void *data);
-static int drm_vm_info(char *buf, char **start, off_t offset,
-                      int request, int *eof, void *data);
-static int drm_clients_info(char *buf, char **start, off_t offset,
-                           int request, int *eof, void *data);
-static int drm_queues_info(char *buf, char **start, off_t offset,
-                          int request, int *eof, void *data);
-static int drm_bufs_info(char *buf, char **start, off_t offset,
-                        int request, int *eof, void *data);
-#if DRM_DEBUG_CODE
-static int drm_vma_info(char *buf, char **start, off_t offset,
-                       int request, int *eof, void *data);
-#endif
-
-/**
- * Proc file list.
- */
-static struct drm_proc_list {
-       const char *name;       /**< file name */
-       int (*f) (char *, char **, off_t, int, int *, void *);          /**< proc callback*/
-} drm_proc_list[] = {
-       {"name", drm_name_info},
-       {"mem", drm_mem_info},
-       {"vm", drm_vm_info},
-       {"clients", drm_clients_info},
-       {"queues", drm_queues_info},
-       {"bufs", drm_bufs_info},
-#if DRM_DEBUG_CODE
-       {"vma", drm_vma_info},
-#endif
-};
-
-#define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list)
-
-/**
- * Initialize the DRI proc filesystem for a device.
- *
- * \param dev DRM device.
- * \param minor device minor number.
- * \param root DRI proc dir entry.
- * \param dev_root resulting DRI device proc dir entry.
- * \return root entry pointer on success, or NULL on failure.
- *
- * Create the DRI proc root entry "/proc/dri", the device proc root entry
- * "/proc/dri/%minor%/", and each entry in proc_list as
- * "/proc/dri/%minor%/%name%".
- */
-int drm_proc_init(struct drm_minor *minor, int minor_id,
-                 struct proc_dir_entry *root)
-{
-       struct proc_dir_entry *ent;
-       int i, j;
-       char name[64];
-
-       sprintf(name, "%d", minor_id);
-       minor->dev_root = proc_mkdir(name, root);
-       if (!minor->dev_root) {
-               DRM_ERROR("Cannot create /proc/dri/%s\n", name);
-               return -1;
-       }
-
-       for (i = 0; i < DRM_PROC_ENTRIES; i++) {
-               ent = create_proc_entry(drm_proc_list[i].name,
-                                       S_IFREG | S_IRUGO, minor->dev_root);
-               if (!ent) {
-                       DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
-                                 name, drm_proc_list[i].name);
-                       for (j = 0; j < i; j++)
-                               remove_proc_entry(drm_proc_list[i].name,
-                                                 minor->dev_root);
-                       remove_proc_entry(name, root);
-                       minor->dev_root = NULL;
-                       return -1;
-               }
-               ent->read_proc = drm_proc_list[i].f;
-               ent->data = minor;
-       }
-
-       return 0;
-}
-
-/**
- * Cleanup the proc filesystem resources.
- *
- * \param minor device minor number.
- * \param root DRI proc dir entry.
- * \param dev_root DRI device proc dir entry.
- * \return always zero.
- *
- * Remove all proc entries created by proc_init().
- */
-int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
-{
-       int i;
-       char name[64];
-
-       if (!root || !minor->dev_root)
-               return 0;
-
-       for (i = 0; i < DRM_PROC_ENTRIES; i++)
-               remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
-       sprintf(name, "%d", minor->index);
-       remove_proc_entry(name, root);
-
-       return 0;
-}
-
-/**
- * Called when "/proc/dri/.../name" is read.
- *
- * \param buf output buffer.
- * \param start start of output data.
- * \param offset requested start offset.
- * \param request requested number of bytes.
- * \param eof whether there is no more data to return.
- * \param data private data.
- * \return number of written bytes.
- *
- * Prints the device name together with the bus id if available.
- */
-static int drm_name_info(char *buf, char **start, off_t offset, int request,
-                        int *eof, void *data)
-{
-       struct drm_minor *minor = (struct drm_minor *) data;
-       struct drm_device *dev = minor->dev;
-       int len = 0;
-
-       if (offset > DRM_PROC_LIMIT) {
-               *eof = 1;
-               return 0;
-       }
-
-       *start = &buf[offset];
-       *eof = 0;
-
-       if (dev->unique) {
-               DRM_PROC_PRINT("%s %s %s\n",
-                              dev->driver->pci_driver.name,
-                              pci_name(dev->pdev), dev->unique);
-       } else {
-               DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name,
-                              pci_name(dev->pdev));
-       }
-
-       if (len > request + offset)
-               return request;
-       *eof = 1;
-       return len - offset;
-}
-
-/**
- * Called when "/proc/dri/.../vm" is read.
- *
- * \param buf output buffer.
- * \param start start of output data.
- * \param offset requested start offset.
- * \param request requested number of bytes.
- * \param eof whether there is no more data to return.
- * \param data private data.
- * \return number of written bytes.
- *
- * Prints information about all mappings in drm_device::maplist.
- */
-static int drm__vm_info(char *buf, char **start, off_t offset, int request,
-                       int *eof, void *data)
-{
-       struct drm_minor *minor = (struct drm_minor *) data;
-       struct drm_device *dev = minor->dev;
-       int len = 0;
-       struct drm_map *map;
-       struct drm_map_list *r_list;
-
-       /* Hardcoded from _DRM_FRAME_BUFFER,
-          _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
-          _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
-       const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
-       const char *type;
-       int i;
-
-       if (offset > DRM_PROC_LIMIT) {
-               *eof = 1;
-               return 0;
-       }
-
-       *start = &buf[offset];
-       *eof = 0;
-
-       DRM_PROC_PRINT("slot     offset       size type flags    "
-                      "address mtrr\n\n");
-       i = 0;
-       list_for_each_entry(r_list, &dev->maplist, head) {
-               map = r_list->map;
-               if (!map)
-                       continue;
-               if (map->type < 0 || map->type > 5)
-                       type = "??";
-               else
-                       type = types[map->type];
-               DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08lx ",
-                              i,
-                              map->offset,
-                              map->size, type, map->flags,
-                              (unsigned long) r_list->user_token);
-               if (map->mtrr < 0) {
-                       DRM_PROC_PRINT("none\n");
-               } else {
-                       DRM_PROC_PRINT("%4d\n", map->mtrr);
-               }
-               i++;
-       }
-
-       if (len > request + offset)
-               return request;
-       *eof = 1;
-       return len - offset;
-}
-
-/**
- * Simply calls _vm_info() while holding the drm_device::struct_mutex lock.
- */
-static int drm_vm_info(char *buf, char **start, off_t offset, int request,
-                      int *eof, void *data)
-{
-       struct drm_minor *minor = (struct drm_minor *) data;
-       struct drm_device *dev = minor->dev;
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-       ret = drm__vm_info(buf, start, offset, request, eof, data);
-       mutex_unlock(&dev->struct_mutex);
-       return ret;
-}
-
-/**
- * Called when "/proc/dri/.../queues" is read.
- *
- * \param buf output buffer.
- * \param start start of output data.
- * \param offset requested start offset.
- * \param request requested number of bytes.
- * \param eof whether there is no more data to return.
- * \param data private data.
- * \return number of written bytes.
- */
-static int drm__queues_info(char *buf, char **start, off_t offset,
-                           int request, int *eof, void *data)
-{
-       struct drm_minor *minor = (struct drm_minor *) data;
-       struct drm_device *dev = minor->dev;
-       int len = 0;
-       int i;
-       struct drm_queue *q;
-
-       if (offset > DRM_PROC_LIMIT) {
-               *eof = 1;
-               return 0;
-       }
-
-       *start = &buf[offset];
-       *eof = 0;
-
-       DRM_PROC_PRINT("  ctx/flags   use   fin"
-                      "   blk/rw/rwf  wait    flushed     queued"
-                      "      locks\n\n");
-       for (i = 0; i < dev->queue_count; i++) {
-               q = dev->queuelist[i];
-               atomic_inc(&q->use_count);
-               DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
-                                  "%5d/0x%03x %5d %5d"
-                                  " %5d/%c%c/%c%c%c %5Zd\n",
-                                  i,
-                                  q->flags,
-                                  atomic_read(&q->use_count),
-                                  atomic_read(&q->finalization),
-                                  atomic_read(&q->block_count),
-                                  atomic_read(&q->block_read) ? 'r' : '-',
-                                  atomic_read(&q->block_write) ? 'w' : '-',
-                                  waitqueue_active(&q->read_queue) ? 'r' : '-',
-                                  waitqueue_active(&q->
-                                                   write_queue) ? 'w' : '-',
-                                  waitqueue_active(&q->
-                                                   flush_queue) ? 'f' : '-',
-                                  DRM_BUFCOUNT(&q->waitlist));
-               atomic_dec(&q->use_count);
-       }
-
-       if (len > request + offset)
-               return request;
-       *eof = 1;
-       return len - offset;
-}
-
-/**
- * Simply calls _queues_info() while holding the drm_device::struct_mutex lock.
- */
-static int drm_queues_info(char *buf, char **start, off_t offset, int request,
-                          int *eof, void *data)
-{
-       struct drm_minor *minor = (struct drm_minor *) data;
-       struct drm_device *dev = minor->dev;
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-       ret = drm__queues_info(buf, start, offset, request, eof, data);
-       mutex_unlock(&dev->struct_mutex);
-       return ret;
-}
-
-/**
- * Called when "/proc/dri/.../bufs" is read.
- *
- * \param buf output buffer.
- * \param start start of output data.
- * \param offset requested start offset.
- * \param request requested number of bytes.
- * \param eof whether there is no more data to return.
- * \param data private data.
- * \return number of written bytes.
- */
-static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
-                         int *eof, void *data)
-{
-       struct drm_minor *minor = (struct drm_minor *) data;
-       struct drm_device *dev = minor->dev;
-       int len = 0;
-       struct drm_device_dma *dma = dev->dma;
-       int i;
-
-       if (!dma || offset > DRM_PROC_LIMIT) {
-               *eof = 1;
-               return 0;
-       }
-
-       *start = &buf[offset];
-       *eof = 0;
-
-       DRM_PROC_PRINT(" o     size count  free  segs pages    kB\n\n");
-       for (i = 0; i <= DRM_MAX_ORDER; i++) {
-               if (dma->bufs[i].buf_count)
-                       DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
-                                      i,
-                                      dma->bufs[i].buf_size,
-                                      dma->bufs[i].buf_count,
-                                      atomic_read(&dma->bufs[i]
-                                                  .freelist.count),
-                                      dma->bufs[i].seg_count,
-                                      dma->bufs[i].seg_count
-                                      * (1 << dma->bufs[i].page_order),
-                                      (dma->bufs[i].seg_count
-                                       * (1 << dma->bufs[i].page_order))
-                                      * PAGE_SIZE / 1024);
-       }
-       DRM_PROC_PRINT("\n");
-       for (i = 0; i < dma->buf_count; i++) {
-               if (i && !(i % 32))
-                       DRM_PROC_PRINT("\n");
-               DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
-       }
-       DRM_PROC_PRINT("\n");
-
-       if (len > request + offset)
-               return request;
-       *eof = 1;
-       return len - offset;
-}
-
-/**
- * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock.
- */
-static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
-                        int *eof, void *data)
-{
-       struct drm_minor *minor = (struct drm_minor *) data;
-       struct drm_device *dev = minor->dev;
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-       ret = drm__bufs_info(buf, start, offset, request, eof, data);
-       mutex_unlock(&dev->struct_mutex);
-       return ret;
-}
-
-/**
- * Called when "/proc/dri/.../clients" is read.
- *
- * \param buf output buffer.
- * \param start start of output data.
- * \param offset requested start offset.
- * \param request requested number of bytes.
- * \param eof whether there is no more data to return.
- * \param data private data.
- * \return number of written bytes.
- */
-static int drm__clients_info(char *buf, char **start, off_t offset,
-                            int request, int *eof, void *data)
-{
-       struct drm_minor *minor = (struct drm_minor *) data;
-       struct drm_device *dev = minor->dev;
-       int len = 0;
-       struct drm_file *priv;
-
-       if (offset > DRM_PROC_LIMIT) {
-               *eof = 1;
-               return 0;
-       }
-
-       *start = &buf[offset];
-       *eof = 0;
-
-       DRM_PROC_PRINT("a dev   pid    uid      magic     ioctls\n\n");
-       list_for_each_entry(priv, &dev->filelist, lhead) {
-               DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
-                              priv->authenticated ? 'y' : 'n',
-                              priv->minor->index,
-                              priv->pid,
-                              priv->uid, priv->magic, priv->ioctl_count);
-       }
-
-       if (len > request + offset)
-               return request;
-       *eof = 1;
-       return len - offset;
-}
-
-/**
- * Simply calls _clients_info() while holding the drm_device::struct_mutex lock.
- */
-static int drm_clients_info(char *buf, char **start, off_t offset,
-                           int request, int *eof, void *data)
-{
-       struct drm_minor *minor = (struct drm_minor *) data;
-       struct drm_device *dev = minor->dev;
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-       ret = drm__clients_info(buf, start, offset, request, eof, data);
-       mutex_unlock(&dev->struct_mutex);
-       return ret;
-}
-
-#if DRM_DEBUG_CODE
-
-static int drm__vma_info(char *buf, char **start, off_t offset, int request,
-                        int *eof, void *data)
-{
-       struct drm_minor *minor = (struct drm_minor *) data;
-       struct drm_device *dev = minor->dev;
-       int len = 0;
-       struct drm_vma_entry *pt;
-       struct vm_area_struct *vma;
-#if defined(__i386__)
-       unsigned int pgprot;
-#endif
-
-       if (offset > DRM_PROC_LIMIT) {
-               *eof = 1;
-               return 0;
-       }
-
-       *start = &buf[offset];
-       *eof = 0;
-
-       DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
-                      atomic_read(&dev->vma_count),
-                      high_memory, virt_to_phys(high_memory));
-       list_for_each_entry(pt, &dev->vmalist, head) {
-               if (!(vma = pt->vma))
-                       continue;
-               DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
-                              pt->pid,
-                              vma->vm_start,
-                              vma->vm_end,
-                              vma->vm_flags & VM_READ ? 'r' : '-',
-                              vma->vm_flags & VM_WRITE ? 'w' : '-',
-                              vma->vm_flags & VM_EXEC ? 'x' : '-',
-                              vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
-                              vma->vm_flags & VM_LOCKED ? 'l' : '-',
-                              vma->vm_flags & VM_IO ? 'i' : '-',
-                              vma->vm_pgoff);
-
-#if defined(__i386__)
-               pgprot = pgprot_val(vma->vm_page_prot);
-               DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
-                              pgprot & _PAGE_PRESENT ? 'p' : '-',
-                              pgprot & _PAGE_RW ? 'w' : 'r',
-                              pgprot & _PAGE_USER ? 'u' : 's',
-                              pgprot & _PAGE_PWT ? 't' : 'b',
-                              pgprot & _PAGE_PCD ? 'u' : 'c',
-                              pgprot & _PAGE_ACCESSED ? 'a' : '-',
-                              pgprot & _PAGE_DIRTY ? 'd' : '-',
-                              pgprot & _PAGE_PSE ? 'm' : 'k',
-                              pgprot & _PAGE_GLOBAL ? 'g' : 'l');
-#endif
-               DRM_PROC_PRINT("\n");
-       }
-
-       if (len > request + offset)
-               return request;
-       *eof = 1;
-       return len - offset;
-}
-
-static int drm_vma_info(char *buf, char **start, off_t offset, int request,
-                       int *eof, void *data)
-{
-       struct drm_minor *minor = (struct drm_minor *) data;
-       struct drm_device *dev = minor->dev;
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-       ret = drm__vma_info(buf, start, offset, request, eof, data);
-       mutex_unlock(&dev->struct_mutex);
-       return ret;
-}
-#endif
diff --git a/drivers/char/drm/drm_sarea.h b/drivers/char/drm/drm_sarea.h
deleted file mode 100644 (file)
index 4800373..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * \file drm_sarea.h
- * \brief SAREA definitions
- *
- * \author Michel Dänzer <michel@daenzer.net>
- */
-
-/*
- * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _DRM_SAREA_H_
-#define _DRM_SAREA_H_
-
-#include "drm.h"
-
-/* SAREA area needs to be at least a page */
-#if defined(__alpha__)
-#define SAREA_MAX                       0x2000
-#elif defined(__ia64__)
-#define SAREA_MAX                       0x10000        /* 64kB */
-#else
-/* Intel 830M driver needs at least 8k SAREA */
-#define SAREA_MAX                       0x2000
-#endif
-
-/** Maximum number of drawables in the SAREA */
-#define SAREA_MAX_DRAWABLES            256
-
-#define SAREA_DRAWABLE_CLAIMED_ENTRY    0x80000000
-
-/** SAREA drawable */
-struct drm_sarea_drawable {
-       unsigned int stamp;
-       unsigned int flags;
-};
-
-/** SAREA frame */
-struct drm_sarea_frame {
-       unsigned int x;
-       unsigned int y;
-       unsigned int width;
-       unsigned int height;
-       unsigned int fullscreen;
-};
-
-/** SAREA */
-struct drm_sarea {
-    /** first thing is always the DRM locking structure */
-       struct drm_hw_lock lock;
-    /** \todo Use readers/writer lock for drm_sarea::drawable_lock */
-       struct drm_hw_lock drawable_lock;
-       struct drm_sarea_drawable drawableTable[SAREA_MAX_DRAWABLES];   /**< drawables */
-       struct drm_sarea_frame frame;   /**< frame */
-       drm_context_t dummy_context;
-};
-
-#ifndef __KERNEL__
-typedef struct drm_sarea_drawable drm_sarea_drawable_t;
-typedef struct drm_sarea_frame drm_sarea_frame_t;
-typedef struct drm_sarea drm_sarea_t;
-#endif
-
-#endif                         /* _DRM_SAREA_H_ */
diff --git a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c
deleted file mode 100644 (file)
index b2b0f3d..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-/**
- * \file drm_scatter.c
- * IOCTLs to manage scatter/gather memory
- *
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
- *
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/vmalloc.h>
-#include "drmP.h"
-
-#define DEBUG_SCATTER 0
-
-static inline void *drm_vmalloc_dma(unsigned long size)
-{
-#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE)
-       return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL | _PAGE_NO_CACHE);
-#else
-       return vmalloc_32(size);
-#endif
-}
-
-void drm_sg_cleanup(struct drm_sg_mem * entry)
-{
-       struct page *page;
-       int i;
-
-       for (i = 0; i < entry->pages; i++) {
-               page = entry->pagelist[i];
-               if (page)
-                       ClearPageReserved(page);
-       }
-
-       vfree(entry->virtual);
-
-       drm_free(entry->busaddr,
-                entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
-       drm_free(entry->pagelist,
-                entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES);
-       drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
-}
-
-#ifdef _LP64
-# define ScatterHandle(x) (unsigned int)((x >> 32) + (x & ((1L << 32) - 1)))
-#else
-# define ScatterHandle(x) (unsigned int)(x)
-#endif
-
-int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
-{
-       struct drm_sg_mem *entry;
-       unsigned long pages, i, j;
-
-       DRM_DEBUG("\n");
-
-       if (!drm_core_check_feature(dev, DRIVER_SG))
-               return -EINVAL;
-
-       if (dev->sg)
-               return -EINVAL;
-
-       entry = drm_alloc(sizeof(*entry), DRM_MEM_SGLISTS);
-       if (!entry)
-               return -ENOMEM;
-
-       memset(entry, 0, sizeof(*entry));
-       pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
-       DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages);
-
-       entry->pages = pages;
-       entry->pagelist = drm_alloc(pages * sizeof(*entry->pagelist),
-                                   DRM_MEM_PAGES);
-       if (!entry->pagelist) {
-               drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
-               return -ENOMEM;
-       }
-
-       memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
-
-       entry->busaddr = drm_alloc(pages * sizeof(*entry->busaddr),
-                                  DRM_MEM_PAGES);
-       if (!entry->busaddr) {
-               drm_free(entry->pagelist,
-                        entry->pages * sizeof(*entry->pagelist),
-                        DRM_MEM_PAGES);
-               drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
-               return -ENOMEM;
-       }
-       memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
-
-       entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT);
-       if (!entry->virtual) {
-               drm_free(entry->busaddr,
-                        entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
-               drm_free(entry->pagelist,
-                        entry->pages * sizeof(*entry->pagelist),
-                        DRM_MEM_PAGES);
-               drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
-               return -ENOMEM;
-       }
-
-       /* This also forces the mapping of COW pages, so our page list
-        * will be valid.  Please don't remove it...
-        */
-       memset(entry->virtual, 0, pages << PAGE_SHIFT);
-
-       entry->handle = ScatterHandle((unsigned long)entry->virtual);
-
-       DRM_DEBUG("handle  = %08lx\n", entry->handle);
-       DRM_DEBUG("virtual = %p\n", entry->virtual);
-
-       for (i = (unsigned long)entry->virtual, j = 0; j < pages;
-            i += PAGE_SIZE, j++) {
-               entry->pagelist[j] = vmalloc_to_page((void *)i);
-               if (!entry->pagelist[j])
-                       goto failed;
-               SetPageReserved(entry->pagelist[j]);
-       }
-
-       request->handle = entry->handle;
-
-       dev->sg = entry;
-
-#if DEBUG_SCATTER
-       /* Verify that each page points to its virtual address, and vice
-        * versa.
-        */
-       {
-               int error = 0;
-
-               for (i = 0; i < pages; i++) {
-                       unsigned long *tmp;
-
-                       tmp = page_address(entry->pagelist[i]);
-                       for (j = 0;
-                            j < PAGE_SIZE / sizeof(unsigned long);
-                            j++, tmp++) {
-                               *tmp = 0xcafebabe;
-                       }
-                       tmp = (unsigned long *)((u8 *) entry->virtual +
-                                               (PAGE_SIZE * i));
-                       for (j = 0;
-                            j < PAGE_SIZE / sizeof(unsigned long);
-                            j++, tmp++) {
-                               if (*tmp != 0xcafebabe && error == 0) {
-                                       error = 1;
-                                       DRM_ERROR("Scatter allocation error, "
-                                                 "pagelist does not match "
-                                                 "virtual mapping\n");
-                               }
-                       }
-                       tmp = page_address(entry->pagelist[i]);
-                       for (j = 0;
-                            j < PAGE_SIZE / sizeof(unsigned long);
-                            j++, tmp++) {
-                               *tmp = 0;
-                       }
-               }
-               if (error == 0)
-                       DRM_ERROR("Scatter allocation matches pagelist\n");
-       }
-#endif
-
-       return 0;
-
-      failed:
-       drm_sg_cleanup(entry);
-       return -ENOMEM;
-}
-EXPORT_SYMBOL(drm_sg_alloc);
-
-
-int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       struct drm_scatter_gather *request = data;
-
-       return drm_sg_alloc(dev, request);
-
-}
-
-int drm_sg_free(struct drm_device *dev, void *data,
-               struct drm_file *file_priv)
-{
-       struct drm_scatter_gather *request = data;
-       struct drm_sg_mem *entry;
-
-       if (!drm_core_check_feature(dev, DRIVER_SG))
-               return -EINVAL;
-
-       entry = dev->sg;
-       dev->sg = NULL;
-
-       if (!entry || entry->handle != request->handle)
-               return -EINVAL;
-
-       DRM_DEBUG("virtual  = %p\n", entry->virtual);
-
-       drm_sg_cleanup(entry);
-
-       return 0;
-}
diff --git a/drivers/char/drm/drm_sman.c b/drivers/char/drm/drm_sman.c
deleted file mode 100644 (file)
index 926f146..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck., ND., USA.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- *
- **************************************************************************/
-/*
- * Simple memory manager interface that keeps track on allocate regions on a
- * per "owner" basis. All regions associated with an "owner" can be released
- * with a simple call. Typically if the "owner" exists. The owner is any
- * "unsigned long" identifier. Can typically be a pointer to a file private
- * struct or a context identifier.
- *
- * Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#include "drm_sman.h"
-
-struct drm_owner_item {
-       struct drm_hash_item owner_hash;
-       struct list_head sman_list;
-       struct list_head mem_blocks;
-};
-
-void drm_sman_takedown(struct drm_sman * sman)
-{
-       drm_ht_remove(&sman->user_hash_tab);
-       drm_ht_remove(&sman->owner_hash_tab);
-       if (sman->mm)
-               drm_free(sman->mm, sman->num_managers * sizeof(*sman->mm),
-                        DRM_MEM_MM);
-}
-
-EXPORT_SYMBOL(drm_sman_takedown);
-
-int
-drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
-             unsigned int user_order, unsigned int owner_order)
-{
-       int ret = 0;
-
-       sman->mm = (struct drm_sman_mm *) drm_calloc(num_managers, sizeof(*sman->mm),
-                                               DRM_MEM_MM);
-       if (!sman->mm) {
-               ret = -ENOMEM;
-               goto out;
-       }
-       sman->num_managers = num_managers;
-       INIT_LIST_HEAD(&sman->owner_items);
-       ret = drm_ht_create(&sman->owner_hash_tab, owner_order);
-       if (ret)
-               goto out1;
-       ret = drm_ht_create(&sman->user_hash_tab, user_order);
-       if (!ret)
-               goto out;
-
-       drm_ht_remove(&sman->owner_hash_tab);
-out1:
-       drm_free(sman->mm, num_managers * sizeof(*sman->mm), DRM_MEM_MM);
-out:
-       return ret;
-}
-
-EXPORT_SYMBOL(drm_sman_init);
-
-static void *drm_sman_mm_allocate(void *private, unsigned long size,
-                                 unsigned alignment)
-{
-       struct drm_mm *mm = (struct drm_mm *) private;
-       struct drm_mm_node *tmp;
-
-       tmp = drm_mm_search_free(mm, size, alignment, 1);
-       if (!tmp) {
-               return NULL;
-       }
-       tmp = drm_mm_get_block(tmp, size, alignment);
-       return tmp;
-}
-
-static void drm_sman_mm_free(void *private, void *ref)
-{
-       struct drm_mm_node *node = (struct drm_mm_node *) ref;
-
-       drm_mm_put_block(node);
-}
-
-static void drm_sman_mm_destroy(void *private)
-{
-       struct drm_mm *mm = (struct drm_mm *) private;
-       drm_mm_takedown(mm);
-       drm_free(mm, sizeof(*mm), DRM_MEM_MM);
-}
-
-static unsigned long drm_sman_mm_offset(void *private, void *ref)
-{
-       struct drm_mm_node *node = (struct drm_mm_node *) ref;
-       return node->start;
-}
-
-int
-drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
-                  unsigned long start, unsigned long size)
-{
-       struct drm_sman_mm *sman_mm;
-       struct drm_mm *mm;
-       int ret;
-
-       BUG_ON(manager >= sman->num_managers);
-
-       sman_mm = &sman->mm[manager];
-       mm = drm_calloc(1, sizeof(*mm), DRM_MEM_MM);
-       if (!mm) {
-               return -ENOMEM;
-       }
-       sman_mm->private = mm;
-       ret = drm_mm_init(mm, start, size);
-
-       if (ret) {
-               drm_free(mm, sizeof(*mm), DRM_MEM_MM);
-               return ret;
-       }
-
-       sman_mm->allocate = drm_sman_mm_allocate;
-       sman_mm->free = drm_sman_mm_free;
-       sman_mm->destroy = drm_sman_mm_destroy;
-       sman_mm->offset = drm_sman_mm_offset;
-
-       return 0;
-}
-
-EXPORT_SYMBOL(drm_sman_set_range);
-
-int
-drm_sman_set_manager(struct drm_sman * sman, unsigned int manager,
-                    struct drm_sman_mm * allocator)
-{
-       BUG_ON(manager >= sman->num_managers);
-       sman->mm[manager] = *allocator;
-
-       return 0;
-}
-EXPORT_SYMBOL(drm_sman_set_manager);
-
-static struct drm_owner_item *drm_sman_get_owner_item(struct drm_sman * sman,
-                                                unsigned long owner)
-{
-       int ret;
-       struct drm_hash_item *owner_hash_item;
-       struct drm_owner_item *owner_item;
-
-       ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item);
-       if (!ret) {
-               return drm_hash_entry(owner_hash_item, struct drm_owner_item,
-                                     owner_hash);
-       }
-
-       owner_item = drm_calloc(1, sizeof(*owner_item), DRM_MEM_MM);
-       if (!owner_item)
-               goto out;
-
-       INIT_LIST_HEAD(&owner_item->mem_blocks);
-       owner_item->owner_hash.key = owner;
-       if (drm_ht_insert_item(&sman->owner_hash_tab, &owner_item->owner_hash))
-               goto out1;
-
-       list_add_tail(&owner_item->sman_list, &sman->owner_items);
-       return owner_item;
-
-out1:
-       drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
-out:
-       return NULL;
-}
-
-struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int manager,
-                                   unsigned long size, unsigned alignment,
-                                   unsigned long owner)
-{
-       void *tmp;
-       struct drm_sman_mm *sman_mm;
-       struct drm_owner_item *owner_item;
-       struct drm_memblock_item *memblock;
-
-       BUG_ON(manager >= sman->num_managers);
-
-       sman_mm = &sman->mm[manager];
-       tmp = sman_mm->allocate(sman_mm->private, size, alignment);
-
-       if (!tmp) {
-               return NULL;
-       }
-
-       memblock = drm_calloc(1, sizeof(*memblock), DRM_MEM_MM);
-
-       if (!memblock)
-               goto out;
-
-       memblock->mm_info = tmp;
-       memblock->mm = sman_mm;
-       memblock->sman = sman;
-
-       if (drm_ht_just_insert_please
-           (&sman->user_hash_tab, &memblock->user_hash,
-            (unsigned long)memblock, 32, 0, 0))
-               goto out1;
-
-       owner_item = drm_sman_get_owner_item(sman, owner);
-       if (!owner_item)
-               goto out2;
-
-       list_add_tail(&memblock->owner_list, &owner_item->mem_blocks);
-
-       return memblock;
-
-out2:
-       drm_ht_remove_item(&sman->user_hash_tab, &memblock->user_hash);
-out1:
-       drm_free(memblock, sizeof(*memblock), DRM_MEM_MM);
-out:
-       sman_mm->free(sman_mm->private, tmp);
-
-       return NULL;
-}
-
-EXPORT_SYMBOL(drm_sman_alloc);
-
-static void drm_sman_free(struct drm_memblock_item *item)
-{
-       struct drm_sman *sman = item->sman;
-
-       list_del(&item->owner_list);
-       drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
-       item->mm->free(item->mm->private, item->mm_info);
-       drm_free(item, sizeof(*item), DRM_MEM_MM);
-}
-
-int drm_sman_free_key(struct drm_sman *sman, unsigned int key)
-{
-       struct drm_hash_item *hash_item;
-       struct drm_memblock_item *memblock_item;
-
-       if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item))
-               return -EINVAL;
-
-       memblock_item = drm_hash_entry(hash_item, struct drm_memblock_item,
-                                      user_hash);
-       drm_sman_free(memblock_item);
-       return 0;
-}
-
-EXPORT_SYMBOL(drm_sman_free_key);
-
-static void drm_sman_remove_owner(struct drm_sman *sman,
-                                 struct drm_owner_item *owner_item)
-{
-       list_del(&owner_item->sman_list);
-       drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
-       drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
-}
-
-int drm_sman_owner_clean(struct drm_sman *sman, unsigned long owner)
-{
-
-       struct drm_hash_item *hash_item;
-       struct drm_owner_item *owner_item;
-
-       if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
-               return -1;
-       }
-
-       owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
-       if (owner_item->mem_blocks.next == &owner_item->mem_blocks) {
-               drm_sman_remove_owner(sman, owner_item);
-               return -1;
-       }
-
-       return 0;
-}
-
-EXPORT_SYMBOL(drm_sman_owner_clean);
-
-static void drm_sman_do_owner_cleanup(struct drm_sman *sman,
-                                     struct drm_owner_item *owner_item)
-{
-       struct drm_memblock_item *entry, *next;
-
-       list_for_each_entry_safe(entry, next, &owner_item->mem_blocks,
-                                owner_list) {
-               drm_sman_free(entry);
-       }
-       drm_sman_remove_owner(sman, owner_item);
-}
-
-void drm_sman_owner_cleanup(struct drm_sman *sman, unsigned long owner)
-{
-
-       struct drm_hash_item *hash_item;
-       struct drm_owner_item *owner_item;
-
-       if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
-
-               return;
-       }
-
-       owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
-       drm_sman_do_owner_cleanup(sman, owner_item);
-}
-
-EXPORT_SYMBOL(drm_sman_owner_cleanup);
-
-void drm_sman_cleanup(struct drm_sman *sman)
-{
-       struct drm_owner_item *entry, *next;
-       unsigned int i;
-       struct drm_sman_mm *sman_mm;
-
-       list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) {
-               drm_sman_do_owner_cleanup(sman, entry);
-       }
-       if (sman->mm) {
-               for (i = 0; i < sman->num_managers; ++i) {
-                       sman_mm = &sman->mm[i];
-                       if (sman_mm->private) {
-                               sman_mm->destroy(sman_mm->private);
-                               sman_mm->private = NULL;
-                       }
-               }
-       }
-}
-
-EXPORT_SYMBOL(drm_sman_cleanup);
diff --git a/drivers/char/drm/drm_sman.h b/drivers/char/drm/drm_sman.h
deleted file mode 100644 (file)
index 08ecf83..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- **************************************************************************/
-/*
- * Simple memory MANager interface that keeps track on allocate regions on a
- * per "owner" basis. All regions associated with an "owner" can be released
- * with a simple call. Typically if the "owner" exists. The owner is any
- * "unsigned long" identifier. Can typically be a pointer to a file private
- * struct or a context identifier.
- *
- * Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#ifndef DRM_SMAN_H
-#define DRM_SMAN_H
-
-#include "drmP.h"
-#include "drm_hashtab.h"
-
-/*
- * A class that is an abstration of a simple memory allocator.
- * The sman implementation provides a default such allocator
- * using the drm_mm.c implementation. But the user can replace it.
- * See the SiS implementation, which may use the SiS FB kernel module
- * for memory management.
- */
-
-struct drm_sman_mm {
-       /* private info. If allocated, needs to be destroyed by the destroy
-          function */
-       void *private;
-
-       /* Allocate a memory block with given size and alignment.
-          Return an opaque reference to the memory block */
-
-       void *(*allocate) (void *private, unsigned long size,
-                          unsigned alignment);
-
-       /* Free a memory block. "ref" is the opaque reference that we got from
-          the "alloc" function */
-
-       void (*free) (void *private, void *ref);
-
-       /* Free all resources associated with this allocator */
-
-       void (*destroy) (void *private);
-
-       /* Return a memory offset from the opaque reference returned from the
-          "alloc" function */
-
-       unsigned long (*offset) (void *private, void *ref);
-};
-
-struct drm_memblock_item {
-       struct list_head owner_list;
-       struct drm_hash_item user_hash;
-       void *mm_info;
-       struct drm_sman_mm *mm;
-       struct drm_sman *sman;
-};
-
-struct drm_sman {
-       struct drm_sman_mm *mm;
-       int num_managers;
-       struct drm_open_hash owner_hash_tab;
-       struct drm_open_hash user_hash_tab;
-       struct list_head owner_items;
-};
-
-/*
- * Take down a memory manager. This function should only be called after a
- * successful init and after a call to drm_sman_cleanup.
- */
-
-extern void drm_sman_takedown(struct drm_sman * sman);
-
-/*
- * Allocate structures for a manager.
- * num_managers are the number of memory pools to manage. (VRAM, AGP, ....)
- * user_order is the log2 of the number of buckets in the user hash table.
- *         set this to approximately log2 of the max number of memory regions
- *         that will be allocated for _all_ pools together.
- * owner_order is the log2 of the number of buckets in the owner hash table.
- *         set this to approximately log2 of
- *         the number of client file connections that will
- *         be using the manager.
- *
- */
-
-extern int drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
-                        unsigned int user_order, unsigned int owner_order);
-
-/*
- * Initialize a drm_mm.c allocator. Should be called only once for each
- * manager unless a customized allogator is used.
- */
-
-extern int drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
-                             unsigned long start, unsigned long size);
-
-/*
- * Initialize a customized allocator for one of the managers.
- * (See the SiS module). The object pointed to by "allocator" is copied,
- * so it can be destroyed after this call.
- */
-
-extern int drm_sman_set_manager(struct drm_sman * sman, unsigned int mananger,
-                               struct drm_sman_mm * allocator);
-
-/*
- * Allocate a memory block. Aligment is not implemented yet.
- */
-
-extern struct drm_memblock_item *drm_sman_alloc(struct drm_sman * sman,
-                                               unsigned int manager,
-                                               unsigned long size,
-                                               unsigned alignment,
-                                               unsigned long owner);
-/*
- * Free a memory block identified by its user hash key.
- */
-
-extern int drm_sman_free_key(struct drm_sman * sman, unsigned int key);
-
-/*
- * returns 1 iff there are no stale memory blocks associated with this owner.
- * Typically called to determine if we need to idle the hardware and call
- * drm_sman_owner_cleanup. If there are no stale memory blocks, it removes all
- * resources associated with owner.
- */
-
-extern int drm_sman_owner_clean(struct drm_sman * sman, unsigned long owner);
-
-/*
- * Frees all stale memory blocks associated with this owner. Note that this
- * requires that the hardware is finished with all blocks, so the graphics engine
- * should be idled before this call is made. This function also frees
- * any resources associated with "owner" and should be called when owner
- * is not going to be referenced anymore.
- */
-
-extern void drm_sman_owner_cleanup(struct drm_sman * sman, unsigned long owner);
-
-/*
- * Frees all stale memory blocks associated with the memory manager.
- * See idling above.
- */
-
-extern void drm_sman_cleanup(struct drm_sman * sman);
-
-#endif
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
deleted file mode 100644 (file)
index c2f584f..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-/**
- * \file drm_stub.h
- * Stub support
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- */
-
-/*
- * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
- *
- * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include "drmP.h"
-#include "drm_core.h"
-
-unsigned int drm_debug = 0;    /* 1 to enable debug output */
-EXPORT_SYMBOL(drm_debug);
-
-MODULE_AUTHOR(CORE_AUTHOR);
-MODULE_DESCRIPTION(CORE_DESC);
-MODULE_LICENSE("GPL and additional rights");
-MODULE_PARM_DESC(debug, "Enable debug output");
-
-module_param_named(debug, drm_debug, int, 0600);
-
-struct idr drm_minors_idr;
-
-struct class *drm_class;
-struct proc_dir_entry *drm_proc_root;
-
-static int drm_minor_get_id(struct drm_device *dev, int type)
-{
-       int new_id;
-       int ret;
-       int base = 0, limit = 63;
-
-again:
-       if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
-               DRM_ERROR("Out of memory expanding drawable idr\n");
-               return -ENOMEM;
-       }
-       mutex_lock(&dev->struct_mutex);
-       ret = idr_get_new_above(&drm_minors_idr, NULL,
-                               base, &new_id);
-       mutex_unlock(&dev->struct_mutex);
-       if (ret == -EAGAIN) {
-               goto again;
-       } else if (ret) {
-               return ret;
-       }
-
-       if (new_id >= limit) {
-               idr_remove(&drm_minors_idr, new_id);
-               return -EINVAL;
-       }
-       return new_id;
-}
-
-static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
-                          const struct pci_device_id *ent,
-                          struct drm_driver *driver)
-{
-       int retcode;
-
-       INIT_LIST_HEAD(&dev->filelist);
-       INIT_LIST_HEAD(&dev->ctxlist);
-       INIT_LIST_HEAD(&dev->vmalist);
-       INIT_LIST_HEAD(&dev->maplist);
-
-       spin_lock_init(&dev->count_lock);
-       spin_lock_init(&dev->drw_lock);
-       spin_lock_init(&dev->tasklet_lock);
-       spin_lock_init(&dev->lock.spinlock);
-       init_timer(&dev->timer);
-       mutex_init(&dev->struct_mutex);
-       mutex_init(&dev->ctxlist_mutex);
-
-       idr_init(&dev->drw_idr);
-
-       dev->pdev = pdev;
-       dev->pci_device = pdev->device;
-       dev->pci_vendor = pdev->vendor;
-
-#ifdef __alpha__
-       dev->hose = pdev->sysdata;
-#endif
-       dev->irq = pdev->irq;
-
-       if (drm_ht_create(&dev->map_hash, 12)) {
-               return -ENOMEM;
-       }
-
-       /* the DRM has 6 basic counters */
-       dev->counters = 6;
-       dev->types[0] = _DRM_STAT_LOCK;
-       dev->types[1] = _DRM_STAT_OPENS;
-       dev->types[2] = _DRM_STAT_CLOSES;
-       dev->types[3] = _DRM_STAT_IOCTLS;
-       dev->types[4] = _DRM_STAT_LOCKS;
-       dev->types[5] = _DRM_STAT_UNLOCKS;
-
-       dev->driver = driver;
-
-       if (drm_core_has_AGP(dev)) {
-               if (drm_device_is_agp(dev))
-                       dev->agp = drm_agp_init(dev);
-               if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
-                   && (dev->agp == NULL)) {
-                       DRM_ERROR("Cannot initialize the agpgart module.\n");
-                       retcode = -EINVAL;
-                       goto error_out_unreg;
-               }
-               if (drm_core_has_MTRR(dev)) {
-                       if (dev->agp)
-                               dev->agp->agp_mtrr =
-                                   mtrr_add(dev->agp->agp_info.aper_base,
-                                            dev->agp->agp_info.aper_size *
-                                            1024 * 1024, MTRR_TYPE_WRCOMB, 1);
-               }
-       }
-
-       if (dev->driver->load)
-               if ((retcode = dev->driver->load(dev, ent->driver_data)))
-                       goto error_out_unreg;
-
-       retcode = drm_ctxbitmap_init(dev);
-       if (retcode) {
-               DRM_ERROR("Cannot allocate memory for context bitmap.\n");
-               goto error_out_unreg;
-       }
-
-       return 0;
-
-      error_out_unreg:
-       drm_lastclose(dev);
-       return retcode;
-}
-
-
-/**
- * Get a secondary minor number.
- *
- * \param dev device data structure
- * \param sec-minor structure to hold the assigned minor
- * \return negative number on failure.
- *
- * Search an empty entry and initialize it to the given parameters, and
- * create the proc init entry via proc_init(). This routines assigns
- * minor numbers to secondary heads of multi-headed cards
- */
-static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
-{
-       struct drm_minor *new_minor;
-       int ret;
-       int minor_id;
-
-       DRM_DEBUG("\n");
-
-       minor_id = drm_minor_get_id(dev, type);
-       if (minor_id < 0)
-               return minor_id;
-
-       new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
-       if (!new_minor) {
-               ret = -ENOMEM;
-               goto err_idr;
-       }
-
-       new_minor->type = type;
-       new_minor->device = MKDEV(DRM_MAJOR, minor_id);
-       new_minor->dev = dev;
-       new_minor->index = minor_id;
-
-       idr_replace(&drm_minors_idr, new_minor, minor_id);
-
-       if (type == DRM_MINOR_LEGACY) {
-               ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
-               if (ret) {
-                       DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
-                       goto err_mem;
-               }
-       } else
-               new_minor->dev_root = NULL;
-
-       ret = drm_sysfs_device_add(new_minor);
-       if (ret) {
-               printk(KERN_ERR
-                      "DRM: Error sysfs_device_add.\n");
-               goto err_g2;
-       }
-       *minor = new_minor;
-
-       DRM_DEBUG("new minor assigned %d\n", minor_id);
-       return 0;
-
-
-err_g2:
-       if (new_minor->type == DRM_MINOR_LEGACY)
-               drm_proc_cleanup(new_minor, drm_proc_root);
-err_mem:
-       kfree(new_minor);
-err_idr:
-       idr_remove(&drm_minors_idr, minor_id);
-       *minor = NULL;
-       return ret;
-}
-
-/**
- * Register.
- *
- * \param pdev - PCI device structure
- * \param ent entry from the PCI ID table with device type flags
- * \return zero on success or a negative number on failure.
- *
- * Attempt to gets inter module "drm" information. If we are first
- * then register the character device and inter module information.
- * Try and register, if we fail to register, backout previous work.
- */
-int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
-               struct drm_driver *driver)
-{
-       struct drm_device *dev;
-       int ret;
-
-       DRM_DEBUG("\n");
-
-       dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
-       if (!dev)
-               return -ENOMEM;
-
-       ret = pci_enable_device(pdev);
-       if (ret)
-               goto err_g1;
-
-       pci_set_master(pdev);
-       if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
-               printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
-               goto err_g2;
-       }
-       if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
-               goto err_g2;
-
-       DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
-                driver->name, driver->major, driver->minor, driver->patchlevel,
-                driver->date, dev->primary->index);
-
-       return 0;
-
-err_g2:
-       pci_disable_device(pdev);
-err_g1:
-       drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
-       return ret;
-}
-
-/**
- * Put a device minor number.
- *
- * \param dev device data structure
- * \return always zero
- *
- * Cleans up the proc resources. If it is the last minor then release the foreign
- * "drm" data, otherwise unregisters the "drm" data, frees the dev list and
- * unregisters the character device.
- */
-int drm_put_dev(struct drm_device * dev)
-{
-       DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
-
-       if (dev->unique) {
-               drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
-               dev->unique = NULL;
-               dev->unique_len = 0;
-       }
-       if (dev->devname) {
-               drm_free(dev->devname, strlen(dev->devname) + 1,
-                        DRM_MEM_DRIVER);
-               dev->devname = NULL;
-       }
-       drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
-       return 0;
-}
-
-/**
- * Put a secondary minor number.
- *
- * \param sec_minor - structure to be released
- * \return always zero
- *
- * Cleans up the proc resources. Not legal for this to be the
- * last minor released.
- *
- */
-int drm_put_minor(struct drm_minor **minor_p)
-{
-       struct drm_minor *minor = *minor_p;
-       DRM_DEBUG("release secondary minor %d\n", minor->index);
-
-       if (minor->type == DRM_MINOR_LEGACY)
-               drm_proc_cleanup(minor, drm_proc_root);
-       drm_sysfs_device_remove(minor);
-
-       idr_remove(&drm_minors_idr, minor->index);
-
-       kfree(minor);
-       *minor_p = NULL;
-       return 0;
-}
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
deleted file mode 100644 (file)
index af211a0..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-
-/*
- * drm_sysfs.c - Modifications to drm_sysfs_class.c to support
- *               extra sysfs attribute from DRM. Normal drm_sysfs_class
- *               does not allow adding attributes.
- *
- * Copyright (c) 2004 Jon Smirl <jonsmirl@gmail.com>
- * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (c) 2003-2004 IBM Corp.
- *
- * This file is released under the GPLv2
- *
- */
-
-#include <linux/device.h>
-#include <linux/kdev_t.h>
-#include <linux/err.h>
-
-#include "drm_core.h"
-#include "drmP.h"
-
-#define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
-
-/**
- * drm_sysfs_suspend - DRM class suspend hook
- * @dev: Linux device to suspend
- * @state: power state to enter
- *
- * Just figures out what the actual struct drm_device associated with
- * @dev is and calls its suspend hook, if present.
- */
-static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
-{
-       struct drm_minor *drm_minor = to_drm_minor(dev);
-       struct drm_device *drm_dev = drm_minor->dev;
-
-       if (drm_dev->driver->suspend)
-               return drm_dev->driver->suspend(drm_dev, state);
-
-       return 0;
-}
-
-/**
- * drm_sysfs_resume - DRM class resume hook
- * @dev: Linux device to resume
- *
- * Just figures out what the actual struct drm_device associated with
- * @dev is and calls its resume hook, if present.
- */
-static int drm_sysfs_resume(struct device *dev)
-{
-       struct drm_minor *drm_minor = to_drm_minor(dev);
-       struct drm_device *drm_dev = drm_minor->dev;
-
-       if (drm_dev->driver->resume)
-               return drm_dev->driver->resume(drm_dev);
-
-       return 0;
-}
-
-/* Display the version of drm_core. This doesn't work right in current design */
-static ssize_t version_show(struct class *dev, char *buf)
-{
-       return sprintf(buf, "%s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR,
-                      CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
-}
-
-static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
-
-/**
- * drm_sysfs_create - create a struct drm_sysfs_class structure
- * @owner: pointer to the module that is to "own" this struct drm_sysfs_class
- * @name: pointer to a string for the name of this class.
- *
- * This is used to create DRM class pointer that can then be used
- * in calls to drm_sysfs_device_add().
- *
- * Note, the pointer created here is to be destroyed when finished by making a
- * call to drm_sysfs_destroy().
- */
-struct class *drm_sysfs_create(struct module *owner, char *name)
-{
-       struct class *class;
-       int err;
-
-       class = class_create(owner, name);
-       if (IS_ERR(class)) {
-               err = PTR_ERR(class);
-               goto err_out;
-       }
-
-       class->suspend = drm_sysfs_suspend;
-       class->resume = drm_sysfs_resume;
-
-       err = class_create_file(class, &class_attr_version);
-       if (err)
-               goto err_out_class;
-
-       return class;
-
-err_out_class:
-       class_destroy(class);
-err_out:
-       return ERR_PTR(err);
-}
-
-/**
- * drm_sysfs_destroy - destroys DRM class
- *
- * Destroy the DRM device class.
- */
-void drm_sysfs_destroy(void)
-{
-       if ((drm_class == NULL) || (IS_ERR(drm_class)))
-               return;
-       class_remove_file(drm_class, &class_attr_version);
-       class_destroy(drm_class);
-}
-
-static ssize_t show_dri(struct device *device, struct device_attribute *attr,
-                       char *buf)
-{
-       struct drm_minor *drm_minor = to_drm_minor(device);
-       struct drm_device *drm_dev = drm_minor->dev;
-       if (drm_dev->driver->dri_library_name)
-               return drm_dev->driver->dri_library_name(drm_dev, buf);
-       return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name);
-}
-
-static struct device_attribute device_attrs[] = {
-       __ATTR(dri_library_name, S_IRUGO, show_dri, NULL),
-};
-
-/**
- * drm_sysfs_device_release - do nothing
- * @dev: Linux device
- *
- * Normally, this would free the DRM device associated with @dev, along
- * with cleaning up any other stuff.  But we do that in the DRM core, so
- * this function can just return and hope that the core does its job.
- */
-static void drm_sysfs_device_release(struct device *dev)
-{
-       return;
-}
-
-/**
- * drm_sysfs_device_add - adds a class device to sysfs for a character driver
- * @dev: DRM device to be added
- * @head: DRM head in question
- *
- * Add a DRM device to the DRM's device model class.  We use @dev's PCI device
- * as the parent for the Linux device, and make sure it has a file containing
- * the driver we're using (for userspace compatibility).
- */
-int drm_sysfs_device_add(struct drm_minor *minor)
-{
-       int err;
-       int i, j;
-       char *minor_str;
-
-       minor->kdev.parent = &minor->dev->pdev->dev;
-       minor->kdev.class = drm_class;
-       minor->kdev.release = drm_sysfs_device_release;
-       minor->kdev.devt = minor->device;
-       minor_str = "card%d";
-
-       snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index);
-
-       err = device_register(&minor->kdev);
-       if (err) {
-               DRM_ERROR("device add failed: %d\n", err);
-               goto err_out;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
-               err = device_create_file(&minor->kdev, &device_attrs[i]);
-               if (err)
-                       goto err_out_files;
-       }
-
-       return 0;
-
-err_out_files:
-       if (i > 0)
-               for (j = 0; j < i; j++)
-                       device_remove_file(&minor->kdev, &device_attrs[i]);
-       device_unregister(&minor->kdev);
-err_out:
-
-       return err;
-}
-
-/**
- * drm_sysfs_device_remove - remove DRM device
- * @dev: DRM device to remove
- *
- * This call unregisters and cleans up a class device that was created with a
- * call to drm_sysfs_device_add()
- */
-void drm_sysfs_device_remove(struct drm_minor *minor)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
-               device_remove_file(&minor->kdev, &device_attrs[i]);
-       device_unregister(&minor->kdev);
-}
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
deleted file mode 100644 (file)
index c234c6f..0000000
+++ /dev/null
@@ -1,673 +0,0 @@
-/**
- * \file drm_vm.c
- * Memory mapping for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#if defined(__ia64__)
-#include <linux/efi.h>
-#endif
-
-static void drm_vm_open(struct vm_area_struct *vma);
-static void drm_vm_close(struct vm_area_struct *vma);
-
-static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
-{
-       pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
-
-#if defined(__i386__) || defined(__x86_64__)
-       if (boot_cpu_data.x86 > 3 && map_type != _DRM_AGP) {
-               pgprot_val(tmp) |= _PAGE_PCD;
-               pgprot_val(tmp) &= ~_PAGE_PWT;
-       }
-#elif defined(__powerpc__)
-       pgprot_val(tmp) |= _PAGE_NO_CACHE;
-       if (map_type == _DRM_REGISTERS)
-               pgprot_val(tmp) |= _PAGE_GUARDED;
-#elif defined(__ia64__)
-       if (efi_range_is_wc(vma->vm_start, vma->vm_end -
-                                   vma->vm_start))
-               tmp = pgprot_writecombine(tmp);
-       else
-               tmp = pgprot_noncached(tmp);
-#elif defined(__sparc__)
-       tmp = pgprot_noncached(tmp);
-#endif
-       return tmp;
-}
-
-static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
-{
-       pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
-
-#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE)
-       tmp |= _PAGE_NO_CACHE;
-#endif
-       return tmp;
-}
-
-/**
- * \c fault method for AGP virtual memory.
- *
- * \param vma virtual memory area.
- * \param address access address.
- * \return pointer to the page structure.
- *
- * Find the right map and if it's AGP memory find the real physical page to
- * map, get the page, increment the use count and return it.
- */
-#if __OS_HAS_AGP
-static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->minor->dev;
-       struct drm_map *map = NULL;
-       struct drm_map_list *r_list;
-       struct drm_hash_item *hash;
-
-       /*
-        * Find the right map
-        */
-       if (!drm_core_has_AGP(dev))
-               goto vm_fault_error;
-
-       if (!dev->agp || !dev->agp->cant_use_aperture)
-               goto vm_fault_error;
-
-       if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash))
-               goto vm_fault_error;
-
-       r_list = drm_hash_entry(hash, struct drm_map_list, hash);
-       map = r_list->map;
-
-       if (map && map->type == _DRM_AGP) {
-               /*
-                * Using vm_pgoff as a selector forces us to use this unusual
-                * addressing scheme.
-                */
-               unsigned long offset = (unsigned long)vmf->virtual_address -
-                                                               vma->vm_start;
-               unsigned long baddr = map->offset + offset;
-               struct drm_agp_mem *agpmem;
-               struct page *page;
-
-#ifdef __alpha__
-               /*
-                * Adjust to a bus-relative address
-                */
-               baddr -= dev->hose->mem_space->start;
-#endif
-
-               /*
-                * It's AGP memory - find the real physical page to map
-                */
-               list_for_each_entry(agpmem, &dev->agp->memory, head) {
-                       if (agpmem->bound <= baddr &&
-                           agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
-                               break;
-               }
-
-               if (!agpmem)
-                       goto vm_fault_error;
-
-               /*
-                * Get the page, inc the use count, and return it
-                */
-               offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
-               page = virt_to_page(__va(agpmem->memory->memory[offset]));
-               get_page(page);
-               vmf->page = page;
-
-               DRM_DEBUG
-                   ("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",
-                    baddr, __va(agpmem->memory->memory[offset]), offset,
-                    page_count(page));
-               return 0;
-       }
-vm_fault_error:
-       return VM_FAULT_SIGBUS; /* Disallow mremap */
-}
-#else                          /* __OS_HAS_AGP */
-static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       return VM_FAULT_SIGBUS;
-}
-#endif                         /* __OS_HAS_AGP */
-
-/**
- * \c nopage method for shared virtual memory.
- *
- * \param vma virtual memory area.
- * \param address access address.
- * \return pointer to the page structure.
- *
- * Get the mapping, find the real physical page to map, get the page, and
- * return it.
- */
-static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       struct drm_map *map = (struct drm_map *) vma->vm_private_data;
-       unsigned long offset;
-       unsigned long i;
-       struct page *page;
-
-       if (!map)
-               return VM_FAULT_SIGBUS; /* Nothing allocated */
-
-       offset = (unsigned long)vmf->virtual_address - vma->vm_start;
-       i = (unsigned long)map->handle + offset;
-       page = vmalloc_to_page((void *)i);
-       if (!page)
-               return VM_FAULT_SIGBUS;
-       get_page(page);
-       vmf->page = page;
-
-       DRM_DEBUG("shm_fault 0x%lx\n", offset);
-       return 0;
-}
-
-/**
- * \c close method for shared virtual memory.
- *
- * \param vma virtual memory area.
- *
- * Deletes map information if we are the last
- * person to close a mapping and it's not in the global maplist.
- */
-static void drm_vm_shm_close(struct vm_area_struct *vma)
-{
-       struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->minor->dev;
-       struct drm_vma_entry *pt, *temp;
-       struct drm_map *map;
-       struct drm_map_list *r_list;
-       int found_maps = 0;
-
-       DRM_DEBUG("0x%08lx,0x%08lx\n",
-                 vma->vm_start, vma->vm_end - vma->vm_start);
-       atomic_dec(&dev->vma_count);
-
-       map = vma->vm_private_data;
-
-       mutex_lock(&dev->struct_mutex);
-       list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
-               if (pt->vma->vm_private_data == map)
-                       found_maps++;
-               if (pt->vma == vma) {
-                       list_del(&pt->head);
-                       drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
-               }
-       }
-
-       /* We were the only map that was found */
-       if (found_maps == 1 && map->flags & _DRM_REMOVABLE) {
-               /* Check to see if we are in the maplist, if we are not, then
-                * we delete this mappings information.
-                */
-               found_maps = 0;
-               list_for_each_entry(r_list, &dev->maplist, head) {
-                       if (r_list->map == map)
-                               found_maps++;
-               }
-
-               if (!found_maps) {
-                       drm_dma_handle_t dmah;
-
-                       switch (map->type) {
-                       case _DRM_REGISTERS:
-                       case _DRM_FRAME_BUFFER:
-                               if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
-                                       int retcode;
-                                       retcode = mtrr_del(map->mtrr,
-                                                          map->offset,
-                                                          map->size);
-                                       DRM_DEBUG("mtrr_del = %d\n", retcode);
-                               }
-                               iounmap(map->handle);
-                               break;
-                       case _DRM_SHM:
-                               vfree(map->handle);
-                               break;
-                       case _DRM_AGP:
-                       case _DRM_SCATTER_GATHER:
-                               break;
-                       case _DRM_CONSISTENT:
-                               dmah.vaddr = map->handle;
-                               dmah.busaddr = map->offset;
-                               dmah.size = map->size;
-                               __drm_pci_free(dev, &dmah);
-                               break;
-                       }
-                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
-               }
-       }
-       mutex_unlock(&dev->struct_mutex);
-}
-
-/**
- * \c fault method for DMA virtual memory.
- *
- * \param vma virtual memory area.
- * \param address access address.
- * \return pointer to the page structure.
- *
- * Determine the page number from the page offset and get it from drm_device_dma::pagelist.
- */
-static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->minor->dev;
-       struct drm_device_dma *dma = dev->dma;
-       unsigned long offset;
-       unsigned long page_nr;
-       struct page *page;
-
-       if (!dma)
-               return VM_FAULT_SIGBUS; /* Error */
-       if (!dma->pagelist)
-               return VM_FAULT_SIGBUS; /* Nothing allocated */
-
-       offset = (unsigned long)vmf->virtual_address - vma->vm_start;   /* vm_[pg]off[set] should be 0 */
-       page_nr = offset >> PAGE_SHIFT; /* page_nr could just be vmf->pgoff */
-       page = virt_to_page((dma->pagelist[page_nr] + (offset & (~PAGE_MASK))));
-
-       get_page(page);
-       vmf->page = page;
-
-       DRM_DEBUG("dma_fault 0x%lx (page %lu)\n", offset, page_nr);
-       return 0;
-}
-
-/**
- * \c fault method for scatter-gather virtual memory.
- *
- * \param vma virtual memory area.
- * \param address access address.
- * \return pointer to the page structure.
- *
- * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
- */
-static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       struct drm_map *map = (struct drm_map *) vma->vm_private_data;
-       struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->minor->dev;
-       struct drm_sg_mem *entry = dev->sg;
-       unsigned long offset;
-       unsigned long map_offset;
-       unsigned long page_offset;
-       struct page *page;
-
-       if (!entry)
-               return VM_FAULT_SIGBUS; /* Error */
-       if (!entry->pagelist)
-               return VM_FAULT_SIGBUS; /* Nothing allocated */
-
-       offset = (unsigned long)vmf->virtual_address - vma->vm_start;
-       map_offset = map->offset - (unsigned long)dev->sg->virtual;
-       page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
-       page = entry->pagelist[page_offset];
-       get_page(page);
-       vmf->page = page;
-
-       return 0;
-}
-
-static int drm_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       return drm_do_vm_fault(vma, vmf);
-}
-
-static int drm_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       return drm_do_vm_shm_fault(vma, vmf);
-}
-
-static int drm_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       return drm_do_vm_dma_fault(vma, vmf);
-}
-
-static int drm_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       return drm_do_vm_sg_fault(vma, vmf);
-}
-
-/** AGP virtual memory operations */
-static struct vm_operations_struct drm_vm_ops = {
-       .fault = drm_vm_fault,
-       .open = drm_vm_open,
-       .close = drm_vm_close,
-};
-
-/** Shared virtual memory operations */
-static struct vm_operations_struct drm_vm_shm_ops = {
-       .fault = drm_vm_shm_fault,
-       .open = drm_vm_open,
-       .close = drm_vm_shm_close,
-};
-
-/** DMA virtual memory operations */
-static struct vm_operations_struct drm_vm_dma_ops = {
-       .fault = drm_vm_dma_fault,
-       .open = drm_vm_open,
-       .close = drm_vm_close,
-};
-
-/** Scatter-gather virtual memory operations */
-static struct vm_operations_struct drm_vm_sg_ops = {
-       .fault = drm_vm_sg_fault,
-       .open = drm_vm_open,
-       .close = drm_vm_close,
-};
-
-/**
- * \c open method for shared virtual memory.
- *
- * \param vma virtual memory area.
- *
- * Create a new drm_vma_entry structure as the \p vma private data entry and
- * add it to drm_device::vmalist.
- */
-static void drm_vm_open_locked(struct vm_area_struct *vma)
-{
-       struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->minor->dev;
-       struct drm_vma_entry *vma_entry;
-
-       DRM_DEBUG("0x%08lx,0x%08lx\n",
-                 vma->vm_start, vma->vm_end - vma->vm_start);
-       atomic_inc(&dev->vma_count);
-
-       vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
-       if (vma_entry) {
-               vma_entry->vma = vma;
-               vma_entry->pid = current->pid;
-               list_add(&vma_entry->head, &dev->vmalist);
-       }
-}
-
-static void drm_vm_open(struct vm_area_struct *vma)
-{
-       struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->minor->dev;
-
-       mutex_lock(&dev->struct_mutex);
-       drm_vm_open_locked(vma);
-       mutex_unlock(&dev->struct_mutex);
-}
-
-/**
- * \c close method for all virtual memory types.
- *
- * \param vma virtual memory area.
- *
- * Search the \p vma private data entry in drm_device::vmalist, unlink it, and
- * free it.
- */
-static void drm_vm_close(struct vm_area_struct *vma)
-{
-       struct drm_file *priv = vma->vm_file->private_data;
-       struct drm_device *dev = priv->minor->dev;
-       struct drm_vma_entry *pt, *temp;
-
-       DRM_DEBUG("0x%08lx,0x%08lx\n",
-                 vma->vm_start, vma->vm_end - vma->vm_start);
-       atomic_dec(&dev->vma_count);
-
-       mutex_lock(&dev->struct_mutex);
-       list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
-               if (pt->vma == vma) {
-                       list_del(&pt->head);
-                       drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
-                       break;
-               }
-       }
-       mutex_unlock(&dev->struct_mutex);
-}
-
-/**
- * mmap DMA memory.
- *
- * \param file_priv DRM file private.
- * \param vma virtual memory area.
- * \return zero on success or a negative number on failure.
- *
- * Sets the virtual memory area operations structure to vm_dma_ops, the file
- * pointer, and calls vm_open().
- */
-static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
-{
-       struct drm_file *priv = filp->private_data;
-       struct drm_device *dev;
-       struct drm_device_dma *dma;
-       unsigned long length = vma->vm_end - vma->vm_start;
-
-       dev = priv->minor->dev;
-       dma = dev->dma;
-       DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
-                 vma->vm_start, vma->vm_end, vma->vm_pgoff);
-
-       /* Length must match exact page count */
-       if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
-               return -EINVAL;
-       }
-
-       if (!capable(CAP_SYS_ADMIN) &&
-           (dma->flags & _DRM_DMA_USE_PCI_RO)) {
-               vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
-#if defined(__i386__) || defined(__x86_64__)
-               pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
-#else
-               /* Ye gads this is ugly.  With more thought
-                  we could move this up higher and use
-                  `protection_map' instead.  */
-               vma->vm_page_prot =
-                   __pgprot(pte_val
-                            (pte_wrprotect
-                             (__pte(pgprot_val(vma->vm_page_prot)))));
-#endif
-       }
-
-       vma->vm_ops = &drm_vm_dma_ops;
-
-       vma->vm_flags |= VM_RESERVED;   /* Don't swap */
-       vma->vm_flags |= VM_DONTEXPAND;
-
-       vma->vm_file = filp;    /* Needed for drm_vm_open() */
-       drm_vm_open_locked(vma);
-       return 0;
-}
-
-unsigned long drm_core_get_map_ofs(struct drm_map * map)
-{
-       return map->offset;
-}
-
-EXPORT_SYMBOL(drm_core_get_map_ofs);
-
-unsigned long drm_core_get_reg_ofs(struct drm_device *dev)
-{
-#ifdef __alpha__
-       return dev->hose->dense_mem_base - dev->hose->mem_space->start;
-#else
-       return 0;
-#endif
-}
-
-EXPORT_SYMBOL(drm_core_get_reg_ofs);
-
-/**
- * mmap DMA memory.
- *
- * \param file_priv DRM file private.
- * \param vma virtual memory area.
- * \return zero on success or a negative number on failure.
- *
- * If the virtual memory area has no offset associated with it then it's a DMA
- * area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist,
- * checks that the restricted flag is not set, sets the virtual memory operations
- * according to the mapping type and remaps the pages. Finally sets the file
- * pointer and calls vm_open().
- */
-static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
-{
-       struct drm_file *priv = filp->private_data;
-       struct drm_device *dev = priv->minor->dev;
-       struct drm_map *map = NULL;
-       unsigned long offset = 0;
-       struct drm_hash_item *hash;
-
-       DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
-                 vma->vm_start, vma->vm_end, vma->vm_pgoff);
-
-       if (!priv->authenticated)
-               return -EACCES;
-
-       /* We check for "dma". On Apple's UniNorth, it's valid to have
-        * the AGP mapped at physical address 0
-        * --BenH.
-        */
-       if (!vma->vm_pgoff
-#if __OS_HAS_AGP
-           && (!dev->agp
-               || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
-#endif
-           )
-               return drm_mmap_dma(filp, vma);
-
-       if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) {
-               DRM_ERROR("Could not find map\n");
-               return -EINVAL;
-       }
-
-       map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
-       if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
-               return -EPERM;
-
-       /* Check for valid size. */
-       if (map->size < vma->vm_end - vma->vm_start)
-               return -EINVAL;
-
-       if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
-               vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
-#if defined(__i386__) || defined(__x86_64__)
-               pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
-#else
-               /* Ye gads this is ugly.  With more thought
-                  we could move this up higher and use
-                  `protection_map' instead.  */
-               vma->vm_page_prot =
-                   __pgprot(pte_val
-                            (pte_wrprotect
-                             (__pte(pgprot_val(vma->vm_page_prot)))));
-#endif
-       }
-
-       switch (map->type) {
-       case _DRM_AGP:
-               if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
-                       /*
-                        * On some platforms we can't talk to bus dma address from the CPU, so for
-                        * memory of type DRM_AGP, we'll deal with sorting out the real physical
-                        * pages and mappings in fault()
-                        */
-#if defined(__powerpc__)
-                       pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
-#endif
-                       vma->vm_ops = &drm_vm_ops;
-                       break;
-               }
-               /* fall through to _DRM_FRAME_BUFFER... */
-       case _DRM_FRAME_BUFFER:
-       case _DRM_REGISTERS:
-               offset = dev->driver->get_reg_ofs(dev);
-               vma->vm_flags |= VM_IO; /* not in core dump */
-               vma->vm_page_prot = drm_io_prot(map->type, vma);
-               if (io_remap_pfn_range(vma, vma->vm_start,
-                                      (map->offset + offset) >> PAGE_SHIFT,
-                                      vma->vm_end - vma->vm_start,
-                                      vma->vm_page_prot))
-                       return -EAGAIN;
-               DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
-                         " offset = 0x%lx\n",
-                         map->type,
-                         vma->vm_start, vma->vm_end, map->offset + offset);
-               vma->vm_ops = &drm_vm_ops;
-               break;
-       case _DRM_CONSISTENT:
-               /* Consistent memory is really like shared memory. But
-                * it's allocated in a different way, so avoid fault */
-               if (remap_pfn_range(vma, vma->vm_start,
-                   page_to_pfn(virt_to_page(map->handle)),
-                   vma->vm_end - vma->vm_start, vma->vm_page_prot))
-                       return -EAGAIN;
-               vma->vm_page_prot = drm_dma_prot(map->type, vma);
-       /* fall through to _DRM_SHM */
-       case _DRM_SHM:
-               vma->vm_ops = &drm_vm_shm_ops;
-               vma->vm_private_data = (void *)map;
-               /* Don't let this area swap.  Change when
-                  DRM_KERNEL advisory is supported. */
-               vma->vm_flags |= VM_RESERVED;
-               break;
-       case _DRM_SCATTER_GATHER:
-               vma->vm_ops = &drm_vm_sg_ops;
-               vma->vm_private_data = (void *)map;
-               vma->vm_flags |= VM_RESERVED;
-               vma->vm_page_prot = drm_dma_prot(map->type, vma);
-               break;
-       default:
-               return -EINVAL; /* This should never happen. */
-       }
-       vma->vm_flags |= VM_RESERVED;   /* Don't swap */
-       vma->vm_flags |= VM_DONTEXPAND;
-
-       vma->vm_file = filp;    /* Needed for drm_vm_open() */
-       drm_vm_open_locked(vma);
-       return 0;
-}
-
-int drm_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       struct drm_file *priv = filp->private_data;
-       struct drm_device *dev = priv->minor->dev;
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-       ret = drm_mmap_locked(filp, vma);
-       mutex_unlock(&dev->struct_mutex);
-
-       return ret;
-}
-EXPORT_SYMBOL(drm_mmap);
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
deleted file mode 100644 (file)
index e5de8ea..0000000
+++ /dev/null
@@ -1,1283 +0,0 @@
-/* i810_dma.c -- DMA support for the i810 -*- linux-c -*-
- * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
- *         Jeff Hartmann <jhartmann@valinux.com>
- *          Keith Whitwell <keith@tungstengraphics.com>
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i810_drm.h"
-#include "i810_drv.h"
-#include <linux/interrupt.h>   /* For task queue support */
-#include <linux/delay.h>
-#include <linux/pagemap.h>
-
-#define I810_BUF_FREE          2
-#define I810_BUF_CLIENT                1
-#define I810_BUF_HARDWARE      0
-
-#define I810_BUF_UNMAPPED 0
-#define I810_BUF_MAPPED   1
-
-static struct drm_buf *i810_freelist_get(struct drm_device * dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int i;
-       int used;
-
-       /* Linear search might not be the best solution */
-
-       for (i = 0; i < dma->buf_count; i++) {
-               struct drm_buf *buf = dma->buflist[i];
-               drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-               /* In use is already a pointer */
-               used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
-                              I810_BUF_CLIENT);
-               if (used == I810_BUF_FREE) {
-                       return buf;
-               }
-       }
-       return NULL;
-}
-
-/* This should only be called if the buffer is not sent to the hardware
- * yet, the hardware updates in use for us once its on the ring buffer.
- */
-
-static int i810_freelist_put(struct drm_device * dev, struct drm_buf * buf)
-{
-       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-       int used;
-
-       /* In use is already a pointer */
-       used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
-       if (used != I810_BUF_CLIENT) {
-               DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
-{
-       struct drm_file *priv = filp->private_data;
-       struct drm_device *dev;
-       drm_i810_private_t *dev_priv;
-       struct drm_buf *buf;
-       drm_i810_buf_priv_t *buf_priv;
-
-       lock_kernel();
-       dev = priv->minor->dev;
-       dev_priv = dev->dev_private;
-       buf = dev_priv->mmap_buffer;
-       buf_priv = buf->dev_private;
-
-       vma->vm_flags |= (VM_IO | VM_DONTCOPY);
-       vma->vm_file = filp;
-
-       buf_priv->currently_mapped = I810_BUF_MAPPED;
-       unlock_kernel();
-
-       if (io_remap_pfn_range(vma, vma->vm_start,
-                              vma->vm_pgoff,
-                              vma->vm_end - vma->vm_start, vma->vm_page_prot))
-               return -EAGAIN;
-       return 0;
-}
-
-static const struct file_operations i810_buffer_fops = {
-       .open = drm_open,
-       .release = drm_release,
-       .ioctl = drm_ioctl,
-       .mmap = i810_mmap_buffers,
-       .fasync = drm_fasync,
-};
-
-static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
-{
-       struct drm_device *dev = file_priv->minor->dev;
-       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       const struct file_operations *old_fops;
-       int retcode = 0;
-
-       if (buf_priv->currently_mapped == I810_BUF_MAPPED)
-               return -EINVAL;
-
-       down_write(&current->mm->mmap_sem);
-       old_fops = file_priv->filp->f_op;
-       file_priv->filp->f_op = &i810_buffer_fops;
-       dev_priv->mmap_buffer = buf;
-       buf_priv->virtual = (void *)do_mmap(file_priv->filp, 0, buf->total,
-                                           PROT_READ | PROT_WRITE,
-                                           MAP_SHARED, buf->bus_address);
-       dev_priv->mmap_buffer = NULL;
-       file_priv->filp->f_op = old_fops;
-       if (IS_ERR(buf_priv->virtual)) {
-               /* Real error */
-               DRM_ERROR("mmap error\n");
-               retcode = PTR_ERR(buf_priv->virtual);
-               buf_priv->virtual = NULL;
-       }
-       up_write(&current->mm->mmap_sem);
-
-       return retcode;
-}
-
-static int i810_unmap_buffer(struct drm_buf * buf)
-{
-       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-       int retcode = 0;
-
-       if (buf_priv->currently_mapped != I810_BUF_MAPPED)
-               return -EINVAL;
-
-       down_write(&current->mm->mmap_sem);
-       retcode = do_munmap(current->mm,
-                           (unsigned long)buf_priv->virtual,
-                           (size_t) buf->total);
-       up_write(&current->mm->mmap_sem);
-
-       buf_priv->currently_mapped = I810_BUF_UNMAPPED;
-       buf_priv->virtual = NULL;
-
-       return retcode;
-}
-
-static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d,
-                              struct drm_file *file_priv)
-{
-       struct drm_buf *buf;
-       drm_i810_buf_priv_t *buf_priv;
-       int retcode = 0;
-
-       buf = i810_freelist_get(dev);
-       if (!buf) {
-               retcode = -ENOMEM;
-               DRM_DEBUG("retcode=%d\n", retcode);
-               return retcode;
-       }
-
-       retcode = i810_map_buffer(buf, file_priv);
-       if (retcode) {
-               i810_freelist_put(dev, buf);
-               DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
-               return retcode;
-       }
-       buf->file_priv = file_priv;
-       buf_priv = buf->dev_private;
-       d->granted = 1;
-       d->request_idx = buf->idx;
-       d->request_size = buf->total;
-       d->virtual = buf_priv->virtual;
-
-       return retcode;
-}
-
-static int i810_dma_cleanup(struct drm_device * dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-
-       /* Make sure interrupts are disabled here because the uninstall ioctl
-        * may not have been called from userspace and after dev_private
-        * is freed, it's too late.
-        */
-       if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ) && dev->irq_enabled)
-               drm_irq_uninstall(dev);
-
-       if (dev->dev_private) {
-               int i;
-               drm_i810_private_t *dev_priv =
-                   (drm_i810_private_t *) dev->dev_private;
-
-               if (dev_priv->ring.virtual_start) {
-                       drm_core_ioremapfree(&dev_priv->ring.map, dev);
-               }
-               if (dev_priv->hw_status_page) {
-                       pci_free_consistent(dev->pdev, PAGE_SIZE,
-                                           dev_priv->hw_status_page,
-                                           dev_priv->dma_status_page);
-                       /* Need to rewrite hardware status page */
-                       I810_WRITE(0x02080, 0x1ffff000);
-               }
-               drm_free(dev->dev_private, sizeof(drm_i810_private_t),
-                        DRM_MEM_DRIVER);
-               dev->dev_private = NULL;
-
-               for (i = 0; i < dma->buf_count; i++) {
-                       struct drm_buf *buf = dma->buflist[i];
-                       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-
-                       if (buf_priv->kernel_virtual && buf->total)
-                               drm_core_ioremapfree(&buf_priv->map, dev);
-               }
-       }
-       return 0;
-}
-
-static int i810_wait_ring(struct drm_device * dev, int n)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
-       int iters = 0;
-       unsigned long end;
-       unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-
-       end = jiffies + (HZ * 3);
-       while (ring->space < n) {
-               ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-               ring->space = ring->head - (ring->tail + 8);
-               if (ring->space < 0)
-                       ring->space += ring->Size;
-
-               if (ring->head != last_head) {
-                       end = jiffies + (HZ * 3);
-                       last_head = ring->head;
-               }
-
-               iters++;
-               if (time_before(end, jiffies)) {
-                       DRM_ERROR("space: %d wanted %d\n", ring->space, n);
-                       DRM_ERROR("lockup\n");
-                       goto out_wait_ring;
-               }
-               udelay(1);
-       }
-
-      out_wait_ring:
-       return iters;
-}
-
-static void i810_kernel_lost_context(struct drm_device * dev)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
-
-       ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-       ring->tail = I810_READ(LP_RING + RING_TAIL);
-       ring->space = ring->head - (ring->tail + 8);
-       if (ring->space < 0)
-               ring->space += ring->Size;
-}
-
-static int i810_freelist_init(struct drm_device * dev, drm_i810_private_t * dev_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int my_idx = 24;
-       u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
-       int i;
-
-       if (dma->buf_count > 1019) {
-               /* Not enough space in the status page for the freelist */
-               return -EINVAL;
-       }
-
-       for (i = 0; i < dma->buf_count; i++) {
-               struct drm_buf *buf = dma->buflist[i];
-               drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-
-               buf_priv->in_use = hw_status++;
-               buf_priv->my_use_idx = my_idx;
-               my_idx += 4;
-
-               *buf_priv->in_use = I810_BUF_FREE;
-
-               buf_priv->map.offset = buf->bus_address;
-               buf_priv->map.size = buf->total;
-               buf_priv->map.type = _DRM_AGP;
-               buf_priv->map.flags = 0;
-               buf_priv->map.mtrr = 0;
-
-               drm_core_ioremap(&buf_priv->map, dev);
-               buf_priv->kernel_virtual = buf_priv->map.handle;
-
-       }
-       return 0;
-}
-
-static int i810_dma_initialize(struct drm_device * dev,
-                              drm_i810_private_t * dev_priv,
-                              drm_i810_init_t * init)
-{
-       struct drm_map_list *r_list;
-       memset(dev_priv, 0, sizeof(drm_i810_private_t));
-
-       list_for_each_entry(r_list, &dev->maplist, head) {
-               if (r_list->map &&
-                   r_list->map->type == _DRM_SHM &&
-                   r_list->map->flags & _DRM_CONTAINS_LOCK) {
-                       dev_priv->sarea_map = r_list->map;
-                       break;
-               }
-       }
-       if (!dev_priv->sarea_map) {
-               dev->dev_private = (void *)dev_priv;
-               i810_dma_cleanup(dev);
-               DRM_ERROR("can not find sarea!\n");
-               return -EINVAL;
-       }
-       dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
-       if (!dev_priv->mmio_map) {
-               dev->dev_private = (void *)dev_priv;
-               i810_dma_cleanup(dev);
-               DRM_ERROR("can not find mmio map!\n");
-               return -EINVAL;
-       }
-       dev->agp_buffer_token = init->buffers_offset;
-       dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
-       if (!dev->agp_buffer_map) {
-               dev->dev_private = (void *)dev_priv;
-               i810_dma_cleanup(dev);
-               DRM_ERROR("can not find dma buffer map!\n");
-               return -EINVAL;
-       }
-
-       dev_priv->sarea_priv = (drm_i810_sarea_t *)
-           ((u8 *) dev_priv->sarea_map->handle + init->sarea_priv_offset);
-
-       dev_priv->ring.Start = init->ring_start;
-       dev_priv->ring.End = init->ring_end;
-       dev_priv->ring.Size = init->ring_size;
-
-       dev_priv->ring.map.offset = dev->agp->base + init->ring_start;
-       dev_priv->ring.map.size = init->ring_size;
-       dev_priv->ring.map.type = _DRM_AGP;
-       dev_priv->ring.map.flags = 0;
-       dev_priv->ring.map.mtrr = 0;
-
-       drm_core_ioremap(&dev_priv->ring.map, dev);
-
-       if (dev_priv->ring.map.handle == NULL) {
-               dev->dev_private = (void *)dev_priv;
-               i810_dma_cleanup(dev);
-               DRM_ERROR("can not ioremap virtual address for"
-                         " ring buffer\n");
-               return -ENOMEM;
-       }
-
-       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
-
-       dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
-
-       dev_priv->w = init->w;
-       dev_priv->h = init->h;
-       dev_priv->pitch = init->pitch;
-       dev_priv->back_offset = init->back_offset;
-       dev_priv->depth_offset = init->depth_offset;
-       dev_priv->front_offset = init->front_offset;
-
-       dev_priv->overlay_offset = init->overlay_offset;
-       dev_priv->overlay_physical = init->overlay_physical;
-
-       dev_priv->front_di1 = init->front_offset | init->pitch_bits;
-       dev_priv->back_di1 = init->back_offset | init->pitch_bits;
-       dev_priv->zi1 = init->depth_offset | init->pitch_bits;
-
-       /* Program Hardware Status Page */
-       dev_priv->hw_status_page =
-           pci_alloc_consistent(dev->pdev, PAGE_SIZE,
-                                &dev_priv->dma_status_page);
-       if (!dev_priv->hw_status_page) {
-               dev->dev_private = (void *)dev_priv;
-               i810_dma_cleanup(dev);
-               DRM_ERROR("Can not allocate hardware status page\n");
-               return -ENOMEM;
-       }
-       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-       DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-
-       I810_WRITE(0x02080, dev_priv->dma_status_page);
-       DRM_DEBUG("Enabled hardware status page\n");
-
-       /* Now we need to init our freelist */
-       if (i810_freelist_init(dev, dev_priv) != 0) {
-               dev->dev_private = (void *)dev_priv;
-               i810_dma_cleanup(dev);
-               DRM_ERROR("Not enough space in the status page for"
-                         " the freelist\n");
-               return -ENOMEM;
-       }
-       dev->dev_private = (void *)dev_priv;
-
-       return 0;
-}
-
-static int i810_dma_init(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i810_private_t *dev_priv;
-       drm_i810_init_t *init = data;
-       int retcode = 0;
-
-       switch (init->func) {
-       case I810_INIT_DMA_1_4:
-               DRM_INFO("Using v1.4 init.\n");
-               dev_priv = drm_alloc(sizeof(drm_i810_private_t),
-                                    DRM_MEM_DRIVER);
-               if (dev_priv == NULL)
-                       return -ENOMEM;
-               retcode = i810_dma_initialize(dev, dev_priv, init);
-               break;
-
-       case I810_CLEANUP_DMA:
-               DRM_INFO("DMA Cleanup\n");
-               retcode = i810_dma_cleanup(dev);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return retcode;
-}
-
-/* Most efficient way to verify state for the i810 is as it is
- * emitted.  Non-conformant state is silently dropped.
- *
- * Use 'volatile' & local var tmp to force the emitted values to be
- * identical to the verified ones.
- */
-static void i810EmitContextVerified(struct drm_device * dev,
-                                   volatile unsigned int *code)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       int i, j = 0;
-       unsigned int tmp;
-       RING_LOCALS;
-
-       BEGIN_LP_RING(I810_CTX_SETUP_SIZE);
-
-       OUT_RING(GFX_OP_COLOR_FACTOR);
-       OUT_RING(code[I810_CTXREG_CF1]);
-
-       OUT_RING(GFX_OP_STIPPLE);
-       OUT_RING(code[I810_CTXREG_ST1]);
-
-       for (i = 4; i < I810_CTX_SETUP_SIZE; i++) {
-               tmp = code[i];
-
-               if ((tmp & (7 << 29)) == (3 << 29) &&
-                   (tmp & (0x1f << 24)) < (0x1d << 24)) {
-                       OUT_RING(tmp);
-                       j++;
-               } else
-                       printk("constext state dropped!!!\n");
-       }
-
-       if (j & 1)
-               OUT_RING(0);
-
-       ADVANCE_LP_RING();
-}
-
-static void i810EmitTexVerified(struct drm_device * dev, volatile unsigned int *code)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       int i, j = 0;
-       unsigned int tmp;
-       RING_LOCALS;
-
-       BEGIN_LP_RING(I810_TEX_SETUP_SIZE);
-
-       OUT_RING(GFX_OP_MAP_INFO);
-       OUT_RING(code[I810_TEXREG_MI1]);
-       OUT_RING(code[I810_TEXREG_MI2]);
-       OUT_RING(code[I810_TEXREG_MI3]);
-
-       for (i = 4; i < I810_TEX_SETUP_SIZE; i++) {
-               tmp = code[i];
-
-               if ((tmp & (7 << 29)) == (3 << 29) &&
-                   (tmp & (0x1f << 24)) < (0x1d << 24)) {
-                       OUT_RING(tmp);
-                       j++;
-               } else
-                       printk("texture state dropped!!!\n");
-       }
-
-       if (j & 1)
-               OUT_RING(0);
-
-       ADVANCE_LP_RING();
-}
-
-/* Need to do some additional checking when setting the dest buffer.
- */
-static void i810EmitDestVerified(struct drm_device * dev,
-                                volatile unsigned int *code)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       unsigned int tmp;
-       RING_LOCALS;
-
-       BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2);
-
-       tmp = code[I810_DESTREG_DI1];
-       if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
-               OUT_RING(CMD_OP_DESTBUFFER_INFO);
-               OUT_RING(tmp);
-       } else
-               DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
-                         tmp, dev_priv->front_di1, dev_priv->back_di1);
-
-       /* invarient:
-        */
-       OUT_RING(CMD_OP_Z_BUFFER_INFO);
-       OUT_RING(dev_priv->zi1);
-
-       OUT_RING(GFX_OP_DESTBUFFER_VARS);
-       OUT_RING(code[I810_DESTREG_DV1]);
-
-       OUT_RING(GFX_OP_DRAWRECT_INFO);
-       OUT_RING(code[I810_DESTREG_DR1]);
-       OUT_RING(code[I810_DESTREG_DR2]);
-       OUT_RING(code[I810_DESTREG_DR3]);
-       OUT_RING(code[I810_DESTREG_DR4]);
-       OUT_RING(0);
-
-       ADVANCE_LP_RING();
-}
-
-static void i810EmitState(struct drm_device * dev)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       unsigned int dirty = sarea_priv->dirty;
-
-       DRM_DEBUG("%x\n", dirty);
-
-       if (dirty & I810_UPLOAD_BUFFERS) {
-               i810EmitDestVerified(dev, sarea_priv->BufferState);
-               sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS;
-       }
-
-       if (dirty & I810_UPLOAD_CTX) {
-               i810EmitContextVerified(dev, sarea_priv->ContextState);
-               sarea_priv->dirty &= ~I810_UPLOAD_CTX;
-       }
-
-       if (dirty & I810_UPLOAD_TEX0) {
-               i810EmitTexVerified(dev, sarea_priv->TexState[0]);
-               sarea_priv->dirty &= ~I810_UPLOAD_TEX0;
-       }
-
-       if (dirty & I810_UPLOAD_TEX1) {
-               i810EmitTexVerified(dev, sarea_priv->TexState[1]);
-               sarea_priv->dirty &= ~I810_UPLOAD_TEX1;
-       }
-}
-
-/* need to verify
- */
-static void i810_dma_dispatch_clear(struct drm_device * dev, int flags,
-                                   unsigned int clear_color,
-                                   unsigned int clear_zval)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int nbox = sarea_priv->nbox;
-       struct drm_clip_rect *pbox = sarea_priv->boxes;
-       int pitch = dev_priv->pitch;
-       int cpp = 2;
-       int i;
-       RING_LOCALS;
-
-       if (dev_priv->current_page == 1) {
-               unsigned int tmp = flags;
-
-               flags &= ~(I810_FRONT | I810_BACK);
-               if (tmp & I810_FRONT)
-                       flags |= I810_BACK;
-               if (tmp & I810_BACK)
-                       flags |= I810_FRONT;
-       }
-
-       i810_kernel_lost_context(dev);
-
-       if (nbox > I810_NR_SAREA_CLIPRECTS)
-               nbox = I810_NR_SAREA_CLIPRECTS;
-
-       for (i = 0; i < nbox; i++, pbox++) {
-               unsigned int x = pbox->x1;
-               unsigned int y = pbox->y1;
-               unsigned int width = (pbox->x2 - x) * cpp;
-               unsigned int height = pbox->y2 - y;
-               unsigned int start = y * pitch + x * cpp;
-
-               if (pbox->x1 > pbox->x2 ||
-                   pbox->y1 > pbox->y2 ||
-                   pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
-                       continue;
-
-               if (flags & I810_FRONT) {
-                       BEGIN_LP_RING(6);
-                       OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
-                       OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
-                       OUT_RING((height << 16) | width);
-                       OUT_RING(start);
-                       OUT_RING(clear_color);
-                       OUT_RING(0);
-                       ADVANCE_LP_RING();
-               }
-
-               if (flags & I810_BACK) {
-                       BEGIN_LP_RING(6);
-                       OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
-                       OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
-                       OUT_RING((height << 16) | width);
-                       OUT_RING(dev_priv->back_offset + start);
-                       OUT_RING(clear_color);
-                       OUT_RING(0);
-                       ADVANCE_LP_RING();
-               }
-
-               if (flags & I810_DEPTH) {
-                       BEGIN_LP_RING(6);
-                       OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
-                       OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
-                       OUT_RING((height << 16) | width);
-                       OUT_RING(dev_priv->depth_offset + start);
-                       OUT_RING(clear_zval);
-                       OUT_RING(0);
-                       ADVANCE_LP_RING();
-               }
-       }
-}
-
-static void i810_dma_dispatch_swap(struct drm_device * dev)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int nbox = sarea_priv->nbox;
-       struct drm_clip_rect *pbox = sarea_priv->boxes;
-       int pitch = dev_priv->pitch;
-       int cpp = 2;
-       int i;
-       RING_LOCALS;
-
-       DRM_DEBUG("swapbuffers\n");
-
-       i810_kernel_lost_context(dev);
-
-       if (nbox > I810_NR_SAREA_CLIPRECTS)
-               nbox = I810_NR_SAREA_CLIPRECTS;
-
-       for (i = 0; i < nbox; i++, pbox++) {
-               unsigned int w = pbox->x2 - pbox->x1;
-               unsigned int h = pbox->y2 - pbox->y1;
-               unsigned int dst = pbox->x1 * cpp + pbox->y1 * pitch;
-               unsigned int start = dst;
-
-               if (pbox->x1 > pbox->x2 ||
-                   pbox->y1 > pbox->y2 ||
-                   pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
-                       continue;
-
-               BEGIN_LP_RING(6);
-               OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
-               OUT_RING(pitch | (0xCC << 16));
-               OUT_RING((h << 16) | (w * cpp));
-               if (dev_priv->current_page == 0)
-                       OUT_RING(dev_priv->front_offset + start);
-               else
-                       OUT_RING(dev_priv->back_offset + start);
-               OUT_RING(pitch);
-               if (dev_priv->current_page == 0)
-                       OUT_RING(dev_priv->back_offset + start);
-               else
-                       OUT_RING(dev_priv->front_offset + start);
-               ADVANCE_LP_RING();
-       }
-}
-
-static void i810_dma_dispatch_vertex(struct drm_device * dev,
-                                    struct drm_buf * buf, int discard, int used)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       struct drm_clip_rect *box = sarea_priv->boxes;
-       int nbox = sarea_priv->nbox;
-       unsigned long address = (unsigned long)buf->bus_address;
-       unsigned long start = address - dev->agp->base;
-       int i = 0;
-       RING_LOCALS;
-
-       i810_kernel_lost_context(dev);
-
-       if (nbox > I810_NR_SAREA_CLIPRECTS)
-               nbox = I810_NR_SAREA_CLIPRECTS;
-
-       if (used > 4 * 1024)
-               used = 0;
-
-       if (sarea_priv->dirty)
-               i810EmitState(dev);
-
-       if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
-               unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
-
-               *(u32 *) buf_priv->kernel_virtual =
-                   ((GFX_OP_PRIMITIVE | prim | ((used / 4) - 2)));
-
-               if (used & 4) {
-                       *(u32 *) ((char *) buf_priv->kernel_virtual + used) = 0;
-                       used += 4;
-               }
-
-               i810_unmap_buffer(buf);
-       }
-
-       if (used) {
-               do {
-                       if (i < nbox) {
-                               BEGIN_LP_RING(4);
-                               OUT_RING(GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
-                                        SC_ENABLE);
-                               OUT_RING(GFX_OP_SCISSOR_INFO);
-                               OUT_RING(box[i].x1 | (box[i].y1 << 16));
-                               OUT_RING((box[i].x2 -
-                                         1) | ((box[i].y2 - 1) << 16));
-                               ADVANCE_LP_RING();
-                       }
-
-                       BEGIN_LP_RING(4);
-                       OUT_RING(CMD_OP_BATCH_BUFFER);
-                       OUT_RING(start | BB1_PROTECTED);
-                       OUT_RING(start + used - 4);
-                       OUT_RING(0);
-                       ADVANCE_LP_RING();
-
-               } while (++i < nbox);
-       }
-
-       if (discard) {
-               dev_priv->counter++;
-
-               (void)cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
-                             I810_BUF_HARDWARE);
-
-               BEGIN_LP_RING(8);
-               OUT_RING(CMD_STORE_DWORD_IDX);
-               OUT_RING(20);
-               OUT_RING(dev_priv->counter);
-               OUT_RING(CMD_STORE_DWORD_IDX);
-               OUT_RING(buf_priv->my_use_idx);
-               OUT_RING(I810_BUF_FREE);
-               OUT_RING(CMD_REPORT_HEAD);
-               OUT_RING(0);
-               ADVANCE_LP_RING();
-       }
-}
-
-static void i810_dma_dispatch_flip(struct drm_device * dev)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       int pitch = dev_priv->pitch;
-       RING_LOCALS;
-
-       DRM_DEBUG("page=%d pfCurrentPage=%d\n",
-                 dev_priv->current_page,
-                 dev_priv->sarea_priv->pf_current_page);
-
-       i810_kernel_lost_context(dev);
-
-       BEGIN_LP_RING(2);
-       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2);
-       /* On i815 at least ASYNC is buggy */
-       /* pitch<<5 is from 11.2.8 p158,
-          its the pitch / 8 then left shifted 8,
-          so (pitch >> 3) << 8 */
-       OUT_RING(CMD_OP_FRONTBUFFER_INFO | (pitch << 5) /*| ASYNC_FLIP */ );
-       if (dev_priv->current_page == 0) {
-               OUT_RING(dev_priv->back_offset);
-               dev_priv->current_page = 1;
-       } else {
-               OUT_RING(dev_priv->front_offset);
-               dev_priv->current_page = 0;
-       }
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       BEGIN_LP_RING(2);
-       OUT_RING(CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       /* Increment the frame counter.  The client-side 3D driver must
-        * throttle the framerate by waiting for this value before
-        * performing the swapbuffer ioctl.
-        */
-       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
-
-}
-
-static void i810_dma_quiescent(struct drm_device * dev)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-
-       i810_kernel_lost_context(dev);
-
-       BEGIN_LP_RING(4);
-       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-       OUT_RING(CMD_REPORT_HEAD);
-       OUT_RING(0);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       i810_wait_ring(dev, dev_priv->ring.Size - 8);
-}
-
-static int i810_flush_queue(struct drm_device * dev)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       int i, ret = 0;
-       RING_LOCALS;
-
-       i810_kernel_lost_context(dev);
-
-       BEGIN_LP_RING(2);
-       OUT_RING(CMD_REPORT_HEAD);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       i810_wait_ring(dev, dev_priv->ring.Size - 8);
-
-       for (i = 0; i < dma->buf_count; i++) {
-               struct drm_buf *buf = dma->buflist[i];
-               drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-
-               int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
-                                  I810_BUF_FREE);
-
-               if (used == I810_BUF_HARDWARE)
-                       DRM_DEBUG("reclaimed from HARDWARE\n");
-               if (used == I810_BUF_CLIENT)
-                       DRM_DEBUG("still on client\n");
-       }
-
-       return ret;
-}
-
-/* Must be called with the lock held */
-static void i810_reclaim_buffers(struct drm_device * dev,
-                                struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int i;
-
-       if (!dma)
-               return;
-       if (!dev->dev_private)
-               return;
-       if (!dma->buflist)
-               return;
-
-       i810_flush_queue(dev);
-
-       for (i = 0; i < dma->buf_count; i++) {
-               struct drm_buf *buf = dma->buflist[i];
-               drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-
-               if (buf->file_priv == file_priv && buf_priv) {
-                       int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
-                                          I810_BUF_FREE);
-
-                       if (used == I810_BUF_CLIENT)
-                               DRM_DEBUG("reclaimed from client\n");
-                       if (buf_priv->currently_mapped == I810_BUF_MAPPED)
-                               buf_priv->currently_mapped = I810_BUF_UNMAPPED;
-               }
-       }
-}
-
-static int i810_flush_ioctl(struct drm_device *dev, void *data,
-                           struct drm_file *file_priv)
-{
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       i810_flush_queue(dev);
-       return 0;
-}
-
-static int i810_dma_vertex(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
-       drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
-           dev_priv->sarea_priv;
-       drm_i810_vertex_t *vertex = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       DRM_DEBUG("idx %d used %d discard %d\n",
-                 vertex->idx, vertex->used, vertex->discard);
-
-       if (vertex->idx < 0 || vertex->idx > dma->buf_count)
-               return -EINVAL;
-
-       i810_dma_dispatch_vertex(dev,
-                                dma->buflist[vertex->idx],
-                                vertex->discard, vertex->used);
-
-       atomic_add(vertex->used, &dev->counts[_DRM_STAT_SECONDARY]);
-       atomic_inc(&dev->counts[_DRM_STAT_DMA]);
-       sarea_priv->last_enqueue = dev_priv->counter - 1;
-       sarea_priv->last_dispatch = (int)hw_status[5];
-
-       return 0;
-}
-
-static int i810_clear_bufs(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv)
-{
-       drm_i810_clear_t *clear = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       /* GH: Someone's doing nasty things... */
-       if (!dev->dev_private) {
-               return -EINVAL;
-       }
-
-       i810_dma_dispatch_clear(dev, clear->flags,
-                               clear->clear_color, clear->clear_depth);
-       return 0;
-}
-
-static int i810_swap_bufs(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv)
-{
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       i810_dma_dispatch_swap(dev);
-       return 0;
-}
-
-static int i810_getage(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
-       drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
-           dev_priv->sarea_priv;
-
-       sarea_priv->last_dispatch = (int)hw_status[5];
-       return 0;
-}
-
-static int i810_getbuf(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       int retcode = 0;
-       drm_i810_dma_t *d = data;
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
-       drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
-           dev_priv->sarea_priv;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       d->granted = 0;
-
-       retcode = i810_dma_get_buffer(dev, d, file_priv);
-
-       DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
-                 task_pid_nr(current), retcode, d->granted);
-
-       sarea_priv->last_dispatch = (int)hw_status[5];
-
-       return retcode;
-}
-
-static int i810_copybuf(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv)
-{
-       /* Never copy - 2.4.x doesn't need it */
-       return 0;
-}
-
-static int i810_docopy(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv)
-{
-       /* Never copy - 2.4.x doesn't need it */
-       return 0;
-}
-
-static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf, int used,
-                                unsigned int last_render)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
-       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       unsigned long address = (unsigned long)buf->bus_address;
-       unsigned long start = address - dev->agp->base;
-       int u;
-       RING_LOCALS;
-
-       i810_kernel_lost_context(dev);
-
-       u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_HARDWARE);
-       if (u != I810_BUF_CLIENT) {
-               DRM_DEBUG("MC found buffer that isn't mine!\n");
-       }
-
-       if (used > 4 * 1024)
-               used = 0;
-
-       sarea_priv->dirty = 0x7f;
-
-       DRM_DEBUG("addr 0x%lx, used 0x%x\n", address, used);
-
-       dev_priv->counter++;
-       DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
-       DRM_DEBUG("start : %lx\n", start);
-       DRM_DEBUG("used : %d\n", used);
-       DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
-
-       if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
-               if (used & 4) {
-                       *(u32 *) ((char *) buf_priv->virtual + used) = 0;
-                       used += 4;
-               }
-
-               i810_unmap_buffer(buf);
-       }
-       BEGIN_LP_RING(4);
-       OUT_RING(CMD_OP_BATCH_BUFFER);
-       OUT_RING(start | BB1_PROTECTED);
-       OUT_RING(start + used - 4);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       BEGIN_LP_RING(8);
-       OUT_RING(CMD_STORE_DWORD_IDX);
-       OUT_RING(buf_priv->my_use_idx);
-       OUT_RING(I810_BUF_FREE);
-       OUT_RING(0);
-
-       OUT_RING(CMD_STORE_DWORD_IDX);
-       OUT_RING(16);
-       OUT_RING(last_render);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-}
-
-static int i810_dma_mc(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
-       drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
-           dev_priv->sarea_priv;
-       drm_i810_mc_t *mc = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (mc->idx >= dma->buf_count || mc->idx < 0)
-               return -EINVAL;
-
-       i810_dma_dispatch_mc(dev, dma->buflist[mc->idx], mc->used,
-                            mc->last_render);
-
-       atomic_add(mc->used, &dev->counts[_DRM_STAT_SECONDARY]);
-       atomic_inc(&dev->counts[_DRM_STAT_DMA]);
-       sarea_priv->last_enqueue = dev_priv->counter - 1;
-       sarea_priv->last_dispatch = (int)hw_status[5];
-
-       return 0;
-}
-
-static int i810_rstatus(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv)
-{
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
-
-       return (int)(((u32 *) (dev_priv->hw_status_page))[4]);
-}
-
-static int i810_ov0_info(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
-       drm_i810_overlay_t *ov = data;
-
-       ov->offset = dev_priv->overlay_offset;
-       ov->physical = dev_priv->overlay_physical;
-
-       return 0;
-}
-
-static int i810_fstatus(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv)
-{
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-       return I810_READ(0x30008);
-}
-
-static int i810_ov0_flip(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       //Tell the overlay to update
-       I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000);
-
-       return 0;
-}
-
-/* Not sure why this isn't set all the time:
- */
-static void i810_do_init_pageflip(struct drm_device * dev)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-
-       DRM_DEBUG("\n");
-       dev_priv->page_flipping = 1;
-       dev_priv->current_page = 0;
-       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
-}
-
-static int i810_do_cleanup_pageflip(struct drm_device * dev)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-
-       DRM_DEBUG("\n");
-       if (dev_priv->current_page != 0)
-               i810_dma_dispatch_flip(dev);
-
-       dev_priv->page_flipping = 0;
-       return 0;
-}
-
-static int i810_flip_bufs(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv)
-{
-       drm_i810_private_t *dev_priv = dev->dev_private;
-
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (!dev_priv->page_flipping)
-               i810_do_init_pageflip(dev);
-
-       i810_dma_dispatch_flip(dev);
-       return 0;
-}
-
-int i810_driver_load(struct drm_device *dev, unsigned long flags)
-{
-       /* i810 has 4 more counters */
-       dev->counters += 4;
-       dev->types[6] = _DRM_STAT_IRQ;
-       dev->types[7] = _DRM_STAT_PRIMARY;
-       dev->types[8] = _DRM_STAT_SECONDARY;
-       dev->types[9] = _DRM_STAT_DMA;
-
-       return 0;
-}
-
-void i810_driver_lastclose(struct drm_device * dev)
-{
-       i810_dma_cleanup(dev);
-}
-
-void i810_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
-{
-       if (dev->dev_private) {
-               drm_i810_private_t *dev_priv = dev->dev_private;
-               if (dev_priv->page_flipping) {
-                       i810_do_cleanup_pageflip(dev);
-               }
-       }
-}
-
-void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
-                                       struct drm_file *file_priv)
-{
-       i810_reclaim_buffers(dev, file_priv);
-}
-
-int i810_driver_dma_quiescent(struct drm_device * dev)
-{
-       i810_dma_quiescent(dev);
-       return 0;
-}
-
-struct drm_ioctl_desc i810_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH)
-};
-
-int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
-
-/**
- * Determine if the device really is AGP or not.
- *
- * All Intel graphics chipsets are treated as AGP, even if they are really
- * PCI-e.
- *
- * \param dev   The device to be tested.
- *
- * \returns
- * A value of 1 is always retured to indictate every i810 is AGP.
- */
-int i810_driver_device_is_agp(struct drm_device * dev)
-{
-       return 1;
-}
diff --git a/drivers/char/drm/i810_drm.h b/drivers/char/drm/i810_drm.h
deleted file mode 100644 (file)
index 7a10bb6..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-#ifndef _I810_DRM_H_
-#define _I810_DRM_H_
-
-/* WARNING: These defines must be the same as what the Xserver uses.
- * if you change them, you must change the defines in the Xserver.
- */
-
-#ifndef _I810_DEFINES_
-#define _I810_DEFINES_
-
-#define I810_DMA_BUF_ORDER             12
-#define I810_DMA_BUF_SZ                (1<<I810_DMA_BUF_ORDER)
-#define I810_DMA_BUF_NR                256
-#define I810_NR_SAREA_CLIPRECTS        8
-
-/* Each region is a minimum of 64k, and there are at most 64 of them.
- */
-#define I810_NR_TEX_REGIONS 64
-#define I810_LOG_MIN_TEX_REGION_SIZE 16
-#endif
-
-#define I810_UPLOAD_TEX0IMAGE  0x1     /* handled clientside */
-#define I810_UPLOAD_TEX1IMAGE  0x2     /* handled clientside */
-#define I810_UPLOAD_CTX        0x4
-#define I810_UPLOAD_BUFFERS    0x8
-#define I810_UPLOAD_TEX0       0x10
-#define I810_UPLOAD_TEX1       0x20
-#define I810_UPLOAD_CLIPRECTS  0x40
-
-/* Indices into buf.Setup where various bits of state are mirrored per
- * context and per buffer.  These can be fired at the card as a unit,
- * or in a piecewise fashion as required.
- */
-
-/* Destbuffer state
- *    - backbuffer linear offset and pitch -- invarient in the current dri
- *    - zbuffer linear offset and pitch -- also invarient
- *    - drawing origin in back and depth buffers.
- *
- * Keep the depth/back buffer state here to accommodate private buffers
- * in the future.
- */
-#define I810_DESTREG_DI0  0    /* CMD_OP_DESTBUFFER_INFO (2 dwords) */
-#define I810_DESTREG_DI1  1
-#define I810_DESTREG_DV0  2    /* GFX_OP_DESTBUFFER_VARS (2 dwords) */
-#define I810_DESTREG_DV1  3
-#define I810_DESTREG_DR0  4    /* GFX_OP_DRAWRECT_INFO (4 dwords) */
-#define I810_DESTREG_DR1  5
-#define I810_DESTREG_DR2  6
-#define I810_DESTREG_DR3  7
-#define I810_DESTREG_DR4  8
-#define I810_DEST_SETUP_SIZE 10
-
-/* Context state
- */
-#define I810_CTXREG_CF0   0    /* GFX_OP_COLOR_FACTOR */
-#define I810_CTXREG_CF1   1
-#define I810_CTXREG_ST0   2    /* GFX_OP_STIPPLE */
-#define I810_CTXREG_ST1   3
-#define I810_CTXREG_VF    4    /* GFX_OP_VERTEX_FMT */
-#define I810_CTXREG_MT    5    /* GFX_OP_MAP_TEXELS */
-#define I810_CTXREG_MC0   6    /* GFX_OP_MAP_COLOR_STAGES - stage 0 */
-#define I810_CTXREG_MC1   7    /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
-#define I810_CTXREG_MC2   8    /* GFX_OP_MAP_COLOR_STAGES - stage 2 */
-#define I810_CTXREG_MA0   9    /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */
-#define I810_CTXREG_MA1   10   /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */
-#define I810_CTXREG_MA2   11   /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */
-#define I810_CTXREG_SDM   12   /* GFX_OP_SRC_DEST_MONO */
-#define I810_CTXREG_FOG   13   /* GFX_OP_FOG_COLOR */
-#define I810_CTXREG_B1    14   /* GFX_OP_BOOL_1 */
-#define I810_CTXREG_B2    15   /* GFX_OP_BOOL_2 */
-#define I810_CTXREG_LCS   16   /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */
-#define I810_CTXREG_PV    17   /* GFX_OP_PV_RULE -- Invarient! */
-#define I810_CTXREG_ZA    18   /* GFX_OP_ZBIAS_ALPHAFUNC */
-#define I810_CTXREG_AA    19   /* GFX_OP_ANTIALIAS */
-#define I810_CTX_SETUP_SIZE 20
-
-/* Texture state (per tex unit)
- */
-#define I810_TEXREG_MI0  0     /* GFX_OP_MAP_INFO (4 dwords) */
-#define I810_TEXREG_MI1  1
-#define I810_TEXREG_MI2  2
-#define I810_TEXREG_MI3  3
-#define I810_TEXREG_MF   4     /* GFX_OP_MAP_FILTER */
-#define I810_TEXREG_MLC  5     /* GFX_OP_MAP_LOD_CTL */
-#define I810_TEXREG_MLL  6     /* GFX_OP_MAP_LOD_LIMITS */
-#define I810_TEXREG_MCS  7     /* GFX_OP_MAP_COORD_SETS ??? */
-#define I810_TEX_SETUP_SIZE 8
-
-/* Flags for clear ioctl
- */
-#define I810_FRONT   0x1
-#define I810_BACK    0x2
-#define I810_DEPTH   0x4
-
-typedef enum _drm_i810_init_func {
-       I810_INIT_DMA = 0x01,
-       I810_CLEANUP_DMA = 0x02,
-       I810_INIT_DMA_1_4 = 0x03
-} drm_i810_init_func_t;
-
-/* This is the init structure after v1.2 */
-typedef struct _drm_i810_init {
-       drm_i810_init_func_t func;
-       unsigned int mmio_offset;
-       unsigned int buffers_offset;
-       int sarea_priv_offset;
-       unsigned int ring_start;
-       unsigned int ring_end;
-       unsigned int ring_size;
-       unsigned int front_offset;
-       unsigned int back_offset;
-       unsigned int depth_offset;
-       unsigned int overlay_offset;
-       unsigned int overlay_physical;
-       unsigned int w;
-       unsigned int h;
-       unsigned int pitch;
-       unsigned int pitch_bits;
-} drm_i810_init_t;
-
-/* This is the init structure prior to v1.2 */
-typedef struct _drm_i810_pre12_init {
-       drm_i810_init_func_t func;
-       unsigned int mmio_offset;
-       unsigned int buffers_offset;
-       int sarea_priv_offset;
-       unsigned int ring_start;
-       unsigned int ring_end;
-       unsigned int ring_size;
-       unsigned int front_offset;
-       unsigned int back_offset;
-       unsigned int depth_offset;
-       unsigned int w;
-       unsigned int h;
-       unsigned int pitch;
-       unsigned int pitch_bits;
-} drm_i810_pre12_init_t;
-
-/* Warning: If you change the SAREA structure you must change the Xserver
- * structure as well */
-
-typedef struct _drm_i810_tex_region {
-       unsigned char next, prev;       /* indices to form a circular LRU  */
-       unsigned char in_use;   /* owned by a client, or free? */
-       int age;                /* tracked by clients to update local LRU's */
-} drm_i810_tex_region_t;
-
-typedef struct _drm_i810_sarea {
-       unsigned int ContextState[I810_CTX_SETUP_SIZE];
-       unsigned int BufferState[I810_DEST_SETUP_SIZE];
-       unsigned int TexState[2][I810_TEX_SETUP_SIZE];
-       unsigned int dirty;
-
-       unsigned int nbox;
-       struct drm_clip_rect boxes[I810_NR_SAREA_CLIPRECTS];
-
-       /* Maintain an LRU of contiguous regions of texture space.  If
-        * you think you own a region of texture memory, and it has an
-        * age different to the one you set, then you are mistaken and
-        * it has been stolen by another client.  If global texAge
-        * hasn't changed, there is no need to walk the list.
-        *
-        * These regions can be used as a proxy for the fine-grained
-        * texture information of other clients - by maintaining them
-        * in the same lru which is used to age their own textures,
-        * clients have an approximate lru for the whole of global
-        * texture space, and can make informed decisions as to which
-        * areas to kick out.  There is no need to choose whether to
-        * kick out your own texture or someone else's - simply eject
-        * them all in LRU order.
-        */
-
-       drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS + 1];
-       /* Last elt is sentinal */
-       int texAge;             /* last time texture was uploaded */
-       int last_enqueue;       /* last time a buffer was enqueued */
-       int last_dispatch;      /* age of the most recently dispatched buffer */
-       int last_quiescent;     /*  */
-       int ctxOwner;           /* last context to upload state */
-
-       int vertex_prim;
-
-       int pf_enabled;         /* is pageflipping allowed? */
-       int pf_active;
-       int pf_current_page;    /* which buffer is being displayed? */
-} drm_i810_sarea_t;
-
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the Xserver file (xf86drmMga.h)
- */
-
-/* i810 specific ioctls
- * The device specific ioctl range is 0x40 to 0x79.
- */
-#define DRM_I810_INIT          0x00
-#define DRM_I810_VERTEX                0x01
-#define DRM_I810_CLEAR         0x02
-#define DRM_I810_FLUSH         0x03
-#define DRM_I810_GETAGE                0x04
-#define DRM_I810_GETBUF                0x05
-#define DRM_I810_SWAP          0x06
-#define DRM_I810_COPY          0x07
-#define DRM_I810_DOCOPY                0x08
-#define DRM_I810_OV0INFO       0x09
-#define DRM_I810_FSTATUS       0x0a
-#define DRM_I810_OV0FLIP       0x0b
-#define DRM_I810_MC            0x0c
-#define DRM_I810_RSTATUS       0x0d
-#define DRM_I810_FLIP          0x0e
-
-#define DRM_IOCTL_I810_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I810_INIT, drm_i810_init_t)
-#define DRM_IOCTL_I810_VERTEX          DRM_IOW( DRM_COMMAND_BASE + DRM_I810_VERTEX, drm_i810_vertex_t)
-#define DRM_IOCTL_I810_CLEAR           DRM_IOW( DRM_COMMAND_BASE + DRM_I810_CLEAR, drm_i810_clear_t)
-#define DRM_IOCTL_I810_FLUSH           DRM_IO(  DRM_COMMAND_BASE + DRM_I810_FLUSH)
-#define DRM_IOCTL_I810_GETAGE          DRM_IO(  DRM_COMMAND_BASE + DRM_I810_GETAGE)
-#define DRM_IOCTL_I810_GETBUF          DRM_IOWR(DRM_COMMAND_BASE + DRM_I810_GETBUF, drm_i810_dma_t)
-#define DRM_IOCTL_I810_SWAP            DRM_IO(  DRM_COMMAND_BASE + DRM_I810_SWAP)
-#define DRM_IOCTL_I810_COPY            DRM_IOW( DRM_COMMAND_BASE + DRM_I810_COPY, drm_i810_copy_t)
-#define DRM_IOCTL_I810_DOCOPY          DRM_IO(  DRM_COMMAND_BASE + DRM_I810_DOCOPY)
-#define DRM_IOCTL_I810_OV0INFO         DRM_IOR( DRM_COMMAND_BASE + DRM_I810_OV0INFO, drm_i810_overlay_t)
-#define DRM_IOCTL_I810_FSTATUS         DRM_IO ( DRM_COMMAND_BASE + DRM_I810_FSTATUS)
-#define DRM_IOCTL_I810_OV0FLIP         DRM_IO ( DRM_COMMAND_BASE + DRM_I810_OV0FLIP)
-#define DRM_IOCTL_I810_MC              DRM_IOW( DRM_COMMAND_BASE + DRM_I810_MC, drm_i810_mc_t)
-#define DRM_IOCTL_I810_RSTATUS         DRM_IO ( DRM_COMMAND_BASE + DRM_I810_RSTATUS)
-#define DRM_IOCTL_I810_FLIP             DRM_IO ( DRM_COMMAND_BASE + DRM_I810_FLIP)
-
-typedef struct _drm_i810_clear {
-       int clear_color;
-       int clear_depth;
-       int flags;
-} drm_i810_clear_t;
-
-/* These may be placeholders if we have more cliprects than
- * I810_NR_SAREA_CLIPRECTS.  In that case, the client sets discard to
- * false, indicating that the buffer will be dispatched again with a
- * new set of cliprects.
- */
-typedef struct _drm_i810_vertex {
-       int idx;                /* buffer index */
-       int used;               /* nr bytes in use */
-       int discard;            /* client is finished with the buffer? */
-} drm_i810_vertex_t;
-
-typedef struct _drm_i810_copy_t {
-       int idx;                /* buffer index */
-       int used;               /* nr bytes in use */
-       void *address;          /* Address to copy from */
-} drm_i810_copy_t;
-
-#define PR_TRIANGLES         (0x0<<18)
-#define PR_TRISTRIP_0        (0x1<<18)
-#define PR_TRISTRIP_1        (0x2<<18)
-#define PR_TRIFAN            (0x3<<18)
-#define PR_POLYGON           (0x4<<18)
-#define PR_LINES             (0x5<<18)
-#define PR_LINESTRIP         (0x6<<18)
-#define PR_RECTS             (0x7<<18)
-#define PR_MASK              (0x7<<18)
-
-typedef struct drm_i810_dma {
-       void *virtual;
-       int request_idx;
-       int request_size;
-       int granted;
-} drm_i810_dma_t;
-
-typedef struct _drm_i810_overlay_t {
-       unsigned int offset;    /* Address of the Overlay Regs */
-       unsigned int physical;
-} drm_i810_overlay_t;
-
-typedef struct _drm_i810_mc {
-       int idx;                /* buffer index */
-       int used;               /* nr bytes in use */
-       int num_blocks;         /* number of GFXBlocks */
-       int *length;            /* List of lengths for GFXBlocks (FUTURE) */
-       unsigned int last_render;       /* Last Render Request */
-} drm_i810_mc_t;
-
-#endif                         /* _I810_DRM_H_ */
diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c
deleted file mode 100644 (file)
index fabb9a8..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/* i810_drv.c -- I810 driver -*- linux-c -*-
- * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Jeff Hartmann <jhartmann@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i810_drm.h"
-#include "i810_drv.h"
-
-#include "drm_pciids.h"
-
-static struct pci_device_id pciidlist[] = {
-       i810_PCI_IDS
-};
-
-static struct drm_driver driver = {
-       .driver_features =
-           DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
-           DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
-       .dev_priv_size = sizeof(drm_i810_buf_priv_t),
-       .load = i810_driver_load,
-       .lastclose = i810_driver_lastclose,
-       .preclose = i810_driver_preclose,
-       .device_is_agp = i810_driver_device_is_agp,
-       .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked,
-       .dma_quiescent = i810_driver_dma_quiescent,
-       .get_map_ofs = drm_core_get_map_ofs,
-       .get_reg_ofs = drm_core_get_reg_ofs,
-       .ioctls = i810_ioctls,
-       .fops = {
-                .owner = THIS_MODULE,
-                .open = drm_open,
-                .release = drm_release,
-                .ioctl = drm_ioctl,
-                .mmap = drm_mmap,
-                .poll = drm_poll,
-                .fasync = drm_fasync,
-       },
-
-       .pci_driver = {
-                .name = DRIVER_NAME,
-                .id_table = pciidlist,
-       },
-
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int __init i810_init(void)
-{
-       driver.num_ioctls = i810_max_ioctl;
-       return drm_init(&driver);
-}
-
-static void __exit i810_exit(void)
-{
-       drm_exit(&driver);
-}
-
-module_init(i810_init);
-module_exit(i810_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
deleted file mode 100644 (file)
index 0118849..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/* i810_drv.h -- Private header for the Matrox g200/g400 driver -*- linux-c -*-
- * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
- *         Jeff Hartmann <jhartmann@valinux.com>
- *
- */
-
-#ifndef _I810_DRV_H_
-#define _I810_DRV_H_
-
-/* General customization:
- */
-
-#define DRIVER_AUTHOR          "VA Linux Systems Inc."
-
-#define DRIVER_NAME            "i810"
-#define DRIVER_DESC            "Intel i810"
-#define DRIVER_DATE            "20030605"
-
-/* Interface history
- *
- * 1.1   - XFree86 4.1
- * 1.2   - XvMC interfaces
- *       - XFree86 4.2
- * 1.2.1 - Disable copying code (leave stub ioctls for backwards compatibility)
- *       - Remove requirement for interrupt (leave stubs again)
- * 1.3   - Add page flipping.
- * 1.4   - fix DRM interface
- */
-#define DRIVER_MAJOR           1
-#define DRIVER_MINOR           4
-#define DRIVER_PATCHLEVEL      0
-
-typedef struct drm_i810_buf_priv {
-       u32 *in_use;
-       int my_use_idx;
-       int currently_mapped;
-       void *virtual;
-       void *kernel_virtual;
-       drm_local_map_t map;
-} drm_i810_buf_priv_t;
-
-typedef struct _drm_i810_ring_buffer {
-       int tail_mask;
-       unsigned long Start;
-       unsigned long End;
-       unsigned long Size;
-       u8 *virtual_start;
-       int head;
-       int tail;
-       int space;
-       drm_local_map_t map;
-} drm_i810_ring_buffer_t;
-
-typedef struct drm_i810_private {
-       struct drm_map *sarea_map;
-       struct drm_map *mmio_map;
-
-       drm_i810_sarea_t *sarea_priv;
-       drm_i810_ring_buffer_t ring;
-
-       void *hw_status_page;
-       unsigned long counter;
-
-       dma_addr_t dma_status_page;
-
-       struct drm_buf *mmap_buffer;
-
-       u32 front_di1, back_di1, zi1;
-
-       int back_offset;
-       int depth_offset;
-       int overlay_offset;
-       int overlay_physical;
-       int w, h;
-       int pitch;
-       int back_pitch;
-       int depth_pitch;
-
-       int do_boxes;
-       int dma_used;
-
-       int current_page;
-       int page_flipping;
-
-       wait_queue_head_t irq_queue;
-       atomic_t irq_received;
-       atomic_t irq_emitted;
-
-       int front_offset;
-} drm_i810_private_t;
-
-                               /* i810_dma.c */
-extern int i810_driver_dma_quiescent(struct drm_device * dev);
-extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
-                                              struct drm_file *file_priv);
-extern int i810_driver_load(struct drm_device *, unsigned long flags);
-extern void i810_driver_lastclose(struct drm_device * dev);
-extern void i810_driver_preclose(struct drm_device * dev,
-                                struct drm_file *file_priv);
-extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
-                                              struct drm_file *file_priv);
-extern int i810_driver_device_is_agp(struct drm_device * dev);
-
-extern struct drm_ioctl_desc i810_ioctls[];
-extern int i810_max_ioctl;
-
-#define I810_BASE(reg)         ((unsigned long) \
-                               dev_priv->mmio_map->handle)
-#define I810_ADDR(reg)         (I810_BASE(reg) + reg)
-#define I810_DEREF(reg)                *(__volatile__ int *)I810_ADDR(reg)
-#define I810_READ(reg)         I810_DEREF(reg)
-#define I810_WRITE(reg,val)    do { I810_DEREF(reg) = val; } while (0)
-#define I810_DEREF16(reg)      *(__volatile__ u16 *)I810_ADDR(reg)
-#define I810_READ16(reg)       I810_DEREF16(reg)
-#define I810_WRITE16(reg,val)  do { I810_DEREF16(reg) = val; } while (0)
-
-#define I810_VERBOSE 0
-#define RING_LOCALS    unsigned int outring, ringmask; \
-                        volatile char *virt;
-
-#define BEGIN_LP_RING(n) do {                                          \
-       if (I810_VERBOSE)                                               \
-               DRM_DEBUG("BEGIN_LP_RING(%d)\n", n);                    \
-       if (dev_priv->ring.space < n*4)                                 \
-               i810_wait_ring(dev, n*4);                               \
-       dev_priv->ring.space -= n*4;                                    \
-       outring = dev_priv->ring.tail;                                  \
-       ringmask = dev_priv->ring.tail_mask;                            \
-       virt = dev_priv->ring.virtual_start;                            \
-} while (0)
-
-#define ADVANCE_LP_RING() do {                                 \
-       if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n");       \
-       dev_priv->ring.tail = outring;                          \
-       I810_WRITE(LP_RING + RING_TAIL, outring);               \
-} while(0)
-
-#define OUT_RING(n) do {                                               \
-       if (I810_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));      \
-       *(volatile unsigned int *)(virt + outring) = n;                 \
-       outring += 4;                                                   \
-       outring &= ringmask;                                            \
-} while (0)
-
-#define GFX_OP_USER_INTERRUPT          ((0<<29)|(2<<23))
-#define GFX_OP_BREAKPOINT_INTERRUPT    ((0<<29)|(1<<23))
-#define CMD_REPORT_HEAD                        (7<<23)
-#define CMD_STORE_DWORD_IDX            ((0x21<<23) | 0x1)
-#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
-
-#define INST_PARSER_CLIENT   0x00000000
-#define INST_OP_FLUSH        0x02000000
-#define INST_FLUSH_MAP_CACHE 0x00000001
-
-#define BB1_START_ADDR_MASK   (~0x7)
-#define BB1_PROTECTED         (1<<0)
-#define BB1_UNPROTECTED       (0<<0)
-#define BB2_END_ADDR_MASK     (~0x7)
-
-#define I810REG_HWSTAM         0x02098
-#define I810REG_INT_IDENTITY_R 0x020a4
-#define I810REG_INT_MASK_R     0x020a8
-#define I810REG_INT_ENABLE_R   0x020a0
-
-#define LP_RING                        0x2030
-#define HP_RING                        0x2040
-#define RING_TAIL              0x00
-#define TAIL_ADDR              0x000FFFF8
-#define RING_HEAD              0x04
-#define HEAD_WRAP_COUNT                0xFFE00000
-#define HEAD_WRAP_ONE          0x00200000
-#define HEAD_ADDR              0x001FFFFC
-#define RING_START             0x08
-#define START_ADDR             0x00FFFFF8
-#define RING_LEN               0x0C
-#define RING_NR_PAGES          0x000FF000
-#define RING_REPORT_MASK       0x00000006
-#define RING_REPORT_64K                0x00000002
-#define RING_REPORT_128K       0x00000004
-#define RING_NO_REPORT         0x00000000
-#define RING_VALID_MASK                0x00000001
-#define RING_VALID             0x00000001
-#define RING_INVALID           0x00000000
-
-#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define SC_UPDATE_SCISSOR       (0x1<<1)
-#define SC_ENABLE_MASK          (0x1<<0)
-#define SC_ENABLE               (0x1<<0)
-
-#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
-#define SCI_YMIN_MASK      (0xffff<<16)
-#define SCI_XMIN_MASK      (0xffff<<0)
-#define SCI_YMAX_MASK      (0xffff<<16)
-#define SCI_XMAX_MASK      (0xffff<<0)
-
-#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
-#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x2)
-#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
-#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
-#define GFX_OP_PRIMITIVE         ((0x3<<29)|(0x1f<<24))
-
-#define CMD_OP_Z_BUFFER_INFO     ((0x0<<29)|(0x16<<23))
-#define CMD_OP_DESTBUFFER_INFO   ((0x0<<29)|(0x15<<23))
-#define CMD_OP_FRONTBUFFER_INFO  ((0x0<<29)|(0x14<<23))
-#define CMD_OP_WAIT_FOR_EVENT    ((0x0<<29)|(0x03<<23))
-
-#define BR00_BITBLT_CLIENT   0x40000000
-#define BR00_OP_COLOR_BLT    0x10000000
-#define BR00_OP_SRC_COPY_BLT 0x10C00000
-#define BR13_SOLID_PATTERN   0x80000000
-
-#define WAIT_FOR_PLANE_A_SCANLINES (1<<1)
-#define WAIT_FOR_PLANE_A_FLIP      (1<<2)
-#define WAIT_FOR_VBLANK (1<<3)
-
-#endif
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
deleted file mode 100644 (file)
index a86ab30..0000000
+++ /dev/null
@@ -1,1553 +0,0 @@
-/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
- * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
- *         Jeff Hartmann <jhartmann@valinux.com>
- *         Keith Whitwell <keith@tungstengraphics.com>
- *         Abraham vd Merwe <abraham@2d3d.co.za>
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i830_drm.h"
-#include "i830_drv.h"
-#include <linux/interrupt.h>   /* For task queue support */
-#include <linux/pagemap.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-
-#define I830_BUF_FREE          2
-#define I830_BUF_CLIENT                1
-#define I830_BUF_HARDWARE      0
-
-#define I830_BUF_UNMAPPED 0
-#define I830_BUF_MAPPED   1
-
-static struct drm_buf *i830_freelist_get(struct drm_device * dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int i;
-       int used;
-
-       /* Linear search might not be the best solution */
-
-       for (i = 0; i < dma->buf_count; i++) {
-               struct drm_buf *buf = dma->buflist[i];
-               drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-               /* In use is already a pointer */
-               used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
-                              I830_BUF_CLIENT);
-               if (used == I830_BUF_FREE) {
-                       return buf;
-               }
-       }
-       return NULL;
-}
-
-/* This should only be called if the buffer is not sent to the hardware
- * yet, the hardware updates in use for us once its on the ring buffer.
- */
-
-static int i830_freelist_put(struct drm_device * dev, struct drm_buf * buf)
-{
-       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-       int used;
-
-       /* In use is already a pointer */
-       used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE);
-       if (used != I830_BUF_CLIENT) {
-               DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
-{
-       struct drm_file *priv = filp->private_data;
-       struct drm_device *dev;
-       drm_i830_private_t *dev_priv;
-       struct drm_buf *buf;
-       drm_i830_buf_priv_t *buf_priv;
-
-       lock_kernel();
-       dev = priv->minor->dev;
-       dev_priv = dev->dev_private;
-       buf = dev_priv->mmap_buffer;
-       buf_priv = buf->dev_private;
-
-       vma->vm_flags |= (VM_IO | VM_DONTCOPY);
-       vma->vm_file = filp;
-
-       buf_priv->currently_mapped = I830_BUF_MAPPED;
-       unlock_kernel();
-
-       if (io_remap_pfn_range(vma, vma->vm_start,
-                              vma->vm_pgoff,
-                              vma->vm_end - vma->vm_start, vma->vm_page_prot))
-               return -EAGAIN;
-       return 0;
-}
-
-static const struct file_operations i830_buffer_fops = {
-       .open = drm_open,
-       .release = drm_release,
-       .ioctl = drm_ioctl,
-       .mmap = i830_mmap_buffers,
-       .fasync = drm_fasync,
-};
-
-static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
-{
-       struct drm_device *dev = file_priv->minor->dev;
-       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       const struct file_operations *old_fops;
-       unsigned long virtual;
-       int retcode = 0;
-
-       if (buf_priv->currently_mapped == I830_BUF_MAPPED)
-               return -EINVAL;
-
-       down_write(&current->mm->mmap_sem);
-       old_fops = file_priv->filp->f_op;
-       file_priv->filp->f_op = &i830_buffer_fops;
-       dev_priv->mmap_buffer = buf;
-       virtual = do_mmap(file_priv->filp, 0, buf->total, PROT_READ | PROT_WRITE,
-                         MAP_SHARED, buf->bus_address);
-       dev_priv->mmap_buffer = NULL;
-       file_priv->filp->f_op = old_fops;
-       if (IS_ERR((void *)virtual)) {  /* ugh */
-               /* Real error */
-               DRM_ERROR("mmap error\n");
-               retcode = PTR_ERR((void *)virtual);
-               buf_priv->virtual = NULL;
-       } else {
-               buf_priv->virtual = (void __user *)virtual;
-       }
-       up_write(&current->mm->mmap_sem);
-
-       return retcode;
-}
-
-static int i830_unmap_buffer(struct drm_buf * buf)
-{
-       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-       int retcode = 0;
-
-       if (buf_priv->currently_mapped != I830_BUF_MAPPED)
-               return -EINVAL;
-
-       down_write(&current->mm->mmap_sem);
-       retcode = do_munmap(current->mm,
-                           (unsigned long)buf_priv->virtual,
-                           (size_t) buf->total);
-       up_write(&current->mm->mmap_sem);
-
-       buf_priv->currently_mapped = I830_BUF_UNMAPPED;
-       buf_priv->virtual = NULL;
-
-       return retcode;
-}
-
-static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d,
-                              struct drm_file *file_priv)
-{
-       struct drm_buf *buf;
-       drm_i830_buf_priv_t *buf_priv;
-       int retcode = 0;
-
-       buf = i830_freelist_get(dev);
-       if (!buf) {
-               retcode = -ENOMEM;
-               DRM_DEBUG("retcode=%d\n", retcode);
-               return retcode;
-       }
-
-       retcode = i830_map_buffer(buf, file_priv);
-       if (retcode) {
-               i830_freelist_put(dev, buf);
-               DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
-               return retcode;
-       }
-       buf->file_priv = file_priv;
-       buf_priv = buf->dev_private;
-       d->granted = 1;
-       d->request_idx = buf->idx;
-       d->request_size = buf->total;
-       d->virtual = buf_priv->virtual;
-
-       return retcode;
-}
-
-static int i830_dma_cleanup(struct drm_device * dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-
-       /* Make sure interrupts are disabled here because the uninstall ioctl
-        * may not have been called from userspace and after dev_private
-        * is freed, it's too late.
-        */
-       if (dev->irq_enabled)
-               drm_irq_uninstall(dev);
-
-       if (dev->dev_private) {
-               int i;
-               drm_i830_private_t *dev_priv =
-                   (drm_i830_private_t *) dev->dev_private;
-
-               if (dev_priv->ring.virtual_start) {
-                       drm_core_ioremapfree(&dev_priv->ring.map, dev);
-               }
-               if (dev_priv->hw_status_page) {
-                       pci_free_consistent(dev->pdev, PAGE_SIZE,
-                                           dev_priv->hw_status_page,
-                                           dev_priv->dma_status_page);
-                       /* Need to rewrite hardware status page */
-                       I830_WRITE(0x02080, 0x1ffff000);
-               }
-
-               drm_free(dev->dev_private, sizeof(drm_i830_private_t),
-                        DRM_MEM_DRIVER);
-               dev->dev_private = NULL;
-
-               for (i = 0; i < dma->buf_count; i++) {
-                       struct drm_buf *buf = dma->buflist[i];
-                       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-                       if (buf_priv->kernel_virtual && buf->total)
-                               drm_core_ioremapfree(&buf_priv->map, dev);
-               }
-       }
-       return 0;
-}
-
-int i830_wait_ring(struct drm_device * dev, int n, const char *caller)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
-       int iters = 0;
-       unsigned long end;
-       unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-
-       end = jiffies + (HZ * 3);
-       while (ring->space < n) {
-               ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-               ring->space = ring->head - (ring->tail + 8);
-               if (ring->space < 0)
-                       ring->space += ring->Size;
-
-               if (ring->head != last_head) {
-                       end = jiffies + (HZ * 3);
-                       last_head = ring->head;
-               }
-
-               iters++;
-               if (time_before(end, jiffies)) {
-                       DRM_ERROR("space: %d wanted %d\n", ring->space, n);
-                       DRM_ERROR("lockup\n");
-                       goto out_wait_ring;
-               }
-               udelay(1);
-               dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
-       }
-
-      out_wait_ring:
-       return iters;
-}
-
-static void i830_kernel_lost_context(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
-
-       ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-       ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
-       ring->space = ring->head - (ring->tail + 8);
-       if (ring->space < 0)
-               ring->space += ring->Size;
-
-       if (ring->head == ring->tail)
-               dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
-}
-
-static int i830_freelist_init(struct drm_device * dev, drm_i830_private_t * dev_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int my_idx = 36;
-       u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
-       int i;
-
-       if (dma->buf_count > 1019) {
-               /* Not enough space in the status page for the freelist */
-               return -EINVAL;
-       }
-
-       for (i = 0; i < dma->buf_count; i++) {
-               struct drm_buf *buf = dma->buflist[i];
-               drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-
-               buf_priv->in_use = hw_status++;
-               buf_priv->my_use_idx = my_idx;
-               my_idx += 4;
-
-               *buf_priv->in_use = I830_BUF_FREE;
-
-               buf_priv->map.offset = buf->bus_address;
-               buf_priv->map.size = buf->total;
-               buf_priv->map.type = _DRM_AGP;
-               buf_priv->map.flags = 0;
-               buf_priv->map.mtrr = 0;
-
-               drm_core_ioremap(&buf_priv->map, dev);
-               buf_priv->kernel_virtual = buf_priv->map.handle;
-       }
-       return 0;
-}
-
-static int i830_dma_initialize(struct drm_device * dev,
-                              drm_i830_private_t * dev_priv,
-                              drm_i830_init_t * init)
-{
-       struct drm_map_list *r_list;
-
-       memset(dev_priv, 0, sizeof(drm_i830_private_t));
-
-       list_for_each_entry(r_list, &dev->maplist, head) {
-               if (r_list->map &&
-                   r_list->map->type == _DRM_SHM &&
-                   r_list->map->flags & _DRM_CONTAINS_LOCK) {
-                       dev_priv->sarea_map = r_list->map;
-                       break;
-               }
-       }
-
-       if (!dev_priv->sarea_map) {
-               dev->dev_private = (void *)dev_priv;
-               i830_dma_cleanup(dev);
-               DRM_ERROR("can not find sarea!\n");
-               return -EINVAL;
-       }
-       dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
-       if (!dev_priv->mmio_map) {
-               dev->dev_private = (void *)dev_priv;
-               i830_dma_cleanup(dev);
-               DRM_ERROR("can not find mmio map!\n");
-               return -EINVAL;
-       }
-       dev->agp_buffer_token = init->buffers_offset;
-       dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
-       if (!dev->agp_buffer_map) {
-               dev->dev_private = (void *)dev_priv;
-               i830_dma_cleanup(dev);
-               DRM_ERROR("can not find dma buffer map!\n");
-               return -EINVAL;
-       }
-
-       dev_priv->sarea_priv = (drm_i830_sarea_t *)
-           ((u8 *) dev_priv->sarea_map->handle + init->sarea_priv_offset);
-
-       dev_priv->ring.Start = init->ring_start;
-       dev_priv->ring.End = init->ring_end;
-       dev_priv->ring.Size = init->ring_size;
-
-       dev_priv->ring.map.offset = dev->agp->base + init->ring_start;
-       dev_priv->ring.map.size = init->ring_size;
-       dev_priv->ring.map.type = _DRM_AGP;
-       dev_priv->ring.map.flags = 0;
-       dev_priv->ring.map.mtrr = 0;
-
-       drm_core_ioremap(&dev_priv->ring.map, dev);
-
-       if (dev_priv->ring.map.handle == NULL) {
-               dev->dev_private = (void *)dev_priv;
-               i830_dma_cleanup(dev);
-               DRM_ERROR("can not ioremap virtual address for"
-                         " ring buffer\n");
-               return -ENOMEM;
-       }
-
-       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
-
-       dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
-
-       dev_priv->w = init->w;
-       dev_priv->h = init->h;
-       dev_priv->pitch = init->pitch;
-       dev_priv->back_offset = init->back_offset;
-       dev_priv->depth_offset = init->depth_offset;
-       dev_priv->front_offset = init->front_offset;
-
-       dev_priv->front_di1 = init->front_offset | init->pitch_bits;
-       dev_priv->back_di1 = init->back_offset | init->pitch_bits;
-       dev_priv->zi1 = init->depth_offset | init->pitch_bits;
-
-       DRM_DEBUG("front_di1 %x\n", dev_priv->front_di1);
-       DRM_DEBUG("back_offset %x\n", dev_priv->back_offset);
-       DRM_DEBUG("back_di1 %x\n", dev_priv->back_di1);
-       DRM_DEBUG("pitch_bits %x\n", init->pitch_bits);
-
-       dev_priv->cpp = init->cpp;
-       /* We are using separate values as placeholders for mechanisms for
-        * private backbuffer/depthbuffer usage.
-        */
-
-       dev_priv->back_pitch = init->back_pitch;
-       dev_priv->depth_pitch = init->depth_pitch;
-       dev_priv->do_boxes = 0;
-       dev_priv->use_mi_batchbuffer_start = 0;
-
-       /* Program Hardware Status Page */
-       dev_priv->hw_status_page =
-           pci_alloc_consistent(dev->pdev, PAGE_SIZE,
-                                &dev_priv->dma_status_page);
-       if (!dev_priv->hw_status_page) {
-               dev->dev_private = (void *)dev_priv;
-               i830_dma_cleanup(dev);
-               DRM_ERROR("Can not allocate hardware status page\n");
-               return -ENOMEM;
-       }
-       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-       DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-
-       I830_WRITE(0x02080, dev_priv->dma_status_page);
-       DRM_DEBUG("Enabled hardware status page\n");
-
-       /* Now we need to init our freelist */
-       if (i830_freelist_init(dev, dev_priv) != 0) {
-               dev->dev_private = (void *)dev_priv;
-               i830_dma_cleanup(dev);
-               DRM_ERROR("Not enough space in the status page for"
-                         " the freelist\n");
-               return -ENOMEM;
-       }
-       dev->dev_private = (void *)dev_priv;
-
-       return 0;
-}
-
-static int i830_dma_init(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i830_private_t *dev_priv;
-       drm_i830_init_t *init = data;
-       int retcode = 0;
-
-       switch (init->func) {
-       case I830_INIT_DMA:
-               dev_priv = drm_alloc(sizeof(drm_i830_private_t),
-                                    DRM_MEM_DRIVER);
-               if (dev_priv == NULL)
-                       return -ENOMEM;
-               retcode = i830_dma_initialize(dev, dev_priv, init);
-               break;
-       case I830_CLEANUP_DMA:
-               retcode = i830_dma_cleanup(dev);
-               break;
-       default:
-               retcode = -EINVAL;
-               break;
-       }
-
-       return retcode;
-}
-
-#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-#define ST1_ENABLE               (1<<16)
-#define ST1_MASK                 (0xffff)
-
-/* Most efficient way to verify state for the i830 is as it is
- * emitted.  Non-conformant state is silently dropped.
- */
-static void i830EmitContextVerified(struct drm_device * dev, unsigned int *code)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       int i, j = 0;
-       unsigned int tmp;
-       RING_LOCALS;
-
-       BEGIN_LP_RING(I830_CTX_SETUP_SIZE + 4);
-
-       for (i = 0; i < I830_CTXREG_BLENDCOLR0; i++) {
-               tmp = code[i];
-               if ((tmp & (7 << 29)) == CMD_3D &&
-                   (tmp & (0x1f << 24)) < (0x1d << 24)) {
-                       OUT_RING(tmp);
-                       j++;
-               } else {
-                       DRM_ERROR("Skipping %d\n", i);
-               }
-       }
-
-       OUT_RING(STATE3D_CONST_BLEND_COLOR_CMD);
-       OUT_RING(code[I830_CTXREG_BLENDCOLR]);
-       j += 2;
-
-       for (i = I830_CTXREG_VF; i < I830_CTXREG_MCSB0; i++) {
-               tmp = code[i];
-               if ((tmp & (7 << 29)) == CMD_3D &&
-                   (tmp & (0x1f << 24)) < (0x1d << 24)) {
-                       OUT_RING(tmp);
-                       j++;
-               } else {
-                       DRM_ERROR("Skipping %d\n", i);
-               }
-       }
-
-       OUT_RING(STATE3D_MAP_COORD_SETBIND_CMD);
-       OUT_RING(code[I830_CTXREG_MCSB1]);
-       j += 2;
-
-       if (j & 1)
-               OUT_RING(0);
-
-       ADVANCE_LP_RING();
-}
-
-static void i830EmitTexVerified(struct drm_device * dev, unsigned int *code)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       int i, j = 0;
-       unsigned int tmp;
-       RING_LOCALS;
-
-       if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO ||
-           (code[I830_TEXREG_MI0] & ~(0xf * LOAD_TEXTURE_MAP0)) ==
-           (STATE3D_LOAD_STATE_IMMEDIATE_2 | 4)) {
-
-               BEGIN_LP_RING(I830_TEX_SETUP_SIZE);
-
-               OUT_RING(code[I830_TEXREG_MI0]);        /* TM0LI */
-               OUT_RING(code[I830_TEXREG_MI1]);        /* TM0S0 */
-               OUT_RING(code[I830_TEXREG_MI2]);        /* TM0S1 */
-               OUT_RING(code[I830_TEXREG_MI3]);        /* TM0S2 */
-               OUT_RING(code[I830_TEXREG_MI4]);        /* TM0S3 */
-               OUT_RING(code[I830_TEXREG_MI5]);        /* TM0S4 */
-
-               for (i = 6; i < I830_TEX_SETUP_SIZE; i++) {
-                       tmp = code[i];
-                       OUT_RING(tmp);
-                       j++;
-               }
-
-               if (j & 1)
-                       OUT_RING(0);
-
-               ADVANCE_LP_RING();
-       } else
-               printk("rejected packet %x\n", code[0]);
-}
-
-static void i830EmitTexBlendVerified(struct drm_device * dev,
-                                    unsigned int *code, unsigned int num)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       int i, j = 0;
-       unsigned int tmp;
-       RING_LOCALS;
-
-       if (!num)
-               return;
-
-       BEGIN_LP_RING(num + 1);
-
-       for (i = 0; i < num; i++) {
-               tmp = code[i];
-               OUT_RING(tmp);
-               j++;
-       }
-
-       if (j & 1)
-               OUT_RING(0);
-
-       ADVANCE_LP_RING();
-}
-
-static void i830EmitTexPalette(struct drm_device * dev,
-                              unsigned int *palette, int number, int is_shared)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       int i;
-       RING_LOCALS;
-
-       return;
-
-       BEGIN_LP_RING(258);
-
-       if (is_shared == 1) {
-               OUT_RING(CMD_OP_MAP_PALETTE_LOAD |
-                        MAP_PALETTE_NUM(0) | MAP_PALETTE_BOTH);
-       } else {
-               OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
-       }
-       for (i = 0; i < 256; i++) {
-               OUT_RING(palette[i]);
-       }
-       OUT_RING(0);
-       /* KW:  WHERE IS THE ADVANCE_LP_RING?  This is effectively a noop!
-        */
-}
-
-/* Need to do some additional checking when setting the dest buffer.
- */
-static void i830EmitDestVerified(struct drm_device * dev, unsigned int *code)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       unsigned int tmp;
-       RING_LOCALS;
-
-       BEGIN_LP_RING(I830_DEST_SETUP_SIZE + 10);
-
-       tmp = code[I830_DESTREG_CBUFADDR];
-       if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
-               if (((int)outring) & 8) {
-                       OUT_RING(0);
-                       OUT_RING(0);
-               }
-
-               OUT_RING(CMD_OP_DESTBUFFER_INFO);
-               OUT_RING(BUF_3D_ID_COLOR_BACK |
-                        BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
-                        BUF_3D_USE_FENCE);
-               OUT_RING(tmp);
-               OUT_RING(0);
-
-               OUT_RING(CMD_OP_DESTBUFFER_INFO);
-               OUT_RING(BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE |
-                        BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
-               OUT_RING(dev_priv->zi1);
-               OUT_RING(0);
-       } else {
-               DRM_ERROR("bad di1 %x (allow %x or %x)\n",
-                         tmp, dev_priv->front_di1, dev_priv->back_di1);
-       }
-
-       /* invarient:
-        */
-
-       OUT_RING(GFX_OP_DESTBUFFER_VARS);
-       OUT_RING(code[I830_DESTREG_DV1]);
-
-       OUT_RING(GFX_OP_DRAWRECT_INFO);
-       OUT_RING(code[I830_DESTREG_DR1]);
-       OUT_RING(code[I830_DESTREG_DR2]);
-       OUT_RING(code[I830_DESTREG_DR3]);
-       OUT_RING(code[I830_DESTREG_DR4]);
-
-       /* Need to verify this */
-       tmp = code[I830_DESTREG_SENABLE];
-       if ((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
-               OUT_RING(tmp);
-       } else {
-               DRM_ERROR("bad scissor enable\n");
-               OUT_RING(0);
-       }
-
-       OUT_RING(GFX_OP_SCISSOR_RECT);
-       OUT_RING(code[I830_DESTREG_SR1]);
-       OUT_RING(code[I830_DESTREG_SR2]);
-       OUT_RING(0);
-
-       ADVANCE_LP_RING();
-}
-
-static void i830EmitStippleVerified(struct drm_device * dev, unsigned int *code)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-
-       BEGIN_LP_RING(2);
-       OUT_RING(GFX_OP_STIPPLE);
-       OUT_RING(code[1]);
-       ADVANCE_LP_RING();
-}
-
-static void i830EmitState(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       unsigned int dirty = sarea_priv->dirty;
-
-       DRM_DEBUG("%s %x\n", __func__, dirty);
-
-       if (dirty & I830_UPLOAD_BUFFERS) {
-               i830EmitDestVerified(dev, sarea_priv->BufferState);
-               sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS;
-       }
-
-       if (dirty & I830_UPLOAD_CTX) {
-               i830EmitContextVerified(dev, sarea_priv->ContextState);
-               sarea_priv->dirty &= ~I830_UPLOAD_CTX;
-       }
-
-       if (dirty & I830_UPLOAD_TEX0) {
-               i830EmitTexVerified(dev, sarea_priv->TexState[0]);
-               sarea_priv->dirty &= ~I830_UPLOAD_TEX0;
-       }
-
-       if (dirty & I830_UPLOAD_TEX1) {
-               i830EmitTexVerified(dev, sarea_priv->TexState[1]);
-               sarea_priv->dirty &= ~I830_UPLOAD_TEX1;
-       }
-
-       if (dirty & I830_UPLOAD_TEXBLEND0) {
-               i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[0],
-                                        sarea_priv->TexBlendStateWordsUsed[0]);
-               sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0;
-       }
-
-       if (dirty & I830_UPLOAD_TEXBLEND1) {
-               i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[1],
-                                        sarea_priv->TexBlendStateWordsUsed[1]);
-               sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1;
-       }
-
-       if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) {
-               i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1);
-       } else {
-               if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
-                       i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0);
-                       sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0);
-               }
-               if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
-                       i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0);
-                       sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1);
-               }
-
-               /* 1.3:
-                */
-#if 0
-               if (dirty & I830_UPLOAD_TEX_PALETTE_N(2)) {
-                       i830EmitTexPalette(dev, sarea_priv->Palette2[0], 0, 0);
-                       sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
-               }
-               if (dirty & I830_UPLOAD_TEX_PALETTE_N(3)) {
-                       i830EmitTexPalette(dev, sarea_priv->Palette2[1], 1, 0);
-                       sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
-               }
-#endif
-       }
-
-       /* 1.3:
-        */
-       if (dirty & I830_UPLOAD_STIPPLE) {
-               i830EmitStippleVerified(dev, sarea_priv->StippleState);
-               sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE;
-       }
-
-       if (dirty & I830_UPLOAD_TEX2) {
-               i830EmitTexVerified(dev, sarea_priv->TexState2);
-               sarea_priv->dirty &= ~I830_UPLOAD_TEX2;
-       }
-
-       if (dirty & I830_UPLOAD_TEX3) {
-               i830EmitTexVerified(dev, sarea_priv->TexState3);
-               sarea_priv->dirty &= ~I830_UPLOAD_TEX3;
-       }
-
-       if (dirty & I830_UPLOAD_TEXBLEND2) {
-               i830EmitTexBlendVerified(dev,
-                                        sarea_priv->TexBlendState2,
-                                        sarea_priv->TexBlendStateWordsUsed2);
-
-               sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2;
-       }
-
-       if (dirty & I830_UPLOAD_TEXBLEND3) {
-               i830EmitTexBlendVerified(dev,
-                                        sarea_priv->TexBlendState3,
-                                        sarea_priv->TexBlendStateWordsUsed3);
-               sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3;
-       }
-}
-
-/* ================================================================
- * Performance monitoring functions
- */
-
-static void i830_fill_box(struct drm_device * dev,
-                         int x, int y, int w, int h, int r, int g, int b)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       u32 color;
-       unsigned int BR13, CMD;
-       RING_LOCALS;
-
-       BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1 << 24);
-       CMD = XY_COLOR_BLT_CMD;
-       x += dev_priv->sarea_priv->boxes[0].x1;
-       y += dev_priv->sarea_priv->boxes[0].y1;
-
-       if (dev_priv->cpp == 4) {
-               BR13 |= (1 << 25);
-               CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
-               color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
-       } else {
-               color = (((r & 0xf8) << 8) |
-                        ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
-       }
-
-       BEGIN_LP_RING(6);
-       OUT_RING(CMD);
-       OUT_RING(BR13);
-       OUT_RING((y << 16) | x);
-       OUT_RING(((y + h) << 16) | (x + w));
-
-       if (dev_priv->current_page == 1) {
-               OUT_RING(dev_priv->front_offset);
-       } else {
-               OUT_RING(dev_priv->back_offset);
-       }
-
-       OUT_RING(color);
-       ADVANCE_LP_RING();
-}
-
-static void i830_cp_performance_boxes(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-
-       /* Purple box for page flipping
-        */
-       if (dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP)
-               i830_fill_box(dev, 4, 4, 8, 8, 255, 0, 255);
-
-       /* Red box if we have to wait for idle at any point
-        */
-       if (dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT)
-               i830_fill_box(dev, 16, 4, 8, 8, 255, 0, 0);
-
-       /* Blue box: lost context?
-        */
-       if (dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT)
-               i830_fill_box(dev, 28, 4, 8, 8, 0, 0, 255);
-
-       /* Yellow box for texture swaps
-        */
-       if (dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD)
-               i830_fill_box(dev, 40, 4, 8, 8, 255, 255, 0);
-
-       /* Green box if hardware never idles (as far as we can tell)
-        */
-       if (!(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY))
-               i830_fill_box(dev, 64, 4, 8, 8, 0, 255, 0);
-
-       /* Draw bars indicating number of buffers allocated
-        * (not a great measure, easily confused)
-        */
-       if (dev_priv->dma_used) {
-               int bar = dev_priv->dma_used / 10240;
-               if (bar > 100)
-                       bar = 100;
-               if (bar < 1)
-                       bar = 1;
-               i830_fill_box(dev, 4, 16, bar, 4, 196, 128, 128);
-               dev_priv->dma_used = 0;
-       }
-
-       dev_priv->sarea_priv->perf_boxes = 0;
-}
-
-static void i830_dma_dispatch_clear(struct drm_device * dev, int flags,
-                                   unsigned int clear_color,
-                                   unsigned int clear_zval,
-                                   unsigned int clear_depthmask)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int nbox = sarea_priv->nbox;
-       struct drm_clip_rect *pbox = sarea_priv->boxes;
-       int pitch = dev_priv->pitch;
-       int cpp = dev_priv->cpp;
-       int i;
-       unsigned int BR13, CMD, D_CMD;
-       RING_LOCALS;
-
-       if (dev_priv->current_page == 1) {
-               unsigned int tmp = flags;
-
-               flags &= ~(I830_FRONT | I830_BACK);
-               if (tmp & I830_FRONT)
-                       flags |= I830_BACK;
-               if (tmp & I830_BACK)
-                       flags |= I830_FRONT;
-       }
-
-       i830_kernel_lost_context(dev);
-
-       switch (cpp) {
-       case 2:
-               BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
-               D_CMD = CMD = XY_COLOR_BLT_CMD;
-               break;
-       case 4:
-               BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24) | (1 << 25);
-               CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
-                      XY_COLOR_BLT_WRITE_RGB);
-               D_CMD = XY_COLOR_BLT_CMD;
-               if (clear_depthmask & 0x00ffffff)
-                       D_CMD |= XY_COLOR_BLT_WRITE_RGB;
-               if (clear_depthmask & 0xff000000)
-                       D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
-               break;
-       default:
-               BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
-               D_CMD = CMD = XY_COLOR_BLT_CMD;
-               break;
-       }
-
-       if (nbox > I830_NR_SAREA_CLIPRECTS)
-               nbox = I830_NR_SAREA_CLIPRECTS;
-
-       for (i = 0; i < nbox; i++, pbox++) {
-               if (pbox->x1 > pbox->x2 ||
-                   pbox->y1 > pbox->y2 ||
-                   pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
-                       continue;
-
-               if (flags & I830_FRONT) {
-                       DRM_DEBUG("clear front\n");
-                       BEGIN_LP_RING(6);
-                       OUT_RING(CMD);
-                       OUT_RING(BR13);
-                       OUT_RING((pbox->y1 << 16) | pbox->x1);
-                       OUT_RING((pbox->y2 << 16) | pbox->x2);
-                       OUT_RING(dev_priv->front_offset);
-                       OUT_RING(clear_color);
-                       ADVANCE_LP_RING();
-               }
-
-               if (flags & I830_BACK) {
-                       DRM_DEBUG("clear back\n");
-                       BEGIN_LP_RING(6);
-                       OUT_RING(CMD);
-                       OUT_RING(BR13);
-                       OUT_RING((pbox->y1 << 16) | pbox->x1);
-                       OUT_RING((pbox->y2 << 16) | pbox->x2);
-                       OUT_RING(dev_priv->back_offset);
-                       OUT_RING(clear_color);
-                       ADVANCE_LP_RING();
-               }
-
-               if (flags & I830_DEPTH) {
-                       DRM_DEBUG("clear depth\n");
-                       BEGIN_LP_RING(6);
-                       OUT_RING(D_CMD);
-                       OUT_RING(BR13);
-                       OUT_RING((pbox->y1 << 16) | pbox->x1);
-                       OUT_RING((pbox->y2 << 16) | pbox->x2);
-                       OUT_RING(dev_priv->depth_offset);
-                       OUT_RING(clear_zval);
-                       ADVANCE_LP_RING();
-               }
-       }
-}
-
-static void i830_dma_dispatch_swap(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int nbox = sarea_priv->nbox;
-       struct drm_clip_rect *pbox = sarea_priv->boxes;
-       int pitch = dev_priv->pitch;
-       int cpp = dev_priv->cpp;
-       int i;
-       unsigned int CMD, BR13;
-       RING_LOCALS;
-
-       DRM_DEBUG("swapbuffers\n");
-
-       i830_kernel_lost_context(dev);
-
-       if (dev_priv->do_boxes)
-               i830_cp_performance_boxes(dev);
-
-       switch (cpp) {
-       case 2:
-               BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
-               CMD = XY_SRC_COPY_BLT_CMD;
-               break;
-       case 4:
-               BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
-               CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
-                      XY_SRC_COPY_BLT_WRITE_RGB);
-               break;
-       default:
-               BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
-               CMD = XY_SRC_COPY_BLT_CMD;
-               break;
-       }
-
-       if (nbox > I830_NR_SAREA_CLIPRECTS)
-               nbox = I830_NR_SAREA_CLIPRECTS;
-
-       for (i = 0; i < nbox; i++, pbox++) {
-               if (pbox->x1 > pbox->x2 ||
-                   pbox->y1 > pbox->y2 ||
-                   pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
-                       continue;
-
-               DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
-                         pbox->x1, pbox->y1, pbox->x2, pbox->y2);
-
-               BEGIN_LP_RING(8);
-               OUT_RING(CMD);
-               OUT_RING(BR13);
-               OUT_RING((pbox->y1 << 16) | pbox->x1);
-               OUT_RING((pbox->y2 << 16) | pbox->x2);
-
-               if (dev_priv->current_page == 0)
-                       OUT_RING(dev_priv->front_offset);
-               else
-                       OUT_RING(dev_priv->back_offset);
-
-               OUT_RING((pbox->y1 << 16) | pbox->x1);
-               OUT_RING(BR13 & 0xffff);
-
-               if (dev_priv->current_page == 0)
-                       OUT_RING(dev_priv->back_offset);
-               else
-                       OUT_RING(dev_priv->front_offset);
-
-               ADVANCE_LP_RING();
-       }
-}
-
-static void i830_dma_dispatch_flip(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-
-       DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
-                 __func__,
-                 dev_priv->current_page,
-                 dev_priv->sarea_priv->pf_current_page);
-
-       i830_kernel_lost_context(dev);
-
-       if (dev_priv->do_boxes) {
-               dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP;
-               i830_cp_performance_boxes(dev);
-       }
-
-       BEGIN_LP_RING(2);
-       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       BEGIN_LP_RING(6);
-       OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
-       OUT_RING(0);
-       if (dev_priv->current_page == 0) {
-               OUT_RING(dev_priv->back_offset);
-               dev_priv->current_page = 1;
-       } else {
-               OUT_RING(dev_priv->front_offset);
-               dev_priv->current_page = 0;
-       }
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       BEGIN_LP_RING(2);
-       OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
-}
-
-static void i830_dma_dispatch_vertex(struct drm_device * dev,
-                                    struct drm_buf * buf, int discard, int used)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-       drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       struct drm_clip_rect *box = sarea_priv->boxes;
-       int nbox = sarea_priv->nbox;
-       unsigned long address = (unsigned long)buf->bus_address;
-       unsigned long start = address - dev->agp->base;
-       int i = 0, u;
-       RING_LOCALS;
-
-       i830_kernel_lost_context(dev);
-
-       if (nbox > I830_NR_SAREA_CLIPRECTS)
-               nbox = I830_NR_SAREA_CLIPRECTS;
-
-       if (discard) {
-               u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
-                           I830_BUF_HARDWARE);
-               if (u != I830_BUF_CLIENT) {
-                       DRM_DEBUG("xxxx 2\n");
-               }
-       }
-
-       if (used > 4 * 1023)
-               used = 0;
-
-       if (sarea_priv->dirty)
-               i830EmitState(dev);
-
-       DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
-                 address, used, nbox);
-
-       dev_priv->counter++;
-       DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
-       DRM_DEBUG("i830_dma_dispatch\n");
-       DRM_DEBUG("start : %lx\n", start);
-       DRM_DEBUG("used : %d\n", used);
-       DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
-
-       if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
-               u32 *vp = buf_priv->kernel_virtual;
-
-               vp[0] = (GFX_OP_PRIMITIVE |
-                        sarea_priv->vertex_prim | ((used / 4) - 2));
-
-               if (dev_priv->use_mi_batchbuffer_start) {
-                       vp[used / 4] = MI_BATCH_BUFFER_END;
-                       used += 4;
-               }
-
-               if (used & 4) {
-                       vp[used / 4] = 0;
-                       used += 4;
-               }
-
-               i830_unmap_buffer(buf);
-       }
-
-       if (used) {
-               do {
-                       if (i < nbox) {
-                               BEGIN_LP_RING(6);
-                               OUT_RING(GFX_OP_DRAWRECT_INFO);
-                               OUT_RING(sarea_priv->
-                                        BufferState[I830_DESTREG_DR1]);
-                               OUT_RING(box[i].x1 | (box[i].y1 << 16));
-                               OUT_RING(box[i].x2 | (box[i].y2 << 16));
-                               OUT_RING(sarea_priv->
-                                        BufferState[I830_DESTREG_DR4]);
-                               OUT_RING(0);
-                               ADVANCE_LP_RING();
-                       }
-
-                       if (dev_priv->use_mi_batchbuffer_start) {
-                               BEGIN_LP_RING(2);
-                               OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
-                               OUT_RING(start | MI_BATCH_NON_SECURE);
-                               ADVANCE_LP_RING();
-                       } else {
-                               BEGIN_LP_RING(4);
-                               OUT_RING(MI_BATCH_BUFFER);
-                               OUT_RING(start | MI_BATCH_NON_SECURE);
-                               OUT_RING(start + used - 4);
-                               OUT_RING(0);
-                               ADVANCE_LP_RING();
-                       }
-
-               } while (++i < nbox);
-       }
-
-       if (discard) {
-               dev_priv->counter++;
-
-               (void)cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
-                             I830_BUF_HARDWARE);
-
-               BEGIN_LP_RING(8);
-               OUT_RING(CMD_STORE_DWORD_IDX);
-               OUT_RING(20);
-               OUT_RING(dev_priv->counter);
-               OUT_RING(CMD_STORE_DWORD_IDX);
-               OUT_RING(buf_priv->my_use_idx);
-               OUT_RING(I830_BUF_FREE);
-               OUT_RING(CMD_REPORT_HEAD);
-               OUT_RING(0);
-               ADVANCE_LP_RING();
-       }
-}
-
-static void i830_dma_quiescent(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-
-       i830_kernel_lost_context(dev);
-
-       BEGIN_LP_RING(4);
-       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-       OUT_RING(CMD_REPORT_HEAD);
-       OUT_RING(0);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
-}
-
-static int i830_flush_queue(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       int i, ret = 0;
-       RING_LOCALS;
-
-       i830_kernel_lost_context(dev);
-
-       BEGIN_LP_RING(2);
-       OUT_RING(CMD_REPORT_HEAD);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
-
-       for (i = 0; i < dma->buf_count; i++) {
-               struct drm_buf *buf = dma->buflist[i];
-               drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-
-               int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,
-                                  I830_BUF_FREE);
-
-               if (used == I830_BUF_HARDWARE)
-                       DRM_DEBUG("reclaimed from HARDWARE\n");
-               if (used == I830_BUF_CLIENT)
-                       DRM_DEBUG("still on client\n");
-       }
-
-       return ret;
-}
-
-/* Must be called with the lock held */
-static void i830_reclaim_buffers(struct drm_device * dev, struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int i;
-
-       if (!dma)
-               return;
-       if (!dev->dev_private)
-               return;
-       if (!dma->buflist)
-               return;
-
-       i830_flush_queue(dev);
-
-       for (i = 0; i < dma->buf_count; i++) {
-               struct drm_buf *buf = dma->buflist[i];
-               drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-
-               if (buf->file_priv == file_priv && buf_priv) {
-                       int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
-                                          I830_BUF_FREE);
-
-                       if (used == I830_BUF_CLIENT)
-                               DRM_DEBUG("reclaimed from client\n");
-                       if (buf_priv->currently_mapped == I830_BUF_MAPPED)
-                               buf_priv->currently_mapped = I830_BUF_UNMAPPED;
-               }
-       }
-}
-
-static int i830_flush_ioctl(struct drm_device *dev, void *data,
-                           struct drm_file *file_priv)
-{
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       i830_flush_queue(dev);
-       return 0;
-}
-
-static int i830_dma_vertex(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
-       drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
-           dev_priv->sarea_priv;
-       drm_i830_vertex_t *vertex = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n",
-                 vertex->idx, vertex->used, vertex->discard);
-
-       if (vertex->idx < 0 || vertex->idx > dma->buf_count)
-               return -EINVAL;
-
-       i830_dma_dispatch_vertex(dev,
-                                dma->buflist[vertex->idx],
-                                vertex->discard, vertex->used);
-
-       sarea_priv->last_enqueue = dev_priv->counter - 1;
-       sarea_priv->last_dispatch = (int)hw_status[5];
-
-       return 0;
-}
-
-static int i830_clear_bufs(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv)
-{
-       drm_i830_clear_t *clear = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       /* GH: Someone's doing nasty things... */
-       if (!dev->dev_private) {
-               return -EINVAL;
-       }
-
-       i830_dma_dispatch_clear(dev, clear->flags,
-                               clear->clear_color,
-                               clear->clear_depth, clear->clear_depthmask);
-       return 0;
-}
-
-static int i830_swap_bufs(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv)
-{
-       DRM_DEBUG("i830_swap_bufs\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       i830_dma_dispatch_swap(dev);
-       return 0;
-}
-
-/* Not sure why this isn't set all the time:
- */
-static void i830_do_init_pageflip(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-
-       DRM_DEBUG("%s\n", __func__);
-       dev_priv->page_flipping = 1;
-       dev_priv->current_page = 0;
-       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
-}
-
-static int i830_do_cleanup_pageflip(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-
-       DRM_DEBUG("%s\n", __func__);
-       if (dev_priv->current_page != 0)
-               i830_dma_dispatch_flip(dev);
-
-       dev_priv->page_flipping = 0;
-       return 0;
-}
-
-static int i830_flip_bufs(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-
-       DRM_DEBUG("%s\n", __func__);
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (!dev_priv->page_flipping)
-               i830_do_init_pageflip(dev);
-
-       i830_dma_dispatch_flip(dev);
-       return 0;
-}
-
-static int i830_getage(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
-       drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
-           dev_priv->sarea_priv;
-
-       sarea_priv->last_dispatch = (int)hw_status[5];
-       return 0;
-}
-
-static int i830_getbuf(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       int retcode = 0;
-       drm_i830_dma_t *d = data;
-       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
-       drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
-           dev_priv->sarea_priv;
-
-       DRM_DEBUG("getbuf\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       d->granted = 0;
-
-       retcode = i830_dma_get_buffer(dev, d, file_priv);
-
-       DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
-                 task_pid_nr(current), retcode, d->granted);
-
-       sarea_priv->last_dispatch = (int)hw_status[5];
-
-       return retcode;
-}
-
-static int i830_copybuf(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv)
-{
-       /* Never copy - 2.4.x doesn't need it */
-       return 0;
-}
-
-static int i830_docopy(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       return 0;
-}
-
-static int i830_getparam(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       drm_i830_getparam_t *param = data;
-       int value;
-
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __func__);
-               return -EINVAL;
-       }
-
-       switch (param->param) {
-       case I830_PARAM_IRQ_ACTIVE:
-               value = dev->irq_enabled;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (copy_to_user(param->value, &value, sizeof(int))) {
-               DRM_ERROR("copy_to_user\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-static int i830_setparam(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       drm_i830_setparam_t *param = data;
-
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __func__);
-               return -EINVAL;
-       }
-
-       switch (param->param) {
-       case I830_SETPARAM_USE_MI_BATCHBUFFER_START:
-               dev_priv->use_mi_batchbuffer_start = param->value;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-int i830_driver_load(struct drm_device *dev, unsigned long flags)
-{
-       /* i830 has 4 more counters */
-       dev->counters += 4;
-       dev->types[6] = _DRM_STAT_IRQ;
-       dev->types[7] = _DRM_STAT_PRIMARY;
-       dev->types[8] = _DRM_STAT_SECONDARY;
-       dev->types[9] = _DRM_STAT_DMA;
-
-       return 0;
-}
-
-void i830_driver_lastclose(struct drm_device * dev)
-{
-       i830_dma_cleanup(dev);
-}
-
-void i830_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
-{
-       if (dev->dev_private) {
-               drm_i830_private_t *dev_priv = dev->dev_private;
-               if (dev_priv->page_flipping) {
-                       i830_do_cleanup_pageflip(dev);
-               }
-       }
-}
-
-void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct drm_file *file_priv)
-{
-       i830_reclaim_buffers(dev, file_priv);
-}
-
-int i830_driver_dma_quiescent(struct drm_device * dev)
-{
-       i830_dma_quiescent(dev);
-       return 0;
-}
-
-struct drm_ioctl_desc i830_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH)
-};
-
-int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
-
-/**
- * Determine if the device really is AGP or not.
- *
- * All Intel graphics chipsets are treated as AGP, even if they are really
- * PCI-e.
- *
- * \param dev   The device to be tested.
- *
- * \returns
- * A value of 1 is always retured to indictate every i8xx is AGP.
- */
-int i830_driver_device_is_agp(struct drm_device * dev)
-{
-       return 1;
-}
diff --git a/drivers/char/drm/i830_drm.h b/drivers/char/drm/i830_drm.h
deleted file mode 100644 (file)
index 4b00d2d..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-#ifndef _I830_DRM_H_
-#define _I830_DRM_H_
-
-/* WARNING: These defines must be the same as what the Xserver uses.
- * if you change them, you must change the defines in the Xserver.
- *
- * KW: Actually, you can't ever change them because doing so would
- * break backwards compatibility.
- */
-
-#ifndef _I830_DEFINES_
-#define _I830_DEFINES_
-
-#define I830_DMA_BUF_ORDER             12
-#define I830_DMA_BUF_SZ                        (1<<I830_DMA_BUF_ORDER)
-#define I830_DMA_BUF_NR                        256
-#define I830_NR_SAREA_CLIPRECTS                8
-
-/* Each region is a minimum of 64k, and there are at most 64 of them.
- */
-#define I830_NR_TEX_REGIONS 64
-#define I830_LOG_MIN_TEX_REGION_SIZE 16
-
-/* KW: These aren't correct but someone set them to two and then
- * released the module.  Now we can't change them as doing so would
- * break backwards compatibility.
- */
-#define I830_TEXTURE_COUNT     2
-#define I830_TEXBLEND_COUNT    I830_TEXTURE_COUNT
-
-#define I830_TEXBLEND_SIZE     12      /* (4 args + op) * 2 + COLOR_FACTOR */
-
-#define I830_UPLOAD_CTX                        0x1
-#define I830_UPLOAD_BUFFERS            0x2
-#define I830_UPLOAD_CLIPRECTS          0x4
-#define I830_UPLOAD_TEX0_IMAGE         0x100   /* handled clientside */
-#define I830_UPLOAD_TEX0_CUBE          0x200   /* handled clientside */
-#define I830_UPLOAD_TEX1_IMAGE         0x400   /* handled clientside */
-#define I830_UPLOAD_TEX1_CUBE          0x800   /* handled clientside */
-#define I830_UPLOAD_TEX2_IMAGE         0x1000  /* handled clientside */
-#define I830_UPLOAD_TEX2_CUBE          0x2000  /* handled clientside */
-#define I830_UPLOAD_TEX3_IMAGE         0x4000  /* handled clientside */
-#define I830_UPLOAD_TEX3_CUBE          0x8000  /* handled clientside */
-#define I830_UPLOAD_TEX_N_IMAGE(n)     (0x100 << (n * 2))
-#define I830_UPLOAD_TEX_N_CUBE(n)      (0x200 << (n * 2))
-#define I830_UPLOAD_TEXIMAGE_MASK      0xff00
-#define I830_UPLOAD_TEX0                       0x10000
-#define I830_UPLOAD_TEX1                       0x20000
-#define I830_UPLOAD_TEX2                       0x40000
-#define I830_UPLOAD_TEX3                       0x80000
-#define I830_UPLOAD_TEX_N(n)           (0x10000 << (n))
-#define I830_UPLOAD_TEX_MASK           0xf0000
-#define I830_UPLOAD_TEXBLEND0          0x100000
-#define I830_UPLOAD_TEXBLEND1          0x200000
-#define I830_UPLOAD_TEXBLEND2          0x400000
-#define I830_UPLOAD_TEXBLEND3          0x800000
-#define I830_UPLOAD_TEXBLEND_N(n)      (0x100000 << (n))
-#define I830_UPLOAD_TEXBLEND_MASK      0xf00000
-#define I830_UPLOAD_TEX_PALETTE_N(n)    (0x1000000 << (n))
-#define I830_UPLOAD_TEX_PALETTE_SHARED 0x4000000
-#define I830_UPLOAD_STIPPLE            0x8000000
-
-/* Indices into buf.Setup where various bits of state are mirrored per
- * context and per buffer.  These can be fired at the card as a unit,
- * or in a piecewise fashion as required.
- */
-
-/* Destbuffer state
- *    - backbuffer linear offset and pitch -- invarient in the current dri
- *    - zbuffer linear offset and pitch -- also invarient
- *    - drawing origin in back and depth buffers.
- *
- * Keep the depth/back buffer state here to accommodate private buffers
- * in the future.
- */
-
-#define I830_DESTREG_CBUFADDR 0
-#define I830_DESTREG_DBUFADDR 1
-#define I830_DESTREG_DV0 2
-#define I830_DESTREG_DV1 3
-#define I830_DESTREG_SENABLE 4
-#define I830_DESTREG_SR0 5
-#define I830_DESTREG_SR1 6
-#define I830_DESTREG_SR2 7
-#define I830_DESTREG_DR0 8
-#define I830_DESTREG_DR1 9
-#define I830_DESTREG_DR2 10
-#define I830_DESTREG_DR3 11
-#define I830_DESTREG_DR4 12
-#define I830_DEST_SETUP_SIZE 13
-
-/* Context state
- */
-#define I830_CTXREG_STATE1             0
-#define I830_CTXREG_STATE2             1
-#define I830_CTXREG_STATE3             2
-#define I830_CTXREG_STATE4             3
-#define I830_CTXREG_STATE5             4
-#define I830_CTXREG_IALPHAB            5
-#define I830_CTXREG_STENCILTST         6
-#define I830_CTXREG_ENABLES_1          7
-#define I830_CTXREG_ENABLES_2          8
-#define I830_CTXREG_AA                 9
-#define I830_CTXREG_FOGCOLOR           10
-#define I830_CTXREG_BLENDCOLR0         11
-#define I830_CTXREG_BLENDCOLR          12      /* Dword 1 of 2 dword command */
-#define I830_CTXREG_VF                 13
-#define I830_CTXREG_VF2                        14
-#define I830_CTXREG_MCSB0              15
-#define I830_CTXREG_MCSB1              16
-#define I830_CTX_SETUP_SIZE            17
-
-/* 1.3: Stipple state
- */
-#define I830_STPREG_ST0 0
-#define I830_STPREG_ST1 1
-#define I830_STP_SETUP_SIZE 2
-
-/* Texture state (per tex unit)
- */
-
-#define I830_TEXREG_MI0        0       /* GFX_OP_MAP_INFO (6 dwords) */
-#define I830_TEXREG_MI1        1
-#define I830_TEXREG_MI2        2
-#define I830_TEXREG_MI3        3
-#define I830_TEXREG_MI4        4
-#define I830_TEXREG_MI5        5
-#define I830_TEXREG_MF 6       /* GFX_OP_MAP_FILTER */
-#define I830_TEXREG_MLC        7       /* GFX_OP_MAP_LOD_CTL */
-#define I830_TEXREG_MLL        8       /* GFX_OP_MAP_LOD_LIMITS */
-#define I830_TEXREG_MCS        9       /* GFX_OP_MAP_COORD_SETS */
-#define I830_TEX_SETUP_SIZE 10
-
-#define I830_TEXREG_TM0LI      0       /* load immediate 2 texture map n */
-#define I830_TEXREG_TM0S0      1
-#define I830_TEXREG_TM0S1      2
-#define I830_TEXREG_TM0S2      3
-#define I830_TEXREG_TM0S3      4
-#define I830_TEXREG_TM0S4      5
-#define I830_TEXREG_NOP0       6       /* noop */
-#define I830_TEXREG_NOP1       7       /* noop */
-#define I830_TEXREG_NOP2       8       /* noop */
-#define __I830_TEXREG_MCS      9       /* GFX_OP_MAP_COORD_SETS -- shared */
-#define __I830_TEX_SETUP_SIZE   10
-
-#define I830_FRONT   0x1
-#define I830_BACK    0x2
-#define I830_DEPTH   0x4
-
-#endif                         /* _I830_DEFINES_ */
-
-typedef struct _drm_i830_init {
-       enum {
-               I830_INIT_DMA = 0x01,
-               I830_CLEANUP_DMA = 0x02
-       } func;
-       unsigned int mmio_offset;
-       unsigned int buffers_offset;
-       int sarea_priv_offset;
-       unsigned int ring_start;
-       unsigned int ring_end;
-       unsigned int ring_size;
-       unsigned int front_offset;
-       unsigned int back_offset;
-       unsigned int depth_offset;
-       unsigned int w;
-       unsigned int h;
-       unsigned int pitch;
-       unsigned int pitch_bits;
-       unsigned int back_pitch;
-       unsigned int depth_pitch;
-       unsigned int cpp;
-} drm_i830_init_t;
-
-/* Warning: If you change the SAREA structure you must change the Xserver
- * structure as well */
-
-typedef struct _drm_i830_tex_region {
-       unsigned char next, prev;       /* indices to form a circular LRU  */
-       unsigned char in_use;   /* owned by a client, or free? */
-       int age;                /* tracked by clients to update local LRU's */
-} drm_i830_tex_region_t;
-
-typedef struct _drm_i830_sarea {
-       unsigned int ContextState[I830_CTX_SETUP_SIZE];
-       unsigned int BufferState[I830_DEST_SETUP_SIZE];
-       unsigned int TexState[I830_TEXTURE_COUNT][I830_TEX_SETUP_SIZE];
-       unsigned int TexBlendState[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE];
-       unsigned int TexBlendStateWordsUsed[I830_TEXBLEND_COUNT];
-       unsigned int Palette[2][256];
-       unsigned int dirty;
-
-       unsigned int nbox;
-       struct drm_clip_rect boxes[I830_NR_SAREA_CLIPRECTS];
-
-       /* Maintain an LRU of contiguous regions of texture space.  If
-        * you think you own a region of texture memory, and it has an
-        * age different to the one you set, then you are mistaken and
-        * it has been stolen by another client.  If global texAge
-        * hasn't changed, there is no need to walk the list.
-        *
-        * These regions can be used as a proxy for the fine-grained
-        * texture information of other clients - by maintaining them
-        * in the same lru which is used to age their own textures,
-        * clients have an approximate lru for the whole of global
-        * texture space, and can make informed decisions as to which
-        * areas to kick out.  There is no need to choose whether to
-        * kick out your own texture or someone else's - simply eject
-        * them all in LRU order.
-        */
-
-       drm_i830_tex_region_t texList[I830_NR_TEX_REGIONS + 1];
-       /* Last elt is sentinal */
-       int texAge;             /* last time texture was uploaded */
-       int last_enqueue;       /* last time a buffer was enqueued */
-       int last_dispatch;      /* age of the most recently dispatched buffer */
-       int last_quiescent;     /*  */
-       int ctxOwner;           /* last context to upload state */
-
-       int vertex_prim;
-
-       int pf_enabled;         /* is pageflipping allowed? */
-       int pf_active;
-       int pf_current_page;    /* which buffer is being displayed? */
-
-       int perf_boxes;         /* performance boxes to be displayed */
-
-       /* Here's the state for texunits 2,3:
-        */
-       unsigned int TexState2[I830_TEX_SETUP_SIZE];
-       unsigned int TexBlendState2[I830_TEXBLEND_SIZE];
-       unsigned int TexBlendStateWordsUsed2;
-
-       unsigned int TexState3[I830_TEX_SETUP_SIZE];
-       unsigned int TexBlendState3[I830_TEXBLEND_SIZE];
-       unsigned int TexBlendStateWordsUsed3;
-
-       unsigned int StippleState[I830_STP_SETUP_SIZE];
-} drm_i830_sarea_t;
-
-/* Flags for perf_boxes
- */
-#define I830_BOX_RING_EMPTY    0x1     /* populated by kernel */
-#define I830_BOX_FLIP          0x2     /* populated by kernel */
-#define I830_BOX_WAIT          0x4     /* populated by kernel & client */
-#define I830_BOX_TEXTURE_LOAD  0x8     /* populated by kernel */
-#define I830_BOX_LOST_CONTEXT  0x10    /* populated by client */
-
-/* I830 specific ioctls
- * The device specific ioctl range is 0x40 to 0x79.
- */
-#define DRM_I830_INIT  0x00
-#define DRM_I830_VERTEX        0x01
-#define DRM_I830_CLEAR 0x02
-#define DRM_I830_FLUSH 0x03
-#define DRM_I830_GETAGE        0x04
-#define DRM_I830_GETBUF        0x05
-#define DRM_I830_SWAP  0x06
-#define DRM_I830_COPY  0x07
-#define DRM_I830_DOCOPY        0x08
-#define DRM_I830_FLIP  0x09
-#define DRM_I830_IRQ_EMIT      0x0a
-#define DRM_I830_IRQ_WAIT      0x0b
-#define DRM_I830_GETPARAM      0x0c
-#define DRM_I830_SETPARAM      0x0d
-
-#define DRM_IOCTL_I830_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_INIT, drm_i830_init_t)
-#define DRM_IOCTL_I830_VERTEX          DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_VERTEX, drm_i830_vertex_t)
-#define DRM_IOCTL_I830_CLEAR           DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_CLEAR, drm_i830_clear_t)
-#define DRM_IOCTL_I830_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_FLUSH)
-#define DRM_IOCTL_I830_GETAGE          DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_GETAGE)
-#define DRM_IOCTL_I830_GETBUF          DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_GETBUF, drm_i830_dma_t)
-#define DRM_IOCTL_I830_SWAP            DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_SWAP)
-#define DRM_IOCTL_I830_COPY            DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_COPY, drm_i830_copy_t)
-#define DRM_IOCTL_I830_DOCOPY          DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_DOCOPY)
-#define DRM_IOCTL_I830_FLIP            DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_FLIP)
-#define DRM_IOCTL_I830_IRQ_EMIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_IRQ_EMIT, drm_i830_irq_emit_t)
-#define DRM_IOCTL_I830_IRQ_WAIT         DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_IRQ_WAIT, drm_i830_irq_wait_t)
-#define DRM_IOCTL_I830_GETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_GETPARAM, drm_i830_getparam_t)
-#define DRM_IOCTL_I830_SETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_SETPARAM, drm_i830_setparam_t)
-
-typedef struct _drm_i830_clear {
-       int clear_color;
-       int clear_depth;
-       int flags;
-       unsigned int clear_colormask;
-       unsigned int clear_depthmask;
-} drm_i830_clear_t;
-
-/* These may be placeholders if we have more cliprects than
- * I830_NR_SAREA_CLIPRECTS.  In that case, the client sets discard to
- * false, indicating that the buffer will be dispatched again with a
- * new set of cliprects.
- */
-typedef struct _drm_i830_vertex {
-       int idx;                /* buffer index */
-       int used;               /* nr bytes in use */
-       int discard;            /* client is finished with the buffer? */
-} drm_i830_vertex_t;
-
-typedef struct _drm_i830_copy_t {
-       int idx;                /* buffer index */
-       int used;               /* nr bytes in use */
-       void __user *address;   /* Address to copy from */
-} drm_i830_copy_t;
-
-typedef struct drm_i830_dma {
-       void __user *virtual;
-       int request_idx;
-       int request_size;
-       int granted;
-} drm_i830_dma_t;
-
-/* 1.3: Userspace can request & wait on irq's:
- */
-typedef struct drm_i830_irq_emit {
-       int __user *irq_seq;
-} drm_i830_irq_emit_t;
-
-typedef struct drm_i830_irq_wait {
-       int irq_seq;
-} drm_i830_irq_wait_t;
-
-/* 1.3: New ioctl to query kernel params:
- */
-#define I830_PARAM_IRQ_ACTIVE            1
-
-typedef struct drm_i830_getparam {
-       int param;
-       int __user *value;
-} drm_i830_getparam_t;
-
-/* 1.3: New ioctl to set kernel params:
- */
-#define I830_SETPARAM_USE_MI_BATCHBUFFER_START            1
-
-typedef struct drm_i830_setparam {
-       int param;
-       int value;
-} drm_i830_setparam_t;
-
-#endif                         /* _I830_DRM_H_ */
diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
deleted file mode 100644 (file)
index 389597e..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/* i830_drv.c -- I810 driver -*- linux-c -*-
- * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Jeff Hartmann <jhartmann@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- *    Abraham vd Merwe <abraham@2d3d.co.za>
- *    Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i830_drm.h"
-#include "i830_drv.h"
-
-#include "drm_pciids.h"
-
-static struct pci_device_id pciidlist[] = {
-       i830_PCI_IDS
-};
-
-static struct drm_driver driver = {
-       .driver_features =
-           DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
-           DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
-#if USE_IRQS
-       .driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ,
-#endif
-       .dev_priv_size = sizeof(drm_i830_buf_priv_t),
-       .load = i830_driver_load,
-       .lastclose = i830_driver_lastclose,
-       .preclose = i830_driver_preclose,
-       .device_is_agp = i830_driver_device_is_agp,
-       .reclaim_buffers_locked = i830_driver_reclaim_buffers_locked,
-       .dma_quiescent = i830_driver_dma_quiescent,
-       .get_map_ofs = drm_core_get_map_ofs,
-       .get_reg_ofs = drm_core_get_reg_ofs,
-#if USE_IRQS
-       .irq_preinstall = i830_driver_irq_preinstall,
-       .irq_postinstall = i830_driver_irq_postinstall,
-       .irq_uninstall = i830_driver_irq_uninstall,
-       .irq_handler = i830_driver_irq_handler,
-#endif
-       .ioctls = i830_ioctls,
-       .fops = {
-                .owner = THIS_MODULE,
-                .open = drm_open,
-                .release = drm_release,
-                .ioctl = drm_ioctl,
-                .mmap = drm_mmap,
-                .poll = drm_poll,
-                .fasync = drm_fasync,
-       },
-
-       .pci_driver = {
-                .name = DRIVER_NAME,
-                .id_table = pciidlist,
-       },
-
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int __init i830_init(void)
-{
-       driver.num_ioctls = i830_max_ioctl;
-       return drm_init(&driver);
-}
-
-static void __exit i830_exit(void)
-{
-       drm_exit(&driver);
-}
-
-module_init(i830_init);
-module_exit(i830_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
deleted file mode 100644 (file)
index b5bf8cc..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-/* i830_drv.h -- Private header for the I830 driver -*- linux-c -*-
- * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
- *         Jeff Hartmann <jhartmann@valinux.com>
- *
- */
-
-#ifndef _I830_DRV_H_
-#define _I830_DRV_H_
-
-/* General customization:
- */
-
-#define DRIVER_AUTHOR          "VA Linux Systems Inc."
-
-#define DRIVER_NAME            "i830"
-#define DRIVER_DESC            "Intel 830M"
-#define DRIVER_DATE            "20021108"
-
-/* Interface history:
- *
- * 1.1: Original.
- * 1.2: ?
- * 1.3: New irq emit/wait ioctls.
- *      New pageflip ioctl.
- *      New getparam ioctl.
- *      State for texunits 3&4 in sarea.
- *      New (alternative) layout for texture state.
- */
-#define DRIVER_MAJOR           1
-#define DRIVER_MINOR           3
-#define DRIVER_PATCHLEVEL      2
-
-/* Driver will work either way: IRQ's save cpu time when waiting for
- * the card, but are subject to subtle interactions between bios,
- * hardware and the driver.
- */
-/* XXX: Add vblank support? */
-#define USE_IRQS 0
-
-typedef struct drm_i830_buf_priv {
-       u32 *in_use;
-       int my_use_idx;
-       int currently_mapped;
-       void __user *virtual;
-       void *kernel_virtual;
-       drm_local_map_t map;
-} drm_i830_buf_priv_t;
-
-typedef struct _drm_i830_ring_buffer {
-       int tail_mask;
-       unsigned long Start;
-       unsigned long End;
-       unsigned long Size;
-       u8 *virtual_start;
-       int head;
-       int tail;
-       int space;
-       drm_local_map_t map;
-} drm_i830_ring_buffer_t;
-
-typedef struct drm_i830_private {
-       struct drm_map *sarea_map;
-       struct drm_map *mmio_map;
-
-       drm_i830_sarea_t *sarea_priv;
-       drm_i830_ring_buffer_t ring;
-
-       void *hw_status_page;
-       unsigned long counter;
-
-       dma_addr_t dma_status_page;
-
-       struct drm_buf *mmap_buffer;
-
-       u32 front_di1, back_di1, zi1;
-
-       int back_offset;
-       int depth_offset;
-       int front_offset;
-       int w, h;
-       int pitch;
-       int back_pitch;
-       int depth_pitch;
-       unsigned int cpp;
-
-       int do_boxes;
-       int dma_used;
-
-       int current_page;
-       int page_flipping;
-
-       wait_queue_head_t irq_queue;
-       atomic_t irq_received;
-       atomic_t irq_emitted;
-
-       int use_mi_batchbuffer_start;
-
-} drm_i830_private_t;
-
-extern struct drm_ioctl_desc i830_ioctls[];
-extern int i830_max_ioctl;
-
-/* i830_irq.c */
-extern int i830_irq_emit(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-extern int i830_irq_wait(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-
-extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
-extern void i830_driver_irq_preinstall(struct drm_device * dev);
-extern void i830_driver_irq_postinstall(struct drm_device * dev);
-extern void i830_driver_irq_uninstall(struct drm_device * dev);
-extern int i830_driver_load(struct drm_device *, unsigned long flags);
-extern void i830_driver_preclose(struct drm_device * dev,
-                                struct drm_file *file_priv);
-extern void i830_driver_lastclose(struct drm_device * dev);
-extern void i830_driver_reclaim_buffers_locked(struct drm_device * dev,
-                                              struct drm_file *file_priv);
-extern int i830_driver_dma_quiescent(struct drm_device * dev);
-extern int i830_driver_device_is_agp(struct drm_device * dev);
-
-#define I830_READ(reg)          DRM_READ32(dev_priv->mmio_map, reg)
-#define I830_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, reg, val)
-#define I830_READ16(reg)        DRM_READ16(dev_priv->mmio_map, reg)
-#define I830_WRITE16(reg,val)   DRM_WRITE16(dev_priv->mmio_map, reg, val)
-
-#define I830_VERBOSE 0
-
-#define RING_LOCALS    unsigned int outring, ringmask, outcount; \
-                        volatile char *virt;
-
-#define BEGIN_LP_RING(n) do {                          \
-       if (I830_VERBOSE)                               \
-               printk("BEGIN_LP_RING(%d)\n", (n));     \
-       if (dev_priv->ring.space < n*4)                 \
-               i830_wait_ring(dev, n*4, __func__);             \
-       outcount = 0;                                   \
-       outring = dev_priv->ring.tail;                  \
-       ringmask = dev_priv->ring.tail_mask;            \
-       virt = dev_priv->ring.virtual_start;            \
-} while (0)
-
-#define OUT_RING(n) do {                                       \
-       if (I830_VERBOSE) printk("   OUT_RING %x\n", (int)(n)); \
-       *(volatile unsigned int *)(virt + outring) = n;         \
-        outcount++;                                            \
-       outring += 4;                                           \
-       outring &= ringmask;                                    \
-} while (0)
-
-#define ADVANCE_LP_RING() do {                                         \
-       if (I830_VERBOSE) printk("ADVANCE_LP_RING %x\n", outring);      \
-       dev_priv->ring.tail = outring;                                  \
-       dev_priv->ring.space -= outcount * 4;                           \
-       I830_WRITE(LP_RING + RING_TAIL, outring);                       \
-} while(0)
-
-extern int i830_wait_ring(struct drm_device * dev, int n, const char *caller);
-
-#define GFX_OP_USER_INTERRUPT          ((0<<29)|(2<<23))
-#define GFX_OP_BREAKPOINT_INTERRUPT    ((0<<29)|(1<<23))
-#define CMD_REPORT_HEAD                        (7<<23)
-#define CMD_STORE_DWORD_IDX            ((0x21<<23) | 0x1)
-#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
-
-#define STATE3D_LOAD_STATE_IMMEDIATE_2      ((0x3<<29)|(0x1d<<24)|(0x03<<16))
-#define LOAD_TEXTURE_MAP0                   (1<<11)
-
-#define INST_PARSER_CLIENT   0x00000000
-#define INST_OP_FLUSH        0x02000000
-#define INST_FLUSH_MAP_CACHE 0x00000001
-
-#define BB1_START_ADDR_MASK   (~0x7)
-#define BB1_PROTECTED         (1<<0)
-#define BB1_UNPROTECTED       (0<<0)
-#define BB2_END_ADDR_MASK     (~0x7)
-
-#define I830REG_HWSTAM         0x02098
-#define I830REG_INT_IDENTITY_R 0x020a4
-#define I830REG_INT_MASK_R     0x020a8
-#define I830REG_INT_ENABLE_R   0x020a0
-
-#define I830_IRQ_RESERVED ((1<<13)|(3<<2))
-
-#define LP_RING                        0x2030
-#define HP_RING                        0x2040
-#define RING_TAIL              0x00
-#define TAIL_ADDR              0x001FFFF8
-#define RING_HEAD              0x04
-#define HEAD_WRAP_COUNT                0xFFE00000
-#define HEAD_WRAP_ONE          0x00200000
-#define HEAD_ADDR              0x001FFFFC
-#define RING_START             0x08
-#define START_ADDR             0x0xFFFFF000
-#define RING_LEN               0x0C
-#define RING_NR_PAGES          0x001FF000
-#define RING_REPORT_MASK       0x00000006
-#define RING_REPORT_64K                0x00000002
-#define RING_REPORT_128K       0x00000004
-#define RING_NO_REPORT         0x00000000
-#define RING_VALID_MASK                0x00000001
-#define RING_VALID             0x00000001
-#define RING_INVALID           0x00000000
-
-#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define SC_UPDATE_SCISSOR       (0x1<<1)
-#define SC_ENABLE_MASK          (0x1<<0)
-#define SC_ENABLE               (0x1<<0)
-
-#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
-#define SCI_YMIN_MASK      (0xffff<<16)
-#define SCI_XMIN_MASK      (0xffff<<0)
-#define SCI_YMAX_MASK      (0xffff<<16)
-#define SCI_XMAX_MASK      (0xffff<<0)
-
-#define GFX_OP_SCISSOR_ENABLE   ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define GFX_OP_SCISSOR_RECT     ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
-#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
-#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
-#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
-#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
-#define GFX_OP_PRIMITIVE         ((0x3<<29)|(0x1f<<24))
-
-#define CMD_OP_DESTBUFFER_INFO  ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
-
-#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
-#define ASYNC_FLIP                (1<<22)
-
-#define CMD_3D                          (0x3<<29)
-#define STATE3D_CONST_BLEND_COLOR_CMD   (CMD_3D|(0x1d<<24)|(0x88<<16))
-#define STATE3D_MAP_COORD_SETBIND_CMD   (CMD_3D|(0x1d<<24)|(0x02<<16))
-
-#define BR00_BITBLT_CLIENT   0x40000000
-#define BR00_OP_COLOR_BLT    0x10000000
-#define BR00_OP_SRC_COPY_BLT 0x10C00000
-#define BR13_SOLID_PATTERN   0x80000000
-
-#define BUF_3D_ID_COLOR_BACK    (0x3<<24)
-#define BUF_3D_ID_DEPTH         (0x7<<24)
-#define BUF_3D_USE_FENCE        (1<<23)
-#define BUF_3D_PITCH(x)         (((x)/4)<<2)
-
-#define CMD_OP_MAP_PALETTE_LOAD        ((3<<29)|(0x1d<<24)|(0x82<<16)|255)
-#define MAP_PALETTE_NUM(x)     ((x<<8) & (1<<8))
-#define MAP_PALETTE_BOTH       (1<<11)
-
-#define XY_COLOR_BLT_CMD               ((2<<29)|(0x50<<22)|0x4)
-#define XY_COLOR_BLT_WRITE_ALPHA       (1<<21)
-#define XY_COLOR_BLT_WRITE_RGB         (1<<20)
-
-#define XY_SRC_COPY_BLT_CMD             ((2<<29)|(0x53<<22)|6)
-#define XY_SRC_COPY_BLT_WRITE_ALPHA     (1<<21)
-#define XY_SRC_COPY_BLT_WRITE_RGB       (1<<20)
-
-#define MI_BATCH_BUFFER                ((0x30<<23)|1)
-#define MI_BATCH_BUFFER_START  (0x31<<23)
-#define MI_BATCH_BUFFER_END    (0xA<<23)
-#define MI_BATCH_NON_SECURE    (1)
-
-#define MI_WAIT_FOR_EVENT       ((0x3<<23))
-#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
-#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
-
-#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
-
-#endif
diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
deleted file mode 100644 (file)
index 91ec2bb..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
- *
- * Copyright 2002 Tungsten Graphics, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Keith Whitwell <keith@tungstengraphics.com>
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i830_drm.h"
-#include "i830_drv.h"
-#include <linux/interrupt.h>   /* For task queue support */
-#include <linux/delay.h>
-
-irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
-{
-       struct drm_device *dev = (struct drm_device *) arg;
-       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-       u16 temp;
-
-       temp = I830_READ16(I830REG_INT_IDENTITY_R);
-       DRM_DEBUG("%x\n", temp);
-
-       if (!(temp & 2))
-               return IRQ_NONE;
-
-       I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
-
-       atomic_inc(&dev_priv->irq_received);
-       wake_up_interruptible(&dev_priv->irq_queue);
-
-       return IRQ_HANDLED;
-}
-
-static int i830_emit_irq(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-
-       DRM_DEBUG("%s\n", __func__);
-
-       atomic_inc(&dev_priv->irq_emitted);
-
-       BEGIN_LP_RING(2);
-       OUT_RING(0);
-       OUT_RING(GFX_OP_USER_INTERRUPT);
-       ADVANCE_LP_RING();
-
-       return atomic_read(&dev_priv->irq_emitted);
-}
-
-static int i830_wait_irq(struct drm_device * dev, int irq_nr)
-{
-       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-       DECLARE_WAITQUEUE(entry, current);
-       unsigned long end = jiffies + HZ * 3;
-       int ret = 0;
-
-       DRM_DEBUG("%s\n", __func__);
-
-       if (atomic_read(&dev_priv->irq_received) >= irq_nr)
-               return 0;
-
-       dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
-
-       add_wait_queue(&dev_priv->irq_queue, &entry);
-
-       for (;;) {
-               __set_current_state(TASK_INTERRUPTIBLE);
-               if (atomic_read(&dev_priv->irq_received) >= irq_nr)
-                       break;
-               if ((signed)(end - jiffies) <= 0) {
-                       DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n",
-                                 I830_READ16(I830REG_INT_IDENTITY_R),
-                                 I830_READ16(I830REG_INT_MASK_R),
-                                 I830_READ16(I830REG_INT_ENABLE_R),
-                                 I830_READ16(I830REG_HWSTAM));
-
-                       ret = -EBUSY;   /* Lockup?  Missed irq? */
-                       break;
-               }
-               schedule_timeout(HZ * 3);
-               if (signal_pending(current)) {
-                       ret = -EINTR;
-                       break;
-               }
-       }
-
-       __set_current_state(TASK_RUNNING);
-       remove_wait_queue(&dev_priv->irq_queue, &entry);
-       return ret;
-}
-
-/* Needs the lock as it touches the ring.
- */
-int i830_irq_emit(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       drm_i830_irq_emit_t *emit = data;
-       int result;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __func__);
-               return -EINVAL;
-       }
-
-       result = i830_emit_irq(dev);
-
-       if (copy_to_user(emit->irq_seq, &result, sizeof(int))) {
-               DRM_ERROR("copy_to_user\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-/* Doesn't need the hardware lock.
- */
-int i830_irq_wait(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
-{
-       drm_i830_private_t *dev_priv = dev->dev_private;
-       drm_i830_irq_wait_t *irqwait = data;
-
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __func__);
-               return -EINVAL;
-       }
-
-       return i830_wait_irq(dev, irqwait->irq_seq);
-}
-
-/* drm_dma.h hooks
-*/
-void i830_driver_irq_preinstall(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-
-       I830_WRITE16(I830REG_HWSTAM, 0xffff);
-       I830_WRITE16(I830REG_INT_MASK_R, 0x0);
-       I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
-       atomic_set(&dev_priv->irq_received, 0);
-       atomic_set(&dev_priv->irq_emitted, 0);
-       init_waitqueue_head(&dev_priv->irq_queue);
-}
-
-void i830_driver_irq_postinstall(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-
-       I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
-}
-
-void i830_driver_irq_uninstall(struct drm_device * dev)
-{
-       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-       if (!dev_priv)
-               return;
-
-       I830_WRITE16(I830REG_INT_MASK_R, 0xffff);
-       I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
-}
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
deleted file mode 100644 (file)
index 8897434..0000000
+++ /dev/null
@@ -1,858 +0,0 @@
-/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
- */
-/*
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i915_drm.h"
-#include "i915_drv.h"
-
-/* Really want an OS-independent resettable timer.  Would like to have
- * this loop run for (eg) 3 sec, but have the timer reset every time
- * the head pointer changes, so that EBUSY only happens if the ring
- * actually stalls for (eg) 3 seconds.
- */
-int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
-       u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-       int i;
-
-       for (i = 0; i < 10000; i++) {
-               ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-               ring->space = ring->head - (ring->tail + 8);
-               if (ring->space < 0)
-                       ring->space += ring->Size;
-               if (ring->space >= n)
-                       return 0;
-
-               dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-
-               if (ring->head != last_head)
-                       i = 0;
-
-               last_head = ring->head;
-       }
-
-       return -EBUSY;
-}
-
-void i915_kernel_lost_context(struct drm_device * dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
-
-       ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-       ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
-       ring->space = ring->head - (ring->tail + 8);
-       if (ring->space < 0)
-               ring->space += ring->Size;
-
-       if (ring->head == ring->tail)
-               dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
-}
-
-static int i915_dma_cleanup(struct drm_device * dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       /* Make sure interrupts are disabled here because the uninstall ioctl
-        * may not have been called from userspace and after dev_private
-        * is freed, it's too late.
-        */
-       if (dev->irq)
-               drm_irq_uninstall(dev);
-
-       if (dev_priv->ring.virtual_start) {
-               drm_core_ioremapfree(&dev_priv->ring.map, dev);
-               dev_priv->ring.virtual_start = 0;
-               dev_priv->ring.map.handle = 0;
-               dev_priv->ring.map.size = 0;
-       }
-
-       if (dev_priv->status_page_dmah) {
-               drm_pci_free(dev, dev_priv->status_page_dmah);
-               dev_priv->status_page_dmah = NULL;
-               /* Need to rewrite hardware status page */
-               I915_WRITE(0x02080, 0x1ffff000);
-       }
-
-       if (dev_priv->status_gfx_addr) {
-               dev_priv->status_gfx_addr = 0;
-               drm_core_ioremapfree(&dev_priv->hws_map, dev);
-               I915_WRITE(0x2080, 0x1ffff000);
-       }
-
-       return 0;
-}
-
-static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-
-       dev_priv->sarea = drm_getsarea(dev);
-       if (!dev_priv->sarea) {
-               DRM_ERROR("can not find sarea!\n");
-               i915_dma_cleanup(dev);
-               return -EINVAL;
-       }
-
-       dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
-       if (!dev_priv->mmio_map) {
-               i915_dma_cleanup(dev);
-               DRM_ERROR("can not find mmio map!\n");
-               return -EINVAL;
-       }
-
-       dev_priv->sarea_priv = (drm_i915_sarea_t *)
-           ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
-
-       dev_priv->ring.Start = init->ring_start;
-       dev_priv->ring.End = init->ring_end;
-       dev_priv->ring.Size = init->ring_size;
-       dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
-
-       dev_priv->ring.map.offset = init->ring_start;
-       dev_priv->ring.map.size = init->ring_size;
-       dev_priv->ring.map.type = 0;
-       dev_priv->ring.map.flags = 0;
-       dev_priv->ring.map.mtrr = 0;
-
-       drm_core_ioremap(&dev_priv->ring.map, dev);
-
-       if (dev_priv->ring.map.handle == NULL) {
-               i915_dma_cleanup(dev);
-               DRM_ERROR("can not ioremap virtual address for"
-                         " ring buffer\n");
-               return -ENOMEM;
-       }
-
-       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
-
-       dev_priv->cpp = init->cpp;
-       dev_priv->back_offset = init->back_offset;
-       dev_priv->front_offset = init->front_offset;
-       dev_priv->current_page = 0;
-       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
-
-       /* We are using separate values as placeholders for mechanisms for
-        * private backbuffer/depthbuffer usage.
-        */
-       dev_priv->use_mi_batchbuffer_start = 0;
-       if (IS_I965G(dev)) /* 965 doesn't support older method */
-               dev_priv->use_mi_batchbuffer_start = 1;
-
-       /* Allow hardware batchbuffers unless told otherwise.
-        */
-       dev_priv->allow_batchbuffer = 1;
-
-       /* Program Hardware Status Page */
-       if (!I915_NEED_GFX_HWS(dev)) {
-               dev_priv->status_page_dmah =
-                       drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
-
-               if (!dev_priv->status_page_dmah) {
-                       i915_dma_cleanup(dev);
-                       DRM_ERROR("Can not allocate hardware status page\n");
-                       return -ENOMEM;
-               }
-               dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
-               dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-
-               memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-               I915_WRITE(0x02080, dev_priv->dma_status_page);
-       }
-       DRM_DEBUG("Enabled hardware status page\n");
-       return 0;
-}
-
-static int i915_dma_resume(struct drm_device * dev)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-
-       DRM_DEBUG("%s\n", __func__);
-
-       if (!dev_priv->sarea) {
-               DRM_ERROR("can not find sarea!\n");
-               return -EINVAL;
-       }
-
-       if (!dev_priv->mmio_map) {
-               DRM_ERROR("can not find mmio map!\n");
-               return -EINVAL;
-       }
-
-       if (dev_priv->ring.map.handle == NULL) {
-               DRM_ERROR("can not ioremap virtual address for"
-                         " ring buffer\n");
-               return -ENOMEM;
-       }
-
-       /* Program Hardware Status Page */
-       if (!dev_priv->hw_status_page) {
-               DRM_ERROR("Can not find hardware status page\n");
-               return -EINVAL;
-       }
-       DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-
-       if (dev_priv->status_gfx_addr != 0)
-               I915_WRITE(0x02080, dev_priv->status_gfx_addr);
-       else
-               I915_WRITE(0x02080, dev_priv->dma_status_page);
-       DRM_DEBUG("Enabled hardware status page\n");
-
-       return 0;
-}
-
-static int i915_dma_init(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i915_init_t *init = data;
-       int retcode = 0;
-
-       switch (init->func) {
-       case I915_INIT_DMA:
-               retcode = i915_initialize(dev, init);
-               break;
-       case I915_CLEANUP_DMA:
-               retcode = i915_dma_cleanup(dev);
-               break;
-       case I915_RESUME_DMA:
-               retcode = i915_dma_resume(dev);
-               break;
-       default:
-               retcode = -EINVAL;
-               break;
-       }
-
-       return retcode;
-}
-
-/* Implement basically the same security restrictions as hardware does
- * for MI_BATCH_NON_SECURE.  These can be made stricter at any time.
- *
- * Most of the calculations below involve calculating the size of a
- * particular instruction.  It's important to get the size right as
- * that tells us where the next instruction to check is.  Any illegal
- * instruction detected will be given a size of zero, which is a
- * signal to abort the rest of the buffer.
- */
-static int do_validate_cmd(int cmd)
-{
-       switch (((cmd >> 29) & 0x7)) {
-       case 0x0:
-               switch ((cmd >> 23) & 0x3f) {
-               case 0x0:
-                       return 1;       /* MI_NOOP */
-               case 0x4:
-                       return 1;       /* MI_FLUSH */
-               default:
-                       return 0;       /* disallow everything else */
-               }
-               break;
-       case 0x1:
-               return 0;       /* reserved */
-       case 0x2:
-               return (cmd & 0xff) + 2;        /* 2d commands */
-       case 0x3:
-               if (((cmd >> 24) & 0x1f) <= 0x18)
-                       return 1;
-
-               switch ((cmd >> 24) & 0x1f) {
-               case 0x1c:
-                       return 1;
-               case 0x1d:
-                       switch ((cmd >> 16) & 0xff) {
-                       case 0x3:
-                               return (cmd & 0x1f) + 2;
-                       case 0x4:
-                               return (cmd & 0xf) + 2;
-                       default:
-                               return (cmd & 0xffff) + 2;
-                       }
-               case 0x1e:
-                       if (cmd & (1 << 23))
-                               return (cmd & 0xffff) + 1;
-                       else
-                               return 1;
-               case 0x1f:
-                       if ((cmd & (1 << 23)) == 0)     /* inline vertices */
-                               return (cmd & 0x1ffff) + 2;
-                       else if (cmd & (1 << 17))       /* indirect random */
-                               if ((cmd & 0xffff) == 0)
-                                       return 0;       /* unknown length, too hard */
-                               else
-                                       return (((cmd & 0xffff) + 1) / 2) + 1;
-                       else
-                               return 2;       /* indirect sequential */
-               default:
-                       return 0;
-               }
-       default:
-               return 0;
-       }
-
-       return 0;
-}
-
-static int validate_cmd(int cmd)
-{
-       int ret = do_validate_cmd(cmd);
-
-/*     printk("validate_cmd( %x ): %d\n", cmd, ret); */
-
-       return ret;
-}
-
-static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       int i;
-       RING_LOCALS;
-
-       if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
-               return -EINVAL;
-
-       BEGIN_LP_RING((dwords+1)&~1);
-
-       for (i = 0; i < dwords;) {
-               int cmd, sz;
-
-               if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
-                       return -EINVAL;
-
-               if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
-                       return -EINVAL;
-
-               OUT_RING(cmd);
-
-               while (++i, --sz) {
-                       if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
-                                                        sizeof(cmd))) {
-                               return -EINVAL;
-                       }
-                       OUT_RING(cmd);
-               }
-       }
-
-       if (dwords & 1)
-               OUT_RING(0);
-
-       ADVANCE_LP_RING();
-
-       return 0;
-}
-
-static int i915_emit_box(struct drm_device * dev,
-                        struct drm_clip_rect __user * boxes,
-                        int i, int DR1, int DR4)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_clip_rect box;
-       RING_LOCALS;
-
-       if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
-               return -EFAULT;
-       }
-
-       if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
-               DRM_ERROR("Bad box %d,%d..%d,%d\n",
-                         box.x1, box.y1, box.x2, box.y2);
-               return -EINVAL;
-       }
-
-       if (IS_I965G(dev)) {
-               BEGIN_LP_RING(4);
-               OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
-               OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
-               OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
-               OUT_RING(DR4);
-               ADVANCE_LP_RING();
-       } else {
-               BEGIN_LP_RING(6);
-               OUT_RING(GFX_OP_DRAWRECT_INFO);
-               OUT_RING(DR1);
-               OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
-               OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
-               OUT_RING(DR4);
-               OUT_RING(0);
-               ADVANCE_LP_RING();
-       }
-
-       return 0;
-}
-
-/* XXX: Emitting the counter should really be moved to part of the IRQ
- * emit. For now, do it in both places:
- */
-
-static void i915_emit_breadcrumb(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-
-       dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
-
-       if (dev_priv->counter > 0x7FFFFFFFUL)
-               dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
-
-       BEGIN_LP_RING(4);
-       OUT_RING(CMD_STORE_DWORD_IDX);
-       OUT_RING(20);
-       OUT_RING(dev_priv->counter);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-}
-
-static int i915_dispatch_cmdbuffer(struct drm_device * dev,
-                                  drm_i915_cmdbuffer_t * cmd)
-{
-       int nbox = cmd->num_cliprects;
-       int i = 0, count, ret;
-
-       if (cmd->sz & 0x3) {
-               DRM_ERROR("alignment");
-               return -EINVAL;
-       }
-
-       i915_kernel_lost_context(dev);
-
-       count = nbox ? nbox : 1;
-
-       for (i = 0; i < count; i++) {
-               if (i < nbox) {
-                       ret = i915_emit_box(dev, cmd->cliprects, i,
-                                           cmd->DR1, cmd->DR4);
-                       if (ret)
-                               return ret;
-               }
-
-               ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
-               if (ret)
-                       return ret;
-       }
-
-       i915_emit_breadcrumb(dev);
-       return 0;
-}
-
-static int i915_dispatch_batchbuffer(struct drm_device * dev,
-                                    drm_i915_batchbuffer_t * batch)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       struct drm_clip_rect __user *boxes = batch->cliprects;
-       int nbox = batch->num_cliprects;
-       int i = 0, count;
-       RING_LOCALS;
-
-       if ((batch->start | batch->used) & 0x7) {
-               DRM_ERROR("alignment");
-               return -EINVAL;
-       }
-
-       i915_kernel_lost_context(dev);
-
-       count = nbox ? nbox : 1;
-
-       for (i = 0; i < count; i++) {
-               if (i < nbox) {
-                       int ret = i915_emit_box(dev, boxes, i,
-                                               batch->DR1, batch->DR4);
-                       if (ret)
-                               return ret;
-               }
-
-               if (dev_priv->use_mi_batchbuffer_start) {
-                       BEGIN_LP_RING(2);
-                       if (IS_I965G(dev)) {
-                               OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
-                               OUT_RING(batch->start);
-                       } else {
-                               OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
-                               OUT_RING(batch->start | MI_BATCH_NON_SECURE);
-                       }
-                       ADVANCE_LP_RING();
-               } else {
-                       BEGIN_LP_RING(4);
-                       OUT_RING(MI_BATCH_BUFFER);
-                       OUT_RING(batch->start | MI_BATCH_NON_SECURE);
-                       OUT_RING(batch->start + batch->used - 4);
-                       OUT_RING(0);
-                       ADVANCE_LP_RING();
-               }
-       }
-
-       i915_emit_breadcrumb(dev);
-
-       return 0;
-}
-
-static int i915_dispatch_flip(struct drm_device * dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-
-       DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
-                 __FUNCTION__,
-                 dev_priv->current_page,
-                 dev_priv->sarea_priv->pf_current_page);
-
-       i915_kernel_lost_context(dev);
-
-       BEGIN_LP_RING(2);
-       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       BEGIN_LP_RING(6);
-       OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
-       OUT_RING(0);
-       if (dev_priv->current_page == 0) {
-               OUT_RING(dev_priv->back_offset);
-               dev_priv->current_page = 1;
-       } else {
-               OUT_RING(dev_priv->front_offset);
-               dev_priv->current_page = 0;
-       }
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       BEGIN_LP_RING(2);
-       OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
-
-       BEGIN_LP_RING(4);
-       OUT_RING(CMD_STORE_DWORD_IDX);
-       OUT_RING(20);
-       OUT_RING(dev_priv->counter);
-       OUT_RING(0);
-       ADVANCE_LP_RING();
-
-       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
-       return 0;
-}
-
-static int i915_quiescent(struct drm_device * dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-
-       i915_kernel_lost_context(dev);
-       return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
-}
-
-static int i915_flush_ioctl(struct drm_device *dev, void *data,
-                           struct drm_file *file_priv)
-{
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       return i915_quiescent(dev);
-}
-
-static int i915_batchbuffer(struct drm_device *dev, void *data,
-                           struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
-       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
-           dev_priv->sarea_priv;
-       drm_i915_batchbuffer_t *batch = data;
-       int ret;
-
-       if (!dev_priv->allow_batchbuffer) {
-               DRM_ERROR("Batchbuffer ioctl disabled\n");
-               return -EINVAL;
-       }
-
-       DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
-                 batch->start, batch->used, batch->num_cliprects);
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
-                                                      batch->num_cliprects *
-                                                      sizeof(struct drm_clip_rect)))
-               return -EFAULT;
-
-       ret = i915_dispatch_batchbuffer(dev, batch);
-
-       sarea_priv->last_dispatch = (int)hw_status[5];
-       return ret;
-}
-
-static int i915_cmdbuffer(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u32 *hw_status = dev_priv->hw_status_page;
-       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
-           dev_priv->sarea_priv;
-       drm_i915_cmdbuffer_t *cmdbuf = data;
-       int ret;
-
-       DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
-                 cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (cmdbuf->num_cliprects &&
-           DRM_VERIFYAREA_READ(cmdbuf->cliprects,
-                               cmdbuf->num_cliprects *
-                               sizeof(struct drm_clip_rect))) {
-               DRM_ERROR("Fault accessing cliprects\n");
-               return -EFAULT;
-       }
-
-       ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
-       if (ret) {
-               DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
-               return ret;
-       }
-
-       sarea_priv->last_dispatch = (int)hw_status[5];
-       return 0;
-}
-
-static int i915_flip_bufs(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv)
-{
-       DRM_DEBUG("%s\n", __FUNCTION__);
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       return i915_dispatch_flip(dev);
-}
-
-static int i915_getparam(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_getparam_t *param = data;
-       int value;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       switch (param->param) {
-       case I915_PARAM_IRQ_ACTIVE:
-               value = dev->irq ? 1 : 0;
-               break;
-       case I915_PARAM_ALLOW_BATCHBUFFER:
-               value = dev_priv->allow_batchbuffer ? 1 : 0;
-               break;
-       case I915_PARAM_LAST_DISPATCH:
-               value = READ_BREADCRUMB(dev_priv);
-               break;
-       default:
-               DRM_ERROR("Unknown parameter %d\n", param->param);
-               return -EINVAL;
-       }
-
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
-               DRM_ERROR("DRM_COPY_TO_USER failed\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-static int i915_setparam(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_setparam_t *param = data;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       switch (param->param) {
-       case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
-               if (!IS_I965G(dev))
-                       dev_priv->use_mi_batchbuffer_start = param->value;
-               break;
-       case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
-               dev_priv->tex_lru_log_granularity = param->value;
-               break;
-       case I915_SETPARAM_ALLOW_BATCHBUFFER:
-               dev_priv->allow_batchbuffer = param->value;
-               break;
-       default:
-               DRM_ERROR("unknown parameter %d\n", param->param);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int i915_set_status_page(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_hws_addr_t *hws = data;
-
-       if (!I915_NEED_GFX_HWS(dev))
-               return -EINVAL;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr);
-
-       dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
-
-       dev_priv->hws_map.offset = dev->agp->base + hws->addr;
-       dev_priv->hws_map.size = 4*1024;
-       dev_priv->hws_map.type = 0;
-       dev_priv->hws_map.flags = 0;
-       dev_priv->hws_map.mtrr = 0;
-
-       drm_core_ioremap(&dev_priv->hws_map, dev);
-       if (dev_priv->hws_map.handle == NULL) {
-               i915_dma_cleanup(dev);
-               dev_priv->status_gfx_addr = 0;
-               DRM_ERROR("can not ioremap virtual address for"
-                               " G33 hw status page\n");
-               return -ENOMEM;
-       }
-       dev_priv->hw_status_page = dev_priv->hws_map.handle;
-
-       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-       I915_WRITE(0x02080, dev_priv->status_gfx_addr);
-       DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
-                       dev_priv->status_gfx_addr);
-       DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
-       return 0;
-}
-
-int i915_driver_load(struct drm_device *dev, unsigned long flags)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long base, size;
-       int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
-
-       /* i915 has 4 more counters */
-       dev->counters += 4;
-       dev->types[6] = _DRM_STAT_IRQ;
-       dev->types[7] = _DRM_STAT_PRIMARY;
-       dev->types[8] = _DRM_STAT_SECONDARY;
-       dev->types[9] = _DRM_STAT_DMA;
-
-       dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
-       if (dev_priv == NULL)
-               return -ENOMEM;
-
-       memset(dev_priv, 0, sizeof(drm_i915_private_t));
-
-       dev->dev_private = (void *)dev_priv;
-
-       /* Add register map (needed for suspend/resume) */
-       base = drm_get_resource_start(dev, mmio_bar);
-       size = drm_get_resource_len(dev, mmio_bar);
-
-       ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
-                        _DRM_KERNEL | _DRM_DRIVER,
-                        &dev_priv->mmio_map);
-       return ret;
-}
-
-int i915_driver_unload(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (dev_priv->mmio_map)
-               drm_rmmap(dev, dev_priv->mmio_map);
-
-       drm_free(dev->dev_private, sizeof(drm_i915_private_t),
-                DRM_MEM_DRIVER);
-
-       return 0;
-}
-
-void i915_driver_lastclose(struct drm_device * dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-
-       if (!dev_priv)
-               return;
-
-       if (dev_priv->agp_heap)
-               i915_mem_takedown(&(dev_priv->agp_heap));
-
-       i915_dma_cleanup(dev);
-}
-
-void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       i915_mem_release(dev, file_priv, dev_priv->agp_heap);
-}
-
-struct drm_ioctl_desc i915_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP,  i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
-       DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
-       DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
-       DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH),
-};
-
-int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
-
-/**
- * Determine if the device really is AGP or not.
- *
- * All Intel graphics chipsets are treated as AGP, even if they are really
- * PCI-e.
- *
- * \param dev   The device to be tested.
- *
- * \returns
- * A value of 1 is always retured to indictate every i9x5 is AGP.
- */
-int i915_driver_device_is_agp(struct drm_device * dev)
-{
-       return 1;
-}
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
deleted file mode 100644 (file)
index 05c66cf..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#ifndef _I915_DRM_H_
-#define _I915_DRM_H_
-
-/* Please note that modifications to all structs defined here are
- * subject to backwards-compatibility constraints.
- */
-
-#include "drm.h"
-
-/* Each region is a minimum of 16k, and there are at most 255 of them.
- */
-#define I915_NR_TEX_REGIONS 255        /* table size 2k - maximum due to use
-                                * of chars for next/prev indices */
-#define I915_LOG_MIN_TEX_REGION_SIZE 14
-
-typedef struct _drm_i915_init {
-       enum {
-               I915_INIT_DMA = 0x01,
-               I915_CLEANUP_DMA = 0x02,
-               I915_RESUME_DMA = 0x03
-       } func;
-       unsigned int mmio_offset;
-       int sarea_priv_offset;
-       unsigned int ring_start;
-       unsigned int ring_end;
-       unsigned int ring_size;
-       unsigned int front_offset;
-       unsigned int back_offset;
-       unsigned int depth_offset;
-       unsigned int w;
-       unsigned int h;
-       unsigned int pitch;
-       unsigned int pitch_bits;
-       unsigned int back_pitch;
-       unsigned int depth_pitch;
-       unsigned int cpp;
-       unsigned int chipset;
-} drm_i915_init_t;
-
-typedef struct _drm_i915_sarea {
-       struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1];
-       int last_upload;        /* last time texture was uploaded */
-       int last_enqueue;       /* last time a buffer was enqueued */
-       int last_dispatch;      /* age of the most recently dispatched buffer */
-       int ctxOwner;           /* last context to upload state */
-       int texAge;
-       int pf_enabled;         /* is pageflipping allowed? */
-       int pf_active;
-       int pf_current_page;    /* which buffer is being displayed? */
-       int perf_boxes;         /* performance boxes to be displayed */
-       int width, height;      /* screen size in pixels */
-
-       drm_handle_t front_handle;
-       int front_offset;
-       int front_size;
-
-       drm_handle_t back_handle;
-       int back_offset;
-       int back_size;
-
-       drm_handle_t depth_handle;
-       int depth_offset;
-       int depth_size;
-
-       drm_handle_t tex_handle;
-       int tex_offset;
-       int tex_size;
-       int log_tex_granularity;
-       int pitch;
-       int rotation;           /* 0, 90, 180 or 270 */
-       int rotated_offset;
-       int rotated_size;
-       int rotated_pitch;
-       int virtualX, virtualY;
-
-       unsigned int front_tiled;
-       unsigned int back_tiled;
-       unsigned int depth_tiled;
-       unsigned int rotated_tiled;
-       unsigned int rotated2_tiled;
-
-       int pipeA_x;
-       int pipeA_y;
-       int pipeA_w;
-       int pipeA_h;
-       int pipeB_x;
-       int pipeB_y;
-       int pipeB_w;
-       int pipeB_h;
-} drm_i915_sarea_t;
-
-/* Flags for perf_boxes
- */
-#define I915_BOX_RING_EMPTY    0x1
-#define I915_BOX_FLIP          0x2
-#define I915_BOX_WAIT          0x4
-#define I915_BOX_TEXTURE_LOAD  0x8
-#define I915_BOX_LOST_CONTEXT  0x10
-
-/* I915 specific ioctls
- * The device specific ioctl range is 0x40 to 0x79.
- */
-#define DRM_I915_INIT          0x00
-#define DRM_I915_FLUSH         0x01
-#define DRM_I915_FLIP          0x02
-#define DRM_I915_BATCHBUFFER   0x03
-#define DRM_I915_IRQ_EMIT      0x04
-#define DRM_I915_IRQ_WAIT      0x05
-#define DRM_I915_GETPARAM      0x06
-#define DRM_I915_SETPARAM      0x07
-#define DRM_I915_ALLOC         0x08
-#define DRM_I915_FREE          0x09
-#define DRM_I915_INIT_HEAP     0x0a
-#define DRM_I915_CMDBUFFER     0x0b
-#define DRM_I915_DESTROY_HEAP  0x0c
-#define DRM_I915_SET_VBLANK_PIPE       0x0d
-#define DRM_I915_GET_VBLANK_PIPE       0x0e
-#define DRM_I915_VBLANK_SWAP   0x0f
-#define DRM_I915_HWS_ADDR      0x11
-
-#define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
-#define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
-#define DRM_IOCTL_I915_FLIP            DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
-#define DRM_IOCTL_I915_BATCHBUFFER     DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
-#define DRM_IOCTL_I915_IRQ_EMIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
-#define DRM_IOCTL_I915_IRQ_WAIT         DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
-#define DRM_IOCTL_I915_GETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t)
-#define DRM_IOCTL_I915_SETPARAM         DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t)
-#define DRM_IOCTL_I915_ALLOC            DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t)
-#define DRM_IOCTL_I915_FREE             DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t)
-#define DRM_IOCTL_I915_INIT_HEAP        DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
-#define DRM_IOCTL_I915_CMDBUFFER       DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
-#define DRM_IOCTL_I915_DESTROY_HEAP    DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
-#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
-#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
-#define DRM_IOCTL_I915_VBLANK_SWAP     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
-
-/* Allow drivers to submit batchbuffers directly to hardware, relying
- * on the security mechanisms provided by hardware.
- */
-typedef struct _drm_i915_batchbuffer {
-       int start;              /* agp offset */
-       int used;               /* nr bytes in use */
-       int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
-       int DR4;                /* window origin for GFX_OP_DRAWRECT_INFO */
-       int num_cliprects;      /* mulitpass with multiple cliprects? */
-       struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
-} drm_i915_batchbuffer_t;
-
-/* As above, but pass a pointer to userspace buffer which can be
- * validated by the kernel prior to sending to hardware.
- */
-typedef struct _drm_i915_cmdbuffer {
-       char __user *buf;       /* pointer to userspace command buffer */
-       int sz;                 /* nr bytes in buf */
-       int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
-       int DR4;                /* window origin for GFX_OP_DRAWRECT_INFO */
-       int num_cliprects;      /* mulitpass with multiple cliprects? */
-       struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
-} drm_i915_cmdbuffer_t;
-
-/* Userspace can request & wait on irq's:
- */
-typedef struct drm_i915_irq_emit {
-       int __user *irq_seq;
-} drm_i915_irq_emit_t;
-
-typedef struct drm_i915_irq_wait {
-       int irq_seq;
-} drm_i915_irq_wait_t;
-
-/* Ioctl to query kernel params:
- */
-#define I915_PARAM_IRQ_ACTIVE            1
-#define I915_PARAM_ALLOW_BATCHBUFFER     2
-#define I915_PARAM_LAST_DISPATCH         3
-
-typedef struct drm_i915_getparam {
-       int param;
-       int __user *value;
-} drm_i915_getparam_t;
-
-/* Ioctl to set kernel params:
- */
-#define I915_SETPARAM_USE_MI_BATCHBUFFER_START            1
-#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY             2
-#define I915_SETPARAM_ALLOW_BATCHBUFFER                   3
-
-typedef struct drm_i915_setparam {
-       int param;
-       int value;
-} drm_i915_setparam_t;
-
-/* A memory manager for regions of shared memory:
- */
-#define I915_MEM_REGION_AGP 1
-
-typedef struct drm_i915_mem_alloc {
-       int region;
-       int alignment;
-       int size;
-       int __user *region_offset;      /* offset from start of fb or agp */
-} drm_i915_mem_alloc_t;
-
-typedef struct drm_i915_mem_free {
-       int region;
-       int region_offset;
-} drm_i915_mem_free_t;
-
-typedef struct drm_i915_mem_init_heap {
-       int region;
-       int size;
-       int start;
-} drm_i915_mem_init_heap_t;
-
-/* Allow memory manager to be torn down and re-initialized (eg on
- * rotate):
- */
-typedef struct drm_i915_mem_destroy_heap {
-       int region;
-} drm_i915_mem_destroy_heap_t;
-
-/* Allow X server to configure which pipes to monitor for vblank signals
- */
-#define        DRM_I915_VBLANK_PIPE_A  1
-#define        DRM_I915_VBLANK_PIPE_B  2
-
-typedef struct drm_i915_vblank_pipe {
-       int pipe;
-} drm_i915_vblank_pipe_t;
-
-/* Schedule buffer swap at given vertical blank:
- */
-typedef struct drm_i915_vblank_swap {
-       drm_drawable_t drawable;
-       enum drm_vblank_seq_type seqtype;
-       unsigned int sequence;
-} drm_i915_vblank_swap_t;
-
-typedef struct drm_i915_hws_addr {
-       uint64_t addr;
-} drm_i915_hws_addr_t;
-
-#endif                         /* _I915_DRM_H_ */
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
deleted file mode 100644 (file)
index 93aed1c..0000000
+++ /dev/null
@@ -1,605 +0,0 @@
-/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
- */
-/*
- *
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i915_drm.h"
-#include "i915_drv.h"
-
-#include "drm_pciids.h"
-
-static struct pci_device_id pciidlist[] = {
-       i915_PCI_IDS
-};
-
-enum pipe {
-    PIPE_A = 0,
-    PIPE_B,
-};
-
-static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-
-       if (pipe == PIPE_A)
-               return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE);
-       else
-               return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE);
-}
-
-static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
-       u32 *array;
-       int i;
-
-       if (!i915_pipe_enabled(dev, pipe))
-               return;
-
-       if (pipe == PIPE_A)
-               array = dev_priv->save_palette_a;
-       else
-               array = dev_priv->save_palette_b;
-
-       for(i = 0; i < 256; i++)
-               array[i] = I915_READ(reg + (i << 2));
-}
-
-static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
-       u32 *array;
-       int i;
-
-       if (!i915_pipe_enabled(dev, pipe))
-               return;
-
-       if (pipe == PIPE_A)
-               array = dev_priv->save_palette_a;
-       else
-               array = dev_priv->save_palette_b;
-
-       for(i = 0; i < 256; i++)
-               I915_WRITE(reg + (i << 2), array[i]);
-}
-
-static u8 i915_read_indexed(u16 index_port, u16 data_port, u8 reg)
-{
-       outb(reg, index_port);
-       return inb(data_port);
-}
-
-static u8 i915_read_ar(u16 st01, u8 reg, u16 palette_enable)
-{
-       inb(st01);
-       outb(palette_enable | reg, VGA_AR_INDEX);
-       return inb(VGA_AR_DATA_READ);
-}
-
-static void i915_write_ar(u8 st01, u8 reg, u8 val, u16 palette_enable)
-{
-       inb(st01);
-       outb(palette_enable | reg, VGA_AR_INDEX);
-       outb(val, VGA_AR_DATA_WRITE);
-}
-
-static void i915_write_indexed(u16 index_port, u16 data_port, u8 reg, u8 val)
-{
-       outb(reg, index_port);
-       outb(val, data_port);
-}
-
-static void i915_save_vga(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int i;
-       u16 cr_index, cr_data, st01;
-
-       /* VGA color palette registers */
-       dev_priv->saveDACMASK = inb(VGA_DACMASK);
-       /* DACCRX automatically increments during read */
-       outb(0, VGA_DACRX);
-       /* Read 3 bytes of color data from each index */
-       for (i = 0; i < 256 * 3; i++)
-               dev_priv->saveDACDATA[i] = inb(VGA_DACDATA);
-
-       /* MSR bits */
-       dev_priv->saveMSR = inb(VGA_MSR_READ);
-       if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
-               cr_index = VGA_CR_INDEX_CGA;
-               cr_data = VGA_CR_DATA_CGA;
-               st01 = VGA_ST01_CGA;
-       } else {
-               cr_index = VGA_CR_INDEX_MDA;
-               cr_data = VGA_CR_DATA_MDA;
-               st01 = VGA_ST01_MDA;
-       }
-
-       /* CRT controller regs */
-       i915_write_indexed(cr_index, cr_data, 0x11,
-                          i915_read_indexed(cr_index, cr_data, 0x11) &
-                          (~0x80));
-       for (i = 0; i <= 0x24; i++)
-               dev_priv->saveCR[i] =
-                       i915_read_indexed(cr_index, cr_data, i);
-       /* Make sure we don't turn off CR group 0 writes */
-       dev_priv->saveCR[0x11] &= ~0x80;
-
-       /* Attribute controller registers */
-       inb(st01);
-       dev_priv->saveAR_INDEX = inb(VGA_AR_INDEX);
-       for (i = 0; i <= 0x14; i++)
-               dev_priv->saveAR[i] = i915_read_ar(st01, i, 0);
-       inb(st01);
-       outb(dev_priv->saveAR_INDEX, VGA_AR_INDEX);
-       inb(st01);
-
-       /* Graphics controller registers */
-       for (i = 0; i < 9; i++)
-               dev_priv->saveGR[i] =
-                       i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, i);
-
-       dev_priv->saveGR[0x10] =
-               i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x10);
-       dev_priv->saveGR[0x11] =
-               i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x11);
-       dev_priv->saveGR[0x18] =
-               i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x18);
-
-       /* Sequencer registers */
-       for (i = 0; i < 8; i++)
-               dev_priv->saveSR[i] =
-                       i915_read_indexed(VGA_SR_INDEX, VGA_SR_DATA, i);
-}
-
-static void i915_restore_vga(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int i;
-       u16 cr_index, cr_data, st01;
-
-       /* MSR bits */
-       outb(dev_priv->saveMSR, VGA_MSR_WRITE);
-       if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
-               cr_index = VGA_CR_INDEX_CGA;
-               cr_data = VGA_CR_DATA_CGA;
-               st01 = VGA_ST01_CGA;
-       } else {
-               cr_index = VGA_CR_INDEX_MDA;
-               cr_data = VGA_CR_DATA_MDA;
-               st01 = VGA_ST01_MDA;
-       }
-
-       /* Sequencer registers, don't write SR07 */
-       for (i = 0; i < 7; i++)
-               i915_write_indexed(VGA_SR_INDEX, VGA_SR_DATA, i,
-                                  dev_priv->saveSR[i]);
-
-       /* CRT controller regs */
-       /* Enable CR group 0 writes */
-       i915_write_indexed(cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
-       for (i = 0; i <= 0x24; i++)
-               i915_write_indexed(cr_index, cr_data, i, dev_priv->saveCR[i]);
-
-       /* Graphics controller regs */
-       for (i = 0; i < 9; i++)
-               i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, i,
-                                  dev_priv->saveGR[i]);
-
-       i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x10,
-                          dev_priv->saveGR[0x10]);
-       i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x11,
-                          dev_priv->saveGR[0x11]);
-       i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x18,
-                          dev_priv->saveGR[0x18]);
-
-       /* Attribute controller registers */
-       inb(st01);
-       for (i = 0; i <= 0x14; i++)
-               i915_write_ar(st01, i, dev_priv->saveAR[i], 0);
-       inb(st01); /* switch back to index mode */
-       outb(dev_priv->saveAR_INDEX | 0x20, VGA_AR_INDEX);
-       inb(st01);
-
-       /* VGA color palette registers */
-       outb(dev_priv->saveDACMASK, VGA_DACMASK);
-       /* DACCRX automatically increments during read */
-       outb(0, VGA_DACWX);
-       /* Read 3 bytes of color data from each index */
-       for (i = 0; i < 256 * 3; i++)
-               outb(dev_priv->saveDACDATA[i], VGA_DACDATA);
-
-}
-
-static int i915_suspend(struct drm_device *dev, pm_message_t state)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int i;
-
-       if (!dev || !dev_priv) {
-               printk(KERN_ERR "dev: %p, dev_priv: %p\n", dev, dev_priv);
-               printk(KERN_ERR "DRM not initialized, aborting suspend.\n");
-               return -ENODEV;
-       }
-
-       if (state.event == PM_EVENT_PRETHAW)
-               return 0;
-
-       pci_save_state(dev->pdev);
-       pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
-
-       /* Display arbitration control */
-       dev_priv->saveDSPARB = I915_READ(DSPARB);
-
-       /* Pipe & plane A info */
-       dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
-       dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
-       dev_priv->saveFPA0 = I915_READ(FPA0);
-       dev_priv->saveFPA1 = I915_READ(FPA1);
-       dev_priv->saveDPLL_A = I915_READ(DPLL_A);
-       if (IS_I965G(dev))
-               dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
-       dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
-       dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
-       dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
-       dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
-       dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
-       dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
-       dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
-
-       dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
-       dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
-       dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
-       dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
-       dev_priv->saveDSPABASE = I915_READ(DSPABASE);
-       if (IS_I965G(dev)) {
-               dev_priv->saveDSPASURF = I915_READ(DSPASURF);
-               dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
-       }
-       i915_save_palette(dev, PIPE_A);
-       dev_priv->savePIPEASTAT = I915_READ(I915REG_PIPEASTAT);
-
-       /* Pipe & plane B info */
-       dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
-       dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
-       dev_priv->saveFPB0 = I915_READ(FPB0);
-       dev_priv->saveFPB1 = I915_READ(FPB1);
-       dev_priv->saveDPLL_B = I915_READ(DPLL_B);
-       if (IS_I965G(dev))
-               dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
-       dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
-       dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
-       dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
-       dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
-       dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
-       dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
-       dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
-
-       dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
-       dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
-       dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
-       dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
-       dev_priv->saveDSPBBASE = I915_READ(DSPBBASE);
-       if (IS_I965GM(dev) || IS_IGD_GM(dev)) {
-               dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
-               dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
-       }
-       i915_save_palette(dev, PIPE_B);
-       dev_priv->savePIPEBSTAT = I915_READ(I915REG_PIPEBSTAT);
-
-       /* CRT state */
-       dev_priv->saveADPA = I915_READ(ADPA);
-
-       /* LVDS state */
-       dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
-       dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
-       dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
-       if (IS_I965G(dev))
-               dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
-       if (IS_MOBILE(dev) && !IS_I830(dev))
-               dev_priv->saveLVDS = I915_READ(LVDS);
-       if (!IS_I830(dev) && !IS_845G(dev))
-               dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
-       dev_priv->saveLVDSPP_ON = I915_READ(LVDSPP_ON);
-       dev_priv->saveLVDSPP_OFF = I915_READ(LVDSPP_OFF);
-       dev_priv->savePP_CYCLE = I915_READ(PP_CYCLE);
-
-       /* FIXME: save TV & SDVO state */
-
-       /* FBC state */
-       dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
-       dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
-       dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
-       dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
-
-       /* Interrupt state */
-       dev_priv->saveIIR = I915_READ(I915REG_INT_IDENTITY_R);
-       dev_priv->saveIER = I915_READ(I915REG_INT_ENABLE_R);
-       dev_priv->saveIMR = I915_READ(I915REG_INT_MASK_R);
-
-       /* VGA state */
-       dev_priv->saveVCLK_DIVISOR_VGA0 = I915_READ(VCLK_DIVISOR_VGA0);
-       dev_priv->saveVCLK_DIVISOR_VGA1 = I915_READ(VCLK_DIVISOR_VGA1);
-       dev_priv->saveVCLK_POST_DIV = I915_READ(VCLK_POST_DIV);
-       dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
-
-       /* Clock gating state */
-       dev_priv->saveD_STATE = I915_READ(D_STATE);
-       dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D);
-
-       /* Cache mode state */
-       dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
-
-       /* Memory Arbitration state */
-       dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
-
-       /* Scratch space */
-       for (i = 0; i < 16; i++) {
-               dev_priv->saveSWF0[i] = I915_READ(SWF0 + (i << 2));
-               dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
-       }
-       for (i = 0; i < 3; i++)
-               dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
-
-       i915_save_vga(dev);
-
-       if (state.event == PM_EVENT_SUSPEND) {
-               /* Shut down the device */
-               pci_disable_device(dev->pdev);
-               pci_set_power_state(dev->pdev, PCI_D3hot);
-       }
-
-       return 0;
-}
-
-static int i915_resume(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int i;
-
-       pci_set_power_state(dev->pdev, PCI_D0);
-       pci_restore_state(dev->pdev);
-       if (pci_enable_device(dev->pdev))
-               return -1;
-       pci_set_master(dev->pdev);
-
-       pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
-
-       I915_WRITE(DSPARB, dev_priv->saveDSPARB);
-
-       /* Pipe & plane A info */
-       /* Prime the clock */
-       if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
-               I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
-                          ~DPLL_VCO_ENABLE);
-               udelay(150);
-       }
-       I915_WRITE(FPA0, dev_priv->saveFPA0);
-       I915_WRITE(FPA1, dev_priv->saveFPA1);
-       /* Actually enable it */
-       I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
-       udelay(150);
-       if (IS_I965G(dev))
-               I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
-       udelay(150);
-
-       /* Restore mode */
-       I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
-       I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
-       I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
-       I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
-       I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
-       I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
-       I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
-
-       /* Restore plane info */
-       I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
-       I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
-       I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
-       I915_WRITE(DSPABASE, dev_priv->saveDSPABASE);
-       I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
-       if (IS_I965G(dev)) {
-               I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
-               I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
-       }
-
-       I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
-
-       i915_restore_palette(dev, PIPE_A);
-       /* Enable the plane */
-       I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
-       I915_WRITE(DSPABASE, I915_READ(DSPABASE));
-
-       /* Pipe & plane B info */
-       if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
-               I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
-                          ~DPLL_VCO_ENABLE);
-               udelay(150);
-       }
-       I915_WRITE(FPB0, dev_priv->saveFPB0);
-       I915_WRITE(FPB1, dev_priv->saveFPB1);
-       /* Actually enable it */
-       I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
-       udelay(150);
-       if (IS_I965G(dev))
-               I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
-       udelay(150);
-
-       /* Restore mode */
-       I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
-       I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
-       I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
-       I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
-       I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
-       I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
-       I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
-
-       /* Restore plane info */
-       I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
-       I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
-       I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
-       I915_WRITE(DSPBBASE, dev_priv->saveDSPBBASE);
-       I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
-       if (IS_I965G(dev)) {
-               I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
-               I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
-       }
-
-       I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
-
-       i915_restore_palette(dev, PIPE_B);
-       /* Enable the plane */
-       I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
-       I915_WRITE(DSPBBASE, I915_READ(DSPBBASE));
-
-       /* CRT state */
-       I915_WRITE(ADPA, dev_priv->saveADPA);
-
-       /* LVDS state */
-       if (IS_I965G(dev))
-               I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
-       if (IS_MOBILE(dev) && !IS_I830(dev))
-               I915_WRITE(LVDS, dev_priv->saveLVDS);
-       if (!IS_I830(dev) && !IS_845G(dev))
-               I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
-
-       I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
-       I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
-       I915_WRITE(LVDSPP_ON, dev_priv->saveLVDSPP_ON);
-       I915_WRITE(LVDSPP_OFF, dev_priv->saveLVDSPP_OFF);
-       I915_WRITE(PP_CYCLE, dev_priv->savePP_CYCLE);
-       I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
-
-       /* FIXME: restore TV & SDVO state */
-
-       /* FBC info */
-       I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
-       I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
-       I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
-       I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
-
-       /* VGA state */
-       I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
-       I915_WRITE(VCLK_DIVISOR_VGA0, dev_priv->saveVCLK_DIVISOR_VGA0);
-       I915_WRITE(VCLK_DIVISOR_VGA1, dev_priv->saveVCLK_DIVISOR_VGA1);
-       I915_WRITE(VCLK_POST_DIV, dev_priv->saveVCLK_POST_DIV);
-       udelay(150);
-
-       /* Clock gating state */
-       I915_WRITE (D_STATE, dev_priv->saveD_STATE);
-       I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
-
-       /* Cache mode state */
-       I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
-
-       /* Memory arbitration state */
-       I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
-
-       for (i = 0; i < 16; i++) {
-               I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF0[i]);
-               I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
-       }
-       for (i = 0; i < 3; i++)
-               I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
-
-       i915_restore_vga(dev);
-
-       return 0;
-}
-
-static struct drm_driver driver = {
-       /* don't use mtrr's here, the Xserver or user space app should
-        * deal with them for intel hardware.
-        */
-       .driver_features =
-           DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
-           DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
-           DRIVER_IRQ_VBL2,
-       .load = i915_driver_load,
-       .unload = i915_driver_unload,
-       .lastclose = i915_driver_lastclose,
-       .preclose = i915_driver_preclose,
-       .suspend = i915_suspend,
-       .resume = i915_resume,
-       .device_is_agp = i915_driver_device_is_agp,
-       .vblank_wait = i915_driver_vblank_wait,
-       .vblank_wait2 = i915_driver_vblank_wait2,
-       .irq_preinstall = i915_driver_irq_preinstall,
-       .irq_postinstall = i915_driver_irq_postinstall,
-       .irq_uninstall = i915_driver_irq_uninstall,
-       .irq_handler = i915_driver_irq_handler,
-       .reclaim_buffers = drm_core_reclaim_buffers,
-       .get_map_ofs = drm_core_get_map_ofs,
-       .get_reg_ofs = drm_core_get_reg_ofs,
-       .ioctls = i915_ioctls,
-       .fops = {
-                .owner = THIS_MODULE,
-                .open = drm_open,
-                .release = drm_release,
-                .ioctl = drm_ioctl,
-                .mmap = drm_mmap,
-                .poll = drm_poll,
-                .fasync = drm_fasync,
-#ifdef CONFIG_COMPAT
-                .compat_ioctl = i915_compat_ioctl,
-#endif
-       },
-
-       .pci_driver = {
-                .name = DRIVER_NAME,
-                .id_table = pciidlist,
-       },
-
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int __init i915_init(void)
-{
-       driver.num_ioctls = i915_max_ioctl;
-       return drm_init(&driver);
-}
-
-static void __exit i915_exit(void)
-{
-       drm_exit(&driver);
-}
-
-module_init(i915_init);
-module_exit(i915_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
deleted file mode 100644 (file)
index d7326d9..0000000
+++ /dev/null
@@ -1,1142 +0,0 @@
-/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
- */
-/*
- *
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#ifndef _I915_DRV_H_
-#define _I915_DRV_H_
-
-/* General customization:
- */
-
-#define DRIVER_AUTHOR          "Tungsten Graphics, Inc."
-
-#define DRIVER_NAME            "i915"
-#define DRIVER_DESC            "Intel Graphics"
-#define DRIVER_DATE            "20060119"
-
-/* Interface history:
- *
- * 1.1: Original.
- * 1.2: Add Power Management
- * 1.3: Add vblank support
- * 1.4: Fix cmdbuffer path, add heap destroy
- * 1.5: Add vblank pipe configuration
- * 1.6: - New ioctl for scheduling buffer swaps on vertical blank
- *      - Support vertical blank on secondary display pipe
- */
-#define DRIVER_MAJOR           1
-#define DRIVER_MINOR           6
-#define DRIVER_PATCHLEVEL      0
-
-typedef struct _drm_i915_ring_buffer {
-       int tail_mask;
-       unsigned long Start;
-       unsigned long End;
-       unsigned long Size;
-       u8 *virtual_start;
-       int head;
-       int tail;
-       int space;
-       drm_local_map_t map;
-} drm_i915_ring_buffer_t;
-
-struct mem_block {
-       struct mem_block *next;
-       struct mem_block *prev;
-       int start;
-       int size;
-       struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */
-};
-
-typedef struct _drm_i915_vbl_swap {
-       struct list_head head;
-       drm_drawable_t drw_id;
-       unsigned int pipe;
-       unsigned int sequence;
-} drm_i915_vbl_swap_t;
-
-typedef struct drm_i915_private {
-       drm_local_map_t *sarea;
-       drm_local_map_t *mmio_map;
-
-       drm_i915_sarea_t *sarea_priv;
-       drm_i915_ring_buffer_t ring;
-
-       drm_dma_handle_t *status_page_dmah;
-       void *hw_status_page;
-       dma_addr_t dma_status_page;
-       unsigned long counter;
-       unsigned int status_gfx_addr;
-       drm_local_map_t hws_map;
-
-       unsigned int cpp;
-       int back_offset;
-       int front_offset;
-       int current_page;
-       int page_flipping;
-       int use_mi_batchbuffer_start;
-
-       wait_queue_head_t irq_queue;
-       atomic_t irq_received;
-       atomic_t irq_emitted;
-
-       int tex_lru_log_granularity;
-       int allow_batchbuffer;
-       struct mem_block *agp_heap;
-       unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
-       int vblank_pipe;
-
-       spinlock_t swaps_lock;
-       drm_i915_vbl_swap_t vbl_swaps;
-       unsigned int swaps_pending;
-
-       /* Register state */
-       u8 saveLBB;
-       u32 saveDSPACNTR;
-       u32 saveDSPBCNTR;
-       u32 saveDSPARB;
-       u32 savePIPEACONF;
-       u32 savePIPEBCONF;
-       u32 savePIPEASRC;
-       u32 savePIPEBSRC;
-       u32 saveFPA0;
-       u32 saveFPA1;
-       u32 saveDPLL_A;
-       u32 saveDPLL_A_MD;
-       u32 saveHTOTAL_A;
-       u32 saveHBLANK_A;
-       u32 saveHSYNC_A;
-       u32 saveVTOTAL_A;
-       u32 saveVBLANK_A;
-       u32 saveVSYNC_A;
-       u32 saveBCLRPAT_A;
-       u32 savePIPEASTAT;
-       u32 saveDSPASTRIDE;
-       u32 saveDSPASIZE;
-       u32 saveDSPAPOS;
-       u32 saveDSPABASE;
-       u32 saveDSPASURF;
-       u32 saveDSPATILEOFF;
-       u32 savePFIT_PGM_RATIOS;
-       u32 saveBLC_PWM_CTL;
-       u32 saveBLC_PWM_CTL2;
-       u32 saveFPB0;
-       u32 saveFPB1;
-       u32 saveDPLL_B;
-       u32 saveDPLL_B_MD;
-       u32 saveHTOTAL_B;
-       u32 saveHBLANK_B;
-       u32 saveHSYNC_B;
-       u32 saveVTOTAL_B;
-       u32 saveVBLANK_B;
-       u32 saveVSYNC_B;
-       u32 saveBCLRPAT_B;
-       u32 savePIPEBSTAT;
-       u32 saveDSPBSTRIDE;
-       u32 saveDSPBSIZE;
-       u32 saveDSPBPOS;
-       u32 saveDSPBBASE;
-       u32 saveDSPBSURF;
-       u32 saveDSPBTILEOFF;
-       u32 saveVCLK_DIVISOR_VGA0;
-       u32 saveVCLK_DIVISOR_VGA1;
-       u32 saveVCLK_POST_DIV;
-       u32 saveVGACNTRL;
-       u32 saveADPA;
-       u32 saveLVDS;
-       u32 saveLVDSPP_ON;
-       u32 saveLVDSPP_OFF;
-       u32 saveDVOA;
-       u32 saveDVOB;
-       u32 saveDVOC;
-       u32 savePP_ON;
-       u32 savePP_OFF;
-       u32 savePP_CONTROL;
-       u32 savePP_CYCLE;
-       u32 savePFIT_CONTROL;
-       u32 save_palette_a[256];
-       u32 save_palette_b[256];
-       u32 saveFBC_CFB_BASE;
-       u32 saveFBC_LL_BASE;
-       u32 saveFBC_CONTROL;
-       u32 saveFBC_CONTROL2;
-       u32 saveIER;
-       u32 saveIIR;
-       u32 saveIMR;
-       u32 saveCACHE_MODE_0;
-       u32 saveD_STATE;
-       u32 saveDSPCLK_GATE_D;
-       u32 saveMI_ARB_STATE;
-       u32 saveSWF0[16];
-       u32 saveSWF1[16];
-       u32 saveSWF2[3];
-       u8 saveMSR;
-       u8 saveSR[8];
-       u8 saveGR[25];
-       u8 saveAR_INDEX;
-       u8 saveAR[21];
-       u8 saveDACMASK;
-       u8 saveDACDATA[256*3]; /* 256 3-byte colors */
-       u8 saveCR[37];
-} drm_i915_private_t;
-
-extern struct drm_ioctl_desc i915_ioctls[];
-extern int i915_max_ioctl;
-
-                               /* i915_dma.c */
-extern void i915_kernel_lost_context(struct drm_device * dev);
-extern int i915_driver_load(struct drm_device *, unsigned long flags);
-extern int i915_driver_unload(struct drm_device *);
-extern void i915_driver_lastclose(struct drm_device * dev);
-extern void i915_driver_preclose(struct drm_device *dev,
-                                struct drm_file *file_priv);
-extern int i915_driver_device_is_agp(struct drm_device * dev);
-extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
-                             unsigned long arg);
-
-/* i915_irq.c */
-extern int i915_irq_emit(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-extern int i915_irq_wait(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-
-extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
-extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
-extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
-extern void i915_driver_irq_preinstall(struct drm_device * dev);
-extern void i915_driver_irq_postinstall(struct drm_device * dev);
-extern void i915_driver_irq_uninstall(struct drm_device * dev);
-extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv);
-extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
-                               struct drm_file *file_priv);
-extern int i915_vblank_swap(struct drm_device *dev, void *data,
-                           struct drm_file *file_priv);
-
-/* i915_mem.c */
-extern int i915_mem_alloc(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv);
-extern int i915_mem_free(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-extern int i915_mem_init_heap(struct drm_device *dev, void *data,
-                             struct drm_file *file_priv);
-extern int i915_mem_destroy_heap(struct drm_device *dev, void *data,
-                                struct drm_file *file_priv);
-extern void i915_mem_takedown(struct mem_block **heap);
-extern void i915_mem_release(struct drm_device * dev,
-                            struct drm_file *file_priv, struct mem_block *heap);
-
-#define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))
-#define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
-#define I915_READ16(reg)       DRM_READ16(dev_priv->mmio_map, (reg))
-#define I915_WRITE16(reg,val)  DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
-
-#define I915_VERBOSE 0
-
-#define RING_LOCALS    unsigned int outring, ringmask, outcount; \
-                        volatile char *virt;
-
-#define BEGIN_LP_RING(n) do {                          \
-       if (I915_VERBOSE)                               \
-               DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n));  \
-       if (dev_priv->ring.space < (n)*4)               \
-               i915_wait_ring(dev, (n)*4, __func__);           \
-       outcount = 0;                                   \
-       outring = dev_priv->ring.tail;                  \
-       ringmask = dev_priv->ring.tail_mask;            \
-       virt = dev_priv->ring.virtual_start;            \
-} while (0)
-
-#define OUT_RING(n) do {                                       \
-       if (I915_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));      \
-       *(volatile unsigned int *)(virt + outring) = (n);       \
-        outcount++;                                            \
-       outring += 4;                                           \
-       outring &= ringmask;                                    \
-} while (0)
-
-#define ADVANCE_LP_RING() do {                                         \
-       if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring);   \
-       dev_priv->ring.tail = outring;                                  \
-       dev_priv->ring.space -= outcount * 4;                           \
-       I915_WRITE(LP_RING + RING_TAIL, outring);                       \
-} while(0)
-
-extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
-
-/* Extended config space */
-#define LBB 0xf4
-
-/* VGA stuff */
-
-#define VGA_ST01_MDA 0x3ba
-#define VGA_ST01_CGA 0x3da
-
-#define VGA_MSR_WRITE 0x3c2
-#define VGA_MSR_READ 0x3cc
-#define   VGA_MSR_MEM_EN (1<<1)
-#define   VGA_MSR_CGA_MODE (1<<0)
-
-#define VGA_SR_INDEX 0x3c4
-#define VGA_SR_DATA 0x3c5
-
-#define VGA_AR_INDEX 0x3c0
-#define   VGA_AR_VID_EN (1<<5)
-#define VGA_AR_DATA_WRITE 0x3c0
-#define VGA_AR_DATA_READ 0x3c1
-
-#define VGA_GR_INDEX 0x3ce
-#define VGA_GR_DATA 0x3cf
-/* GR05 */
-#define   VGA_GR_MEM_READ_MODE_SHIFT 3
-#define     VGA_GR_MEM_READ_MODE_PLANE 1
-/* GR06 */
-#define   VGA_GR_MEM_MODE_MASK 0xc
-#define   VGA_GR_MEM_MODE_SHIFT 2
-#define   VGA_GR_MEM_A0000_AFFFF 0
-#define   VGA_GR_MEM_A0000_BFFFF 1
-#define   VGA_GR_MEM_B0000_B7FFF 2
-#define   VGA_GR_MEM_B0000_BFFFF 3
-
-#define VGA_DACMASK 0x3c6
-#define VGA_DACRX 0x3c7
-#define VGA_DACWX 0x3c8
-#define VGA_DACDATA 0x3c9
-
-#define VGA_CR_INDEX_MDA 0x3b4
-#define VGA_CR_DATA_MDA 0x3b5
-#define VGA_CR_INDEX_CGA 0x3d4
-#define VGA_CR_DATA_CGA 0x3d5
-
-#define GFX_OP_USER_INTERRUPT          ((0<<29)|(2<<23))
-#define GFX_OP_BREAKPOINT_INTERRUPT    ((0<<29)|(1<<23))
-#define CMD_REPORT_HEAD                        (7<<23)
-#define CMD_STORE_DWORD_IDX            ((0x21<<23) | 0x1)
-#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
-
-#define INST_PARSER_CLIENT   0x00000000
-#define INST_OP_FLUSH        0x02000000
-#define INST_FLUSH_MAP_CACHE 0x00000001
-
-#define BB1_START_ADDR_MASK   (~0x7)
-#define BB1_PROTECTED         (1<<0)
-#define BB1_UNPROTECTED       (0<<0)
-#define BB2_END_ADDR_MASK     (~0x7)
-
-/* Framebuffer compression */
-#define FBC_CFB_BASE           0x03200 /* 4k page aligned */
-#define FBC_LL_BASE            0x03204 /* 4k page aligned */
-#define FBC_CONTROL            0x03208
-#define   FBC_CTL_EN           (1<<31)
-#define   FBC_CTL_PERIODIC     (1<<30)
-#define   FBC_CTL_INTERVAL_SHIFT (16)
-#define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
-#define   FBC_CTL_STRIDE_SHIFT (5)
-#define   FBC_CTL_FENCENO      (1<<0)
-#define FBC_COMMAND            0x0320c
-#define   FBC_CMD_COMPRESS     (1<<0)
-#define FBC_STATUS             0x03210
-#define   FBC_STAT_COMPRESSING (1<<31)
-#define   FBC_STAT_COMPRESSED  (1<<30)
-#define   FBC_STAT_MODIFIED    (1<<29)
-#define   FBC_STAT_CURRENT_LINE        (1<<0)
-#define FBC_CONTROL2           0x03214
-#define   FBC_CTL_FENCE_DBL    (0<<4)
-#define   FBC_CTL_IDLE_IMM     (0<<2)
-#define   FBC_CTL_IDLE_FULL    (1<<2)
-#define   FBC_CTL_IDLE_LINE    (2<<2)
-#define   FBC_CTL_IDLE_DEBUG   (3<<2)
-#define   FBC_CTL_CPU_FENCE    (1<<1)
-#define   FBC_CTL_PLANEA       (0<<0)
-#define   FBC_CTL_PLANEB       (1<<0)
-#define FBC_FENCE_OFF          0x0321b
-
-#define FBC_LL_SIZE            (1536)
-#define FBC_LL_PAD             (32)
-
-/* Interrupt bits:
- */
-#define USER_INT_FLAG    (1<<1)
-#define VSYNC_PIPEB_FLAG (1<<5)
-#define VSYNC_PIPEA_FLAG (1<<7)
-#define HWB_OOM_FLAG     (1<<13) /* binner out of memory */
-
-#define I915REG_HWSTAM         0x02098
-#define I915REG_INT_IDENTITY_R 0x020a4
-#define I915REG_INT_MASK_R     0x020a8
-#define I915REG_INT_ENABLE_R   0x020a0
-
-#define I915REG_PIPEASTAT      0x70024
-#define I915REG_PIPEBSTAT      0x71024
-
-#define I915_VBLANK_INTERRUPT_ENABLE   (1UL<<17)
-#define I915_VBLANK_CLEAR              (1UL<<1)
-
-#define SRX_INDEX              0x3c4
-#define SRX_DATA               0x3c5
-#define SR01                   1
-#define SR01_SCREEN_OFF                (1<<5)
-
-#define PPCR                   0x61204
-#define PPCR_ON                        (1<<0)
-
-#define DVOB                   0x61140
-#define DVOB_ON                        (1<<31)
-#define DVOC                   0x61160
-#define DVOC_ON                        (1<<31)
-#define LVDS                   0x61180
-#define LVDS_ON                        (1<<31)
-
-#define ADPA                   0x61100
-#define ADPA_DPMS_MASK         (~(3<<10))
-#define ADPA_DPMS_ON           (0<<10)
-#define ADPA_DPMS_SUSPEND      (1<<10)
-#define ADPA_DPMS_STANDBY      (2<<10)
-#define ADPA_DPMS_OFF          (3<<10)
-
-#define NOPID                   0x2094
-#define LP_RING                        0x2030
-#define HP_RING                        0x2040
-/* The binner has its own ring buffer:
- */
-#define HWB_RING               0x2400
-
-#define RING_TAIL              0x00
-#define TAIL_ADDR              0x001FFFF8
-#define RING_HEAD              0x04
-#define HEAD_WRAP_COUNT                0xFFE00000
-#define HEAD_WRAP_ONE          0x00200000
-#define HEAD_ADDR              0x001FFFFC
-#define RING_START             0x08
-#define START_ADDR             0x0xFFFFF000
-#define RING_LEN               0x0C
-#define RING_NR_PAGES          0x001FF000
-#define RING_REPORT_MASK       0x00000006
-#define RING_REPORT_64K                0x00000002
-#define RING_REPORT_128K       0x00000004
-#define RING_NO_REPORT         0x00000000
-#define RING_VALID_MASK                0x00000001
-#define RING_VALID             0x00000001
-#define RING_INVALID           0x00000000
-
-/* Instruction parser error reg:
- */
-#define IPEIR                  0x2088
-
-/* Scratch pad debug 0 reg:
- */
-#define SCPD0                  0x209c
-
-/* Error status reg:
- */
-#define ESR                    0x20b8
-
-/* Secondary DMA fetch address debug reg:
- */
-#define DMA_FADD_S             0x20d4
-
-/* Memory Interface Arbitration State
- */
-#define MI_ARB_STATE           0x20e4
-
-/* Cache mode 0 reg.
- *  - Manipulating render cache behaviour is central
- *    to the concept of zone rendering, tuning this reg can help avoid
- *    unnecessary render cache reads and even writes (for z/stencil)
- *    at beginning and end of scene.
- *
- * - To change a bit, write to this reg with a mask bit set and the
- * bit of interest either set or cleared.  EG: (BIT<<16) | BIT to set.
- */
-#define Cache_Mode_0           0x2120
-#define CACHE_MODE_0           0x2120
-#define CM0_MASK_SHIFT          16
-#define CM0_IZ_OPT_DISABLE      (1<<6)
-#define CM0_ZR_OPT_DISABLE      (1<<5)
-#define CM0_DEPTH_EVICT_DISABLE (1<<4)
-#define CM0_COLOR_EVICT_DISABLE (1<<3)
-#define CM0_DEPTH_WRITE_DISABLE (1<<1)
-#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
-
-
-/* Graphics flush control.  A CPU write flushes the GWB of all writes.
- * The data is discarded.
- */
-#define GFX_FLSH_CNTL          0x2170
-
-/* Binner control.  Defines the location of the bin pointer list:
- */
-#define BINCTL                 0x2420
-#define BC_MASK                        (1 << 9)
-
-/* Binned scene info.
- */
-#define BINSCENE               0x2428
-#define BS_OP_LOAD             (1 << 8)
-#define BS_MASK                        (1 << 22)
-
-/* Bin command parser debug reg:
- */
-#define BCPD                   0x2480
-
-/* Bin memory control debug reg:
- */
-#define BMCD                   0x2484
-
-/* Bin data cache debug reg:
- */
-#define BDCD                   0x2488
-
-/* Binner pointer cache debug reg:
- */
-#define BPCD                   0x248c
-
-/* Binner scratch pad debug reg:
- */
-#define BINSKPD                        0x24f0
-
-/* HWB scratch pad debug reg:
- */
-#define HWBSKPD                        0x24f4
-
-/* Binner memory pool reg:
- */
-#define BMP_BUFFER             0x2430
-#define BMP_PAGE_SIZE_4K       (0 << 10)
-#define BMP_BUFFER_SIZE_SHIFT  1
-#define BMP_ENABLE             (1 << 0)
-
-/* Get/put memory from the binner memory pool:
- */
-#define BMP_GET                        0x2438
-#define BMP_PUT                        0x2440
-#define BMP_OFFSET_SHIFT       5
-
-/* 3D state packets:
- */
-#define GFX_OP_RASTER_RULES    ((0x3<<29)|(0x7<<24))
-
-#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define SC_UPDATE_SCISSOR       (0x1<<1)
-#define SC_ENABLE_MASK          (0x1<<0)
-#define SC_ENABLE               (0x1<<0)
-
-#define GFX_OP_LOAD_INDIRECT   ((0x3<<29)|(0x1d<<24)|(0x7<<16))
-
-#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
-#define SCI_YMIN_MASK      (0xffff<<16)
-#define SCI_XMIN_MASK      (0xffff<<0)
-#define SCI_YMAX_MASK      (0xffff<<16)
-#define SCI_XMAX_MASK      (0xffff<<0)
-
-#define GFX_OP_SCISSOR_ENABLE   ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define GFX_OP_SCISSOR_RECT     ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
-#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
-#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
-#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
-#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
-
-#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2)
-
-#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
-#define XY_SRC_COPY_BLT_CMD            ((2<<29)|(0x53<<22)|6)
-#define XY_SRC_COPY_BLT_WRITE_ALPHA    (1<<21)
-#define XY_SRC_COPY_BLT_WRITE_RGB      (1<<20)
-#define XY_SRC_COPY_BLT_SRC_TILED      (1<<15)
-#define XY_SRC_COPY_BLT_DST_TILED      (1<<11)
-
-#define MI_BATCH_BUFFER                ((0x30<<23)|1)
-#define MI_BATCH_BUFFER_START  (0x31<<23)
-#define MI_BATCH_BUFFER_END    (0xA<<23)
-#define MI_BATCH_NON_SECURE    (1)
-#define MI_BATCH_NON_SECURE_I965 (1<<8)
-
-#define MI_WAIT_FOR_EVENT       ((0x3<<23))
-#define MI_WAIT_FOR_PLANE_B_FLIP      (1<<6)
-#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
-#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
-
-#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
-
-#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
-#define ASYNC_FLIP                (1<<22)
-#define DISPLAY_PLANE_A           (0<<20)
-#define DISPLAY_PLANE_B           (1<<20)
-
-/* Display regs */
-#define DSPACNTR                0x70180
-#define DSPBCNTR                0x71180
-#define DISPPLANE_SEL_PIPE_MASK                 (1<<24)
-
-/* Define the region of interest for the binner:
- */
-#define CMD_OP_BIN_CONTROL      ((0x3<<29)|(0x1d<<24)|(0x84<<16)|4)
-
-#define CMD_OP_DESTBUFFER_INFO  ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
-
-#define CMD_MI_FLUSH         (0x04 << 23)
-#define MI_NO_WRITE_FLUSH    (1 << 2)
-#define MI_READ_FLUSH        (1 << 0)
-#define MI_EXE_FLUSH         (1 << 1)
-#define MI_END_SCENE         (1 << 4) /* flush binner and incr scene count */
-#define MI_SCENE_COUNT       (1 << 3) /* just increment scene count */
-
-#define BREADCRUMB_BITS 31
-#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
-
-#define READ_BREADCRUMB(dev_priv)  (((volatile u32*)(dev_priv->hw_status_page))[5])
-#define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
-
-#define BLC_PWM_CTL            0x61254
-#define BACKLIGHT_MODULATION_FREQ_SHIFT                (17)
-
-#define BLC_PWM_CTL2           0x61250
-/**
- * This is the most significant 15 bits of the number of backlight cycles in a
- * complete cycle of the modulated backlight control.
- *
- * The actual value is this field multiplied by two.
- */
-#define BACKLIGHT_MODULATION_FREQ_MASK         (0x7fff << 17)
-#define BLM_LEGACY_MODE                                (1 << 16)
-/**
- * This is the number of cycles out of the backlight modulation cycle for which
- * the backlight is on.
- *
- * This field must be no greater than the number of cycles in the complete
- * backlight modulation cycle.
- */
-#define BACKLIGHT_DUTY_CYCLE_SHIFT             (0)
-#define BACKLIGHT_DUTY_CYCLE_MASK              (0xffff)
-
-#define I915_GCFGC                     0xf0
-#define I915_LOW_FREQUENCY_ENABLE              (1 << 7)
-#define I915_DISPLAY_CLOCK_190_200_MHZ         (0 << 4)
-#define I915_DISPLAY_CLOCK_333_MHZ             (4 << 4)
-#define I915_DISPLAY_CLOCK_MASK                        (7 << 4)
-
-#define I855_HPLLCC                    0xc0
-#define I855_CLOCK_CONTROL_MASK                        (3 << 0)
-#define I855_CLOCK_133_200                     (0 << 0)
-#define I855_CLOCK_100_200                     (1 << 0)
-#define I855_CLOCK_100_133                     (2 << 0)
-#define I855_CLOCK_166_250                     (3 << 0)
-
-/* p317, 319
- */
-#define VCLK2_VCO_M        0x6008 /* treat as 16 bit? (includes msbs) */
-#define VCLK2_VCO_N        0x600a
-#define VCLK2_VCO_DIV_SEL  0x6012
-
-#define VCLK_DIVISOR_VGA0   0x6000
-#define VCLK_DIVISOR_VGA1   0x6004
-#define VCLK_POST_DIV      0x6010
-/** Selects a post divisor of 4 instead of 2. */
-# define VGA1_PD_P2_DIV_4      (1 << 15)
-/** Overrides the p2 post divisor field */
-# define VGA1_PD_P1_DIV_2      (1 << 13)
-# define VGA1_PD_P1_SHIFT      8
-/** P1 value is 2 greater than this field */
-# define VGA1_PD_P1_MASK       (0x1f << 8)
-/** Selects a post divisor of 4 instead of 2. */
-# define VGA0_PD_P2_DIV_4      (1 << 7)
-/** Overrides the p2 post divisor field */
-# define VGA0_PD_P1_DIV_2      (1 << 5)
-# define VGA0_PD_P1_SHIFT      0
-/** P1 value is 2 greater than this field */
-# define VGA0_PD_P1_MASK       (0x1f << 0)
-
-/* PCI D state control register */
-#define D_STATE                0x6104
-#define DSPCLK_GATE_D  0x6200
-
-/* I830 CRTC registers */
-#define HTOTAL_A       0x60000
-#define HBLANK_A       0x60004
-#define HSYNC_A                0x60008
-#define VTOTAL_A       0x6000c
-#define VBLANK_A       0x60010
-#define VSYNC_A                0x60014
-#define PIPEASRC       0x6001c
-#define BCLRPAT_A      0x60020
-#define VSYNCSHIFT_A   0x60028
-
-#define HTOTAL_B       0x61000
-#define HBLANK_B       0x61004
-#define HSYNC_B                0x61008
-#define VTOTAL_B       0x6100c
-#define VBLANK_B       0x61010
-#define VSYNC_B                0x61014
-#define PIPEBSRC       0x6101c
-#define BCLRPAT_B      0x61020
-#define VSYNCSHIFT_B   0x61028
-
-#define PP_STATUS      0x61200
-# define PP_ON                                 (1 << 31)
-/**
- * Indicates that all dependencies of the panel are on:
- *
- * - PLL enabled
- * - pipe enabled
- * - LVDS/DVOB/DVOC on
- */
-# define PP_READY                              (1 << 30)
-# define PP_SEQUENCE_NONE                      (0 << 28)
-# define PP_SEQUENCE_ON                                (1 << 28)
-# define PP_SEQUENCE_OFF                       (2 << 28)
-# define PP_SEQUENCE_MASK                      0x30000000
-#define PP_CONTROL     0x61204
-# define POWER_TARGET_ON                       (1 << 0)
-
-#define LVDSPP_ON       0x61208
-#define LVDSPP_OFF      0x6120c
-#define PP_CYCLE        0x61210
-
-#define PFIT_CONTROL   0x61230
-# define PFIT_ENABLE                           (1 << 31)
-# define PFIT_PIPE_MASK                                (3 << 29)
-# define PFIT_PIPE_SHIFT                       29
-# define VERT_INTERP_DISABLE                   (0 << 10)
-# define VERT_INTERP_BILINEAR                  (1 << 10)
-# define VERT_INTERP_MASK                      (3 << 10)
-# define VERT_AUTO_SCALE                       (1 << 9)
-# define HORIZ_INTERP_DISABLE                  (0 << 6)
-# define HORIZ_INTERP_BILINEAR                 (1 << 6)
-# define HORIZ_INTERP_MASK                     (3 << 6)
-# define HORIZ_AUTO_SCALE                      (1 << 5)
-# define PANEL_8TO6_DITHER_ENABLE              (1 << 3)
-
-#define PFIT_PGM_RATIOS        0x61234
-# define PFIT_VERT_SCALE_MASK                  0xfff00000
-# define PFIT_HORIZ_SCALE_MASK                 0x0000fff0
-
-#define PFIT_AUTO_RATIOS       0x61238
-
-
-#define DPLL_A         0x06014
-#define DPLL_B         0x06018
-# define DPLL_VCO_ENABLE                       (1 << 31)
-# define DPLL_DVO_HIGH_SPEED                   (1 << 30)
-# define DPLL_SYNCLOCK_ENABLE                  (1 << 29)
-# define DPLL_VGA_MODE_DIS                     (1 << 28)
-# define DPLLB_MODE_DAC_SERIAL                 (1 << 26) /* i915 */
-# define DPLLB_MODE_LVDS                       (2 << 26) /* i915 */
-# define DPLL_MODE_MASK                                (3 << 26)
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10       (0 << 24) /* i915 */
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5                (1 << 24) /* i915 */
-# define DPLLB_LVDS_P2_CLOCK_DIV_14            (0 << 24) /* i915 */
-# define DPLLB_LVDS_P2_CLOCK_DIV_7             (1 << 24) /* i915 */
-# define DPLL_P2_CLOCK_DIV_MASK                        0x03000000 /* i915 */
-# define DPLL_FPA01_P1_POST_DIV_MASK           0x00ff0000 /* i915 */
-/**
- *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
- * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
- */
-# define DPLL_FPA01_P1_POST_DIV_MASK_I830      0x001f0000
-/**
- * The i830 generation, in LVDS mode, defines P1 as the bit number set within
- * this field (only one bit may be set).
- */
-# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
-# define DPLL_FPA01_P1_POST_DIV_SHIFT          16
-# define PLL_P2_DIVIDE_BY_4                    (1 << 23) /* i830, required in DVO non-gang */
-# define PLL_P1_DIVIDE_BY_TWO                  (1 << 21) /* i830 */
-# define PLL_REF_INPUT_DREFCLK                 (0 << 13)
-# define PLL_REF_INPUT_TVCLKINA                        (1 << 13) /* i830 */
-# define PLL_REF_INPUT_TVCLKINBC               (2 << 13) /* SDVO TVCLKIN */
-# define PLLB_REF_INPUT_SPREADSPECTRUMIN       (3 << 13)
-# define PLL_REF_INPUT_MASK                    (3 << 13)
-# define PLL_LOAD_PULSE_PHASE_SHIFT            9
-/*
- * Parallel to Serial Load Pulse phase selection.
- * Selects the phase for the 10X DPLL clock for the PCIe
- * digital display port. The range is 4 to 13; 10 or more
- * is just a flip delay. The default is 6
- */
-# define PLL_LOAD_PULSE_PHASE_MASK             (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
-# define DISPLAY_RATE_SELECT_FPA1              (1 << 8)
-
-/**
- * SDVO multiplier for 945G/GM. Not used on 965.
- *
- * \sa DPLL_MD_UDI_MULTIPLIER_MASK
- */
-# define SDVO_MULTIPLIER_MASK                  0x000000ff
-# define SDVO_MULTIPLIER_SHIFT_HIRES           4
-# define SDVO_MULTIPLIER_SHIFT_VGA             0
-
-/** @defgroup DPLL_MD
- * @{
- */
-/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
-#define DPLL_A_MD              0x0601c
-/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
-#define DPLL_B_MD              0x06020
-/**
- * UDI pixel divider, controlling how many pixels are stuffed into a packet.
- *
- * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
- */
-# define DPLL_MD_UDI_DIVIDER_MASK              0x3f000000
-# define DPLL_MD_UDI_DIVIDER_SHIFT             24
-/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
-# define DPLL_MD_VGA_UDI_DIVIDER_MASK          0x003f0000
-# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT         16
-/**
- * SDVO/UDI pixel multiplier.
- *
- * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
- * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
- * modes, the bus rate would be below the limits, so SDVO allows for stuffing
- * dummy bytes in the datastream at an increased clock rate, with both sides of
- * the link knowing how many bytes are fill.
- *
- * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
- * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
- * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
- * through an SDVO command.
- *
- * This register field has values of multiplication factor minus 1, with
- * a maximum multiplier of 5 for SDVO.
- */
-# define DPLL_MD_UDI_MULTIPLIER_MASK           0x00003f00
-# define DPLL_MD_UDI_MULTIPLIER_SHIFT          8
-/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
- * This best be set to the default value (3) or the CRT won't work. No,
- * I don't entirely understand what this does...
- */
-# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK       0x0000003f
-# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT      0
-/** @} */
-
-#define DPLL_TEST              0x606c
-# define DPLLB_TEST_SDVO_DIV_1                 (0 << 22)
-# define DPLLB_TEST_SDVO_DIV_2                 (1 << 22)
-# define DPLLB_TEST_SDVO_DIV_4                 (2 << 22)
-# define DPLLB_TEST_SDVO_DIV_MASK              (3 << 22)
-# define DPLLB_TEST_N_BYPASS                   (1 << 19)
-# define DPLLB_TEST_M_BYPASS                   (1 << 18)
-# define DPLLB_INPUT_BUFFER_ENABLE             (1 << 16)
-# define DPLLA_TEST_N_BYPASS                   (1 << 3)
-# define DPLLA_TEST_M_BYPASS                   (1 << 2)
-# define DPLLA_INPUT_BUFFER_ENABLE             (1 << 0)
-
-#define ADPA                   0x61100
-#define ADPA_DAC_ENABLE                (1<<31)
-#define ADPA_DAC_DISABLE       0
-#define ADPA_PIPE_SELECT_MASK  (1<<30)
-#define ADPA_PIPE_A_SELECT     0
-#define ADPA_PIPE_B_SELECT     (1<<30)
-#define ADPA_USE_VGA_HVPOLARITY (1<<15)
-#define ADPA_SETS_HVPOLARITY   0
-#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
-#define ADPA_VSYNC_CNTL_ENABLE 0
-#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
-#define ADPA_HSYNC_CNTL_ENABLE 0
-#define ADPA_VSYNC_ACTIVE_HIGH (1<<4)
-#define ADPA_VSYNC_ACTIVE_LOW  0
-#define ADPA_HSYNC_ACTIVE_HIGH (1<<3)
-#define ADPA_HSYNC_ACTIVE_LOW  0
-
-#define FPA0           0x06040
-#define FPA1           0x06044
-#define FPB0           0x06048
-#define FPB1           0x0604c
-# define FP_N_DIV_MASK                         0x003f0000
-# define FP_N_DIV_SHIFT                                16
-# define FP_M1_DIV_MASK                                0x00003f00
-# define FP_M1_DIV_SHIFT                       8
-# define FP_M2_DIV_MASK                                0x0000003f
-# define FP_M2_DIV_SHIFT                       0
-
-
-#define PORT_HOTPLUG_EN                0x61110
-# define SDVOB_HOTPLUG_INT_EN                  (1 << 26)
-# define SDVOC_HOTPLUG_INT_EN                  (1 << 25)
-# define TV_HOTPLUG_INT_EN                     (1 << 18)
-# define CRT_HOTPLUG_INT_EN                    (1 << 9)
-# define CRT_HOTPLUG_FORCE_DETECT              (1 << 3)
-
-#define PORT_HOTPLUG_STAT      0x61114
-# define CRT_HOTPLUG_INT_STATUS                        (1 << 11)
-# define TV_HOTPLUG_INT_STATUS                 (1 << 10)
-# define CRT_HOTPLUG_MONITOR_MASK              (3 << 8)
-# define CRT_HOTPLUG_MONITOR_COLOR             (3 << 8)
-# define CRT_HOTPLUG_MONITOR_MONO              (2 << 8)
-# define CRT_HOTPLUG_MONITOR_NONE              (0 << 8)
-# define SDVOC_HOTPLUG_INT_STATUS              (1 << 7)
-# define SDVOB_HOTPLUG_INT_STATUS              (1 << 6)
-
-#define SDVOB                  0x61140
-#define SDVOC                  0x61160
-#define SDVO_ENABLE                            (1 << 31)
-#define SDVO_PIPE_B_SELECT                     (1 << 30)
-#define SDVO_STALL_SELECT                      (1 << 29)
-#define SDVO_INTERRUPT_ENABLE                  (1 << 26)
-/**
- * 915G/GM SDVO pixel multiplier.
- *
- * Programmed value is multiplier - 1, up to 5x.
- *
- * \sa DPLL_MD_UDI_MULTIPLIER_MASK
- */
-#define SDVO_PORT_MULTIPLY_MASK                        (7 << 23)
-#define SDVO_PORT_MULTIPLY_SHIFT               23
-#define SDVO_PHASE_SELECT_MASK                 (15 << 19)
-#define SDVO_PHASE_SELECT_DEFAULT              (6 << 19)
-#define SDVO_CLOCK_OUTPUT_INVERT               (1 << 18)
-#define SDVOC_GANG_MODE                                (1 << 16)
-#define SDVO_BORDER_ENABLE                     (1 << 7)
-#define SDVOB_PCIE_CONCURRENCY                 (1 << 3)
-#define SDVO_DETECTED                          (1 << 2)
-/* Bits to be preserved when writing */
-#define SDVOB_PRESERVE_MASK                    ((1 << 17) | (1 << 16) | (1 << 14))
-#define SDVOC_PRESERVE_MASK                    (1 << 17)
-
-/** @defgroup LVDS
- * @{
- */
-/**
- * This register controls the LVDS output enable, pipe selection, and data
- * format selection.
- *
- * All of the clock/data pairs are force powered down by power sequencing.
- */
-#define LVDS                   0x61180
-/**
- * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
- * the DPLL semantics change when the LVDS is assigned to that pipe.
- */
-# define LVDS_PORT_EN                  (1 << 31)
-/** Selects pipe B for LVDS data.  Must be set on pre-965. */
-# define LVDS_PIPEB_SELECT             (1 << 30)
-
-/**
- * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
- * pixel.
- */
-# define LVDS_A0A2_CLKA_POWER_MASK     (3 << 8)
-# define LVDS_A0A2_CLKA_POWER_DOWN     (0 << 8)
-# define LVDS_A0A2_CLKA_POWER_UP       (3 << 8)
-/**
- * Controls the A3 data pair, which contains the additional LSBs for 24 bit
- * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
- * on.
- */
-# define LVDS_A3_POWER_MASK            (3 << 6)
-# define LVDS_A3_POWER_DOWN            (0 << 6)
-# define LVDS_A3_POWER_UP              (3 << 6)
-/**
- * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
- * is set.
- */
-# define LVDS_CLKB_POWER_MASK          (3 << 4)
-# define LVDS_CLKB_POWER_DOWN          (0 << 4)
-# define LVDS_CLKB_POWER_UP            (3 << 4)
-
-/**
- * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
- * setting for whether we are in dual-channel mode.  The B3 pair will
- * additionally only be powered up when LVDS_A3_POWER_UP is set.
- */
-# define LVDS_B0B3_POWER_MASK          (3 << 2)
-# define LVDS_B0B3_POWER_DOWN          (0 << 2)
-# define LVDS_B0B3_POWER_UP            (3 << 2)
-
-#define PIPEACONF 0x70008
-#define PIPEACONF_ENABLE       (1<<31)
-#define PIPEACONF_DISABLE      0
-#define PIPEACONF_DOUBLE_WIDE  (1<<30)
-#define I965_PIPECONF_ACTIVE   (1<<30)
-#define PIPEACONF_SINGLE_WIDE  0
-#define PIPEACONF_PIPE_UNLOCKED 0
-#define PIPEACONF_PIPE_LOCKED  (1<<25)
-#define PIPEACONF_PALETTE      0
-#define PIPEACONF_GAMMA                (1<<24)
-#define PIPECONF_FORCE_BORDER  (1<<25)
-#define PIPECONF_PROGRESSIVE   (0 << 21)
-#define PIPECONF_INTERLACE_W_FIELD_INDICATION  (6 << 21)
-#define PIPECONF_INTERLACE_FIELD_0_ONLY                (7 << 21)
-
-#define DSPARB   0x70030
-#define DSPARB_CSTART_MASK     (0x7f << 7)
-#define DSPARB_CSTART_SHIFT    7
-#define DSPARB_BSTART_MASK     (0x7f)           
-#define DSPARB_BSTART_SHIFT    0
-
-#define PIPEBCONF 0x71008
-#define PIPEBCONF_ENABLE       (1<<31)
-#define PIPEBCONF_DISABLE      0
-#define PIPEBCONF_DOUBLE_WIDE  (1<<30)
-#define PIPEBCONF_DISABLE      0
-#define PIPEBCONF_GAMMA                (1<<24)
-#define PIPEBCONF_PALETTE      0
-
-#define PIPEBGCMAXRED          0x71010
-#define PIPEBGCMAXGREEN                0x71014
-#define PIPEBGCMAXBLUE         0x71018
-#define PIPEBSTAT              0x71024
-#define PIPEBFRAMEHIGH         0x71040
-#define PIPEBFRAMEPIXEL                0x71044
-
-#define DSPACNTR               0x70180
-#define DSPBCNTR               0x71180
-#define DISPLAY_PLANE_ENABLE                   (1<<31)
-#define DISPLAY_PLANE_DISABLE                  0
-#define DISPPLANE_GAMMA_ENABLE                 (1<<30)
-#define DISPPLANE_GAMMA_DISABLE                        0
-#define DISPPLANE_PIXFORMAT_MASK               (0xf<<26)
-#define DISPPLANE_8BPP                         (0x2<<26)
-#define DISPPLANE_15_16BPP                     (0x4<<26)
-#define DISPPLANE_16BPP                                (0x5<<26)
-#define DISPPLANE_32BPP_NO_ALPHA               (0x6<<26)
-#define DISPPLANE_32BPP                                (0x7<<26)
-#define DISPPLANE_STEREO_ENABLE                        (1<<25)
-#define DISPPLANE_STEREO_DISABLE               0
-#define DISPPLANE_SEL_PIPE_MASK                        (1<<24)
-#define DISPPLANE_SEL_PIPE_A                   0
-#define DISPPLANE_SEL_PIPE_B                   (1<<24)
-#define DISPPLANE_SRC_KEY_ENABLE               (1<<22)
-#define DISPPLANE_SRC_KEY_DISABLE              0
-#define DISPPLANE_LINE_DOUBLE                  (1<<20)
-#define DISPPLANE_NO_LINE_DOUBLE               0
-#define DISPPLANE_STEREO_POLARITY_FIRST                0
-#define DISPPLANE_STEREO_POLARITY_SECOND       (1<<18)
-/* plane B only */
-#define DISPPLANE_ALPHA_TRANS_ENABLE           (1<<15)
-#define DISPPLANE_ALPHA_TRANS_DISABLE          0
-#define DISPPLANE_SPRITE_ABOVE_DISPLAYA                0
-#define DISPPLANE_SPRITE_ABOVE_OVERLAY         (1)
-
-#define DSPABASE               0x70184
-#define DSPASTRIDE             0x70188
-
-#define DSPBBASE               0x71184
-#define DSPBADDR               DSPBBASE
-#define DSPBSTRIDE             0x71188
-
-#define DSPAKEYVAL             0x70194
-#define DSPAKEYMASK            0x70198
-
-#define DSPAPOS                        0x7018C /* reserved */
-#define DSPASIZE               0x70190
-#define DSPBPOS                        0x7118C
-#define DSPBSIZE               0x71190
-
-#define DSPASURF               0x7019C
-#define DSPATILEOFF            0x701A4
-
-#define DSPBSURF               0x7119C
-#define DSPBTILEOFF            0x711A4
-
-#define VGACNTRL               0x71400
-# define VGA_DISP_DISABLE                      (1 << 31)
-# define VGA_2X_MODE                           (1 << 30)
-# define VGA_PIPE_B_SELECT                     (1 << 29)
-
-/*
- * Some BIOS scratch area registers.  The 845 (and 830?) store the amount
- * of video memory available to the BIOS in SWF1.
- */
-
-#define SWF0                   0x71410
-
-/*
- * 855 scratch registers.
- */
-#define SWF10                  0x70410
-
-#define SWF30                  0x72414
-
-/*
- * Overlay registers.  These are overlay registers accessed via MMIO.
- * Those loaded via the overlay register page are defined in i830_video.c.
- */
-#define OVADD                  0x30000
-
-#define DOVSTA                 0x30008
-#define OC_BUF                 (0x3<<20)
-
-#define OGAMC5                 0x30010
-#define OGAMC4                 0x30014
-#define OGAMC3                 0x30018
-#define OGAMC2                 0x3001c
-#define OGAMC1                 0x30020
-#define OGAMC0                 0x30024
-/*
- * Palette registers
- */
-#define PALETTE_A              0x0a000
-#define PALETTE_B              0x0a800
-
-#define IS_I830(dev) ((dev)->pci_device == 0x3577)
-#define IS_845G(dev) ((dev)->pci_device == 0x2562)
-#define IS_I85X(dev) ((dev)->pci_device == 0x3582)
-#define IS_I855(dev) ((dev)->pci_device == 0x3582)
-#define IS_I865G(dev) ((dev)->pci_device == 0x2572)
-
-#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a)
-#define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
-#define IS_I945G(dev) ((dev)->pci_device == 0x2772)
-#define IS_I945GM(dev) ((dev)->pci_device == 0x27A2 ||\
-                       (dev)->pci_device == 0x27AE)
-#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \
-                      (dev)->pci_device == 0x2982 || \
-                      (dev)->pci_device == 0x2992 || \
-                      (dev)->pci_device == 0x29A2 || \
-                      (dev)->pci_device == 0x2A02 || \
-                      (dev)->pci_device == 0x2A12 || \
-                      (dev)->pci_device == 0x2A42 || \
-                      (dev)->pci_device == 0x2E02 || \
-                      (dev)->pci_device == 0x2E12 || \
-                      (dev)->pci_device == 0x2E22)
-
-#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
-
-#define IS_IGD_GM(dev) ((dev)->pci_device == 0x2A42)
-
-#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \
-                    (dev)->pci_device == 0x2E12 || \
-                    (dev)->pci_device == 0x2E22)
-
-#define IS_G33(dev)    ((dev)->pci_device == 0x29C2 || \
-                       (dev)->pci_device == 0x29B2 ||  \
-                       (dev)->pci_device == 0x29D2)
-
-#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
-                     IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev))
-
-#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
-                       IS_I945GM(dev) || IS_I965GM(dev) || IS_IGD_GM(dev))
-
-#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_IGD_GM(dev) || IS_G4X(dev))
-
-#define PRIMARY_RINGBUFFER_SIZE         (128*1024)
-
-#endif
diff --git a/drivers/char/drm/i915_ioc32.c b/drivers/char/drm/i915_ioc32.c
deleted file mode 100644 (file)
index 1fe68a2..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/**
- * \file i915_ioc32.c
- *
- * 32-bit ioctl compatibility routines for the i915 DRM.
- *
- * \author Alan Hourihane <alanh@fairlite.demon.co.uk>
- *
- *
- * Copyright (C) Paul Mackerras 2005
- * Copyright (C) Alan Hourihane 2005
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <linux/compat.h>
-
-#include "drmP.h"
-#include "drm.h"
-#include "i915_drm.h"
-
-typedef struct _drm_i915_batchbuffer32 {
-       int start;              /* agp offset */
-       int used;               /* nr bytes in use */
-       int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
-       int DR4;                /* window origin for GFX_OP_DRAWRECT_INFO */
-       int num_cliprects;      /* mulitpass with multiple cliprects? */
-       u32 cliprects;          /* pointer to userspace cliprects */
-} drm_i915_batchbuffer32_t;
-
-static int compat_i915_batchbuffer(struct file *file, unsigned int cmd,
-                                  unsigned long arg)
-{
-       drm_i915_batchbuffer32_t batchbuffer32;
-       drm_i915_batchbuffer_t __user *batchbuffer;
-
-       if (copy_from_user
-           (&batchbuffer32, (void __user *)arg, sizeof(batchbuffer32)))
-               return -EFAULT;
-
-       batchbuffer = compat_alloc_user_space(sizeof(*batchbuffer));
-       if (!access_ok(VERIFY_WRITE, batchbuffer, sizeof(*batchbuffer))
-           || __put_user(batchbuffer32.start, &batchbuffer->start)
-           || __put_user(batchbuffer32.used, &batchbuffer->used)
-           || __put_user(batchbuffer32.DR1, &batchbuffer->DR1)
-           || __put_user(batchbuffer32.DR4, &batchbuffer->DR4)
-           || __put_user(batchbuffer32.num_cliprects,
-                         &batchbuffer->num_cliprects)
-           || __put_user((int __user *)(unsigned long)batchbuffer32.cliprects,
-                         &batchbuffer->cliprects))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_I915_BATCHBUFFER,
-                        (unsigned long)batchbuffer);
-}
-
-typedef struct _drm_i915_cmdbuffer32 {
-       u32 buf;                /* pointer to userspace command buffer */
-       int sz;                 /* nr bytes in buf */
-       int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
-       int DR4;                /* window origin for GFX_OP_DRAWRECT_INFO */
-       int num_cliprects;      /* mulitpass with multiple cliprects? */
-       u32 cliprects;          /* pointer to userspace cliprects */
-} drm_i915_cmdbuffer32_t;
-
-static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
-                                unsigned long arg)
-{
-       drm_i915_cmdbuffer32_t cmdbuffer32;
-       drm_i915_cmdbuffer_t __user *cmdbuffer;
-
-       if (copy_from_user
-           (&cmdbuffer32, (void __user *)arg, sizeof(cmdbuffer32)))
-               return -EFAULT;
-
-       cmdbuffer = compat_alloc_user_space(sizeof(*cmdbuffer));
-       if (!access_ok(VERIFY_WRITE, cmdbuffer, sizeof(*cmdbuffer))
-           || __put_user((int __user *)(unsigned long)cmdbuffer32.buf,
-                         &cmdbuffer->buf)
-           || __put_user(cmdbuffer32.sz, &cmdbuffer->sz)
-           || __put_user(cmdbuffer32.DR1, &cmdbuffer->DR1)
-           || __put_user(cmdbuffer32.DR4, &cmdbuffer->DR4)
-           || __put_user(cmdbuffer32.num_cliprects, &cmdbuffer->num_cliprects)
-           || __put_user((int __user *)(unsigned long)cmdbuffer32.cliprects,
-                         &cmdbuffer->cliprects))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer);
-}
-
-typedef struct drm_i915_irq_emit32 {
-       u32 irq_seq;
-} drm_i915_irq_emit32_t;
-
-static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
-                               unsigned long arg)
-{
-       drm_i915_irq_emit32_t req32;
-       drm_i915_irq_emit_t __user *request;
-
-       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user((int __user *)(unsigned long)req32.irq_seq,
-                         &request->irq_seq))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request);
-}
-typedef struct drm_i915_getparam32 {
-       int param;
-       u32 value;
-} drm_i915_getparam32_t;
-
-static int compat_i915_getparam(struct file *file, unsigned int cmd,
-                               unsigned long arg)
-{
-       drm_i915_getparam32_t req32;
-       drm_i915_getparam_t __user *request;
-
-       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user(req32.param, &request->param)
-           || __put_user((void __user *)(unsigned long)req32.value,
-                         &request->value))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_I915_GETPARAM, (unsigned long)request);
-}
-
-typedef struct drm_i915_mem_alloc32 {
-       int region;
-       int alignment;
-       int size;
-       u32 region_offset;      /* offset from start of fb or agp */
-} drm_i915_mem_alloc32_t;
-
-static int compat_i915_alloc(struct file *file, unsigned int cmd,
-                            unsigned long arg)
-{
-       drm_i915_mem_alloc32_t req32;
-       drm_i915_mem_alloc_t __user *request;
-
-       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user(req32.region, &request->region)
-           || __put_user(req32.alignment, &request->alignment)
-           || __put_user(req32.size, &request->size)
-           || __put_user((void __user *)(unsigned long)req32.region_offset,
-                         &request->region_offset))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_I915_ALLOC, (unsigned long)request);
-}
-
-drm_ioctl_compat_t *i915_compat_ioctls[] = {
-       [DRM_I915_BATCHBUFFER] = compat_i915_batchbuffer,
-       [DRM_I915_CMDBUFFER] = compat_i915_cmdbuffer,
-       [DRM_I915_GETPARAM] = compat_i915_getparam,
-       [DRM_I915_IRQ_EMIT] = compat_i915_irq_emit,
-       [DRM_I915_ALLOC] = compat_i915_alloc
-};
-
-/**
- * Called whenever a 32-bit process running under a 64-bit kernel
- * performs an ioctl on /dev/dri/card<n>.
- *
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
- */
-long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       unsigned int nr = DRM_IOCTL_NR(cmd);
-       drm_ioctl_compat_t *fn = NULL;
-       int ret;
-
-       if (nr < DRM_COMMAND_BASE)
-               return drm_compat_ioctl(filp, cmd, arg);
-
-       if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
-               fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
-
-       lock_kernel();          /* XXX for now */
-       if (fn != NULL)
-               ret = (*fn) (filp, cmd, arg);
-       else
-               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
-
-       return ret;
-}
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
deleted file mode 100644 (file)
index f7f16e7..0000000
+++ /dev/null
@@ -1,623 +0,0 @@
-/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-
- */
-/*
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i915_drm.h"
-#include "i915_drv.h"
-
-#define USER_INT_FLAG (1<<1)
-#define VSYNC_PIPEB_FLAG (1<<5)
-#define VSYNC_PIPEA_FLAG (1<<7)
-
-#define MAX_NOPID ((u32)~0)
-
-/**
- * Emit blits for scheduled buffer swaps.
- *
- * This function will be called with the HW lock held.
- */
-static void i915_vblank_tasklet(struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       unsigned long irqflags;
-       struct list_head *list, *tmp, hits, *hit;
-       int nhits, nrects, slice[2], upper[2], lower[2], i;
-       unsigned counter[2] = { atomic_read(&dev->vbl_received),
-                               atomic_read(&dev->vbl_received2) };
-       struct drm_drawable_info *drw;
-       drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       u32 cpp = dev_priv->cpp;
-       u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
-                               XY_SRC_COPY_BLT_WRITE_ALPHA |
-                               XY_SRC_COPY_BLT_WRITE_RGB)
-                            : XY_SRC_COPY_BLT_CMD;
-       u32 src_pitch = sarea_priv->pitch * cpp;
-       u32 dst_pitch = sarea_priv->pitch * cpp;
-       u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24);
-       RING_LOCALS;
-
-       if (sarea_priv->front_tiled) {
-               cmd |= XY_SRC_COPY_BLT_DST_TILED;
-               dst_pitch >>= 2;
-       }
-       if (sarea_priv->back_tiled) {
-               cmd |= XY_SRC_COPY_BLT_SRC_TILED;
-               src_pitch >>= 2;
-       }
-
-       DRM_DEBUG("\n");
-
-       INIT_LIST_HEAD(&hits);
-
-       nhits = nrects = 0;
-
-       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
-
-       /* Find buffer swaps scheduled for this vertical blank */
-       list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
-               drm_i915_vbl_swap_t *vbl_swap =
-                       list_entry(list, drm_i915_vbl_swap_t, head);
-
-               if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
-                       continue;
-
-               list_del(list);
-               dev_priv->swaps_pending--;
-
-               spin_unlock(&dev_priv->swaps_lock);
-               spin_lock(&dev->drw_lock);
-
-               drw = drm_get_drawable_info(dev, vbl_swap->drw_id);
-
-               if (!drw) {
-                       spin_unlock(&dev->drw_lock);
-                       drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
-                       spin_lock(&dev_priv->swaps_lock);
-                       continue;
-               }
-
-               list_for_each(hit, &hits) {
-                       drm_i915_vbl_swap_t *swap_cmp =
-                               list_entry(hit, drm_i915_vbl_swap_t, head);
-                       struct drm_drawable_info *drw_cmp =
-                               drm_get_drawable_info(dev, swap_cmp->drw_id);
-
-                       if (drw_cmp &&
-                           drw_cmp->rects[0].y1 > drw->rects[0].y1) {
-                               list_add_tail(list, hit);
-                               break;
-                       }
-               }
-
-               spin_unlock(&dev->drw_lock);
-
-               /* List of hits was empty, or we reached the end of it */
-               if (hit == &hits)
-                       list_add_tail(list, hits.prev);
-
-               nhits++;
-
-               spin_lock(&dev_priv->swaps_lock);
-       }
-
-       if (nhits == 0) {
-               spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
-               return;
-       }
-
-       spin_unlock(&dev_priv->swaps_lock);
-
-       i915_kernel_lost_context(dev);
-
-       if (IS_I965G(dev)) {
-               BEGIN_LP_RING(4);
-
-               OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
-               OUT_RING(0);
-               OUT_RING(((sarea_priv->width - 1) & 0xffff) | ((sarea_priv->height - 1) << 16));
-               OUT_RING(0);
-               ADVANCE_LP_RING();
-       } else {
-               BEGIN_LP_RING(6);
-
-               OUT_RING(GFX_OP_DRAWRECT_INFO);
-               OUT_RING(0);
-               OUT_RING(0);
-               OUT_RING(sarea_priv->width | sarea_priv->height << 16);
-               OUT_RING(sarea_priv->width | sarea_priv->height << 16);
-               OUT_RING(0);
-
-               ADVANCE_LP_RING();
-       }
-
-       sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
-
-       upper[0] = upper[1] = 0;
-       slice[0] = max(sarea_priv->pipeA_h / nhits, 1);
-       slice[1] = max(sarea_priv->pipeB_h / nhits, 1);
-       lower[0] = sarea_priv->pipeA_y + slice[0];
-       lower[1] = sarea_priv->pipeB_y + slice[0];
-
-       spin_lock(&dev->drw_lock);
-
-       /* Emit blits for buffer swaps, partitioning both outputs into as many
-        * slices as there are buffer swaps scheduled in order to avoid tearing
-        * (based on the assumption that a single buffer swap would always
-        * complete before scanout starts).
-        */
-       for (i = 0; i++ < nhits;
-            upper[0] = lower[0], lower[0] += slice[0],
-            upper[1] = lower[1], lower[1] += slice[1]) {
-               if (i == nhits)
-                       lower[0] = lower[1] = sarea_priv->height;
-
-               list_for_each(hit, &hits) {
-                       drm_i915_vbl_swap_t *swap_hit =
-                               list_entry(hit, drm_i915_vbl_swap_t, head);
-                       struct drm_clip_rect *rect;
-                       int num_rects, pipe;
-                       unsigned short top, bottom;
-
-                       drw = drm_get_drawable_info(dev, swap_hit->drw_id);
-
-                       if (!drw)
-                               continue;
-
-                       rect = drw->rects;
-                       pipe = swap_hit->pipe;
-                       top = upper[pipe];
-                       bottom = lower[pipe];
-
-                       for (num_rects = drw->num_rects; num_rects--; rect++) {
-                               int y1 = max(rect->y1, top);
-                               int y2 = min(rect->y2, bottom);
-
-                               if (y1 >= y2)
-                                       continue;
-
-                               BEGIN_LP_RING(8);
-
-                               OUT_RING(cmd);
-                               OUT_RING(ropcpp | dst_pitch);
-                               OUT_RING((y1 << 16) | rect->x1);
-                               OUT_RING((y2 << 16) | rect->x2);
-                               OUT_RING(sarea_priv->front_offset);
-                               OUT_RING((y1 << 16) | rect->x1);
-                               OUT_RING(src_pitch);
-                               OUT_RING(sarea_priv->back_offset);
-
-                               ADVANCE_LP_RING();
-                       }
-               }
-       }
-
-       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-
-       list_for_each_safe(hit, tmp, &hits) {
-               drm_i915_vbl_swap_t *swap_hit =
-                       list_entry(hit, drm_i915_vbl_swap_t, head);
-
-               list_del(hit);
-
-               drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER);
-       }
-}
-
-irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
-{
-       struct drm_device *dev = (struct drm_device *) arg;
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u16 temp;
-       u32 pipea_stats, pipeb_stats;
-
-       pipea_stats = I915_READ(I915REG_PIPEASTAT);
-       pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
-
-       temp = I915_READ16(I915REG_INT_IDENTITY_R);
-
-       temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
-
-       DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
-
-       if (temp == 0)
-               return IRQ_NONE;
-
-       I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
-       (void) I915_READ16(I915REG_INT_IDENTITY_R);
-       DRM_READMEMORYBARRIER();
-
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-
-       if (temp & USER_INT_FLAG)
-               DRM_WAKEUP(&dev_priv->irq_queue);
-
-       if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
-               int vblank_pipe = dev_priv->vblank_pipe;
-
-               if ((vblank_pipe &
-                    (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
-                   == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
-                       if (temp & VSYNC_PIPEA_FLAG)
-                               atomic_inc(&dev->vbl_received);
-                       if (temp & VSYNC_PIPEB_FLAG)
-                               atomic_inc(&dev->vbl_received2);
-               } else if (((temp & VSYNC_PIPEA_FLAG) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
-                          ((temp & VSYNC_PIPEB_FLAG) &&
-                           (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
-                       atomic_inc(&dev->vbl_received);
-
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
-
-               if (dev_priv->swaps_pending > 0)
-                       drm_locked_tasklet(dev, i915_vblank_tasklet);
-               I915_WRITE(I915REG_PIPEASTAT,
-                       pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
-                       I915_VBLANK_CLEAR);
-               I915_WRITE(I915REG_PIPEBSTAT,
-                       pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
-                       I915_VBLANK_CLEAR);
-       }
-
-       return IRQ_HANDLED;
-}
-
-static int i915_emit_irq(struct drm_device * dev)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-
-       i915_kernel_lost_context(dev);
-
-       DRM_DEBUG("\n");
-
-       dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
-
-       if (dev_priv->counter > 0x7FFFFFFFUL)
-               dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
-
-       BEGIN_LP_RING(6);
-       OUT_RING(CMD_STORE_DWORD_IDX);
-       OUT_RING(20);
-       OUT_RING(dev_priv->counter);
-       OUT_RING(0);
-       OUT_RING(0);
-       OUT_RING(GFX_OP_USER_INTERRUPT);
-       ADVANCE_LP_RING();
-
-       return dev_priv->counter;
-}
-
-static int i915_wait_irq(struct drm_device * dev, int irq_nr)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       int ret = 0;
-
-       DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
-                 READ_BREADCRUMB(dev_priv));
-
-       if (READ_BREADCRUMB(dev_priv) >= irq_nr)
-               return 0;
-
-       dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-
-       DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
-                   READ_BREADCRUMB(dev_priv) >= irq_nr);
-
-       if (ret == -EBUSY) {
-               DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
-                         READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
-       }
-
-       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-       return ret;
-}
-
-static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
-                                     atomic_t *counter)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       unsigned int cur_vblank;
-       int ret = 0;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(counter))
-                       - *sequence) <= (1<<23)));
-
-       *sequence = cur_vblank;
-
-       return ret;
-}
-
-
-int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
-{
-       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
-}
-
-int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
-{
-       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
-}
-
-/* Needs the lock as it touches the ring.
- */
-int i915_irq_emit(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_irq_emit_t *emit = data;
-       int result;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       result = i915_emit_irq(dev);
-
-       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
-               DRM_ERROR("copy_to_user\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-/* Doesn't need the hardware lock.
- */
-int i915_irq_wait(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_irq_wait_t *irqwait = data;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       return i915_wait_irq(dev, irqwait->irq_seq);
-}
-
-static void i915_enable_interrupt (struct drm_device *dev)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u16 flag;
-
-       flag = 0;
-       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
-               flag |= VSYNC_PIPEA_FLAG;
-       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
-               flag |= VSYNC_PIPEB_FLAG;
-
-       I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
-}
-
-/* Set the vblank monitor pipe
- */
-int i915_vblank_pipe_set(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_vblank_pipe_t *pipe = data;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
-               DRM_ERROR("called with invalid pipe 0x%x\n", pipe->pipe);
-               return -EINVAL;
-       }
-
-       dev_priv->vblank_pipe = pipe->pipe;
-
-       i915_enable_interrupt (dev);
-
-       return 0;
-}
-
-int i915_vblank_pipe_get(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_vblank_pipe_t *pipe = data;
-       u16 flag;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       flag = I915_READ(I915REG_INT_ENABLE_R);
-       pipe->pipe = 0;
-       if (flag & VSYNC_PIPEA_FLAG)
-               pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
-       if (flag & VSYNC_PIPEB_FLAG)
-               pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
-
-       return 0;
-}
-
-/**
- * Schedule buffer swap at given vertical blank.
- */
-int i915_vblank_swap(struct drm_device *dev, void *data,
-                    struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_vblank_swap_t *swap = data;
-       drm_i915_vbl_swap_t *vbl_swap;
-       unsigned int pipe, seqtype, curseq;
-       unsigned long irqflags;
-       struct list_head *list;
-
-       if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __func__);
-               return -EINVAL;
-       }
-
-       if (dev_priv->sarea_priv->rotation) {
-               DRM_DEBUG("Rotation not supported\n");
-               return -EINVAL;
-       }
-
-       if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
-                            _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
-               DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype);
-               return -EINVAL;
-       }
-
-       pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
-
-       seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
-
-       if (!(dev_priv->vblank_pipe & (1 << pipe))) {
-               DRM_ERROR("Invalid pipe %d\n", pipe);
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&dev->drw_lock, irqflags);
-
-       if (!drm_get_drawable_info(dev, swap->drawable)) {
-               spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-               DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable);
-               return -EINVAL;
-       }
-
-       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
-
-       curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
-
-       if (seqtype == _DRM_VBLANK_RELATIVE)
-               swap->sequence += curseq;
-
-       if ((curseq - swap->sequence) <= (1<<23)) {
-               if (swap->seqtype & _DRM_VBLANK_NEXTONMISS) {
-                       swap->sequence = curseq + 1;
-               } else {
-                       DRM_DEBUG("Missed target sequence\n");
-                       return -EINVAL;
-               }
-       }
-
-       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
-
-       list_for_each(list, &dev_priv->vbl_swaps.head) {
-               vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
-
-               if (vbl_swap->drw_id == swap->drawable &&
-                   vbl_swap->pipe == pipe &&
-                   vbl_swap->sequence == swap->sequence) {
-                       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
-                       DRM_DEBUG("Already scheduled\n");
-                       return 0;
-               }
-       }
-
-       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
-
-       if (dev_priv->swaps_pending >= 100) {
-               DRM_DEBUG("Too many swaps queued\n");
-               return -EBUSY;
-       }
-
-       vbl_swap = drm_calloc(1, sizeof(*vbl_swap), DRM_MEM_DRIVER);
-
-       if (!vbl_swap) {
-               DRM_ERROR("Failed to allocate memory to queue swap\n");
-               return -ENOMEM;
-       }
-
-       DRM_DEBUG("\n");
-
-       vbl_swap->drw_id = swap->drawable;
-       vbl_swap->pipe = pipe;
-       vbl_swap->sequence = swap->sequence;
-
-       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
-
-       list_add_tail(&vbl_swap->head, &dev_priv->vbl_swaps.head);
-       dev_priv->swaps_pending++;
-
-       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
-
-       return 0;
-}
-
-/* drm_dma.h hooks
-*/
-void i915_driver_irq_preinstall(struct drm_device * dev)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-
-       I915_WRITE16(I915REG_HWSTAM, 0xfffe);
-       I915_WRITE16(I915REG_INT_MASK_R, 0x0);
-       I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
-}
-
-void i915_driver_irq_postinstall(struct drm_device * dev)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-
-       spin_lock_init(&dev_priv->swaps_lock);
-       INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
-       dev_priv->swaps_pending = 0;
-
-       if (!dev_priv->vblank_pipe)
-               dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
-       i915_enable_interrupt(dev);
-       DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
-}
-
-void i915_driver_irq_uninstall(struct drm_device * dev)
-{
-       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-       u16 temp;
-
-       if (!dev_priv)
-               return;
-
-       I915_WRITE16(I915REG_HWSTAM, 0xffff);
-       I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
-       I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
-
-       temp = I915_READ16(I915REG_INT_IDENTITY_R);
-       I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
-}
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
deleted file mode 100644 (file)
index 6126a60..0000000
+++ /dev/null
@@ -1,386 +0,0 @@
-/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
- */
-/*
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i915_drm.h"
-#include "i915_drv.h"
-
-/* This memory manager is integrated into the global/local lru
- * mechanisms used by the clients.  Specifically, it operates by
- * setting the 'in_use' fields of the global LRU to indicate whether
- * this region is privately allocated to a client.
- *
- * This does require the client to actually respect that field.
- *
- * Currently no effort is made to allocate 'private' memory in any
- * clever way - the LRU information isn't used to determine which
- * block to allocate, and the ring is drained prior to allocations --
- * in other words allocation is expensive.
- */
-static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       struct drm_tex_region *list;
-       unsigned shift, nr;
-       unsigned start;
-       unsigned end;
-       unsigned i;
-       int age;
-
-       shift = dev_priv->tex_lru_log_granularity;
-       nr = I915_NR_TEX_REGIONS;
-
-       start = p->start >> shift;
-       end = (p->start + p->size - 1) >> shift;
-
-       age = ++sarea_priv->texAge;
-       list = sarea_priv->texList;
-
-       /* Mark the regions with the new flag and update their age.  Move
-        * them to head of list to preserve LRU semantics.
-        */
-       for (i = start; i <= end; i++) {
-               list[i].in_use = in_use;
-               list[i].age = age;
-
-               /* remove_from_list(i)
-                */
-               list[(unsigned)list[i].next].prev = list[i].prev;
-               list[(unsigned)list[i].prev].next = list[i].next;
-
-               /* insert_at_head(list, i)
-                */
-               list[i].prev = nr;
-               list[i].next = list[nr].next;
-               list[(unsigned)list[nr].next].prev = i;
-               list[nr].next = i;
-       }
-}
-
-/* Very simple allocator for agp memory, working on a static range
- * already mapped into each client's address space.
- */
-
-static struct mem_block *split_block(struct mem_block *p, int start, int size,
-                                    struct drm_file *file_priv)
-{
-       /* Maybe cut off the start of an existing block */
-       if (start > p->start) {
-               struct mem_block *newblock =
-                   drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
-               if (!newblock)
-                       goto out;
-               newblock->start = start;
-               newblock->size = p->size - (start - p->start);
-               newblock->file_priv = NULL;
-               newblock->next = p->next;
-               newblock->prev = p;
-               p->next->prev = newblock;
-               p->next = newblock;
-               p->size -= newblock->size;
-               p = newblock;
-       }
-
-       /* Maybe cut off the end of an existing block */
-       if (size < p->size) {
-               struct mem_block *newblock =
-                   drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
-               if (!newblock)
-                       goto out;
-               newblock->start = start + size;
-               newblock->size = p->size - size;
-               newblock->file_priv = NULL;
-               newblock->next = p->next;
-               newblock->prev = p;
-               p->next->prev = newblock;
-               p->next = newblock;
-               p->size = size;
-       }
-
-      out:
-       /* Our block is in the middle */
-       p->file_priv = file_priv;
-       return p;
-}
-
-static struct mem_block *alloc_block(struct mem_block *heap, int size,
-                                    int align2, struct drm_file *file_priv)
-{
-       struct mem_block *p;
-       int mask = (1 << align2) - 1;
-
-       for (p = heap->next; p != heap; p = p->next) {
-               int start = (p->start + mask) & ~mask;
-               if (p->file_priv == NULL && start + size <= p->start + p->size)
-                       return split_block(p, start, size, file_priv);
-       }
-
-       return NULL;
-}
-
-static struct mem_block *find_block(struct mem_block *heap, int start)
-{
-       struct mem_block *p;
-
-       for (p = heap->next; p != heap; p = p->next)
-               if (p->start == start)
-                       return p;
-
-       return NULL;
-}
-
-static void free_block(struct mem_block *p)
-{
-       p->file_priv = NULL;
-
-       /* Assumes a single contiguous range.  Needs a special file_priv in
-        * 'heap' to stop it being subsumed.
-        */
-       if (p->next->file_priv == NULL) {
-               struct mem_block *q = p->next;
-               p->size += q->size;
-               p->next = q->next;
-               p->next->prev = p;
-               drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
-       }
-
-       if (p->prev->file_priv == NULL) {
-               struct mem_block *q = p->prev;
-               q->size += p->size;
-               q->next = p->next;
-               q->next->prev = q;
-               drm_free(p, sizeof(*q), DRM_MEM_BUFLISTS);
-       }
-}
-
-/* Initialize.  How to check for an uninitialized heap?
- */
-static int init_heap(struct mem_block **heap, int start, int size)
-{
-       struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFLISTS);
-
-       if (!blocks)
-               return -ENOMEM;
-
-       *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFLISTS);
-       if (!*heap) {
-               drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFLISTS);
-               return -ENOMEM;
-       }
-
-       blocks->start = start;
-       blocks->size = size;
-       blocks->file_priv = NULL;
-       blocks->next = blocks->prev = *heap;
-
-       memset(*heap, 0, sizeof(**heap));
-       (*heap)->file_priv = (struct drm_file *) - 1;
-       (*heap)->next = (*heap)->prev = blocks;
-       return 0;
-}
-
-/* Free all blocks associated with the releasing file.
- */
-void i915_mem_release(struct drm_device * dev, struct drm_file *file_priv,
-                     struct mem_block *heap)
-{
-       struct mem_block *p;
-
-       if (!heap || !heap->next)
-               return;
-
-       for (p = heap->next; p != heap; p = p->next) {
-               if (p->file_priv == file_priv) {
-                       p->file_priv = NULL;
-                       mark_block(dev, p, 0);
-               }
-       }
-
-       /* Assumes a single contiguous range.  Needs a special file_priv in
-        * 'heap' to stop it being subsumed.
-        */
-       for (p = heap->next; p != heap; p = p->next) {
-               while (p->file_priv == NULL && p->next->file_priv == NULL) {
-                       struct mem_block *q = p->next;
-                       p->size += q->size;
-                       p->next = q->next;
-                       p->next->prev = p;
-                       drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
-               }
-       }
-}
-
-/* Shutdown.
- */
-void i915_mem_takedown(struct mem_block **heap)
-{
-       struct mem_block *p;
-
-       if (!*heap)
-               return;
-
-       for (p = (*heap)->next; p != *heap;) {
-               struct mem_block *q = p;
-               p = p->next;
-               drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
-       }
-
-       drm_free(*heap, sizeof(**heap), DRM_MEM_BUFLISTS);
-       *heap = NULL;
-}
-
-static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region)
-{
-       switch (region) {
-       case I915_MEM_REGION_AGP:
-               return &dev_priv->agp_heap;
-       default:
-               return NULL;
-       }
-}
-
-/* IOCTL HANDLERS */
-
-int i915_mem_alloc(struct drm_device *dev, void *data,
-                  struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_mem_alloc_t *alloc = data;
-       struct mem_block *block, **heap;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       heap = get_heap(dev_priv, alloc->region);
-       if (!heap || !*heap)
-               return -EFAULT;
-
-       /* Make things easier on ourselves: all allocations at least
-        * 4k aligned.
-        */
-       if (alloc->alignment < 12)
-               alloc->alignment = 12;
-
-       block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv);
-
-       if (!block)
-               return -ENOMEM;
-
-       mark_block(dev, block, 1);
-
-       if (DRM_COPY_TO_USER(alloc->region_offset, &block->start,
-                            sizeof(int))) {
-               DRM_ERROR("copy_to_user\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-int i915_mem_free(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_mem_free_t *memfree = data;
-       struct mem_block *block, **heap;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       heap = get_heap(dev_priv, memfree->region);
-       if (!heap || !*heap)
-               return -EFAULT;
-
-       block = find_block(*heap, memfree->region_offset);
-       if (!block)
-               return -EFAULT;
-
-       if (block->file_priv != file_priv)
-               return -EPERM;
-
-       mark_block(dev, block, 0);
-       free_block(block);
-       return 0;
-}
-
-int i915_mem_init_heap(struct drm_device *dev, void *data,
-                      struct drm_file *file_priv)
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_mem_init_heap_t *initheap = data;
-       struct mem_block **heap;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       heap = get_heap(dev_priv, initheap->region);
-       if (!heap)
-               return -EFAULT;
-
-       if (*heap) {
-               DRM_ERROR("heap already initialized?");
-               return -EFAULT;
-       }
-
-       return init_heap(heap, initheap->start, initheap->size);
-}
-
-int i915_mem_destroy_heap( struct drm_device *dev, void *data,
-                          struct drm_file *file_priv )
-{
-       drm_i915_private_t *dev_priv = dev->dev_private;
-       drm_i915_mem_destroy_heap_t *destroyheap = data;
-       struct mem_block **heap;
-
-       if ( !dev_priv ) {
-               DRM_ERROR( "called with no initialization\n" );
-               return -EINVAL;
-       }
-
-       heap = get_heap( dev_priv, destroyheap->region );
-       if (!heap) {
-               DRM_ERROR("get_heap failed");
-               return -EFAULT;
-       }
-
-       if (!*heap) {
-               DRM_ERROR("heap not initialized?");
-               return -EFAULT;
-       }
-
-       i915_mem_takedown( heap );
-       return 0;
-}
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
deleted file mode 100644 (file)
index c1d12db..0000000
+++ /dev/null
@@ -1,1162 +0,0 @@
-/* mga_dma.c -- DMA support for mga g200/g400 -*- linux-c -*-
- * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file mga_dma.c
- * DMA support for MGA G200 / G400.
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Jeff Hartmann <jhartmann@valinux.com>
- * \author Keith Whitwell <keith@tungstengraphics.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "drm_sarea.h"
-#include "mga_drm.h"
-#include "mga_drv.h"
-
-#define MGA_DEFAULT_USEC_TIMEOUT       10000
-#define MGA_FREELIST_DEBUG             0
-
-#define MINIMAL_CLEANUP 0
-#define FULL_CLEANUP 1
-static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup);
-
-/* ================================================================
- * Engine control
- */
-
-int mga_do_wait_for_idle(drm_mga_private_t * dev_priv)
-{
-       u32 status = 0;
-       int i;
-       DRM_DEBUG("\n");
-
-       for (i = 0; i < dev_priv->usec_timeout; i++) {
-               status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
-               if (status == MGA_ENDPRDMASTS) {
-                       MGA_WRITE8(MGA_CRTC_INDEX, 0);
-                       return 0;
-               }
-               DRM_UDELAY(1);
-       }
-
-#if MGA_DMA_DEBUG
-       DRM_ERROR("failed!\n");
-       DRM_INFO("   status=0x%08x\n", status);
-#endif
-       return -EBUSY;
-}
-
-static int mga_do_dma_reset(drm_mga_private_t * dev_priv)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_primary_buffer_t *primary = &dev_priv->prim;
-
-       DRM_DEBUG("\n");
-
-       /* The primary DMA stream should look like new right about now.
-        */
-       primary->tail = 0;
-       primary->space = primary->size;
-       primary->last_flush = 0;
-
-       sarea_priv->last_wrap = 0;
-
-       /* FIXME: Reset counters, buffer ages etc...
-        */
-
-       /* FIXME: What else do we need to reinitialize?  WARP stuff?
-        */
-
-       return 0;
-}
-
-/* ================================================================
- * Primary DMA stream
- */
-
-void mga_do_dma_flush(drm_mga_private_t * dev_priv)
-{
-       drm_mga_primary_buffer_t *primary = &dev_priv->prim;
-       u32 head, tail;
-       u32 status = 0;
-       int i;
-       DMA_LOCALS;
-       DRM_DEBUG("\n");
-
-       /* We need to wait so that we can do an safe flush */
-       for (i = 0; i < dev_priv->usec_timeout; i++) {
-               status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
-               if (status == MGA_ENDPRDMASTS)
-                       break;
-               DRM_UDELAY(1);
-       }
-
-       if (primary->tail == primary->last_flush) {
-               DRM_DEBUG("   bailing out...\n");
-               return;
-       }
-
-       tail = primary->tail + dev_priv->primary->offset;
-
-       /* We need to pad the stream between flushes, as the card
-        * actually (partially?) reads the first of these commands.
-        * See page 4-16 in the G400 manual, middle of the page or so.
-        */
-       BEGIN_DMA(1);
-
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
-
-       ADVANCE_DMA();
-
-       primary->last_flush = primary->tail;
-
-       head = MGA_READ(MGA_PRIMADDRESS);
-
-       if (head <= tail) {
-               primary->space = primary->size - primary->tail;
-       } else {
-               primary->space = head - tail;
-       }
-
-       DRM_DEBUG("   head = 0x%06lx\n", head - dev_priv->primary->offset);
-       DRM_DEBUG("   tail = 0x%06lx\n", tail - dev_priv->primary->offset);
-       DRM_DEBUG("  space = 0x%06x\n", primary->space);
-
-       mga_flush_write_combine();
-       MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
-
-       DRM_DEBUG("done.\n");
-}
-
-void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
-{
-       drm_mga_primary_buffer_t *primary = &dev_priv->prim;
-       u32 head, tail;
-       DMA_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_DMA_WRAP();
-
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
-
-       ADVANCE_DMA();
-
-       tail = primary->tail + dev_priv->primary->offset;
-
-       primary->tail = 0;
-       primary->last_flush = 0;
-       primary->last_wrap++;
-
-       head = MGA_READ(MGA_PRIMADDRESS);
-
-       if (head == dev_priv->primary->offset) {
-               primary->space = primary->size;
-       } else {
-               primary->space = head - dev_priv->primary->offset;
-       }
-
-       DRM_DEBUG("   head = 0x%06lx\n", head - dev_priv->primary->offset);
-       DRM_DEBUG("   tail = 0x%06x\n", primary->tail);
-       DRM_DEBUG("   wrap = %d\n", primary->last_wrap);
-       DRM_DEBUG("  space = 0x%06x\n", primary->space);
-
-       mga_flush_write_combine();
-       MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
-
-       set_bit(0, &primary->wrapped);
-       DRM_DEBUG("done.\n");
-}
-
-void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv)
-{
-       drm_mga_primary_buffer_t *primary = &dev_priv->prim;
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       u32 head = dev_priv->primary->offset;
-       DRM_DEBUG("\n");
-
-       sarea_priv->last_wrap++;
-       DRM_DEBUG("   wrap = %d\n", sarea_priv->last_wrap);
-
-       mga_flush_write_combine();
-       MGA_WRITE(MGA_PRIMADDRESS, head | MGA_DMA_GENERAL);
-
-       clear_bit(0, &primary->wrapped);
-       DRM_DEBUG("done.\n");
-}
-
-/* ================================================================
- * Freelist management
- */
-
-#define MGA_BUFFER_USED                ~0
-#define MGA_BUFFER_FREE                0
-
-#if MGA_FREELIST_DEBUG
-static void mga_freelist_print(struct drm_device * dev)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_freelist_t *entry;
-
-       DRM_INFO("\n");
-       DRM_INFO("current dispatch: last=0x%x done=0x%x\n",
-                dev_priv->sarea_priv->last_dispatch,
-                (unsigned int)(MGA_READ(MGA_PRIMADDRESS) -
-                               dev_priv->primary->offset));
-       DRM_INFO("current freelist:\n");
-
-       for (entry = dev_priv->head->next; entry; entry = entry->next) {
-               DRM_INFO("   %p   idx=%2d  age=0x%x 0x%06lx\n",
-                        entry, entry->buf->idx, entry->age.head,
-                        entry->age.head - dev_priv->primary->offset);
-       }
-       DRM_INFO("\n");
-}
-#endif
-
-static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_mga_buf_priv_t *buf_priv;
-       drm_mga_freelist_t *entry;
-       int i;
-       DRM_DEBUG("count=%d\n", dma->buf_count);
-
-       dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
-       if (dev_priv->head == NULL)
-               return -ENOMEM;
-
-       memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
-       SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0);
-
-       for (i = 0; i < dma->buf_count; i++) {
-               buf = dma->buflist[i];
-               buf_priv = buf->dev_private;
-
-               entry = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
-               if (entry == NULL)
-                       return -ENOMEM;
-
-               memset(entry, 0, sizeof(drm_mga_freelist_t));
-
-               entry->next = dev_priv->head->next;
-               entry->prev = dev_priv->head;
-               SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
-               entry->buf = buf;
-
-               if (dev_priv->head->next != NULL)
-                       dev_priv->head->next->prev = entry;
-               if (entry->next == NULL)
-                       dev_priv->tail = entry;
-
-               buf_priv->list_entry = entry;
-               buf_priv->discard = 0;
-               buf_priv->dispatched = 0;
-
-               dev_priv->head->next = entry;
-       }
-
-       return 0;
-}
-
-static void mga_freelist_cleanup(struct drm_device * dev)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_freelist_t *entry;
-       drm_mga_freelist_t *next;
-       DRM_DEBUG("\n");
-
-       entry = dev_priv->head;
-       while (entry) {
-               next = entry->next;
-               drm_free(entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
-               entry = next;
-       }
-
-       dev_priv->head = dev_priv->tail = NULL;
-}
-
-#if 0
-/* FIXME: Still needed?
- */
-static void mga_freelist_reset(struct drm_device * dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_mga_buf_priv_t *buf_priv;
-       int i;
-
-       for (i = 0; i < dma->buf_count; i++) {
-               buf = dma->buflist[i];
-               buf_priv = buf->dev_private;
-               SET_AGE(&buf_priv->list_entry->age, MGA_BUFFER_FREE, 0);
-       }
-}
-#endif
-
-static struct drm_buf *mga_freelist_get(struct drm_device * dev)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_freelist_t *next;
-       drm_mga_freelist_t *prev;
-       drm_mga_freelist_t *tail = dev_priv->tail;
-       u32 head, wrap;
-       DRM_DEBUG("\n");
-
-       head = MGA_READ(MGA_PRIMADDRESS);
-       wrap = dev_priv->sarea_priv->last_wrap;
-
-       DRM_DEBUG("   tail=0x%06lx %d\n",
-                 tail->age.head ?
-                 tail->age.head - dev_priv->primary->offset : 0,
-                 tail->age.wrap);
-       DRM_DEBUG("   head=0x%06lx %d\n",
-                 head - dev_priv->primary->offset, wrap);
-
-       if (TEST_AGE(&tail->age, head, wrap)) {
-               prev = dev_priv->tail->prev;
-               next = dev_priv->tail;
-               prev->next = NULL;
-               next->prev = next->next = NULL;
-               dev_priv->tail = prev;
-               SET_AGE(&next->age, MGA_BUFFER_USED, 0);
-               return next->buf;
-       }
-
-       DRM_DEBUG("returning NULL!\n");
-       return NULL;
-}
-
-int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_buf_priv_t *buf_priv = buf->dev_private;
-       drm_mga_freelist_t *head, *entry, *prev;
-
-       DRM_DEBUG("age=0x%06lx wrap=%d\n",
-                 buf_priv->list_entry->age.head -
-                 dev_priv->primary->offset, buf_priv->list_entry->age.wrap);
-
-       entry = buf_priv->list_entry;
-       head = dev_priv->head;
-
-       if (buf_priv->list_entry->age.head == MGA_BUFFER_USED) {
-               SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
-               prev = dev_priv->tail;
-               prev->next = entry;
-               entry->prev = prev;
-               entry->next = NULL;
-       } else {
-               prev = head->next;
-               head->next = entry;
-               prev->prev = entry;
-               entry->prev = head;
-               entry->next = prev;
-       }
-
-       return 0;
-}
-
-/* ================================================================
- * DMA initialization, cleanup
- */
-
-int mga_driver_load(struct drm_device * dev, unsigned long flags)
-{
-       drm_mga_private_t *dev_priv;
-
-       dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
-       if (!dev_priv)
-               return -ENOMEM;
-
-       dev->dev_private = (void *)dev_priv;
-       memset(dev_priv, 0, sizeof(drm_mga_private_t));
-
-       dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
-       dev_priv->chipset = flags;
-
-       dev_priv->mmio_base = drm_get_resource_start(dev, 1);
-       dev_priv->mmio_size = drm_get_resource_len(dev, 1);
-
-       dev->counters += 3;
-       dev->types[6] = _DRM_STAT_IRQ;
-       dev->types[7] = _DRM_STAT_PRIMARY;
-       dev->types[8] = _DRM_STAT_SECONDARY;
-
-       return 0;
-}
-
-#if __OS_HAS_AGP
-/**
- * Bootstrap the driver for AGP DMA.
- *
- * \todo
- * Investigate whether there is any benifit to storing the WARP microcode in
- * AGP memory.  If not, the microcode may as well always be put in PCI
- * memory.
- *
- * \todo
- * This routine needs to set dma_bs->agp_mode to the mode actually configured
- * in the hardware.  Looking just at the Linux AGP driver code, I don't see
- * an easy way to determine this.
- *
- * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
- */
-static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
-                                   drm_mga_dma_bootstrap_t * dma_bs)
-{
-       drm_mga_private_t *const dev_priv =
-           (drm_mga_private_t *) dev->dev_private;
-       unsigned int warp_size = mga_warp_microcode_size(dev_priv);
-       int err;
-       unsigned offset;
-       const unsigned secondary_size = dma_bs->secondary_bin_count
-           * dma_bs->secondary_bin_size;
-       const unsigned agp_size = (dma_bs->agp_size << 20);
-       struct drm_buf_desc req;
-       struct drm_agp_mode mode;
-       struct drm_agp_info info;
-       struct drm_agp_buffer agp_req;
-       struct drm_agp_binding bind_req;
-
-       /* Acquire AGP. */
-       err = drm_agp_acquire(dev);
-       if (err) {
-               DRM_ERROR("Unable to acquire AGP: %d\n", err);
-               return err;
-       }
-
-       err = drm_agp_info(dev, &info);
-       if (err) {
-               DRM_ERROR("Unable to get AGP info: %d\n", err);
-               return err;
-       }
-
-       mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode;
-       err = drm_agp_enable(dev, mode);
-       if (err) {
-               DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode);
-               return err;
-       }
-
-       /* In addition to the usual AGP mode configuration, the G200 AGP cards
-        * need to have the AGP mode "manually" set.
-        */
-
-       if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
-               if (mode.mode & 0x02) {
-                       MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
-               } else {
-                       MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
-               }
-       }
-
-       /* Allocate and bind AGP memory. */
-       agp_req.size = agp_size;
-       agp_req.type = 0;
-       err = drm_agp_alloc(dev, &agp_req);
-       if (err) {
-               dev_priv->agp_size = 0;
-               DRM_ERROR("Unable to allocate %uMB AGP memory\n",
-                         dma_bs->agp_size);
-               return err;
-       }
-
-       dev_priv->agp_size = agp_size;
-       dev_priv->agp_handle = agp_req.handle;
-
-       bind_req.handle = agp_req.handle;
-       bind_req.offset = 0;
-       err = drm_agp_bind(dev, &bind_req);
-       if (err) {
-               DRM_ERROR("Unable to bind AGP memory: %d\n", err);
-               return err;
-       }
-
-       /* Make drm_addbufs happy by not trying to create a mapping for less
-        * than a page.
-        */
-       if (warp_size < PAGE_SIZE)
-               warp_size = PAGE_SIZE;
-
-       offset = 0;
-       err = drm_addmap(dev, offset, warp_size,
-                        _DRM_AGP, _DRM_READ_ONLY, &dev_priv->warp);
-       if (err) {
-               DRM_ERROR("Unable to map WARP microcode: %d\n", err);
-               return err;
-       }
-
-       offset += warp_size;
-       err = drm_addmap(dev, offset, dma_bs->primary_size,
-                        _DRM_AGP, _DRM_READ_ONLY, &dev_priv->primary);
-       if (err) {
-               DRM_ERROR("Unable to map primary DMA region: %d\n", err);
-               return err;
-       }
-
-       offset += dma_bs->primary_size;
-       err = drm_addmap(dev, offset, secondary_size,
-                        _DRM_AGP, 0, &dev->agp_buffer_map);
-       if (err) {
-               DRM_ERROR("Unable to map secondary DMA region: %d\n", err);
-               return err;
-       }
-
-       (void)memset(&req, 0, sizeof(req));
-       req.count = dma_bs->secondary_bin_count;
-       req.size = dma_bs->secondary_bin_size;
-       req.flags = _DRM_AGP_BUFFER;
-       req.agp_start = offset;
-
-       err = drm_addbufs_agp(dev, &req);
-       if (err) {
-               DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
-               return err;
-       }
-
-       {
-               struct drm_map_list *_entry;
-               unsigned long agp_token = 0;
-
-               list_for_each_entry(_entry, &dev->maplist, head) {
-                       if (_entry->map == dev->agp_buffer_map)
-                               agp_token = _entry->user_token;
-               }
-               if (!agp_token)
-                       return -EFAULT;
-
-               dev->agp_buffer_token = agp_token;
-       }
-
-       offset += secondary_size;
-       err = drm_addmap(dev, offset, agp_size - offset,
-                        _DRM_AGP, 0, &dev_priv->agp_textures);
-       if (err) {
-               DRM_ERROR("Unable to map AGP texture region %d\n", err);
-               return err;
-       }
-
-       drm_core_ioremap(dev_priv->warp, dev);
-       drm_core_ioremap(dev_priv->primary, dev);
-       drm_core_ioremap(dev->agp_buffer_map, dev);
-
-       if (!dev_priv->warp->handle ||
-           !dev_priv->primary->handle || !dev->agp_buffer_map->handle) {
-               DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n",
-                         dev_priv->warp->handle, dev_priv->primary->handle,
-                         dev->agp_buffer_map->handle);
-               return -ENOMEM;
-       }
-
-       dev_priv->dma_access = MGA_PAGPXFER;
-       dev_priv->wagp_enable = MGA_WAGP_ENABLE;
-
-       DRM_INFO("Initialized card for AGP DMA.\n");
-       return 0;
-}
-#else
-static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
-                                   drm_mga_dma_bootstrap_t * dma_bs)
-{
-       return -EINVAL;
-}
-#endif
-
-/**
- * Bootstrap the driver for PCI DMA.
- *
- * \todo
- * The algorithm for decreasing the size of the primary DMA buffer could be
- * better.  The size should be rounded up to the nearest page size, then
- * decrease the request size by a single page each pass through the loop.
- *
- * \todo
- * Determine whether the maximum address passed to drm_pci_alloc is correct.
- * The same goes for drm_addbufs_pci.
- *
- * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
- */
-static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
-                                   drm_mga_dma_bootstrap_t * dma_bs)
-{
-       drm_mga_private_t *const dev_priv =
-           (drm_mga_private_t *) dev->dev_private;
-       unsigned int warp_size = mga_warp_microcode_size(dev_priv);
-       unsigned int primary_size;
-       unsigned int bin_count;
-       int err;
-       struct drm_buf_desc req;
-
-       if (dev->dma == NULL) {
-               DRM_ERROR("dev->dma is NULL\n");
-               return -EFAULT;
-       }
-
-       /* Make drm_addbufs happy by not trying to create a mapping for less
-        * than a page.
-        */
-       if (warp_size < PAGE_SIZE)
-               warp_size = PAGE_SIZE;
-
-       /* The proper alignment is 0x100 for this mapping */
-       err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT,
-                        _DRM_READ_ONLY, &dev_priv->warp);
-       if (err != 0) {
-               DRM_ERROR("Unable to create mapping for WARP microcode: %d\n",
-                         err);
-               return err;
-       }
-
-       /* Other than the bottom two bits being used to encode other
-        * information, there don't appear to be any restrictions on the
-        * alignment of the primary or secondary DMA buffers.
-        */
-
-       for (primary_size = dma_bs->primary_size; primary_size != 0;
-            primary_size >>= 1) {
-               /* The proper alignment for this mapping is 0x04 */
-               err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT,
-                                _DRM_READ_ONLY, &dev_priv->primary);
-               if (!err)
-                       break;
-       }
-
-       if (err != 0) {
-               DRM_ERROR("Unable to allocate primary DMA region: %d\n", err);
-               return -ENOMEM;
-       }
-
-       if (dev_priv->primary->size != dma_bs->primary_size) {
-               DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n",
-                        dma_bs->primary_size,
-                        (unsigned)dev_priv->primary->size);
-               dma_bs->primary_size = dev_priv->primary->size;
-       }
-
-       for (bin_count = dma_bs->secondary_bin_count; bin_count > 0;
-            bin_count--) {
-               (void)memset(&req, 0, sizeof(req));
-               req.count = bin_count;
-               req.size = dma_bs->secondary_bin_size;
-
-               err = drm_addbufs_pci(dev, &req);
-               if (!err) {
-                       break;
-               }
-       }
-
-       if (bin_count == 0) {
-               DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
-               return err;
-       }
-
-       if (bin_count != dma_bs->secondary_bin_count) {
-               DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u "
-                        "to %u.\n", dma_bs->secondary_bin_count, bin_count);
-
-               dma_bs->secondary_bin_count = bin_count;
-       }
-
-       dev_priv->dma_access = 0;
-       dev_priv->wagp_enable = 0;
-
-       dma_bs->agp_mode = 0;
-
-       DRM_INFO("Initialized card for PCI DMA.\n");
-       return 0;
-}
-
-static int mga_do_dma_bootstrap(struct drm_device * dev,
-                               drm_mga_dma_bootstrap_t * dma_bs)
-{
-       const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
-       int err;
-       drm_mga_private_t *const dev_priv =
-           (drm_mga_private_t *) dev->dev_private;
-
-       dev_priv->used_new_dma_init = 1;
-
-       /* The first steps are the same for both PCI and AGP based DMA.  Map
-        * the cards MMIO registers and map a status page.
-        */
-       err = drm_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size,
-                        _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio);
-       if (err) {
-               DRM_ERROR("Unable to map MMIO region: %d\n", err);
-               return err;
-       }
-
-       err = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
-                        _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
-                        &dev_priv->status);
-       if (err) {
-               DRM_ERROR("Unable to map status region: %d\n", err);
-               return err;
-       }
-
-       /* The DMA initialization procedure is slightly different for PCI and
-        * AGP cards.  AGP cards just allocate a large block of AGP memory and
-        * carve off portions of it for internal uses.  The remaining memory
-        * is returned to user-mode to be used for AGP textures.
-        */
-       if (is_agp) {
-               err = mga_do_agp_dma_bootstrap(dev, dma_bs);
-       }
-
-       /* If we attempted to initialize the card for AGP DMA but failed,
-        * clean-up any mess that may have been created.
-        */
-
-       if (err) {
-               mga_do_cleanup_dma(dev, MINIMAL_CLEANUP);
-       }
-
-       /* Not only do we want to try and initialized PCI cards for PCI DMA,
-        * but we also try to initialized AGP cards that could not be
-        * initialized for AGP DMA.  This covers the case where we have an AGP
-        * card in a system with an unsupported AGP chipset.  In that case the
-        * card will be detected as AGP, but we won't be able to allocate any
-        * AGP memory, etc.
-        */
-
-       if (!is_agp || err) {
-               err = mga_do_pci_dma_bootstrap(dev, dma_bs);
-       }
-
-       return err;
-}
-
-int mga_dma_bootstrap(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv)
-{
-       drm_mga_dma_bootstrap_t *bootstrap = data;
-       int err;
-       static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };
-       const drm_mga_private_t *const dev_priv =
-               (drm_mga_private_t *) dev->dev_private;
-
-       err = mga_do_dma_bootstrap(dev, bootstrap);
-       if (err) {
-               mga_do_cleanup_dma(dev, FULL_CLEANUP);
-               return err;
-       }
-
-       if (dev_priv->agp_textures != NULL) {
-               bootstrap->texture_handle = dev_priv->agp_textures->offset;
-               bootstrap->texture_size = dev_priv->agp_textures->size;
-       } else {
-               bootstrap->texture_handle = 0;
-               bootstrap->texture_size = 0;
-       }
-
-       bootstrap->agp_mode = modes[bootstrap->agp_mode & 0x07];
-
-       return err;
-}
-
-static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init)
-{
-       drm_mga_private_t *dev_priv;
-       int ret;
-       DRM_DEBUG("\n");
-
-       dev_priv = dev->dev_private;
-
-       if (init->sgram) {
-               dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
-       } else {
-               dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
-       }
-       dev_priv->maccess = init->maccess;
-
-       dev_priv->fb_cpp = init->fb_cpp;
-       dev_priv->front_offset = init->front_offset;
-       dev_priv->front_pitch = init->front_pitch;
-       dev_priv->back_offset = init->back_offset;
-       dev_priv->back_pitch = init->back_pitch;
-
-       dev_priv->depth_cpp = init->depth_cpp;
-       dev_priv->depth_offset = init->depth_offset;
-       dev_priv->depth_pitch = init->depth_pitch;
-
-       /* FIXME: Need to support AGP textures...
-        */
-       dev_priv->texture_offset = init->texture_offset[0];
-       dev_priv->texture_size = init->texture_size[0];
-
-       dev_priv->sarea = drm_getsarea(dev);
-       if (!dev_priv->sarea) {
-               DRM_ERROR("failed to find sarea!\n");
-               return -EINVAL;
-       }
-
-       if (!dev_priv->used_new_dma_init) {
-
-               dev_priv->dma_access = MGA_PAGPXFER;
-               dev_priv->wagp_enable = MGA_WAGP_ENABLE;
-
-               dev_priv->status = drm_core_findmap(dev, init->status_offset);
-               if (!dev_priv->status) {
-                       DRM_ERROR("failed to find status page!\n");
-                       return -EINVAL;
-               }
-               dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
-               if (!dev_priv->mmio) {
-                       DRM_ERROR("failed to find mmio region!\n");
-                       return -EINVAL;
-               }
-               dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
-               if (!dev_priv->warp) {
-                       DRM_ERROR("failed to find warp microcode region!\n");
-                       return -EINVAL;
-               }
-               dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
-               if (!dev_priv->primary) {
-                       DRM_ERROR("failed to find primary dma region!\n");
-                       return -EINVAL;
-               }
-               dev->agp_buffer_token = init->buffers_offset;
-               dev->agp_buffer_map =
-                   drm_core_findmap(dev, init->buffers_offset);
-               if (!dev->agp_buffer_map) {
-                       DRM_ERROR("failed to find dma buffer region!\n");
-                       return -EINVAL;
-               }
-
-               drm_core_ioremap(dev_priv->warp, dev);
-               drm_core_ioremap(dev_priv->primary, dev);
-               drm_core_ioremap(dev->agp_buffer_map, dev);
-       }
-
-       dev_priv->sarea_priv =
-           (drm_mga_sarea_t *) ((u8 *) dev_priv->sarea->handle +
-                                init->sarea_priv_offset);
-
-       if (!dev_priv->warp->handle ||
-           !dev_priv->primary->handle ||
-           ((dev_priv->dma_access != 0) &&
-            ((dev->agp_buffer_map == NULL) ||
-             (dev->agp_buffer_map->handle == NULL)))) {
-               DRM_ERROR("failed to ioremap agp regions!\n");
-               return -ENOMEM;
-       }
-
-       ret = mga_warp_install_microcode(dev_priv);
-       if (ret < 0) {
-               DRM_ERROR("failed to install WARP ucode!: %d\n", ret);
-               return ret;
-       }
-
-       ret = mga_warp_init(dev_priv);
-       if (ret < 0) {
-               DRM_ERROR("failed to init WARP engine!: %d\n", ret);
-               return ret;
-       }
-
-       dev_priv->prim.status = (u32 *) dev_priv->status->handle;
-
-       mga_do_wait_for_idle(dev_priv);
-
-       /* Init the primary DMA registers.
-        */
-       MGA_WRITE(MGA_PRIMADDRESS, dev_priv->primary->offset | MGA_DMA_GENERAL);
-#if 0
-       MGA_WRITE(MGA_PRIMPTR, virt_to_bus((void *)dev_priv->prim.status) | MGA_PRIMPTREN0 |    /* Soft trap, SECEND, SETUPEND */
-                 MGA_PRIMPTREN1);      /* DWGSYNC */
-#endif
-
-       dev_priv->prim.start = (u8 *) dev_priv->primary->handle;
-       dev_priv->prim.end = ((u8 *) dev_priv->primary->handle
-                             + dev_priv->primary->size);
-       dev_priv->prim.size = dev_priv->primary->size;
-
-       dev_priv->prim.tail = 0;
-       dev_priv->prim.space = dev_priv->prim.size;
-       dev_priv->prim.wrapped = 0;
-
-       dev_priv->prim.last_flush = 0;
-       dev_priv->prim.last_wrap = 0;
-
-       dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;
-
-       dev_priv->prim.status[0] = dev_priv->primary->offset;
-       dev_priv->prim.status[1] = 0;
-
-       dev_priv->sarea_priv->last_wrap = 0;
-       dev_priv->sarea_priv->last_frame.head = 0;
-       dev_priv->sarea_priv->last_frame.wrap = 0;
-
-       if (mga_freelist_init(dev, dev_priv) < 0) {
-               DRM_ERROR("could not initialize freelist\n");
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
-{
-       int err = 0;
-       DRM_DEBUG("\n");
-
-       /* Make sure interrupts are disabled here because the uninstall ioctl
-        * may not have been called from userspace and after dev_private
-        * is freed, it's too late.
-        */
-       if (dev->irq_enabled)
-               drm_irq_uninstall(dev);
-
-       if (dev->dev_private) {
-               drm_mga_private_t *dev_priv = dev->dev_private;
-
-               if ((dev_priv->warp != NULL)
-                   && (dev_priv->warp->type != _DRM_CONSISTENT))
-                       drm_core_ioremapfree(dev_priv->warp, dev);
-
-               if ((dev_priv->primary != NULL)
-                   && (dev_priv->primary->type != _DRM_CONSISTENT))
-                       drm_core_ioremapfree(dev_priv->primary, dev);
-
-               if (dev->agp_buffer_map != NULL)
-                       drm_core_ioremapfree(dev->agp_buffer_map, dev);
-
-               if (dev_priv->used_new_dma_init) {
-#if __OS_HAS_AGP
-                       if (dev_priv->agp_handle != 0) {
-                               struct drm_agp_binding unbind_req;
-                               struct drm_agp_buffer free_req;
-
-                               unbind_req.handle = dev_priv->agp_handle;
-                               drm_agp_unbind(dev, &unbind_req);
-
-                               free_req.handle = dev_priv->agp_handle;
-                               drm_agp_free(dev, &free_req);
-
-                               dev_priv->agp_textures = NULL;
-                               dev_priv->agp_size = 0;
-                               dev_priv->agp_handle = 0;
-                       }
-
-                       if ((dev->agp != NULL) && dev->agp->acquired) {
-                               err = drm_agp_release(dev);
-                       }
-#endif
-               }
-
-               dev_priv->warp = NULL;
-               dev_priv->primary = NULL;
-               dev_priv->sarea = NULL;
-               dev_priv->sarea_priv = NULL;
-               dev->agp_buffer_map = NULL;
-
-               if (full_cleanup) {
-                       dev_priv->mmio = NULL;
-                       dev_priv->status = NULL;
-                       dev_priv->used_new_dma_init = 0;
-               }
-
-               memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
-               dev_priv->warp_pipe = 0;
-               memset(dev_priv->warp_pipe_phys, 0,
-                      sizeof(dev_priv->warp_pipe_phys));
-
-               if (dev_priv->head != NULL) {
-                       mga_freelist_cleanup(dev);
-               }
-       }
-
-       return err;
-}
-
-int mga_dma_init(struct drm_device *dev, void *data,
-                struct drm_file *file_priv)
-{
-       drm_mga_init_t *init = data;
-       int err;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       switch (init->func) {
-       case MGA_INIT_DMA:
-               err = mga_do_init_dma(dev, init);
-               if (err) {
-                       (void)mga_do_cleanup_dma(dev, FULL_CLEANUP);
-               }
-               return err;
-       case MGA_CLEANUP_DMA:
-               return mga_do_cleanup_dma(dev, FULL_CLEANUP);
-       }
-
-       return -EINVAL;
-}
-
-/* ================================================================
- * Primary DMA stream management
- */
-
-int mga_dma_flush(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
-{
-       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-       struct drm_lock *lock = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       DRM_DEBUG("%s%s%s\n",
-                 (lock->flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
-                 (lock->flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
-                 (lock->flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "");
-
-       WRAP_WAIT_WITH_RETURN(dev_priv);
-
-       if (lock->flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) {
-               mga_do_dma_flush(dev_priv);
-       }
-
-       if (lock->flags & _DRM_LOCK_QUIESCENT) {
-#if MGA_DMA_DEBUG
-               int ret = mga_do_wait_for_idle(dev_priv);
-               if (ret < 0)
-                       DRM_INFO("-EBUSY\n");
-               return ret;
-#else
-               return mga_do_wait_for_idle(dev_priv);
-#endif
-       } else {
-               return 0;
-       }
-}
-
-int mga_dma_reset(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
-{
-       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       return mga_do_dma_reset(dev_priv);
-}
-
-/* ================================================================
- * DMA buffer management
- */
-
-static int mga_dma_get_buffers(struct drm_device * dev,
-                              struct drm_file *file_priv, struct drm_dma * d)
-{
-       struct drm_buf *buf;
-       int i;
-
-       for (i = d->granted_count; i < d->request_count; i++) {
-               buf = mga_freelist_get(dev);
-               if (!buf)
-                       return -EAGAIN;
-
-               buf->file_priv = file_priv;
-
-               if (DRM_COPY_TO_USER(&d->request_indices[i],
-                                    &buf->idx, sizeof(buf->idx)))
-                       return -EFAULT;
-               if (DRM_COPY_TO_USER(&d->request_sizes[i],
-                                    &buf->total, sizeof(buf->total)))
-                       return -EFAULT;
-
-               d->granted_count++;
-       }
-       return 0;
-}
-
-int mga_dma_buffers(struct drm_device *dev, void *data,
-                   struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-       struct drm_dma *d = data;
-       int ret = 0;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       /* Please don't send us buffers.
-        */
-       if (d->send_count != 0) {
-               DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-                         DRM_CURRENTPID, d->send_count);
-               return -EINVAL;
-       }
-
-       /* We'll send you buffers.
-        */
-       if (d->request_count < 0 || d->request_count > dma->buf_count) {
-               DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         DRM_CURRENTPID, d->request_count, dma->buf_count);
-               return -EINVAL;
-       }
-
-       WRAP_TEST_WITH_RETURN(dev_priv);
-
-       d->granted_count = 0;
-
-       if (d->request_count) {
-               ret = mga_dma_get_buffers(dev, file_priv, d);
-       }
-
-       return ret;
-}
-
-/**
- * Called just before the module is unloaded.
- */
-int mga_driver_unload(struct drm_device * dev)
-{
-       drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
-       dev->dev_private = NULL;
-
-       return 0;
-}
-
-/**
- * Called when the last opener of the device is closed.
- */
-void mga_driver_lastclose(struct drm_device * dev)
-{
-       mga_do_cleanup_dma(dev, FULL_CLEANUP);
-}
-
-int mga_driver_dma_quiescent(struct drm_device * dev)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       return mga_do_wait_for_idle(dev_priv);
-}
diff --git a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h
deleted file mode 100644 (file)
index 944b50a..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-/* mga_drm.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*-
- * Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Jeff Hartmann <jhartmann@valinux.com>
- *    Keith Whitwell <keith@tungstengraphics.com>
- *
- * Rewritten by:
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#ifndef __MGA_DRM_H__
-#define __MGA_DRM_H__
-
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the Xserver file (mga_sarea.h)
- */
-
-#ifndef __MGA_SAREA_DEFINES__
-#define __MGA_SAREA_DEFINES__
-
-/* WARP pipe flags
- */
-#define MGA_F                  0x1     /* fog */
-#define MGA_A                  0x2     /* alpha */
-#define MGA_S                  0x4     /* specular */
-#define MGA_T2                 0x8     /* multitexture */
-
-#define MGA_WARP_TGZ           0
-#define MGA_WARP_TGZF          (MGA_F)
-#define MGA_WARP_TGZA          (MGA_A)
-#define MGA_WARP_TGZAF         (MGA_F|MGA_A)
-#define MGA_WARP_TGZS          (MGA_S)
-#define MGA_WARP_TGZSF         (MGA_S|MGA_F)
-#define MGA_WARP_TGZSA         (MGA_S|MGA_A)
-#define MGA_WARP_TGZSAF                (MGA_S|MGA_F|MGA_A)
-#define MGA_WARP_T2GZ          (MGA_T2)
-#define MGA_WARP_T2GZF         (MGA_T2|MGA_F)
-#define MGA_WARP_T2GZA         (MGA_T2|MGA_A)
-#define MGA_WARP_T2GZAF                (MGA_T2|MGA_A|MGA_F)
-#define MGA_WARP_T2GZS         (MGA_T2|MGA_S)
-#define MGA_WARP_T2GZSF                (MGA_T2|MGA_S|MGA_F)
-#define MGA_WARP_T2GZSA                (MGA_T2|MGA_S|MGA_A)
-#define MGA_WARP_T2GZSAF       (MGA_T2|MGA_S|MGA_F|MGA_A)
-
-#define MGA_MAX_G200_PIPES     8       /* no multitex */
-#define MGA_MAX_G400_PIPES     16
-#define MGA_MAX_WARP_PIPES     MGA_MAX_G400_PIPES
-#define MGA_WARP_UCODE_SIZE    32768   /* in bytes */
-
-#define MGA_CARD_TYPE_G200     1
-#define MGA_CARD_TYPE_G400     2
-#define MGA_CARD_TYPE_G450     3       /* not currently used */
-#define MGA_CARD_TYPE_G550     4
-
-#define MGA_FRONT              0x1
-#define MGA_BACK               0x2
-#define MGA_DEPTH              0x4
-
-/* What needs to be changed for the current vertex dma buffer?
- */
-#define MGA_UPLOAD_CONTEXT     0x1
-#define MGA_UPLOAD_TEX0                0x2
-#define MGA_UPLOAD_TEX1                0x4
-#define MGA_UPLOAD_PIPE                0x8
-#define MGA_UPLOAD_TEX0IMAGE   0x10    /* handled client-side */
-#define MGA_UPLOAD_TEX1IMAGE   0x20    /* handled client-side */
-#define MGA_UPLOAD_2D          0x40
-#define MGA_WAIT_AGE           0x80    /* handled client-side */
-#define MGA_UPLOAD_CLIPRECTS   0x100   /* handled client-side */
-#if 0
-#define MGA_DMA_FLUSH          0x200   /* set when someone gets the lock
-                                          quiescent */
-#endif
-
-/* 32 buffers of 64k each, total 2 meg.
- */
-#define MGA_BUFFER_SIZE                (1 << 16)
-#define MGA_NUM_BUFFERS                128
-
-/* Keep these small for testing.
- */
-#define MGA_NR_SAREA_CLIPRECTS 8
-
-/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
- * regions, subject to a minimum region size of (1<<16) == 64k.
- *
- * Clients may subdivide regions internally, but when sharing between
- * clients, the region size is the minimum granularity.
- */
-
-#define MGA_CARD_HEAP                  0
-#define MGA_AGP_HEAP                   1
-#define MGA_NR_TEX_HEAPS               2
-#define MGA_NR_TEX_REGIONS             16
-#define MGA_LOG_MIN_TEX_REGION_SIZE    16
-
-#define  DRM_MGA_IDLE_RETRY          2048
-
-#endif                         /* __MGA_SAREA_DEFINES__ */
-
-/* Setup registers for 3D context
- */
-typedef struct {
-       unsigned int dstorg;
-       unsigned int maccess;
-       unsigned int plnwt;
-       unsigned int dwgctl;
-       unsigned int alphactrl;
-       unsigned int fogcolor;
-       unsigned int wflag;
-       unsigned int tdualstage0;
-       unsigned int tdualstage1;
-       unsigned int fcol;
-       unsigned int stencil;
-       unsigned int stencilctl;
-} drm_mga_context_regs_t;
-
-/* Setup registers for 2D, X server
- */
-typedef struct {
-       unsigned int pitch;
-} drm_mga_server_regs_t;
-
-/* Setup registers for each texture unit
- */
-typedef struct {
-       unsigned int texctl;
-       unsigned int texctl2;
-       unsigned int texfilter;
-       unsigned int texbordercol;
-       unsigned int texorg;
-       unsigned int texwidth;
-       unsigned int texheight;
-       unsigned int texorg1;
-       unsigned int texorg2;
-       unsigned int texorg3;
-       unsigned int texorg4;
-} drm_mga_texture_regs_t;
-
-/* General aging mechanism
- */
-typedef struct {
-       unsigned int head;      /* Position of head pointer          */
-       unsigned int wrap;      /* Primary DMA wrap count            */
-} drm_mga_age_t;
-
-typedef struct _drm_mga_sarea {
-       /* The channel for communication of state information to the kernel
-        * on firing a vertex dma buffer.
-        */
-       drm_mga_context_regs_t context_state;
-       drm_mga_server_regs_t server_state;
-       drm_mga_texture_regs_t tex_state[2];
-       unsigned int warp_pipe;
-       unsigned int dirty;
-       unsigned int vertsize;
-
-       /* The current cliprects, or a subset thereof.
-        */
-       struct drm_clip_rect boxes[MGA_NR_SAREA_CLIPRECTS];
-       unsigned int nbox;
-
-       /* Information about the most recently used 3d drawable.  The
-        * client fills in the req_* fields, the server fills in the
-        * exported_ fields and puts the cliprects into boxes, above.
-        *
-        * The client clears the exported_drawable field before
-        * clobbering the boxes data.
-        */
-       unsigned int req_drawable;      /* the X drawable id */
-       unsigned int req_draw_buffer;   /* MGA_FRONT or MGA_BACK */
-
-       unsigned int exported_drawable;
-       unsigned int exported_index;
-       unsigned int exported_stamp;
-       unsigned int exported_buffers;
-       unsigned int exported_nfront;
-       unsigned int exported_nback;
-       int exported_back_x, exported_front_x, exported_w;
-       int exported_back_y, exported_front_y, exported_h;
-       struct drm_clip_rect exported_boxes[MGA_NR_SAREA_CLIPRECTS];
-
-       /* Counters for aging textures and for client-side throttling.
-        */
-       unsigned int status[4];
-       unsigned int last_wrap;
-
-       drm_mga_age_t last_frame;
-       unsigned int last_enqueue;      /* last time a buffer was enqueued */
-       unsigned int last_dispatch;     /* age of the most recently dispatched buffer */
-       unsigned int last_quiescent;    /*  */
-
-       /* LRU lists for texture memory in agp space and on the card.
-        */
-       struct drm_tex_region texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
-       unsigned int texAge[MGA_NR_TEX_HEAPS];
-
-       /* Mechanism to validate card state.
-        */
-       int ctxOwner;
-} drm_mga_sarea_t;
-
-/* MGA specific ioctls
- * The device specific ioctl range is 0x40 to 0x79.
- */
-#define DRM_MGA_INIT     0x00
-#define DRM_MGA_FLUSH    0x01
-#define DRM_MGA_RESET    0x02
-#define DRM_MGA_SWAP     0x03
-#define DRM_MGA_CLEAR    0x04
-#define DRM_MGA_VERTEX   0x05
-#define DRM_MGA_INDICES  0x06
-#define DRM_MGA_ILOAD    0x07
-#define DRM_MGA_BLIT     0x08
-#define DRM_MGA_GETPARAM 0x09
-
-/* 3.2:
- * ioctls for operating on fences.
- */
-#define DRM_MGA_SET_FENCE      0x0a
-#define DRM_MGA_WAIT_FENCE     0x0b
-#define DRM_MGA_DMA_BOOTSTRAP  0x0c
-
-#define DRM_IOCTL_MGA_INIT     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t)
-#define DRM_IOCTL_MGA_FLUSH    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t)
-#define DRM_IOCTL_MGA_RESET    DRM_IO(  DRM_COMMAND_BASE + DRM_MGA_RESET)
-#define DRM_IOCTL_MGA_SWAP     DRM_IO(  DRM_COMMAND_BASE + DRM_MGA_SWAP)
-#define DRM_IOCTL_MGA_CLEAR    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t)
-#define DRM_IOCTL_MGA_VERTEX   DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t)
-#define DRM_IOCTL_MGA_INDICES  DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t)
-#define DRM_IOCTL_MGA_ILOAD    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t)
-#define DRM_IOCTL_MGA_BLIT     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t)
-#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t)
-#define DRM_IOCTL_MGA_SET_FENCE     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, uint32_t)
-#define DRM_IOCTL_MGA_WAIT_FENCE    DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, uint32_t)
-#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t)
-
-typedef struct _drm_mga_warp_index {
-       int installed;
-       unsigned long phys_addr;
-       int size;
-} drm_mga_warp_index_t;
-
-typedef struct drm_mga_init {
-       enum {
-               MGA_INIT_DMA = 0x01,
-               MGA_CLEANUP_DMA = 0x02
-       } func;
-
-       unsigned long sarea_priv_offset;
-
-       int chipset;
-       int sgram;
-
-       unsigned int maccess;
-
-       unsigned int fb_cpp;
-       unsigned int front_offset, front_pitch;
-       unsigned int back_offset, back_pitch;
-
-       unsigned int depth_cpp;
-       unsigned int depth_offset, depth_pitch;
-
-       unsigned int texture_offset[MGA_NR_TEX_HEAPS];
-       unsigned int texture_size[MGA_NR_TEX_HEAPS];
-
-       unsigned long fb_offset;
-       unsigned long mmio_offset;
-       unsigned long status_offset;
-       unsigned long warp_offset;
-       unsigned long primary_offset;
-       unsigned long buffers_offset;
-} drm_mga_init_t;
-
-typedef struct drm_mga_dma_bootstrap {
-       /**
-        * \name AGP texture region
-        *
-        * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will
-        * be filled in with the actual AGP texture settings.
-        *
-        * \warning
-        * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode
-        * is zero, it means that PCI memory (most likely through the use of
-        * an IOMMU) is being used for "AGP" textures.
-        */
-       /*@{ */
-       unsigned long texture_handle; /**< Handle used to map AGP textures. */
-       uint32_t texture_size;        /**< Size of the AGP texture region. */
-       /*@} */
-
-       /**
-        * Requested size of the primary DMA region.
-        *
-        * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
-        * filled in with the actual AGP mode.  If AGP was not available
-        */
-       uint32_t primary_size;
-
-       /**
-        * Requested number of secondary DMA buffers.
-        *
-        * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
-        * filled in with the actual number of secondary DMA buffers
-        * allocated.  Particularly when PCI DMA is used, this may be
-        * (subtantially) less than the number requested.
-        */
-       uint32_t secondary_bin_count;
-
-       /**
-        * Requested size of each secondary DMA buffer.
-        *
-        * While the kernel \b is free to reduce
-        * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed
-        * to reduce dma_mga_dma_bootstrap::secondary_bin_size.
-        */
-       uint32_t secondary_bin_size;
-
-       /**
-        * Bit-wise mask of AGPSTAT2_* values.  Currently only \c AGPSTAT2_1X,
-        * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported.  If this value is
-        * zero, it means that PCI DMA should be used, even if AGP is
-        * possible.
-        *
-        * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
-        * filled in with the actual AGP mode.  If AGP was not available
-        * (i.e., PCI DMA was used), this value will be zero.
-        */
-       uint32_t agp_mode;
-
-       /**
-        * Desired AGP GART size, measured in megabytes.
-        */
-       uint8_t agp_size;
-} drm_mga_dma_bootstrap_t;
-
-typedef struct drm_mga_clear {
-       unsigned int flags;
-       unsigned int clear_color;
-       unsigned int clear_depth;
-       unsigned int color_mask;
-       unsigned int depth_mask;
-} drm_mga_clear_t;
-
-typedef struct drm_mga_vertex {
-       int idx;                /* buffer to queue */
-       int used;               /* bytes in use */
-       int discard;            /* client finished with buffer?  */
-} drm_mga_vertex_t;
-
-typedef struct drm_mga_indices {
-       int idx;                /* buffer to queue */
-       unsigned int start;
-       unsigned int end;
-       int discard;            /* client finished with buffer?  */
-} drm_mga_indices_t;
-
-typedef struct drm_mga_iload {
-       int idx;
-       unsigned int dstorg;
-       unsigned int length;
-} drm_mga_iload_t;
-
-typedef struct _drm_mga_blit {
-       unsigned int planemask;
-       unsigned int srcorg;
-       unsigned int dstorg;
-       int src_pitch, dst_pitch;
-       int delta_sx, delta_sy;
-       int delta_dx, delta_dy;
-       int height, ydir;       /* flip image vertically */
-       int source_pitch, dest_pitch;
-} drm_mga_blit_t;
-
-/* 3.1: An ioctl to get parameters that aren't available to the 3d
- * client any other way.
- */
-#define MGA_PARAM_IRQ_NR            1
-
-/* 3.2: Query the actual card type.  The DDX only distinguishes between
- * G200 chips and non-G200 chips, which it calls G400.  It turns out that
- * there are some very sublte differences between the G4x0 chips and the G550
- * chips.  Using this parameter query, a client-side driver can detect the
- * difference between a G4x0 and a G550.
- */
-#define MGA_PARAM_CARD_TYPE         2
-
-typedef struct drm_mga_getparam {
-       int param;
-       void __user *value;
-} drm_mga_getparam_t;
-
-#endif
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
deleted file mode 100644 (file)
index 5572939..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/* mga_drv.c -- Matrox G200/G400 driver -*- linux-c -*-
- * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "mga_drm.h"
-#include "mga_drv.h"
-
-#include "drm_pciids.h"
-
-static int mga_driver_device_is_agp(struct drm_device * dev);
-
-static struct pci_device_id pciidlist[] = {
-       mga_PCI_IDS
-};
-
-static struct drm_driver driver = {
-       .driver_features =
-           DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
-           DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
-           DRIVER_IRQ_VBL,
-       .dev_priv_size = sizeof(drm_mga_buf_priv_t),
-       .load = mga_driver_load,
-       .unload = mga_driver_unload,
-       .lastclose = mga_driver_lastclose,
-       .dma_quiescent = mga_driver_dma_quiescent,
-       .device_is_agp = mga_driver_device_is_agp,
-       .vblank_wait = mga_driver_vblank_wait,
-       .irq_preinstall = mga_driver_irq_preinstall,
-       .irq_postinstall = mga_driver_irq_postinstall,
-       .irq_uninstall = mga_driver_irq_uninstall,
-       .irq_handler = mga_driver_irq_handler,
-       .reclaim_buffers = drm_core_reclaim_buffers,
-       .get_map_ofs = drm_core_get_map_ofs,
-       .get_reg_ofs = drm_core_get_reg_ofs,
-       .ioctls = mga_ioctls,
-       .dma_ioctl = mga_dma_buffers,
-       .fops = {
-                .owner = THIS_MODULE,
-                .open = drm_open,
-                .release = drm_release,
-                .ioctl = drm_ioctl,
-                .mmap = drm_mmap,
-                .poll = drm_poll,
-                .fasync = drm_fasync,
-#ifdef CONFIG_COMPAT
-                .compat_ioctl = mga_compat_ioctl,
-#endif
-                },
-       .pci_driver = {
-                .name = DRIVER_NAME,
-                .id_table = pciidlist,
-       },
-
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int __init mga_init(void)
-{
-       driver.num_ioctls = mga_max_ioctl;
-       return drm_init(&driver);
-}
-
-static void __exit mga_exit(void)
-{
-       drm_exit(&driver);
-}
-
-module_init(mga_init);
-module_exit(mga_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
-
-/**
- * Determine if the device really is AGP or not.
- *
- * In addition to the usual tests performed by \c drm_device_is_agp, this
- * function detects PCI G450 cards that appear to the system exactly like
- * AGP G450 cards.
- *
- * \param dev   The device to be tested.
- *
- * \returns
- * If the device is a PCI G450, zero is returned.  Otherwise 2 is returned.
- */
-static int mga_driver_device_is_agp(struct drm_device * dev)
-{
-       const struct pci_dev *const pdev = dev->pdev;
-
-       /* There are PCI versions of the G450.  These cards have the
-        * same PCI ID as the AGP G450, but have an additional PCI-to-PCI
-        * bridge chip.  We detect these cards, which are not currently
-        * supported by this driver, by looking at the device ID of the
-        * bus the "card" is on.  If vendor is 0x3388 (Hint Corp) and the
-        * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the
-        * device.
-        */
-
-       if ((pdev->device == 0x0525) && pdev->bus->self
-           && (pdev->bus->self->vendor == 0x3388)
-           && (pdev->bus->self->device == 0x0021)) {
-               return 0;
-       }
-
-       return 2;
-}
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
deleted file mode 100644 (file)
index f6ebd24..0000000
+++ /dev/null
@@ -1,687 +0,0 @@
-/* mga_drv.h -- Private header for the Matrox G200/G400 driver -*- linux-c -*-
- * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#ifndef __MGA_DRV_H__
-#define __MGA_DRV_H__
-
-/* General customization:
- */
-
-#define DRIVER_AUTHOR          "Gareth Hughes, VA Linux Systems Inc."
-
-#define DRIVER_NAME            "mga"
-#define DRIVER_DESC            "Matrox G200/G400"
-#define DRIVER_DATE            "20051102"
-
-#define DRIVER_MAJOR           3
-#define DRIVER_MINOR           2
-#define DRIVER_PATCHLEVEL      1
-
-typedef struct drm_mga_primary_buffer {
-       u8 *start;
-       u8 *end;
-       int size;
-
-       u32 tail;
-       int space;
-       volatile long wrapped;
-
-       volatile u32 *status;
-
-       u32 last_flush;
-       u32 last_wrap;
-
-       u32 high_mark;
-} drm_mga_primary_buffer_t;
-
-typedef struct drm_mga_freelist {
-       struct drm_mga_freelist *next;
-       struct drm_mga_freelist *prev;
-       drm_mga_age_t age;
-       struct drm_buf *buf;
-} drm_mga_freelist_t;
-
-typedef struct {
-       drm_mga_freelist_t *list_entry;
-       int discard;
-       int dispatched;
-} drm_mga_buf_priv_t;
-
-typedef struct drm_mga_private {
-       drm_mga_primary_buffer_t prim;
-       drm_mga_sarea_t *sarea_priv;
-
-       drm_mga_freelist_t *head;
-       drm_mga_freelist_t *tail;
-
-       unsigned int warp_pipe;
-       unsigned long warp_pipe_phys[MGA_MAX_WARP_PIPES];
-
-       int chipset;
-       int usec_timeout;
-
-       /**
-        * If set, the new DMA initialization sequence was used.  This is
-        * primarilly used to select how the driver should uninitialized its
-        * internal DMA structures.
-        */
-       int used_new_dma_init;
-
-       /**
-        * If AGP memory is used for DMA buffers, this will be the value
-        * \c MGA_PAGPXFER.  Otherwise, it will be zero (for a PCI transfer).
-        */
-       u32 dma_access;
-
-       /**
-        * If AGP memory is used for DMA buffers, this will be the value
-        * \c MGA_WAGP_ENABLE.  Otherwise, it will be zero (for a PCI
-        * transfer).
-        */
-       u32 wagp_enable;
-
-       /**
-        * \name MMIO region parameters.
-        *
-        * \sa drm_mga_private_t::mmio
-        */
-       /*@{ */
-       u32 mmio_base;             /**< Bus address of base of MMIO. */
-       u32 mmio_size;             /**< Size of the MMIO region. */
-       /*@} */
-
-       u32 clear_cmd;
-       u32 maccess;
-
-       wait_queue_head_t fence_queue;
-       atomic_t last_fence_retired;
-       u32 next_fence_to_post;
-
-       unsigned int fb_cpp;
-       unsigned int front_offset;
-       unsigned int front_pitch;
-       unsigned int back_offset;
-       unsigned int back_pitch;
-
-       unsigned int depth_cpp;
-       unsigned int depth_offset;
-       unsigned int depth_pitch;
-
-       unsigned int texture_offset;
-       unsigned int texture_size;
-
-       drm_local_map_t *sarea;
-       drm_local_map_t *mmio;
-       drm_local_map_t *status;
-       drm_local_map_t *warp;
-       drm_local_map_t *primary;
-       drm_local_map_t *agp_textures;
-
-       unsigned long agp_handle;
-       unsigned int agp_size;
-} drm_mga_private_t;
-
-extern struct drm_ioctl_desc mga_ioctls[];
-extern int mga_max_ioctl;
-
-                               /* mga_dma.c */
-extern int mga_dma_bootstrap(struct drm_device *dev, void *data,
-                            struct drm_file *file_priv);
-extern int mga_dma_init(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv);
-extern int mga_dma_flush(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-extern int mga_dma_reset(struct drm_device *dev, void *data,
-                        struct drm_file *file_priv);
-extern int mga_dma_buffers(struct drm_device *dev, void *data,
-                          struct drm_file *file_priv);
-extern int mga_driver_load(struct drm_device *dev, unsigned long flags);
-extern int mga_driver_unload(struct drm_device * dev);
-extern void mga_driver_lastclose(struct drm_device * dev);
-extern int mga_driver_dma_quiescent(struct drm_device * dev);
-
-extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
-
-extern void mga_do_dma_flush(drm_mga_private_t * dev_priv);
-extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv);
-extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
-
-extern int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf);
-
-                               /* mga_warp.c */
-extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
-extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
-extern int mga_warp_init(drm_mga_private_t * dev_priv);
-
-                               /* mga_irq.c */
-extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
-extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
-extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
-extern void mga_driver_irq_preinstall(struct drm_device * dev);
-extern void mga_driver_irq_postinstall(struct drm_device * dev);
-extern void mga_driver_irq_uninstall(struct drm_device * dev);
-extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
-                            unsigned long arg);
-
-#define mga_flush_write_combine()      DRM_WRITEMEMORYBARRIER()
-
-#if defined(__linux__) && defined(__alpha__)
-#define MGA_BASE( reg )                ((unsigned long)(dev_priv->mmio->handle))
-#define MGA_ADDR( reg )                (MGA_BASE(reg) + reg)
-
-#define MGA_DEREF( reg )       *(volatile u32 *)MGA_ADDR( reg )
-#define MGA_DEREF8( reg )      *(volatile u8 *)MGA_ADDR( reg )
-
-#define MGA_READ( reg )                (_MGA_READ((u32 *)MGA_ADDR(reg)))
-#define MGA_READ8( reg )       (_MGA_READ((u8 *)MGA_ADDR(reg)))
-#define MGA_WRITE( reg, val )  do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0)
-#define MGA_WRITE8( reg, val )  do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0)
-
-static inline u32 _MGA_READ(u32 * addr)
-{
-       DRM_MEMORYBARRIER();
-       return *(volatile u32 *)addr;
-}
-#else
-#define MGA_READ8( reg )       DRM_READ8(dev_priv->mmio, (reg))
-#define MGA_READ( reg )                DRM_READ32(dev_priv->mmio, (reg))
-#define MGA_WRITE8( reg, val )  DRM_WRITE8(dev_priv->mmio, (reg), (val))
-#define MGA_WRITE( reg, val )  DRM_WRITE32(dev_priv->mmio, (reg), (val))
-#endif
-
-#define DWGREG0                0x1c00
-#define DWGREG0_END    0x1dff
-#define DWGREG1                0x2c00
-#define DWGREG1_END    0x2dff
-
-#define ISREG0(r)      (r >= DWGREG0 && r <= DWGREG0_END)
-#define DMAREG0(r)     (u8)((r - DWGREG0) >> 2)
-#define DMAREG1(r)     (u8)(((r - DWGREG1) >> 2) | 0x80)
-#define DMAREG(r)      (ISREG0(r) ? DMAREG0(r) : DMAREG1(r))
-
-/* ================================================================
- * Helper macross...
- */
-
-#define MGA_EMIT_STATE( dev_priv, dirty )                              \
-do {                                                                   \
-       if ( (dirty) & ~MGA_UPLOAD_CLIPRECTS ) {                        \
-               if ( dev_priv->chipset >= MGA_CARD_TYPE_G400 ) {        \
-                       mga_g400_emit_state( dev_priv );                \
-               } else {                                                \
-                       mga_g200_emit_state( dev_priv );                \
-               }                                                       \
-       }                                                               \
-} while (0)
-
-#define WRAP_TEST_WITH_RETURN( dev_priv )                              \
-do {                                                                   \
-       if ( test_bit( 0, &dev_priv->prim.wrapped ) ) {                 \
-               if ( mga_is_idle( dev_priv ) ) {                        \
-                       mga_do_dma_wrap_end( dev_priv );                \
-               } else if ( dev_priv->prim.space <                      \
-                           dev_priv->prim.high_mark ) {                \
-                       if ( MGA_DMA_DEBUG )                            \
-                               DRM_INFO( "wrap...\n");         \
-                       return -EBUSY;                  \
-               }                                                       \
-       }                                                               \
-} while (0)
-
-#define WRAP_WAIT_WITH_RETURN( dev_priv )                              \
-do {                                                                   \
-       if ( test_bit( 0, &dev_priv->prim.wrapped ) ) {                 \
-               if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {           \
-                       if ( MGA_DMA_DEBUG )                            \
-                               DRM_INFO( "wrap...\n");         \
-                       return -EBUSY;                  \
-               }                                                       \
-               mga_do_dma_wrap_end( dev_priv );                        \
-       }                                                               \
-} while (0)
-
-/* ================================================================
- * Primary DMA command stream
- */
-
-#define MGA_VERBOSE    0
-
-#define DMA_LOCALS     unsigned int write; volatile u8 *prim;
-
-#define DMA_BLOCK_SIZE (5 * sizeof(u32))
-
-#define BEGIN_DMA( n )                                                 \
-do {                                                                   \
-       if ( MGA_VERBOSE ) {                                            \
-               DRM_INFO( "BEGIN_DMA( %d )\n", (n) );           \
-               DRM_INFO( "   space=0x%x req=0x%Zx\n",                  \
-                         dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \
-       }                                                               \
-       prim = dev_priv->prim.start;                                    \
-       write = dev_priv->prim.tail;                                    \
-} while (0)
-
-#define BEGIN_DMA_WRAP()                                               \
-do {                                                                   \
-       if ( MGA_VERBOSE ) {                                            \
-               DRM_INFO( "BEGIN_DMA()\n" );                            \
-               DRM_INFO( "   space=0x%x\n", dev_priv->prim.space );    \
-       }                                                               \
-       prim = dev_priv->prim.start;                                    \
-       write = dev_priv->prim.tail;                                    \
-} while (0)
-
-#define ADVANCE_DMA()                                                  \
-do {                                                                   \
-       dev_priv->prim.tail = write;                                    \
-       if ( MGA_VERBOSE ) {                                            \
-               DRM_INFO( "ADVANCE_DMA() tail=0x%05x sp=0x%x\n",        \
-                         write, dev_priv->prim.space );                \
-       }                                                               \
-} while (0)
-
-#define FLUSH_DMA()                                                    \
-do {                                                                   \
-       if ( 0 ) {                                                      \
-               DRM_INFO( "\n" );                                       \
-               DRM_INFO( "   tail=0x%06x head=0x%06lx\n",              \
-                         dev_priv->prim.tail,                          \
-                         MGA_READ( MGA_PRIMADDRESS ) -                 \
-                         dev_priv->primary->offset );                  \
-       }                                                               \
-       if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) {                \
-               if ( dev_priv->prim.space <                             \
-                    dev_priv->prim.high_mark ) {                       \
-                       mga_do_dma_wrap_start( dev_priv );              \
-               } else {                                                \
-                       mga_do_dma_flush( dev_priv );                   \
-               }                                                       \
-       }                                                               \
-} while (0)
-
-/* Never use this, always use DMA_BLOCK(...) for primary DMA output.
- */
-#define DMA_WRITE( offset, val )                                       \
-do {                                                                   \
-       if ( MGA_VERBOSE ) {                                            \
-               DRM_INFO( "   DMA_WRITE( 0x%08x ) at 0x%04Zx\n",        \
-                         (u32)(val), write + (offset) * sizeof(u32) ); \
-       }                                                               \
-       *(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \
-} while (0)
-
-#define DMA_BLOCK( reg0, val0, reg1, val1, reg2, val2, reg3, val3 )    \
-do {                                                                   \
-       DMA_WRITE( 0, ((DMAREG( reg0 ) << 0) |                          \
-                      (DMAREG( reg1 ) << 8) |                          \
-                      (DMAREG( reg2 ) << 16) |                         \
-                      (DMAREG( reg3 ) << 24)) );                       \
-       DMA_WRITE( 1, val0 );                                           \
-       DMA_WRITE( 2, val1 );                                           \
-       DMA_WRITE( 3, val2 );                                           \
-       DMA_WRITE( 4, val3 );                                           \
-       write += DMA_BLOCK_SIZE;                                        \
-} while (0)
-
-/* Buffer aging via primary DMA stream head pointer.
- */
-
-#define SET_AGE( age, h, w )                                           \
-do {                                                                   \
-       (age)->head = h;                                                \
-       (age)->wrap = w;                                                \
-} while (0)
-
-#define TEST_AGE( age, h, w )          ( (age)->wrap < w ||            \
-                                         ( (age)->wrap == w &&         \
-                                           (age)->head < h ) )
-
-#define AGE_BUFFER( buf_priv )                                         \
-do {                                                                   \
-       drm_mga_freelist_t *entry = (buf_priv)->list_entry;             \
-       if ( (buf_priv)->dispatched ) {                                 \
-               entry->age.head = (dev_priv->prim.tail +                \
-                                  dev_priv->primary->offset);          \
-               entry->age.wrap = dev_priv->sarea_priv->last_wrap;      \
-       } else {                                                        \
-               entry->age.head = 0;                                    \
-               entry->age.wrap = 0;                                    \
-       }                                                               \
-} while (0)
-
-#define MGA_ENGINE_IDLE_MASK           (MGA_SOFTRAPEN |                \
-                                        MGA_DWGENGSTS |                \
-                                        MGA_ENDPRDMASTS)
-#define MGA_DMA_IDLE_MASK              (MGA_SOFTRAPEN |                \
-                                        MGA_ENDPRDMASTS)
-
-#define MGA_DMA_DEBUG                  0
-
-/* A reduced set of the mga registers.
- */
-#define MGA_CRTC_INDEX                 0x1fd4
-#define MGA_CRTC_DATA                  0x1fd5
-
-/* CRTC11 */
-#define MGA_VINTCLR                    (1 << 4)
-#define MGA_VINTEN                     (1 << 5)
-
-#define MGA_ALPHACTRL                  0x2c7c
-#define MGA_AR0                                0x1c60
-#define MGA_AR1                                0x1c64
-#define MGA_AR2                                0x1c68
-#define MGA_AR3                                0x1c6c
-#define MGA_AR4                                0x1c70
-#define MGA_AR5                                0x1c74
-#define MGA_AR6                                0x1c78
-
-#define MGA_CXBNDRY                    0x1c80
-#define MGA_CXLEFT                     0x1ca0
-#define MGA_CXRIGHT                    0x1ca4
-
-#define MGA_DMAPAD                     0x1c54
-#define MGA_DSTORG                     0x2cb8
-#define MGA_DWGCTL                     0x1c00
-#      define MGA_OPCOD_MASK                   (15 << 0)
-#      define MGA_OPCOD_TRAP                   (4 << 0)
-#      define MGA_OPCOD_TEXTURE_TRAP           (6 << 0)
-#      define MGA_OPCOD_BITBLT                 (8 << 0)
-#      define MGA_OPCOD_ILOAD                  (9 << 0)
-#      define MGA_ATYPE_MASK                   (7 << 4)
-#      define MGA_ATYPE_RPL                    (0 << 4)
-#      define MGA_ATYPE_RSTR                   (1 << 4)
-#      define MGA_ATYPE_ZI                     (3 << 4)
-#      define MGA_ATYPE_BLK                    (4 << 4)
-#      define MGA_ATYPE_I                      (7 << 4)
-#      define MGA_LINEAR                       (1 << 7)
-#      define MGA_ZMODE_MASK                   (7 << 8)
-#      define MGA_ZMODE_NOZCMP                 (0 << 8)
-#      define MGA_ZMODE_ZE                     (2 << 8)
-#      define MGA_ZMODE_ZNE                    (3 << 8)
-#      define MGA_ZMODE_ZLT                    (4 << 8)
-#      define MGA_ZMODE_ZLTE                   (5 << 8)
-#      define MGA_ZMODE_ZGT                    (6 << 8)
-#      define MGA_ZMODE_ZGTE                   (7 << 8)
-#      define MGA_SOLID                        (1 << 11)
-#      define MGA_ARZERO                       (1 << 12)
-#      define MGA_SGNZERO                      (1 << 13)
-#      define MGA_SHIFTZERO                    (1 << 14)
-#      define MGA_BOP_MASK                     (15 << 16)
-#      define MGA_BOP_ZERO                     (0 << 16)
-#      define MGA_BOP_DST                      (10 << 16)
-#      define MGA_BOP_SRC                      (12 << 16)
-#      define MGA_BOP_ONE                      (15 << 16)
-#      define MGA_TRANS_SHIFT                  20
-#      define MGA_TRANS_MASK                   (15 << 20)
-#      define MGA_BLTMOD_MASK                  (15 << 25)
-#      define MGA_BLTMOD_BMONOLEF              (0 << 25)
-#      define MGA_BLTMOD_BMONOWF               (4 << 25)
-#      define MGA_BLTMOD_PLAN                  (1 << 25)
-#      define MGA_BLTMOD_BFCOL                 (2 << 25)
-#      define MGA_BLTMOD_BU32BGR               (3 << 25)
-#      define MGA_BLTMOD_BU32RGB               (7 << 25)
-#      define MGA_BLTMOD_BU24BGR               (11 << 25)
-#      define MGA_BLTMOD_BU24RGB               (15 << 25)
-#      define MGA_PATTERN                      (1 << 29)
-#      define MGA_TRANSC                       (1 << 30)
-#      define MGA_CLIPDIS                      (1 << 31)
-#define MGA_DWGSYNC                    0x2c4c
-
-#define MGA_FCOL                       0x1c24
-#define MGA_FIFOSTATUS                 0x1e10
-#define MGA_FOGCOL                     0x1cf4
-#define MGA_FXBNDRY                    0x1c84
-#define MGA_FXLEFT                     0x1ca8
-#define MGA_FXRIGHT                    0x1cac
-
-#define MGA_ICLEAR                     0x1e18
-#      define MGA_SOFTRAPICLR                  (1 << 0)
-#      define MGA_VLINEICLR                    (1 << 5)
-#define MGA_IEN                                0x1e1c
-#      define MGA_SOFTRAPIEN                   (1 << 0)
-#      define MGA_VLINEIEN                     (1 << 5)
-
-#define MGA_LEN                                0x1c5c
-
-#define MGA_MACCESS                    0x1c04
-
-#define MGA_PITCH                      0x1c8c
-#define MGA_PLNWT                      0x1c1c
-#define MGA_PRIMADDRESS                        0x1e58
-#      define MGA_DMA_GENERAL                  (0 << 0)
-#      define MGA_DMA_BLIT                     (1 << 0)
-#      define MGA_DMA_VECTOR                   (2 << 0)
-#      define MGA_DMA_VERTEX                   (3 << 0)
-#define MGA_PRIMEND                    0x1e5c
-#      define MGA_PRIMNOSTART                  (1 << 0)
-#      define MGA_PAGPXFER                     (1 << 1)
-#define MGA_PRIMPTR                    0x1e50
-#      define MGA_PRIMPTREN0                   (1 << 0)
-#      define MGA_PRIMPTREN1                   (1 << 1)
-
-#define MGA_RST                                0x1e40
-#      define MGA_SOFTRESET                    (1 << 0)
-#      define MGA_SOFTEXTRST                   (1 << 1)
-
-#define MGA_SECADDRESS                 0x2c40
-#define MGA_SECEND                     0x2c44
-#define MGA_SETUPADDRESS               0x2cd0
-#define MGA_SETUPEND                   0x2cd4
-#define MGA_SGN                                0x1c58
-#define MGA_SOFTRAP                    0x2c48
-#define MGA_SRCORG                     0x2cb4
-#      define MGA_SRMMAP_MASK                  (1 << 0)
-#      define MGA_SRCMAP_FB                    (0 << 0)
-#      define MGA_SRCMAP_SYSMEM                (1 << 0)
-#      define MGA_SRCACC_MASK                  (1 << 1)
-#      define MGA_SRCACC_PCI                   (0 << 1)
-#      define MGA_SRCACC_AGP                   (1 << 1)
-#define MGA_STATUS                     0x1e14
-#      define MGA_SOFTRAPEN                    (1 << 0)
-#      define MGA_VSYNCPEN                     (1 << 4)
-#      define MGA_VLINEPEN                     (1 << 5)
-#      define MGA_DWGENGSTS                    (1 << 16)
-#      define MGA_ENDPRDMASTS                  (1 << 17)
-#define MGA_STENCIL                    0x2cc8
-#define MGA_STENCILCTL                 0x2ccc
-
-#define MGA_TDUALSTAGE0                        0x2cf8
-#define MGA_TDUALSTAGE1                        0x2cfc
-#define MGA_TEXBORDERCOL               0x2c5c
-#define MGA_TEXCTL                     0x2c30
-#define MGA_TEXCTL2                    0x2c3c
-#      define MGA_DUALTEX                      (1 << 7)
-#      define MGA_G400_TC2_MAGIC               (1 << 15)
-#      define MGA_MAP1_ENABLE                  (1 << 31)
-#define MGA_TEXFILTER                  0x2c58
-#define MGA_TEXHEIGHT                  0x2c2c
-#define MGA_TEXORG                     0x2c24
-#      define MGA_TEXORGMAP_MASK               (1 << 0)
-#      define MGA_TEXORGMAP_FB                 (0 << 0)
-#      define MGA_TEXORGMAP_SYSMEM             (1 << 0)
-#      define MGA_TEXORGACC_MASK               (1 << 1)
-#      define MGA_TEXORGACC_PCI                (0 << 1)
-#      define MGA_TEXORGACC_AGP                (1 << 1)
-#define MGA_TEXORG1                    0x2ca4
-#define MGA_TEXORG2                    0x2ca8
-#define MGA_TEXORG3                    0x2cac
-#define MGA_TEXORG4                    0x2cb0
-#define MGA_TEXTRANS                   0x2c34
-#define MGA_TEXTRANSHIGH               0x2c38
-#define MGA_TEXWIDTH                   0x2c28
-
-#define MGA_WACCEPTSEQ                 0x1dd4
-#define MGA_WCODEADDR                  0x1e6c
-#define MGA_WFLAG                      0x1dc4
-#define MGA_WFLAG1                     0x1de0
-#define MGA_WFLAGNB                    0x1e64
-#define MGA_WFLAGNB1                   0x1e08
-#define MGA_WGETMSB                    0x1dc8
-#define MGA_WIADDR                     0x1dc0
-#define MGA_WIADDR2                    0x1dd8
-#      define MGA_WMODE_SUSPEND                (0 << 0)
-#      define MGA_WMODE_RESUME                 (1 << 0)
-#      define MGA_WMODE_JUMP                   (2 << 0)
-#      define MGA_WMODE_START                  (3 << 0)
-#      define MGA_WAGP_ENABLE                  (1 << 2)
-#define MGA_WMISC                      0x1e70
-#      define MGA_WUCODECACHE_ENABLE           (1 << 0)
-#      define MGA_WMASTER_ENABLE               (1 << 1)
-#      define MGA_WCACHEFLUSH_ENABLE           (1 << 3)
-#define MGA_WVRTXSZ                    0x1dcc
-
-#define MGA_YBOT                       0x1c9c
-#define MGA_YDST                       0x1c90
-#define MGA_YDSTLEN                    0x1c88
-#define MGA_YDSTORG                    0x1c94
-#define MGA_YTOP                       0x1c98
-
-#define MGA_ZORG                       0x1c0c
-
-/* This finishes the current batch of commands
- */
-#define MGA_EXEC                       0x0100
-
-/* AGP PLL encoding (for G200 only).
- */
-#define MGA_AGP_PLL                    0x1e4c
-#      define MGA_AGP2XPLL_DISABLE             (0 << 0)
-#      define MGA_AGP2XPLL_ENABLE              (1 << 0)
-
-/* Warp registers
- */
-#define MGA_WR0                                0x2d00
-#define MGA_WR1                                0x2d04
-#define MGA_WR2                                0x2d08
-#define MGA_WR3                                0x2d0c
-#define MGA_WR4                                0x2d10
-#define MGA_WR5                                0x2d14
-#define MGA_WR6                                0x2d18
-#define MGA_WR7                                0x2d1c
-#define MGA_WR8                                0x2d20
-#define MGA_WR9                                0x2d24
-#define MGA_WR10                       0x2d28
-#define MGA_WR11                       0x2d2c
-#define MGA_WR12                       0x2d30
-#define MGA_WR13                       0x2d34
-#define MGA_WR14                       0x2d38
-#define MGA_WR15                       0x2d3c
-#define MGA_WR16                       0x2d40
-#define MGA_WR17                       0x2d44
-#define MGA_WR18                       0x2d48
-#define MGA_WR19                       0x2d4c
-#define MGA_WR20                       0x2d50
-#define MGA_WR21                       0x2d54
-#define MGA_WR22                       0x2d58
-#define MGA_WR23                       0x2d5c
-#define MGA_WR24                       0x2d60
-#define MGA_WR25                       0x2d64
-#define MGA_WR26                       0x2d68
-#define MGA_WR27                       0x2d6c
-#define MGA_WR28                       0x2d70
-#define MGA_WR29                       0x2d74
-#define MGA_WR30                       0x2d78
-#define MGA_WR31                       0x2d7c
-#define MGA_WR32                       0x2d80
-#define MGA_WR33                       0x2d84
-#define MGA_WR34                       0x2d88
-#define MGA_WR35                       0x2d8c
-#define MGA_WR36                       0x2d90
-#define MGA_WR37                       0x2d94
-#define MGA_WR38                       0x2d98
-#define MGA_WR39                       0x2d9c
-#define MGA_WR40                       0x2da0
-#define MGA_WR41                       0x2da4
-#define MGA_WR42                       0x2da8
-#define MGA_WR43                       0x2dac
-#define MGA_WR44                       0x2db0
-#define MGA_WR45                       0x2db4
-#define MGA_WR46                       0x2db8
-#define MGA_WR47                       0x2dbc
-#define MGA_WR48                       0x2dc0
-#define MGA_WR49                       0x2dc4
-#define MGA_WR50                       0x2dc8
-#define MGA_WR51                       0x2dcc
-#define MGA_WR52                       0x2dd0
-#define MGA_WR53                       0x2dd4
-#define MGA_WR54                       0x2dd8
-#define MGA_WR55                       0x2ddc
-#define MGA_WR56                       0x2de0
-#define MGA_WR57                       0x2de4
-#define MGA_WR58                       0x2de8
-#define MGA_WR59                       0x2dec
-#define MGA_WR60                       0x2df0
-#define MGA_WR61                       0x2df4
-#define MGA_WR62                       0x2df8
-#define MGA_WR63                       0x2dfc
-#      define MGA_G400_WR_MAGIC                (1 << 6)
-#      define MGA_G400_WR56_MAGIC              0x46480000      /* 12800.0f */
-
-#define MGA_ILOAD_ALIGN                64
-#define MGA_ILOAD_MASK         (MGA_ILOAD_ALIGN - 1)
-
-#define MGA_DWGCTL_FLUSH       (MGA_OPCOD_TEXTURE_TRAP |               \
-                                MGA_ATYPE_I |                          \
-                                MGA_ZMODE_NOZCMP |                     \
-                                MGA_ARZERO |                           \
-                                MGA_SGNZERO |                          \
-                                MGA_BOP_SRC |                          \
-                                (15 << MGA_TRANS_SHIFT))
-
-#define MGA_DWGCTL_CLEAR       (MGA_OPCOD_TRAP |                       \
-                                MGA_ZMODE_NOZCMP |                     \
-                                MGA_SOLID |                            \
-                                MGA_ARZERO |                           \
-                                MGA_SGNZERO |                          \
-                                MGA_SHIFTZERO |                        \
-                                MGA_BOP_SRC |                          \
-                                (0 << MGA_TRANS_SHIFT) |               \
-                                MGA_BLTMOD_BMONOLEF |                  \
-                                MGA_TRANSC |                           \
-                                MGA_CLIPDIS)
-
-#define MGA_DWGCTL_COPY                (MGA_OPCOD_BITBLT |                     \
-                                MGA_ATYPE_RPL |                        \
-                                MGA_SGNZERO |                          \
-                                MGA_SHIFTZERO |                        \
-                                MGA_BOP_SRC |                          \
-                                (0 << MGA_TRANS_SHIFT) |               \
-                                MGA_BLTMOD_BFCOL |                     \
-                                MGA_CLIPDIS)
-
-/* Simple idle test.
- */
-static __inline__ int mga_is_idle(drm_mga_private_t * dev_priv)
-{
-       u32 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
-       return (status == MGA_ENDPRDMASTS);
-}
-
-#endif
diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c
deleted file mode 100644 (file)
index 30d0047..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/**
- * \file mga_ioc32.c
- *
- * 32-bit ioctl compatibility routines for the MGA DRM.
- *
- * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich
- *
- *
- * Copyright (C) Paul Mackerras 2005
- * Copyright (C) Egbert Eich 2003,2004
- * Copyright (C) Dave Airlie 2005
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <linux/compat.h>
-
-#include "drmP.h"
-#include "drm.h"
-#include "mga_drm.h"
-
-typedef struct drm32_mga_init {
-       int func;
-       u32 sarea_priv_offset;
-       int chipset;
-       int sgram;
-       unsigned int maccess;
-       unsigned int fb_cpp;
-       unsigned int front_offset, front_pitch;
-       unsigned int back_offset, back_pitch;
-       unsigned int depth_cpp;
-       unsigned int depth_offset, depth_pitch;
-       unsigned int texture_offset[MGA_NR_TEX_HEAPS];
-       unsigned int texture_size[MGA_NR_TEX_HEAPS];
-       u32 fb_offset;
-       u32 mmio_offset;
-       u32 status_offset;
-       u32 warp_offset;
-       u32 primary_offset;
-       u32 buffers_offset;
-} drm_mga_init32_t;
-
-static int compat_mga_init(struct file *file, unsigned int cmd,
-                          unsigned long arg)
-{
-       drm_mga_init32_t init32;
-       drm_mga_init_t __user *init;
-       int err = 0, i;
-
-       if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
-               return -EFAULT;
-
-       init = compat_alloc_user_space(sizeof(*init));
-       if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
-           || __put_user(init32.func, &init->func)
-           || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
-           || __put_user(init32.chipset, &init->chipset)
-           || __put_user(init32.sgram, &init->sgram)
-           || __put_user(init32.maccess, &init->maccess)
-           || __put_user(init32.fb_cpp, &init->fb_cpp)
-           || __put_user(init32.front_offset, &init->front_offset)
-           || __put_user(init32.front_pitch, &init->front_pitch)
-           || __put_user(init32.back_offset, &init->back_offset)
-           || __put_user(init32.back_pitch, &init->back_pitch)
-           || __put_user(init32.depth_cpp, &init->depth_cpp)
-           || __put_user(init32.depth_offset, &init->depth_offset)
-           || __put_user(init32.depth_pitch, &init->depth_pitch)
-           || __put_user(init32.fb_offset, &init->fb_offset)
-           || __put_user(init32.mmio_offset, &init->mmio_offset)
-           || __put_user(init32.status_offset, &init->status_offset)
-           || __put_user(init32.warp_offset, &init->warp_offset)
-           || __put_user(init32.primary_offset, &init->primary_offset)
-           || __put_user(init32.buffers_offset, &init->buffers_offset))
-               return -EFAULT;
-
-       for (i = 0; i < MGA_NR_TEX_HEAPS; i++) {
-               err |=
-                   __put_user(init32.texture_offset[i],
-                              &init->texture_offset[i]);
-               err |=
-                   __put_user(init32.texture_size[i], &init->texture_size[i]);
-       }
-       if (err)
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_MGA_INIT, (unsigned long)init);
-}
-
-typedef struct drm_mga_getparam32 {
-       int param;
-       u32 value;
-} drm_mga_getparam32_t;
-
-static int compat_mga_getparam(struct file *file, unsigned int cmd,
-                              unsigned long arg)
-{
-       drm_mga_getparam32_t getparam32;
-       drm_mga_getparam_t __user *getparam;
-
-       if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
-               return -EFAULT;
-
-       getparam = compat_alloc_user_space(sizeof(*getparam));
-       if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
-           || __put_user(getparam32.param, &getparam->param)
-           || __put_user((void __user *)(unsigned long)getparam32.value,
-                         &getparam->value))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
-}
-
-typedef struct drm_mga_drm_bootstrap32 {
-       u32 texture_handle;
-       u32 texture_size;
-       u32 primary_size;
-       u32 secondary_bin_count;
-       u32 secondary_bin_size;
-       u32 agp_mode;
-       u8 agp_size;
-} drm_mga_dma_bootstrap32_t;
-
-static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd,
-                                   unsigned long arg)
-{
-       drm_mga_dma_bootstrap32_t dma_bootstrap32;
-       drm_mga_dma_bootstrap_t __user *dma_bootstrap;
-       int err;
-
-       if (copy_from_user(&dma_bootstrap32, (void __user *)arg,
-                          sizeof(dma_bootstrap32)))
-               return -EFAULT;
-
-       dma_bootstrap = compat_alloc_user_space(sizeof(*dma_bootstrap));
-       if (!access_ok(VERIFY_WRITE, dma_bootstrap, sizeof(*dma_bootstrap))
-           || __put_user(dma_bootstrap32.texture_handle,
-                         &dma_bootstrap->texture_handle)
-           || __put_user(dma_bootstrap32.texture_size,
-                         &dma_bootstrap->texture_size)
-           || __put_user(dma_bootstrap32.primary_size,
-                         &dma_bootstrap->primary_size)
-           || __put_user(dma_bootstrap32.secondary_bin_count,
-                         &dma_bootstrap->secondary_bin_count)
-           || __put_user(dma_bootstrap32.secondary_bin_size,
-                         &dma_bootstrap->secondary_bin_size)
-           || __put_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
-           || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
-               return -EFAULT;
-
-       err = drm_ioctl(file->f_path.dentry->d_inode, file,
-                       DRM_IOCTL_MGA_DMA_BOOTSTRAP,
-                       (unsigned long)dma_bootstrap);
-       if (err)
-               return err;
-
-       if (__get_user(dma_bootstrap32.texture_handle,
-                      &dma_bootstrap->texture_handle)
-           || __get_user(dma_bootstrap32.texture_size,
-                         &dma_bootstrap->texture_size)
-           || __get_user(dma_bootstrap32.primary_size,
-                         &dma_bootstrap->primary_size)
-           || __get_user(dma_bootstrap32.secondary_bin_count,
-                         &dma_bootstrap->secondary_bin_count)
-           || __get_user(dma_bootstrap32.secondary_bin_size,
-                         &dma_bootstrap->secondary_bin_size)
-           || __get_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
-           || __get_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
-               return -EFAULT;
-
-       if (copy_to_user((void __user *)arg, &dma_bootstrap32,
-                        sizeof(dma_bootstrap32)))
-               return -EFAULT;
-
-       return 0;
-}
-
-drm_ioctl_compat_t *mga_compat_ioctls[] = {
-       [DRM_MGA_INIT] = compat_mga_init,
-       [DRM_MGA_GETPARAM] = compat_mga_getparam,
-       [DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap,
-};
-
-/**
- * Called whenever a 32-bit process running under a 64-bit kernel
- * performs an ioctl on /dev/dri/card<n>.
- *
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
- */
-long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       unsigned int nr = DRM_IOCTL_NR(cmd);
-       drm_ioctl_compat_t *fn = NULL;
-       int ret;
-
-       if (nr < DRM_COMMAND_BASE)
-               return drm_compat_ioctl(filp, cmd, arg);
-
-       if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls))
-               fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE];
-
-       lock_kernel();          /* XXX for now */
-       if (fn != NULL)
-               ret = (*fn) (filp, cmd, arg);
-       else
-               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
-
-       return ret;
-}
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
deleted file mode 100644 (file)
index 9302cb8..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*-
- *
- * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
- *
- * The Weather Channel (TM) funded Tungsten Graphics to develop the
- * initial release of the Radeon 8500 driver under the XFree86 license.
- * This notice must be preserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- *    Eric Anholt <anholt@FreeBSD.org>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "mga_drm.h"
-#include "mga_drv.h"
-
-irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
-{
-       struct drm_device *dev = (struct drm_device *) arg;
-       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-       int status;
-       int handled = 0;
-
-       status = MGA_READ(MGA_STATUS);
-
-       /* VBLANK interrupt */
-       if (status & MGA_VLINEPEN) {
-               MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
-               atomic_inc(&dev->vbl_received);
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
-               handled = 1;
-       }
-
-       /* SOFTRAP interrupt */
-       if (status & MGA_SOFTRAPEN) {
-               const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
-               const u32 prim_end = MGA_READ(MGA_PRIMEND);
-
-               MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);
-
-               /* In addition to clearing the interrupt-pending bit, we
-                * have to write to MGA_PRIMEND to re-start the DMA operation.
-                */
-               if ((prim_start & ~0x03) != (prim_end & ~0x03)) {
-                       MGA_WRITE(MGA_PRIMEND, prim_end);
-               }
-
-               atomic_inc(&dev_priv->last_fence_retired);
-               DRM_WAKEUP(&dev_priv->fence_queue);
-               handled = 1;
-       }
-
-       if (handled) {
-               return IRQ_HANDLED;
-       }
-       return IRQ_NONE;
-}
-
-int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
-{
-       unsigned int cur_vblank;
-       int ret = 0;
-
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using vertical blanks...
-        */
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(&dev->vbl_received))
-                     - *sequence) <= (1 << 23)));
-
-       *sequence = cur_vblank;
-
-       return ret;
-}
-
-int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
-{
-       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-       unsigned int cur_fence;
-       int ret = 0;
-
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using fences.
-        */
-       DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ,
-                   (((cur_fence = atomic_read(&dev_priv->last_fence_retired))
-                     - *sequence) <= (1 << 23)));
-
-       *sequence = cur_fence;
-
-       return ret;
-}
-
-void mga_driver_irq_preinstall(struct drm_device * dev)
-{
-       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-
-       /* Disable *all* interrupts */
-       MGA_WRITE(MGA_IEN, 0);
-       /* Clear bits if they're already high */
-       MGA_WRITE(MGA_ICLEAR, ~0);
-}
-
-void mga_driver_irq_postinstall(struct drm_device * dev)
-{
-       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-
-       DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
-
-       /* Turn on vertical blank interrupt and soft trap interrupt. */
-       MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
-}
-
-void mga_driver_irq_uninstall(struct drm_device * dev)
-{
-       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
-       if (!dev_priv)
-               return;
-
-       /* Disable *all* interrupts */
-       MGA_WRITE(MGA_IEN, 0);
-
-       dev->irq_enabled = 0;
-}
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
deleted file mode 100644 (file)
index d3f8aad..0000000
+++ /dev/null
@@ -1,1104 +0,0 @@
-/* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*-
- * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Jeff Hartmann <jhartmann@valinux.com>
- *    Keith Whitwell <keith@tungstengraphics.com>
- *
- * Rewritten by:
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "mga_drm.h"
-#include "mga_drv.h"
-
-/* ================================================================
- * DMA hardware state programming functions
- */
-
-static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
-                              struct drm_clip_rect * box)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-       unsigned int pitch = dev_priv->front_pitch;
-       DMA_LOCALS;
-
-       BEGIN_DMA(2);
-
-       /* Force reset of DWGCTL on G400 (eliminates clip disable bit).
-        */
-       if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
-               DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl,
-                         MGA_LEN + MGA_EXEC, 0x80000000,
-                         MGA_DWGCTL, ctx->dwgctl,
-                         MGA_LEN + MGA_EXEC, 0x80000000);
-       }
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1,
-                 MGA_YTOP, box->y1 * pitch, MGA_YBOT, (box->y2 - 1) * pitch);
-
-       ADVANCE_DMA();
-}
-
-static __inline__ void mga_g200_emit_context(drm_mga_private_t * dev_priv)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-       DMA_LOCALS;
-
-       BEGIN_DMA(3);
-
-       DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
-                 MGA_MACCESS, ctx->maccess,
-                 MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
-
-       DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
-                 MGA_FOGCOL, ctx->fogcolor,
-                 MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset);
-
-       DMA_BLOCK(MGA_FCOL, ctx->fcol,
-                 MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
-
-       ADVANCE_DMA();
-}
-
-static __inline__ void mga_g400_emit_context(drm_mga_private_t * dev_priv)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-       DMA_LOCALS;
-
-       BEGIN_DMA(4);
-
-       DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
-                 MGA_MACCESS, ctx->maccess,
-                 MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
-
-       DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
-                 MGA_FOGCOL, ctx->fogcolor,
-                 MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset);
-
-       DMA_BLOCK(MGA_WFLAG1, ctx->wflag,
-                 MGA_TDUALSTAGE0, ctx->tdualstage0,
-                 MGA_TDUALSTAGE1, ctx->tdualstage1, MGA_FCOL, ctx->fcol);
-
-       DMA_BLOCK(MGA_STENCIL, ctx->stencil,
-                 MGA_STENCILCTL, ctx->stencilctl,
-                 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
-
-       ADVANCE_DMA();
-}
-
-static __inline__ void mga_g200_emit_tex0(drm_mga_private_t * dev_priv)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
-       DMA_LOCALS;
-
-       BEGIN_DMA(4);
-
-       DMA_BLOCK(MGA_TEXCTL2, tex->texctl2,
-                 MGA_TEXCTL, tex->texctl,
-                 MGA_TEXFILTER, tex->texfilter,
-                 MGA_TEXBORDERCOL, tex->texbordercol);
-
-       DMA_BLOCK(MGA_TEXORG, tex->texorg,
-                 MGA_TEXORG1, tex->texorg1,
-                 MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
-
-       DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
-                 MGA_TEXWIDTH, tex->texwidth,
-                 MGA_TEXHEIGHT, tex->texheight, MGA_WR24, tex->texwidth);
-
-       DMA_BLOCK(MGA_WR34, tex->texheight,
-                 MGA_TEXTRANS, 0x0000ffff,
-                 MGA_TEXTRANSHIGH, 0x0000ffff, MGA_DMAPAD, 0x00000000);
-
-       ADVANCE_DMA();
-}
-
-static __inline__ void mga_g400_emit_tex0(drm_mga_private_t * dev_priv)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
-       DMA_LOCALS;
-
-/*     printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */
-/*            tex->texctl, tex->texctl2); */
-
-       BEGIN_DMA(6);
-
-       DMA_BLOCK(MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC,
-                 MGA_TEXCTL, tex->texctl,
-                 MGA_TEXFILTER, tex->texfilter,
-                 MGA_TEXBORDERCOL, tex->texbordercol);
-
-       DMA_BLOCK(MGA_TEXORG, tex->texorg,
-                 MGA_TEXORG1, tex->texorg1,
-                 MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
-
-       DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
-                 MGA_TEXWIDTH, tex->texwidth,
-                 MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000);
-
-       DMA_BLOCK(MGA_WR57, 0x00000000,
-                 MGA_WR53, 0x00000000,
-                 MGA_WR61, 0x00000000, MGA_WR52, MGA_G400_WR_MAGIC);
-
-       DMA_BLOCK(MGA_WR60, MGA_G400_WR_MAGIC,
-                 MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC,
-                 MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC,
-                 MGA_DMAPAD, 0x00000000);
-
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000,
-                 MGA_TEXTRANS, 0x0000ffff, MGA_TEXTRANSHIGH, 0x0000ffff);
-
-       ADVANCE_DMA();
-}
-
-static __inline__ void mga_g400_emit_tex1(drm_mga_private_t * dev_priv)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
-       DMA_LOCALS;
-
-/*     printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg,  */
-/*            tex->texctl, tex->texctl2); */
-
-       BEGIN_DMA(5);
-
-       DMA_BLOCK(MGA_TEXCTL2, (tex->texctl2 |
-                               MGA_MAP1_ENABLE |
-                               MGA_G400_TC2_MAGIC),
-                 MGA_TEXCTL, tex->texctl,
-                 MGA_TEXFILTER, tex->texfilter,
-                 MGA_TEXBORDERCOL, tex->texbordercol);
-
-       DMA_BLOCK(MGA_TEXORG, tex->texorg,
-                 MGA_TEXORG1, tex->texorg1,
-                 MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
-
-       DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
-                 MGA_TEXWIDTH, tex->texwidth,
-                 MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000);
-
-       DMA_BLOCK(MGA_WR57, 0x00000000,
-                 MGA_WR53, 0x00000000,
-                 MGA_WR61, 0x00000000,
-                 MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC);
-
-       DMA_BLOCK(MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC,
-                 MGA_TEXTRANS, 0x0000ffff,
-                 MGA_TEXTRANSHIGH, 0x0000ffff,
-                 MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC);
-
-       ADVANCE_DMA();
-}
-
-static __inline__ void mga_g200_emit_pipe(drm_mga_private_t * dev_priv)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       unsigned int pipe = sarea_priv->warp_pipe;
-       DMA_LOCALS;
-
-       BEGIN_DMA(3);
-
-       DMA_BLOCK(MGA_WIADDR, MGA_WMODE_SUSPEND,
-                 MGA_WVRTXSZ, 0x00000007,
-                 MGA_WFLAG, 0x00000000, MGA_WR24, 0x00000000);
-
-       DMA_BLOCK(MGA_WR25, 0x00000100,
-                 MGA_WR34, 0x00000000,
-                 MGA_WR42, 0x0000ffff, MGA_WR60, 0x0000ffff);
-
-       /* Padding required to to hardware bug.
-        */
-       DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
-                 MGA_DMAPAD, 0xffffffff,
-                 MGA_DMAPAD, 0xffffffff,
-                 MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
-                              MGA_WMODE_START | dev_priv->wagp_enable));
-
-       ADVANCE_DMA();
-}
-
-static __inline__ void mga_g400_emit_pipe(drm_mga_private_t * dev_priv)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       unsigned int pipe = sarea_priv->warp_pipe;
-       DMA_LOCALS;
-
-/*     printk("mga_g400_emit_pipe %x\n", pipe); */
-
-       BEGIN_DMA(10);
-
-       DMA_BLOCK(MGA_WIADDR2, MGA_WMODE_SUSPEND,
-                 MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
-
-       if (pipe & MGA_T2) {
-               DMA_BLOCK(MGA_WVRTXSZ, 0x00001e09,
-                         MGA_DMAPAD, 0x00000000,
-                         MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
-
-               DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
-                         MGA_WACCEPTSEQ, 0x00000000,
-                         MGA_WACCEPTSEQ, 0x00000000,
-                         MGA_WACCEPTSEQ, 0x1e000000);
-       } else {
-               if (dev_priv->warp_pipe & MGA_T2) {
-                       /* Flush the WARP pipe */
-                       DMA_BLOCK(MGA_YDST, 0x00000000,
-                                 MGA_FXLEFT, 0x00000000,
-                                 MGA_FXRIGHT, 0x00000001,
-                                 MGA_DWGCTL, MGA_DWGCTL_FLUSH);
-
-                       DMA_BLOCK(MGA_LEN + MGA_EXEC, 0x00000001,
-                                 MGA_DWGSYNC, 0x00007000,
-                                 MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
-                                 MGA_LEN + MGA_EXEC, 0x00000000);
-
-                       DMA_BLOCK(MGA_TEXCTL2, (MGA_DUALTEX |
-                                               MGA_G400_TC2_MAGIC),
-                                 MGA_LEN + MGA_EXEC, 0x00000000,
-                                 MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
-                                 MGA_DMAPAD, 0x00000000);
-               }
-
-               DMA_BLOCK(MGA_WVRTXSZ, 0x00001807,
-                         MGA_DMAPAD, 0x00000000,
-                         MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
-
-               DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
-                         MGA_WACCEPTSEQ, 0x00000000,
-                         MGA_WACCEPTSEQ, 0x00000000,
-                         MGA_WACCEPTSEQ, 0x18000000);
-       }
-
-       DMA_BLOCK(MGA_WFLAG, 0x00000000,
-                 MGA_WFLAG1, 0x00000000,
-                 MGA_WR56, MGA_G400_WR56_MAGIC, MGA_DMAPAD, 0x00000000);
-
-       DMA_BLOCK(MGA_WR49, 0x00000000, /* tex0              */
-                 MGA_WR57, 0x00000000, /* tex0              */
-                 MGA_WR53, 0x00000000, /* tex1              */
-                 MGA_WR61, 0x00000000);        /* tex1              */
-
-       DMA_BLOCK(MGA_WR54, MGA_G400_WR_MAGIC,  /* tex0 width        */
-                 MGA_WR62, MGA_G400_WR_MAGIC,  /* tex0 height       */
-                 MGA_WR52, MGA_G400_WR_MAGIC,  /* tex1 width        */
-                 MGA_WR60, MGA_G400_WR_MAGIC); /* tex1 height       */
-
-       /* Padding required to to hardware bug */
-       DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
-                 MGA_DMAPAD, 0xffffffff,
-                 MGA_DMAPAD, 0xffffffff,
-                 MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
-                               MGA_WMODE_START | dev_priv->wagp_enable));
-
-       ADVANCE_DMA();
-}
-
-static void mga_g200_emit_state(drm_mga_private_t * dev_priv)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       unsigned int dirty = sarea_priv->dirty;
-
-       if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
-               mga_g200_emit_pipe(dev_priv);
-               dev_priv->warp_pipe = sarea_priv->warp_pipe;
-       }
-
-       if (dirty & MGA_UPLOAD_CONTEXT) {
-               mga_g200_emit_context(dev_priv);
-               sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
-       }
-
-       if (dirty & MGA_UPLOAD_TEX0) {
-               mga_g200_emit_tex0(dev_priv);
-               sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
-       }
-}
-
-static void mga_g400_emit_state(drm_mga_private_t * dev_priv)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       unsigned int dirty = sarea_priv->dirty;
-       int multitex = sarea_priv->warp_pipe & MGA_T2;
-
-       if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
-               mga_g400_emit_pipe(dev_priv);
-               dev_priv->warp_pipe = sarea_priv->warp_pipe;
-       }
-
-       if (dirty & MGA_UPLOAD_CONTEXT) {
-               mga_g400_emit_context(dev_priv);
-               sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
-       }
-
-       if (dirty & MGA_UPLOAD_TEX0) {
-               mga_g400_emit_tex0(dev_priv);
-               sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
-       }
-
-       if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
-               mga_g400_emit_tex1(dev_priv);
-               sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
-       }
-}
-
-/* ================================================================
- * SAREA state verification
- */
-
-/* Disallow all write destinations except the front and backbuffer.
- */
-static int mga_verify_context(drm_mga_private_t * dev_priv)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-
-       if (ctx->dstorg != dev_priv->front_offset &&
-           ctx->dstorg != dev_priv->back_offset) {
-               DRM_ERROR("*** bad DSTORG: %x (front %x, back %x)\n\n",
-                         ctx->dstorg, dev_priv->front_offset,
-                         dev_priv->back_offset);
-               ctx->dstorg = 0;
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/* Disallow texture reads from PCI space.
- */
-static int mga_verify_tex(drm_mga_private_t * dev_priv, int unit)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
-       unsigned int org;
-
-       org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK);
-
-       if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) {
-               DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit);
-               tex->texorg = 0;
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int mga_verify_state(drm_mga_private_t * dev_priv)
-{
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       unsigned int dirty = sarea_priv->dirty;
-       int ret = 0;
-
-       if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
-               sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
-
-       if (dirty & MGA_UPLOAD_CONTEXT)
-               ret |= mga_verify_context(dev_priv);
-
-       if (dirty & MGA_UPLOAD_TEX0)
-               ret |= mga_verify_tex(dev_priv, 0);
-
-       if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
-               if (dirty & MGA_UPLOAD_TEX1)
-                       ret |= mga_verify_tex(dev_priv, 1);
-
-               if (dirty & MGA_UPLOAD_PIPE)
-                       ret |= (sarea_priv->warp_pipe > MGA_MAX_G400_PIPES);
-       } else {
-               if (dirty & MGA_UPLOAD_PIPE)
-                       ret |= (sarea_priv->warp_pipe > MGA_MAX_G200_PIPES);
-       }
-
-       return (ret == 0);
-}
-
-static int mga_verify_iload(drm_mga_private_t * dev_priv,
-                           unsigned int dstorg, unsigned int length)
-{
-       if (dstorg < dev_priv->texture_offset ||
-           dstorg + length > (dev_priv->texture_offset +
-                              dev_priv->texture_size)) {
-               DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg);
-               return -EINVAL;
-       }
-
-       if (length & MGA_ILOAD_MASK) {
-               DRM_ERROR("*** bad iload length: 0x%x\n",
-                         length & MGA_ILOAD_MASK);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int mga_verify_blit(drm_mga_private_t * dev_priv,
-                          unsigned int srcorg, unsigned int dstorg)
-{
-       if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
-           (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) {
-               DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/* ================================================================
- *
- */
-
-static void mga_dma_dispatch_clear(struct drm_device * dev, drm_mga_clear_t * clear)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-       struct drm_clip_rect *pbox = sarea_priv->boxes;
-       int nbox = sarea_priv->nbox;
-       int i;
-       DMA_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_DMA(1);
-
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000,
-                 MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
-
-       ADVANCE_DMA();
-
-       for (i = 0; i < nbox; i++) {
-               struct drm_clip_rect *box = &pbox[i];
-               u32 height = box->y2 - box->y1;
-
-               DRM_DEBUG("   from=%d,%d to=%d,%d\n",
-                         box->x1, box->y1, box->x2, box->y2);
-
-               if (clear->flags & MGA_FRONT) {
-                       BEGIN_DMA(2);
-
-                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                                 MGA_PLNWT, clear->color_mask,
-                                 MGA_YDSTLEN, (box->y1 << 16) | height,
-                                 MGA_FXBNDRY, (box->x2 << 16) | box->x1);
-
-                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                                 MGA_FCOL, clear->clear_color,
-                                 MGA_DSTORG, dev_priv->front_offset,
-                                 MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
-
-                       ADVANCE_DMA();
-               }
-
-               if (clear->flags & MGA_BACK) {
-                       BEGIN_DMA(2);
-
-                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                                 MGA_PLNWT, clear->color_mask,
-                                 MGA_YDSTLEN, (box->y1 << 16) | height,
-                                 MGA_FXBNDRY, (box->x2 << 16) | box->x1);
-
-                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                                 MGA_FCOL, clear->clear_color,
-                                 MGA_DSTORG, dev_priv->back_offset,
-                                 MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
-
-                       ADVANCE_DMA();
-               }
-
-               if (clear->flags & MGA_DEPTH) {
-                       BEGIN_DMA(2);
-
-                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                                 MGA_PLNWT, clear->depth_mask,
-                                 MGA_YDSTLEN, (box->y1 << 16) | height,
-                                 MGA_FXBNDRY, (box->x2 << 16) | box->x1);
-
-                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                                 MGA_FCOL, clear->clear_depth,
-                                 MGA_DSTORG, dev_priv->depth_offset,
-                                 MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
-
-                       ADVANCE_DMA();
-               }
-
-       }
-
-       BEGIN_DMA(1);
-
-       /* Force reset of DWGCTL */
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000,
-                 MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
-
-       ADVANCE_DMA();
-
-       FLUSH_DMA();
-}
-
-static void mga_dma_dispatch_swap(struct drm_device * dev)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-       struct drm_clip_rect *pbox = sarea_priv->boxes;
-       int nbox = sarea_priv->nbox;
-       int i;
-       DMA_LOCALS;
-       DRM_DEBUG("\n");
-
-       sarea_priv->last_frame.head = dev_priv->prim.tail;
-       sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap;
-
-       BEGIN_DMA(4 + nbox);
-
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000,
-                 MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
-
-       DMA_BLOCK(MGA_DSTORG, dev_priv->front_offset,
-                 MGA_MACCESS, dev_priv->maccess,
-                 MGA_SRCORG, dev_priv->back_offset,
-                 MGA_AR5, dev_priv->front_pitch);
-
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000,
-                 MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY);
-
-       for (i = 0; i < nbox; i++) {
-               struct drm_clip_rect *box = &pbox[i];
-               u32 height = box->y2 - box->y1;
-               u32 start = box->y1 * dev_priv->front_pitch;
-
-               DRM_DEBUG("   from=%d,%d to=%d,%d\n",
-                         box->x1, box->y1, box->x2, box->y2);
-
-               DMA_BLOCK(MGA_AR0, start + box->x2 - 1,
-                         MGA_AR3, start + box->x1,
-                         MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1,
-                         MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height);
-       }
-
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_PLNWT, ctx->plnwt,
-                 MGA_SRCORG, dev_priv->front_offset, MGA_DWGCTL, ctx->dwgctl);
-
-       ADVANCE_DMA();
-
-       FLUSH_DMA();
-
-       DRM_DEBUG("... done.\n");
-}
-
-static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_buf_priv_t *buf_priv = buf->dev_private;
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       u32 address = (u32) buf->bus_address;
-       u32 length = (u32) buf->used;
-       int i = 0;
-       DMA_LOCALS;
-       DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used);
-
-       if (buf->used) {
-               buf_priv->dispatched = 1;
-
-               MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
-
-               do {
-                       if (i < sarea_priv->nbox) {
-                               mga_emit_clip_rect(dev_priv,
-                                                  &sarea_priv->boxes[i]);
-                       }
-
-                       BEGIN_DMA(1);
-
-                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                                 MGA_DMAPAD, 0x00000000,
-                                 MGA_SECADDRESS, (address |
-                                                  MGA_DMA_VERTEX),
-                                 MGA_SECEND, ((address + length) |
-                                              dev_priv->dma_access));
-
-                       ADVANCE_DMA();
-               } while (++i < sarea_priv->nbox);
-       }
-
-       if (buf_priv->discard) {
-               AGE_BUFFER(buf_priv);
-               buf->pending = 0;
-               buf->used = 0;
-               buf_priv->dispatched = 0;
-
-               mga_freelist_put(dev, buf);
-       }
-
-       FLUSH_DMA();
-}
-
-static void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * buf,
-                                    unsigned int start, unsigned int end)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_buf_priv_t *buf_priv = buf->dev_private;
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       u32 address = (u32) buf->bus_address;
-       int i = 0;
-       DMA_LOCALS;
-       DRM_DEBUG("buf=%d start=%d end=%d\n", buf->idx, start, end);
-
-       if (start != end) {
-               buf_priv->dispatched = 1;
-
-               MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
-
-               do {
-                       if (i < sarea_priv->nbox) {
-                               mga_emit_clip_rect(dev_priv,
-                                                  &sarea_priv->boxes[i]);
-                       }
-
-                       BEGIN_DMA(1);
-
-                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                                 MGA_DMAPAD, 0x00000000,
-                                 MGA_SETUPADDRESS, address + start,
-                                 MGA_SETUPEND, ((address + end) |
-                                                dev_priv->dma_access));
-
-                       ADVANCE_DMA();
-               } while (++i < sarea_priv->nbox);
-       }
-
-       if (buf_priv->discard) {
-               AGE_BUFFER(buf_priv);
-               buf->pending = 0;
-               buf->used = 0;
-               buf_priv->dispatched = 0;
-
-               mga_freelist_put(dev, buf);
-       }
-
-       FLUSH_DMA();
-}
-
-/* This copies a 64 byte aligned agp region to the frambuffer with a
- * standard blit, the ioctl needs to do checking.
- */
-static void mga_dma_dispatch_iload(struct drm_device * dev, struct drm_buf * buf,
-                                  unsigned int dstorg, unsigned int length)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_buf_priv_t *buf_priv = buf->dev_private;
-       drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
-       u32 srcorg =
-           buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM;
-       u32 y2;
-       DMA_LOCALS;
-       DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used);
-
-       y2 = length / 64;
-
-       BEGIN_DMA(5);
-
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000,
-                 MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
-
-       DMA_BLOCK(MGA_DSTORG, dstorg,
-                 MGA_MACCESS, 0x00000000, MGA_SRCORG, srcorg, MGA_AR5, 64);
-
-       DMA_BLOCK(MGA_PITCH, 64,
-                 MGA_PLNWT, 0xffffffff,
-                 MGA_DMAPAD, 0x00000000, MGA_DWGCTL, MGA_DWGCTL_COPY);
-
-       DMA_BLOCK(MGA_AR0, 63,
-                 MGA_AR3, 0,
-                 MGA_FXBNDRY, (63 << 16) | 0, MGA_YDSTLEN + MGA_EXEC, y2);
-
-       DMA_BLOCK(MGA_PLNWT, ctx->plnwt,
-                 MGA_SRCORG, dev_priv->front_offset,
-                 MGA_PITCH, dev_priv->front_pitch, MGA_DWGSYNC, 0x00007000);
-
-       ADVANCE_DMA();
-
-       AGE_BUFFER(buf_priv);
-
-       buf->pending = 0;
-       buf->used = 0;
-       buf_priv->dispatched = 0;
-
-       mga_freelist_put(dev, buf);
-
-       FLUSH_DMA();
-}
-
-static void mga_dma_dispatch_blit(struct drm_device * dev, drm_mga_blit_t * blit)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
-       struct drm_clip_rect *pbox = sarea_priv->boxes;
-       int nbox = sarea_priv->nbox;
-       u32 scandir = 0, i;
-       DMA_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_DMA(4 + nbox);
-
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000,
-                 MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
-
-       DMA_BLOCK(MGA_DWGCTL, MGA_DWGCTL_COPY,
-                 MGA_PLNWT, blit->planemask,
-                 MGA_SRCORG, blit->srcorg, MGA_DSTORG, blit->dstorg);
-
-       DMA_BLOCK(MGA_SGN, scandir,
-                 MGA_MACCESS, dev_priv->maccess,
-                 MGA_AR5, blit->ydir * blit->src_pitch,
-                 MGA_PITCH, blit->dst_pitch);
-
-       for (i = 0; i < nbox; i++) {
-               int srcx = pbox[i].x1 + blit->delta_sx;
-               int srcy = pbox[i].y1 + blit->delta_sy;
-               int dstx = pbox[i].x1 + blit->delta_dx;
-               int dsty = pbox[i].y1 + blit->delta_dy;
-               int h = pbox[i].y2 - pbox[i].y1;
-               int w = pbox[i].x2 - pbox[i].x1 - 1;
-               int start;
-
-               if (blit->ydir == -1) {
-                       srcy = blit->height - srcy - 1;
-               }
-
-               start = srcy * blit->src_pitch + srcx;
-
-               DMA_BLOCK(MGA_AR0, start + w,
-                         MGA_AR3, start,
-                         MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff),
-                         MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h);
-       }
-
-       /* Do something to flush AGP?
-        */
-
-       /* Force reset of DWGCTL */
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_PLNWT, ctx->plnwt,
-                 MGA_PITCH, dev_priv->front_pitch, MGA_DWGCTL, ctx->dwgctl);
-
-       ADVANCE_DMA();
-}
-
-/* ================================================================
- *
- */
-
-static int mga_dma_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_clear_t *clear = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
-               sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
-
-       WRAP_TEST_WITH_RETURN(dev_priv);
-
-       mga_dma_dispatch_clear(dev, clear);
-
-       /* Make sure we restore the 3D state next time.
-        */
-       dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
-
-       return 0;
-}
-
-static int mga_dma_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
-               sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
-
-       WRAP_TEST_WITH_RETURN(dev_priv);
-
-       mga_dma_dispatch_swap(dev);
-
-       /* Make sure we restore the 3D state next time.
-        */
-       dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
-
-       return 0;
-}
-
-static int mga_dma_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_mga_buf_priv_t *buf_priv;
-       drm_mga_vertex_t *vertex = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (vertex->idx < 0 || vertex->idx > dma->buf_count)
-               return -EINVAL;
-       buf = dma->buflist[vertex->idx];
-       buf_priv = buf->dev_private;
-
-       buf->used = vertex->used;
-       buf_priv->discard = vertex->discard;
-
-       if (!mga_verify_state(dev_priv)) {
-               if (vertex->discard) {
-                       if (buf_priv->dispatched == 1)
-                               AGE_BUFFER(buf_priv);
-                       buf_priv->dispatched = 0;
-                       mga_freelist_put(dev, buf);
-               }
-               return -EINVAL;
-       }
-
-       WRAP_TEST_WITH_RETURN(dev_priv);
-
-       mga_dma_dispatch_vertex(dev, buf);
-
-       return 0;
-}
-
-static int mga_dma_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_mga_buf_priv_t *buf_priv;
-       drm_mga_indices_t *indices = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (indices->idx < 0 || indices->idx > dma->buf_count)
-               return -EINVAL;
-
-       buf = dma->buflist[indices->idx];
-       buf_priv = buf->dev_private;
-
-       buf_priv->discard = indices->discard;
-
-       if (!mga_verify_state(dev_priv)) {
-               if (indices->discard) {
-                       if (buf_priv->dispatched == 1)
-                               AGE_BUFFER(buf_priv);
-                       buf_priv->dispatched = 0;
-                       mga_freelist_put(dev, buf);
-               }
-               return -EINVAL;
-       }
-
-       WRAP_TEST_WITH_RETURN(dev_priv);
-
-       mga_dma_dispatch_indices(dev, buf, indices->start, indices->end);
-
-       return 0;
-}
-
-static int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       struct drm_buf *buf;
-       drm_mga_buf_priv_t *buf_priv;
-       drm_mga_iload_t *iload = data;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-#if 0
-       if (mga_do_wait_for_idle(dev_priv) < 0) {
-               if (MGA_DMA_DEBUG)
-                       DRM_INFO("-EBUSY\n");
-               return -EBUSY;
-       }
-#endif
-       if (iload->idx < 0 || iload->idx > dma->buf_count)
-               return -EINVAL;
-
-       buf = dma->buflist[iload->idx];
-       buf_priv = buf->dev_private;
-
-       if (mga_verify_iload(dev_priv, iload->dstorg, iload->length)) {
-               mga_freelist_put(dev, buf);
-               return -EINVAL;
-       }
-
-       WRAP_TEST_WITH_RETURN(dev_priv);
-
-       mga_dma_dispatch_iload(dev, buf, iload->dstorg, iload->length);
-
-       /* Make sure we restore the 3D state next time.
-        */
-       dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
-
-       return 0;
-}
-
-static int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_mga_blit_t *blit = data;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
-               sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
-
-       if (mga_verify_blit(dev_priv, blit->srcorg, blit->dstorg))
-               return -EINVAL;
-
-       WRAP_TEST_WITH_RETURN(dev_priv);
-
-       mga_dma_dispatch_blit(dev, blit);
-
-       /* Make sure we restore the 3D state next time.
-        */
-       dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
-
-       return 0;
-}
-
-static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       drm_mga_getparam_t *param = data;
-       int value;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
-
-       switch (param->param) {
-       case MGA_PARAM_IRQ_NR:
-               value = dev->irq;
-               break;
-       case MGA_PARAM_CARD_TYPE:
-               value = dev_priv->chipset;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
-               DRM_ERROR("copy_to_user\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       u32 *fence = data;
-       DMA_LOCALS;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
-
-       /* I would normal do this assignment in the declaration of fence,
-        * but dev_priv may be NULL.
-        */
-
-       *fence = dev_priv->next_fence_to_post;
-       dev_priv->next_fence_to_post++;
-
-       BEGIN_DMA(1);
-       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000,
-                 MGA_DMAPAD, 0x00000000, MGA_SOFTRAP, 0x00000000);
-       ADVANCE_DMA();
-
-       return 0;
-}
-
-static int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file *
-file_priv)
-{
-       drm_mga_private_t *dev_priv = dev->dev_private;
-       u32 *fence = data;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
-
-       mga_driver_fence_wait(dev, fence);
-       return 0;
-}
-
-struct drm_ioctl_desc mga_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_MGA_FLUSH, mga_dma_flush, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_RESET, mga_dma_reset, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_SWAP, mga_dma_swap, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_CLEAR, mga_dma_clear, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_VERTEX, mga_dma_vertex, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_INDICES, mga_dma_indices, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_ILOAD, mga_dma_iload, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_BLIT, mga_dma_blit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_GETPARAM, mga_getparam, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_SET_FENCE, mga_set_fence, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-};
-
-int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
diff --git a/drivers/char/drm/mga_ucode.h b/drivers/char/drm/mga_ucode.h
deleted file mode 100644 (file)
index b611e27..0000000
+++ /dev/null
@@ -1,11645 +0,0 @@
-/* mga_ucode.h -- Matrox G200/G400 WARP engine microcode -*- linux-c -*-
- * Created: Thu Jan 11 21:20:43 2001 by gareth@valinux.com
- *
- * Copyright 1999 Matrox Graphics Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * MATROX GRAPHICS INC., OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
- * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Kernel-based WARP engine management:
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * WARP pipes are named according to the functions they perform, where:
- *
- *   - T stands for computation of texture stage 0
- *   - T2 stands for computation of both texture stage 0 and texture stage 1
- *   - G stands for computation of triangle intensity (Gouraud interpolation)
- *   - Z stands for computation of Z buffer interpolation
- *   - S stands for computation of specular highlight
- *   - A stands for computation of the alpha channel
- *   - F stands for computation of vertex fog interpolation
- */
-
-static unsigned char warp_g200_tgz[] = {
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x98, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x81, 0x04,
-       0x89, 0x04,
-       0x01, 0x04,
-       0x09, 0x04,
-
-       0xC9, 0x41, 0xC0, 0xEC,
-       0x11, 0x04,
-       0x00, 0xE0,
-
-       0x41, 0xCC, 0x41, 0xCD,
-       0x49, 0xCC, 0x49, 0xCD,
-
-       0xD1, 0x41, 0xC0, 0xEC,
-       0x51, 0xCC, 0x51, 0xCD,
-
-       0x80, 0x04,
-       0x10, 0x04,
-       0x08, 0x04,
-       0x00, 0xE0,
-
-       0x00, 0xCC, 0xC0, 0xCD,
-       0xD1, 0x49, 0xC0, 0xEC,
-
-       0x8A, 0x1F, 0x20, 0xE9,
-       0x8B, 0x3F, 0x20, 0xE9,
-
-       0x41, 0x3C, 0x41, 0xAD,
-       0x49, 0x3C, 0x49, 0xAD,
-
-       0x10, 0xCC, 0x10, 0xCD,
-       0x08, 0xCC, 0x08, 0xCD,
-
-       0xB9, 0x41, 0x49, 0xBB,
-       0x1F, 0xF0, 0x41, 0xCD,
-
-       0x51, 0x3C, 0x51, 0xAD,
-       0x00, 0x98, 0x80, 0xE9,
-
-       0x72, 0x80, 0x07, 0xEA,
-       0x24, 0x1F, 0x20, 0xE9,
-
-       0x15, 0x41, 0x49, 0xBD,
-       0x1D, 0x41, 0x51, 0xBD,
-
-       0x2E, 0x41, 0x2A, 0xB8,
-       0x34, 0x53, 0xA0, 0xE8,
-
-       0x15, 0x30,
-       0x1D, 0x30,
-       0x58, 0xE3,
-       0x00, 0xE0,
-
-       0xB5, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x24, 0x43, 0xA0, 0xE8,
-       0x2C, 0x4B, 0xA0, 0xE8,
-
-       0x15, 0x72,
-       0x09, 0xE3,
-       0x00, 0xE0,
-       0x1D, 0x72,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0x97, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x6C, 0x64, 0xC8, 0xEC,
-       0x98, 0xE1,
-       0xB5, 0x05,
-
-       0xBD, 0x05,
-       0x2E, 0x30,
-       0x32, 0xC0, 0xA0, 0xE8,
-
-       0x33, 0xC0, 0xA0, 0xE8,
-       0x74, 0x64, 0xC8, 0xEC,
-
-       0x40, 0x3C, 0x40, 0xAD,
-       0x32, 0x6A,
-       0x2A, 0x30,
-
-       0x20, 0x73,
-       0x33, 0x6A,
-       0x00, 0xE0,
-       0x28, 0x73,
-
-       0x1C, 0x72,
-       0x83, 0xE2,
-       0x60, 0x80, 0x15, 0xEA,
-
-       0xB8, 0x3D, 0x28, 0xDF,
-       0x30, 0x35, 0x20, 0xDF,
-
-       0x40, 0x30,
-       0x00, 0xE0,
-       0xCC, 0xE2,
-       0x64, 0x72,
-
-       0x25, 0x42, 0x52, 0xBF,
-       0x2D, 0x42, 0x4A, 0xBF,
-
-       0x30, 0x2E, 0x30, 0xDF,
-       0x38, 0x2E, 0x38, 0xDF,
-
-       0x18, 0x1D, 0x45, 0xE9,
-       0x1E, 0x15, 0x45, 0xE9,
-
-       0x2B, 0x49, 0x51, 0xBD,
-       0x00, 0xE0,
-       0x1F, 0x73,
-
-       0x38, 0x38, 0x40, 0xAF,
-       0x30, 0x30, 0x40, 0xAF,
-
-       0x24, 0x1F, 0x24, 0xDF,
-       0x1D, 0x32, 0x20, 0xE9,
-
-       0x2C, 0x1F, 0x2C, 0xDF,
-       0x1A, 0x33, 0x20, 0xE9,
-
-       0xB0, 0x10,
-       0x08, 0xE3,
-       0x40, 0x10,
-       0xB8, 0x10,
-
-       0x26, 0xF0, 0x30, 0xCD,
-       0x2F, 0xF0, 0x38, 0xCD,
-
-       0x2B, 0x80, 0x20, 0xE9,
-       0x2A, 0x80, 0x20, 0xE9,
-
-       0xA6, 0x20,
-       0x88, 0xE2,
-       0x00, 0xE0,
-       0xAF, 0x20,
-
-       0x28, 0x2A, 0x26, 0xAF,
-       0x20, 0x2A, 0xC0, 0xAF,
-
-       0x34, 0x1F, 0x34, 0xDF,
-       0x46, 0x24, 0x46, 0xDF,
-
-       0x28, 0x30, 0x80, 0xBF,
-       0x20, 0x38, 0x80, 0xBF,
-
-       0x47, 0x24, 0x47, 0xDF,
-       0x4E, 0x2C, 0x4E, 0xDF,
-
-       0x4F, 0x2C, 0x4F, 0xDF,
-       0x56, 0x34, 0x56, 0xDF,
-
-       0x28, 0x15, 0x28, 0xDF,
-       0x20, 0x1D, 0x20, 0xDF,
-
-       0x57, 0x34, 0x57, 0xDF,
-       0x00, 0xE0,
-       0x1D, 0x05,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x89, 0xE2,
-       0x2B, 0x30,
-
-       0x3F, 0xC1, 0x1D, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA0, 0x68,
-       0xBF, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x20, 0xC0, 0x20, 0xAF,
-       0x28, 0x05,
-       0x97, 0x74,
-
-       0x00, 0xE0,
-       0x2A, 0x10,
-       0x16, 0xC0, 0x20, 0xE9,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x8C, 0xE2,
-       0x95, 0x05,
-
-       0x28, 0xC1, 0x28, 0xAD,
-       0x1F, 0xC1, 0x15, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA8, 0x67,
-       0x9F, 0x6B,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x28, 0xC0, 0x28, 0xAD,
-       0x1D, 0x25,
-       0x20, 0x05,
-
-       0x28, 0x32, 0x80, 0xAD,
-       0x40, 0x2A, 0x40, 0xBD,
-
-       0x1C, 0x80, 0x20, 0xE9,
-       0x20, 0x33, 0x20, 0xAD,
-
-       0x20, 0x73,
-       0x00, 0xE0,
-       0xB6, 0x49, 0x51, 0xBB,
-
-       0x26, 0x2F, 0xB0, 0xE8,
-       0x19, 0x20, 0x20, 0xE9,
-
-       0x35, 0x20, 0x35, 0xDF,
-       0x3D, 0x20, 0x3D, 0xDF,
-
-       0x15, 0x20, 0x15, 0xDF,
-       0x1D, 0x20, 0x1D, 0xDF,
-
-       0x26, 0xD0, 0x26, 0xCD,
-       0x29, 0x49, 0x2A, 0xB8,
-
-       0x26, 0x40, 0x80, 0xBD,
-       0x3B, 0x48, 0x50, 0xBD,
-
-       0x3E, 0x54, 0x57, 0x9F,
-       0x00, 0xE0,
-       0x82, 0xE1,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x26, 0x30,
-       0x29, 0x30,
-       0x48, 0x3C, 0x48, 0xAD,
-
-       0x2B, 0x72,
-       0xC2, 0xE1,
-       0x2C, 0xC0, 0x44, 0xC2,
-
-       0x05, 0x24, 0x34, 0xBF,
-       0x0D, 0x24, 0x2C, 0xBF,
-
-       0x2D, 0x46, 0x4E, 0xBF,
-       0x25, 0x46, 0x56, 0xBF,
-
-       0x20, 0x1D, 0x6F, 0x8F,
-       0x32, 0x3E, 0x5F, 0xE9,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x30,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x33, 0x1E, 0x5F, 0xE9,
-
-       0x05, 0x44, 0x54, 0xB2,
-       0x0D, 0x44, 0x4C, 0xB2,
-
-       0x19, 0xC0, 0xB0, 0xE8,
-       0x34, 0xC0, 0x44, 0xC4,
-
-       0x33, 0x73,
-       0x00, 0xE0,
-       0x3E, 0x62, 0x57, 0x9F,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0xE0,
-       0x0D, 0x20,
-
-       0x84, 0x3E, 0x58, 0xE9,
-       0x28, 0x1D, 0x6F, 0x8F,
-
-       0x05, 0x20,
-       0x00, 0xE0,
-       0x85, 0x1E, 0x58, 0xE9,
-
-       0x9B, 0x3B, 0x33, 0xDF,
-       0x20, 0x20, 0x42, 0xAF,
-
-       0x30, 0x42, 0x56, 0x9F,
-       0x80, 0x3E, 0x57, 0xE9,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x30, 0x80, 0x5F, 0xE9,
-
-       0x28, 0x28, 0x24, 0xAF,
-       0x81, 0x1E, 0x57, 0xE9,
-
-       0x05, 0x47, 0x57, 0xBF,
-       0x0D, 0x47, 0x4F, 0xBF,
-
-       0x88, 0x80, 0x58, 0xE9,
-       0x1B, 0x29, 0x1B, 0xDF,
-
-       0x30, 0x1D, 0x6F, 0x8F,
-       0x3A, 0x30, 0x4F, 0xE9,
-
-       0x1C, 0x30, 0x26, 0xDF,
-       0x09, 0xE3,
-       0x3B, 0x05,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x3B, 0x3F, 0x4F, 0xE9,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x00, 0xE0,
-       0xAC, 0x20,
-
-       0x2D, 0x44, 0x4C, 0xB4,
-       0x2C, 0x1C, 0xC0, 0xAF,
-
-       0x25, 0x44, 0x54, 0xB4,
-       0x00, 0xE0,
-       0xC8, 0x30,
-
-       0x30, 0x46, 0x30, 0xAF,
-       0x1B, 0x1B, 0x48, 0xAF,
-
-       0x00, 0xE0,
-       0x25, 0x20,
-       0x38, 0x2C, 0x4F, 0xE9,
-
-       0x86, 0x80, 0x57, 0xE9,
-       0x38, 0x1D, 0x6F, 0x8F,
-
-       0x28, 0x74,
-       0x00, 0xE0,
-       0x0D, 0x44, 0x4C, 0xB0,
-
-       0x05, 0x44, 0x54, 0xB0,
-       0x2D, 0x20,
-       0x9B, 0x10,
-
-       0x82, 0x3E, 0x57, 0xE9,
-       0x32, 0xF0, 0x1B, 0xCD,
-
-       0x1E, 0xBD, 0x59, 0x9F,
-       0x83, 0x1E, 0x57, 0xE9,
-
-       0x38, 0x47, 0x38, 0xAF,
-       0x34, 0x20,
-       0x2A, 0x30,
-
-       0x00, 0xE0,
-       0x0D, 0x20,
-       0x32, 0x20,
-       0x05, 0x20,
-
-       0x87, 0x80, 0x57, 0xE9,
-       0x1F, 0x54, 0x57, 0x9F,
-
-       0x17, 0x42, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x6A,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x37, 0x1E, 0x4F, 0xE9,
-
-       0x37, 0x32, 0x2A, 0xAF,
-       0x00, 0xE0,
-       0x32, 0x00,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x27, 0xC0, 0x44, 0xC0,
-
-       0x36, 0x1F, 0x4F, 0xE9,
-       0x1F, 0x1F, 0x26, 0xDF,
-
-       0x37, 0x1B, 0x37, 0xBF,
-       0x17, 0x26, 0x17, 0xDF,
-
-       0x3E, 0x17, 0x4F, 0xE9,
-       0x3F, 0x3F, 0x4F, 0xE9,
-
-       0x34, 0x1F, 0x34, 0xAF,
-       0x2B, 0x05,
-       0xA7, 0x20,
-
-       0x33, 0x2B, 0x37, 0xDF,
-       0x27, 0x17, 0xC0, 0xAF,
-
-       0x34, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x03, 0x80, 0x0A, 0xEA,
-       0x17, 0xC1, 0x2B, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xB3, 0x68,
-       0x97, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x33, 0xC0, 0x33, 0xAF,
-       0x3C, 0x27, 0x4F, 0xE9,
-
-       0x57, 0x39, 0x20, 0xE9,
-       0x28, 0x19, 0x60, 0xEC,
-
-       0x2B, 0x32, 0x20, 0xE9,
-       0x1D, 0x3B, 0x20, 0xE9,
-
-       0xB3, 0x05,
-       0x00, 0xE0,
-       0x16, 0x28, 0x20, 0xE9,
-
-       0x23, 0x3B, 0x33, 0xAD,
-       0x1E, 0x2B, 0x20, 0xE9,
-
-       0x1C, 0x80, 0x20, 0xE9,
-       0x57, 0x36, 0x20, 0xE9,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x90, 0xE2,
-       0x00, 0xE0,
-
-       0x85, 0xFF, 0x20, 0xEA,
-       0x19, 0xC8, 0xC1, 0xCD,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x9F, 0x41, 0x49, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x25, 0x41, 0x49, 0xBD,
-       0x2D, 0x41, 0x51, 0xBD,
-
-       0x0D, 0x80, 0x07, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x35, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x25, 0x30,
-       0x2D, 0x30,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0xA7, 0x5B, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x84, 0xFF, 0x0A, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC9, 0x41, 0xC8, 0xEC,
-       0x42, 0xE1,
-       0x00, 0xE0,
-
-       0x82, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC8, 0x40, 0xC0, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x7F, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-};
-
-static unsigned char warp_g200_tgza[] = {
-
-       0x00, 0x98, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x81, 0x04,
-       0x89, 0x04,
-       0x01, 0x04,
-       0x09, 0x04,
-
-       0xC9, 0x41, 0xC0, 0xEC,
-       0x11, 0x04,
-       0x00, 0xE0,
-
-       0x41, 0xCC, 0x41, 0xCD,
-       0x49, 0xCC, 0x49, 0xCD,
-
-       0xD1, 0x41, 0xC0, 0xEC,
-       0x51, 0xCC, 0x51, 0xCD,
-
-       0x80, 0x04,
-       0x10, 0x04,
-       0x08, 0x04,
-       0x00, 0xE0,
-
-       0x00, 0xCC, 0xC0, 0xCD,
-       0xD1, 0x49, 0xC0, 0xEC,
-
-       0x8A, 0x1F, 0x20, 0xE9,
-       0x8B, 0x3F, 0x20, 0xE9,
-
-       0x41, 0x3C, 0x41, 0xAD,
-       0x49, 0x3C, 0x49, 0xAD,
-
-       0x10, 0xCC, 0x10, 0xCD,
-       0x08, 0xCC, 0x08, 0xCD,
-
-       0xB9, 0x41, 0x49, 0xBB,
-       0x1F, 0xF0, 0x41, 0xCD,
-
-       0x51, 0x3C, 0x51, 0xAD,
-       0x00, 0x98, 0x80, 0xE9,
-
-       0x7D, 0x80, 0x07, 0xEA,
-       0x24, 0x1F, 0x20, 0xE9,
-
-       0x15, 0x41, 0x49, 0xBD,
-       0x1D, 0x41, 0x51, 0xBD,
-
-       0x2E, 0x41, 0x2A, 0xB8,
-       0x34, 0x53, 0xA0, 0xE8,
-
-       0x15, 0x30,
-       0x1D, 0x30,
-       0x58, 0xE3,
-       0x00, 0xE0,
-
-       0xB5, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x24, 0x43, 0xA0, 0xE8,
-       0x2C, 0x4B, 0xA0, 0xE8,
-
-       0x15, 0x72,
-       0x09, 0xE3,
-       0x00, 0xE0,
-       0x1D, 0x72,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0x97, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x6C, 0x64, 0xC8, 0xEC,
-       0x98, 0xE1,
-       0xB5, 0x05,
-
-       0xBD, 0x05,
-       0x2E, 0x30,
-       0x32, 0xC0, 0xA0, 0xE8,
-
-       0x33, 0xC0, 0xA0, 0xE8,
-       0x74, 0x64, 0xC8, 0xEC,
-
-       0x40, 0x3C, 0x40, 0xAD,
-       0x32, 0x6A,
-       0x2A, 0x30,
-
-       0x20, 0x73,
-       0x33, 0x6A,
-       0x00, 0xE0,
-       0x28, 0x73,
-
-       0x1C, 0x72,
-       0x83, 0xE2,
-       0x6B, 0x80, 0x15, 0xEA,
-
-       0xB8, 0x3D, 0x28, 0xDF,
-       0x30, 0x35, 0x20, 0xDF,
-
-       0x40, 0x30,
-       0x00, 0xE0,
-       0xCC, 0xE2,
-       0x64, 0x72,
-
-       0x25, 0x42, 0x52, 0xBF,
-       0x2D, 0x42, 0x4A, 0xBF,
-
-       0x30, 0x2E, 0x30, 0xDF,
-       0x38, 0x2E, 0x38, 0xDF,
-
-       0x18, 0x1D, 0x45, 0xE9,
-       0x1E, 0x15, 0x45, 0xE9,
-
-       0x2B, 0x49, 0x51, 0xBD,
-       0x00, 0xE0,
-       0x1F, 0x73,
-
-       0x38, 0x38, 0x40, 0xAF,
-       0x30, 0x30, 0x40, 0xAF,
-
-       0x24, 0x1F, 0x24, 0xDF,
-       0x1D, 0x32, 0x20, 0xE9,
-
-       0x2C, 0x1F, 0x2C, 0xDF,
-       0x1A, 0x33, 0x20, 0xE9,
-
-       0xB0, 0x10,
-       0x08, 0xE3,
-       0x40, 0x10,
-       0xB8, 0x10,
-
-       0x26, 0xF0, 0x30, 0xCD,
-       0x2F, 0xF0, 0x38, 0xCD,
-
-       0x2B, 0x80, 0x20, 0xE9,
-       0x2A, 0x80, 0x20, 0xE9,
-
-       0xA6, 0x20,
-       0x88, 0xE2,
-       0x00, 0xE0,
-       0xAF, 0x20,
-
-       0x28, 0x2A, 0x26, 0xAF,
-       0x20, 0x2A, 0xC0, 0xAF,
-
-       0x34, 0x1F, 0x34, 0xDF,
-       0x46, 0x24, 0x46, 0xDF,
-
-       0x28, 0x30, 0x80, 0xBF,
-       0x20, 0x38, 0x80, 0xBF,
-
-       0x47, 0x24, 0x47, 0xDF,
-       0x4E, 0x2C, 0x4E, 0xDF,
-
-       0x4F, 0x2C, 0x4F, 0xDF,
-       0x56, 0x34, 0x56, 0xDF,
-
-       0x28, 0x15, 0x28, 0xDF,
-       0x20, 0x1D, 0x20, 0xDF,
-
-       0x57, 0x34, 0x57, 0xDF,
-       0x00, 0xE0,
-       0x1D, 0x05,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x89, 0xE2,
-       0x2B, 0x30,
-
-       0x3F, 0xC1, 0x1D, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA0, 0x68,
-       0xBF, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x20, 0xC0, 0x20, 0xAF,
-       0x28, 0x05,
-       0x97, 0x74,
-
-       0x00, 0xE0,
-       0x2A, 0x10,
-       0x16, 0xC0, 0x20, 0xE9,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x8C, 0xE2,
-       0x95, 0x05,
-
-       0x28, 0xC1, 0x28, 0xAD,
-       0x1F, 0xC1, 0x15, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA8, 0x67,
-       0x9F, 0x6B,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x28, 0xC0, 0x28, 0xAD,
-       0x1D, 0x25,
-       0x20, 0x05,
-
-       0x28, 0x32, 0x80, 0xAD,
-       0x40, 0x2A, 0x40, 0xBD,
-
-       0x1C, 0x80, 0x20, 0xE9,
-       0x20, 0x33, 0x20, 0xAD,
-
-       0x20, 0x73,
-       0x00, 0xE0,
-       0xB6, 0x49, 0x51, 0xBB,
-
-       0x26, 0x2F, 0xB0, 0xE8,
-       0x19, 0x20, 0x20, 0xE9,
-
-       0x35, 0x20, 0x35, 0xDF,
-       0x3D, 0x20, 0x3D, 0xDF,
-
-       0x15, 0x20, 0x15, 0xDF,
-       0x1D, 0x20, 0x1D, 0xDF,
-
-       0x26, 0xD0, 0x26, 0xCD,
-       0x29, 0x49, 0x2A, 0xB8,
-
-       0x26, 0x40, 0x80, 0xBD,
-       0x3B, 0x48, 0x50, 0xBD,
-
-       0x3E, 0x54, 0x57, 0x9F,
-       0x00, 0xE0,
-       0x82, 0xE1,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x26, 0x30,
-       0x29, 0x30,
-       0x48, 0x3C, 0x48, 0xAD,
-
-       0x2B, 0x72,
-       0xC2, 0xE1,
-       0x2C, 0xC0, 0x44, 0xC2,
-
-       0x05, 0x24, 0x34, 0xBF,
-       0x0D, 0x24, 0x2C, 0xBF,
-
-       0x2D, 0x46, 0x4E, 0xBF,
-       0x25, 0x46, 0x56, 0xBF,
-
-       0x20, 0x1D, 0x6F, 0x8F,
-       0x32, 0x3E, 0x5F, 0xE9,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x30,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x33, 0x1E, 0x5F, 0xE9,
-
-       0x05, 0x44, 0x54, 0xB2,
-       0x0D, 0x44, 0x4C, 0xB2,
-
-       0x19, 0xC0, 0xB0, 0xE8,
-       0x34, 0xC0, 0x44, 0xC4,
-
-       0x33, 0x73,
-       0x00, 0xE0,
-       0x3E, 0x62, 0x57, 0x9F,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0xE0,
-       0x0D, 0x20,
-
-       0x84, 0x3E, 0x58, 0xE9,
-       0x28, 0x1D, 0x6F, 0x8F,
-
-       0x05, 0x20,
-       0x00, 0xE0,
-       0x85, 0x1E, 0x58, 0xE9,
-
-       0x9B, 0x3B, 0x33, 0xDF,
-       0x20, 0x20, 0x42, 0xAF,
-
-       0x30, 0x42, 0x56, 0x9F,
-       0x80, 0x3E, 0x57, 0xE9,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x30, 0x80, 0x5F, 0xE9,
-
-       0x28, 0x28, 0x24, 0xAF,
-       0x81, 0x1E, 0x57, 0xE9,
-
-       0x05, 0x47, 0x57, 0xBF,
-       0x0D, 0x47, 0x4F, 0xBF,
-
-       0x88, 0x80, 0x58, 0xE9,
-       0x1B, 0x29, 0x1B, 0xDF,
-
-       0x30, 0x1D, 0x6F, 0x8F,
-       0x3A, 0x30, 0x4F, 0xE9,
-
-       0x1C, 0x30, 0x26, 0xDF,
-       0x09, 0xE3,
-       0x3B, 0x05,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x3B, 0x3F, 0x4F, 0xE9,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x00, 0xE0,
-       0xAC, 0x20,
-
-       0x2D, 0x44, 0x4C, 0xB4,
-       0x2C, 0x1C, 0xC0, 0xAF,
-
-       0x25, 0x44, 0x54, 0xB4,
-       0x00, 0xE0,
-       0xC8, 0x30,
-
-       0x30, 0x46, 0x30, 0xAF,
-       0x1B, 0x1B, 0x48, 0xAF,
-
-       0x00, 0xE0,
-       0x25, 0x20,
-       0x38, 0x2C, 0x4F, 0xE9,
-
-       0x86, 0x80, 0x57, 0xE9,
-       0x38, 0x1D, 0x6F, 0x8F,
-
-       0x28, 0x74,
-       0x00, 0xE0,
-       0x0D, 0x44, 0x4C, 0xB0,
-
-       0x05, 0x44, 0x54, 0xB0,
-       0x2D, 0x20,
-       0x9B, 0x10,
-
-       0x82, 0x3E, 0x57, 0xE9,
-       0x32, 0xF0, 0x1B, 0xCD,
-
-       0x1E, 0xBD, 0x59, 0x9F,
-       0x83, 0x1E, 0x57, 0xE9,
-
-       0x38, 0x47, 0x38, 0xAF,
-       0x34, 0x20,
-       0x2A, 0x30,
-
-       0x00, 0xE0,
-       0x0D, 0x20,
-       0x32, 0x20,
-       0x05, 0x20,
-
-       0x87, 0x80, 0x57, 0xE9,
-       0x1F, 0x54, 0x57, 0x9F,
-
-       0x17, 0x42, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x6A,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x37, 0x1E, 0x4F, 0xE9,
-
-       0x37, 0x32, 0x2A, 0xAF,
-       0x00, 0xE0,
-       0x32, 0x00,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x27, 0xC0, 0x44, 0xC0,
-
-       0x36, 0x1F, 0x4F, 0xE9,
-       0x1F, 0x1F, 0x26, 0xDF,
-
-       0x37, 0x1B, 0x37, 0xBF,
-       0x17, 0x26, 0x17, 0xDF,
-
-       0x3E, 0x17, 0x4F, 0xE9,
-       0x3F, 0x3F, 0x4F, 0xE9,
-
-       0x34, 0x1F, 0x34, 0xAF,
-       0x2B, 0x05,
-       0xA7, 0x20,
-
-       0x33, 0x2B, 0x37, 0xDF,
-       0x27, 0x17, 0xC0, 0xAF,
-
-       0x34, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x2D, 0x44, 0x4C, 0xB6,
-       0x25, 0x44, 0x54, 0xB6,
-
-       0x03, 0x80, 0x2A, 0xEA,
-       0x17, 0xC1, 0x2B, 0xBD,
-
-       0x2D, 0x20,
-       0x25, 0x20,
-       0x07, 0xC0, 0x44, 0xC6,
-
-       0xB3, 0x68,
-       0x97, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x33, 0xC0, 0x33, 0xAF,
-       0x3C, 0x27, 0x4F, 0xE9,
-
-       0x1F, 0x62, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x3F, 0x3D, 0x5D, 0x9F,
-       0x00, 0xE0,
-       0x07, 0x20,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x28, 0x19, 0x60, 0xEC,
-
-       0xB3, 0x05,
-       0x00, 0xE0,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x23, 0x3B, 0x33, 0xAD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x1F, 0x26, 0x1F, 0xDF,
-       0x9D, 0x1F, 0x4F, 0xE9,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x9E, 0x3F, 0x4F, 0xE9,
-
-       0x07, 0x07, 0x1F, 0xAF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x9C, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x57, 0x39, 0x20, 0xE9,
-
-       0x16, 0x28, 0x20, 0xE9,
-       0x1D, 0x3B, 0x20, 0xE9,
-
-       0x1E, 0x2B, 0x20, 0xE9,
-       0x2B, 0x32, 0x20, 0xE9,
-
-       0x1C, 0x23, 0x20, 0xE9,
-       0x57, 0x36, 0x20, 0xE9,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x90, 0xE2,
-       0x00, 0xE0,
-
-       0x7A, 0xFF, 0x20, 0xEA,
-       0x19, 0xC8, 0xC1, 0xCD,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x9F, 0x41, 0x49, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x25, 0x41, 0x49, 0xBD,
-       0x2D, 0x41, 0x51, 0xBD,
-
-       0x0D, 0x80, 0x07, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x35, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x25, 0x30,
-       0x2D, 0x30,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0xA7, 0x5B, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x79, 0xFF, 0x0A, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC9, 0x41, 0xC8, 0xEC,
-       0x42, 0xE1,
-       0x00, 0xE0,
-
-       0x77, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC8, 0x40, 0xC0, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x74, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-};
-
-static unsigned char warp_g200_tgzaf[] = {
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x98, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x81, 0x04,
-       0x89, 0x04,
-       0x01, 0x04,
-       0x09, 0x04,
-
-       0xC9, 0x41, 0xC0, 0xEC,
-       0x11, 0x04,
-       0x00, 0xE0,
-
-       0x41, 0xCC, 0x41, 0xCD,
-       0x49, 0xCC, 0x49, 0xCD,
-
-       0xD1, 0x41, 0xC0, 0xEC,
-       0x51, 0xCC, 0x51, 0xCD,
-
-       0x80, 0x04,
-       0x10, 0x04,
-       0x08, 0x04,
-       0x00, 0xE0,
-
-       0x00, 0xCC, 0xC0, 0xCD,
-       0xD1, 0x49, 0xC0, 0xEC,
-
-       0x8A, 0x1F, 0x20, 0xE9,
-       0x8B, 0x3F, 0x20, 0xE9,
-
-       0x41, 0x3C, 0x41, 0xAD,
-       0x49, 0x3C, 0x49, 0xAD,
-
-       0x10, 0xCC, 0x10, 0xCD,
-       0x08, 0xCC, 0x08, 0xCD,
-
-       0xB9, 0x41, 0x49, 0xBB,
-       0x1F, 0xF0, 0x41, 0xCD,
-
-       0x51, 0x3C, 0x51, 0xAD,
-       0x00, 0x98, 0x80, 0xE9,
-
-       0x83, 0x80, 0x07, 0xEA,
-       0x24, 0x1F, 0x20, 0xE9,
-
-       0x21, 0x45, 0x80, 0xE8,
-       0x1A, 0x4D, 0x80, 0xE8,
-
-       0x31, 0x55, 0x80, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0x41, 0x49, 0xBD,
-       0x1D, 0x41, 0x51, 0xBD,
-
-       0x2E, 0x41, 0x2A, 0xB8,
-       0x34, 0x53, 0xA0, 0xE8,
-
-       0x15, 0x30,
-       0x1D, 0x30,
-       0x58, 0xE3,
-       0x00, 0xE0,
-
-       0xB5, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x24, 0x43, 0xA0, 0xE8,
-       0x2C, 0x4B, 0xA0, 0xE8,
-
-       0x15, 0x72,
-       0x09, 0xE3,
-       0x00, 0xE0,
-       0x1D, 0x72,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0x97, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x6C, 0x64, 0xC8, 0xEC,
-       0x98, 0xE1,
-       0xB5, 0x05,
-
-       0xBD, 0x05,
-       0x2E, 0x30,
-       0x32, 0xC0, 0xA0, 0xE8,
-
-       0x33, 0xC0, 0xA0, 0xE8,
-       0x74, 0x64, 0xC8, 0xEC,
-
-       0x40, 0x3C, 0x40, 0xAD,
-       0x32, 0x6A,
-       0x2A, 0x30,
-
-       0x20, 0x73,
-       0x33, 0x6A,
-       0x00, 0xE0,
-       0x28, 0x73,
-
-       0x1C, 0x72,
-       0x83, 0xE2,
-       0x6F, 0x80, 0x15, 0xEA,
-
-       0xB8, 0x3D, 0x28, 0xDF,
-       0x30, 0x35, 0x20, 0xDF,
-
-       0x40, 0x30,
-       0x00, 0xE0,
-       0xCC, 0xE2,
-       0x64, 0x72,
-
-       0x25, 0x42, 0x52, 0xBF,
-       0x2D, 0x42, 0x4A, 0xBF,
-
-       0x30, 0x2E, 0x30, 0xDF,
-       0x38, 0x2E, 0x38, 0xDF,
-
-       0x18, 0x1D, 0x45, 0xE9,
-       0x1E, 0x15, 0x45, 0xE9,
-
-       0x2B, 0x49, 0x51, 0xBD,
-       0x00, 0xE0,
-       0x1F, 0x73,
-
-       0x38, 0x38, 0x40, 0xAF,
-       0x30, 0x30, 0x40, 0xAF,
-
-       0x24, 0x1F, 0x24, 0xDF,
-       0x1D, 0x32, 0x20, 0xE9,
-
-       0x2C, 0x1F, 0x2C, 0xDF,
-       0x1A, 0x33, 0x20, 0xE9,
-
-       0xB0, 0x10,
-       0x08, 0xE3,
-       0x40, 0x10,
-       0xB8, 0x10,
-
-       0x26, 0xF0, 0x30, 0xCD,
-       0x2F, 0xF0, 0x38, 0xCD,
-
-       0x2B, 0x80, 0x20, 0xE9,
-       0x2A, 0x80, 0x20, 0xE9,
-
-       0xA6, 0x20,
-       0x88, 0xE2,
-       0x00, 0xE0,
-       0xAF, 0x20,
-
-       0x28, 0x2A, 0x26, 0xAF,
-       0x20, 0x2A, 0xC0, 0xAF,
-
-       0x34, 0x1F, 0x34, 0xDF,
-       0x46, 0x24, 0x46, 0xDF,
-
-       0x28, 0x30, 0x80, 0xBF,
-       0x20, 0x38, 0x80, 0xBF,
-
-       0x47, 0x24, 0x47, 0xDF,
-       0x4E, 0x2C, 0x4E, 0xDF,
-
-       0x4F, 0x2C, 0x4F, 0xDF,
-       0x56, 0x34, 0x56, 0xDF,
-
-       0x28, 0x15, 0x28, 0xDF,
-       0x20, 0x1D, 0x20, 0xDF,
-
-       0x57, 0x34, 0x57, 0xDF,
-       0x00, 0xE0,
-       0x1D, 0x05,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x89, 0xE2,
-       0x2B, 0x30,
-
-       0x3F, 0xC1, 0x1D, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA0, 0x68,
-       0xBF, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x20, 0xC0, 0x20, 0xAF,
-       0x28, 0x05,
-       0x97, 0x74,
-
-       0x00, 0xE0,
-       0x2A, 0x10,
-       0x16, 0xC0, 0x20, 0xE9,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x8C, 0xE2,
-       0x95, 0x05,
-
-       0x28, 0xC1, 0x28, 0xAD,
-       0x1F, 0xC1, 0x15, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA8, 0x67,
-       0x9F, 0x6B,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x28, 0xC0, 0x28, 0xAD,
-       0x1D, 0x25,
-       0x20, 0x05,
-
-       0x28, 0x32, 0x80, 0xAD,
-       0x40, 0x2A, 0x40, 0xBD,
-
-       0x1C, 0x80, 0x20, 0xE9,
-       0x20, 0x33, 0x20, 0xAD,
-
-       0x20, 0x73,
-       0x00, 0xE0,
-       0xB6, 0x49, 0x51, 0xBB,
-
-       0x26, 0x2F, 0xB0, 0xE8,
-       0x19, 0x20, 0x20, 0xE9,
-
-       0x35, 0x20, 0x35, 0xDF,
-       0x3D, 0x20, 0x3D, 0xDF,
-
-       0x15, 0x20, 0x15, 0xDF,
-       0x1D, 0x20, 0x1D, 0xDF,
-
-       0x26, 0xD0, 0x26, 0xCD,
-       0x29, 0x49, 0x2A, 0xB8,
-
-       0x26, 0x40, 0x80, 0xBD,
-       0x3B, 0x48, 0x50, 0xBD,
-
-       0x3E, 0x54, 0x57, 0x9F,
-       0x00, 0xE0,
-       0x82, 0xE1,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x26, 0x30,
-       0x29, 0x30,
-       0x48, 0x3C, 0x48, 0xAD,
-
-       0x2B, 0x72,
-       0xC2, 0xE1,
-       0x2C, 0xC0, 0x44, 0xC2,
-
-       0x05, 0x24, 0x34, 0xBF,
-       0x0D, 0x24, 0x2C, 0xBF,
-
-       0x2D, 0x46, 0x4E, 0xBF,
-       0x25, 0x46, 0x56, 0xBF,
-
-       0x20, 0x1D, 0x6F, 0x8F,
-       0x32, 0x3E, 0x5F, 0xE9,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x30,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x33, 0x1E, 0x5F, 0xE9,
-
-       0x05, 0x44, 0x54, 0xB2,
-       0x0D, 0x44, 0x4C, 0xB2,
-
-       0x19, 0xC0, 0xB0, 0xE8,
-       0x34, 0xC0, 0x44, 0xC4,
-
-       0x33, 0x73,
-       0x00, 0xE0,
-       0x3E, 0x62, 0x57, 0x9F,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0xE0,
-       0x0D, 0x20,
-
-       0x84, 0x3E, 0x58, 0xE9,
-       0x28, 0x1D, 0x6F, 0x8F,
-
-       0x05, 0x20,
-       0x00, 0xE0,
-       0x85, 0x1E, 0x58, 0xE9,
-
-       0x9B, 0x3B, 0x33, 0xDF,
-       0x20, 0x20, 0x42, 0xAF,
-
-       0x30, 0x42, 0x56, 0x9F,
-       0x80, 0x3E, 0x57, 0xE9,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x30, 0x80, 0x5F, 0xE9,
-
-       0x28, 0x28, 0x24, 0xAF,
-       0x81, 0x1E, 0x57, 0xE9,
-
-       0x05, 0x47, 0x57, 0xBF,
-       0x0D, 0x47, 0x4F, 0xBF,
-
-       0x88, 0x80, 0x58, 0xE9,
-       0x1B, 0x29, 0x1B, 0xDF,
-
-       0x30, 0x1D, 0x6F, 0x8F,
-       0x3A, 0x30, 0x4F, 0xE9,
-
-       0x1C, 0x30, 0x26, 0xDF,
-       0x09, 0xE3,
-       0x3B, 0x05,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x3B, 0x3F, 0x4F, 0xE9,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x00, 0xE0,
-       0xAC, 0x20,
-
-       0x2D, 0x44, 0x4C, 0xB4,
-       0x2C, 0x1C, 0xC0, 0xAF,
-
-       0x25, 0x44, 0x54, 0xB4,
-       0x00, 0xE0,
-       0xC8, 0x30,
-
-       0x30, 0x46, 0x30, 0xAF,
-       0x1B, 0x1B, 0x48, 0xAF,
-
-       0x00, 0xE0,
-       0x25, 0x20,
-       0x38, 0x2C, 0x4F, 0xE9,
-
-       0x86, 0x80, 0x57, 0xE9,
-       0x38, 0x1D, 0x6F, 0x8F,
-
-       0x28, 0x74,
-       0x00, 0xE0,
-       0x0D, 0x44, 0x4C, 0xB0,
-
-       0x05, 0x44, 0x54, 0xB0,
-       0x2D, 0x20,
-       0x9B, 0x10,
-
-       0x82, 0x3E, 0x57, 0xE9,
-       0x32, 0xF0, 0x1B, 0xCD,
-
-       0x1E, 0xBD, 0x59, 0x9F,
-       0x83, 0x1E, 0x57, 0xE9,
-
-       0x38, 0x47, 0x38, 0xAF,
-       0x34, 0x20,
-       0x2A, 0x30,
-
-       0x00, 0xE0,
-       0x0D, 0x20,
-       0x32, 0x20,
-       0x05, 0x20,
-
-       0x87, 0x80, 0x57, 0xE9,
-       0x1F, 0x54, 0x57, 0x9F,
-
-       0x17, 0x42, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x6A,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x37, 0x1E, 0x4F, 0xE9,
-
-       0x37, 0x32, 0x2A, 0xAF,
-       0x00, 0xE0,
-       0x32, 0x00,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x27, 0xC0, 0x44, 0xC0,
-
-       0x36, 0x1F, 0x4F, 0xE9,
-       0x1F, 0x1F, 0x26, 0xDF,
-
-       0x37, 0x1B, 0x37, 0xBF,
-       0x17, 0x26, 0x17, 0xDF,
-
-       0x3E, 0x17, 0x4F, 0xE9,
-       0x3F, 0x3F, 0x4F, 0xE9,
-
-       0x34, 0x1F, 0x34, 0xAF,
-       0x2B, 0x05,
-       0xA7, 0x20,
-
-       0x33, 0x2B, 0x37, 0xDF,
-       0x27, 0x17, 0xC0, 0xAF,
-
-       0x34, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x0D, 0x21, 0x1A, 0xB6,
-       0x05, 0x21, 0x31, 0xB6,
-
-       0x2D, 0x44, 0x4C, 0xB6,
-       0x25, 0x44, 0x54, 0xB6,
-
-       0x03, 0x80, 0x2A, 0xEA,
-       0x17, 0xC1, 0x2B, 0xBD,
-
-       0x0D, 0x20,
-       0x05, 0x20,
-       0x2F, 0xC0, 0x21, 0xC6,
-
-       0xB3, 0x68,
-       0x97, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x33, 0xC0, 0x33, 0xAF,
-       0x3C, 0x27, 0x4F, 0xE9,
-
-       0x00, 0xE0,
-       0x25, 0x20,
-       0x07, 0xC0, 0x44, 0xC6,
-
-       0x17, 0x50, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x2D, 0x20,
-
-       0x37, 0x0F, 0x5C, 0x9F,
-       0x00, 0xE0,
-       0x2F, 0x20,
-
-       0x1F, 0x62, 0x57, 0x9F,
-       0x00, 0xE0,
-       0x07, 0x20,
-
-       0x3F, 0x3D, 0x5D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x28, 0x19, 0x60, 0xEC,
-
-       0xB3, 0x05,
-       0x00, 0xE0,
-       0x17, 0x26, 0x17, 0xDF,
-
-       0x23, 0x3B, 0x33, 0xAD,
-       0x35, 0x17, 0x4F, 0xE9,
-
-       0x1F, 0x26, 0x1F, 0xDF,
-       0x9D, 0x1F, 0x4F, 0xE9,
-
-       0x9E, 0x3F, 0x4F, 0xE9,
-       0x39, 0x37, 0x4F, 0xE9,
-
-       0x2F, 0x2F, 0x17, 0xAF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x07, 0x07, 0x1F, 0xAF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x31, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x9C, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x57, 0x39, 0x20, 0xE9,
-
-       0x16, 0x28, 0x20, 0xE9,
-       0x1D, 0x3B, 0x20, 0xE9,
-
-       0x1E, 0x2B, 0x20, 0xE9,
-       0x2B, 0x32, 0x20, 0xE9,
-
-       0x1C, 0x23, 0x20, 0xE9,
-       0x57, 0x36, 0x20, 0xE9,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x90, 0xE2,
-       0x00, 0xE0,
-
-       0x74, 0xFF, 0x20, 0xEA,
-       0x19, 0xC8, 0xC1, 0xCD,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x9F, 0x41, 0x49, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x25, 0x41, 0x49, 0xBD,
-       0x2D, 0x41, 0x51, 0xBD,
-
-       0x0D, 0x80, 0x07, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x35, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x25, 0x30,
-       0x2D, 0x30,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0xA7, 0x5B, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x73, 0xFF, 0x0A, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC9, 0x41, 0xC8, 0xEC,
-       0x42, 0xE1,
-       0x00, 0xE0,
-
-       0x71, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC8, 0x40, 0xC0, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x6E, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-};
-
-static unsigned char warp_g200_tgzf[] = {
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x98, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x81, 0x04,
-       0x89, 0x04,
-       0x01, 0x04,
-       0x09, 0x04,
-
-       0xC9, 0x41, 0xC0, 0xEC,
-       0x11, 0x04,
-       0x00, 0xE0,
-
-       0x41, 0xCC, 0x41, 0xCD,
-       0x49, 0xCC, 0x49, 0xCD,
-
-       0xD1, 0x41, 0xC0, 0xEC,
-       0x51, 0xCC, 0x51, 0xCD,
-
-       0x80, 0x04,
-       0x10, 0x04,
-       0x08, 0x04,
-       0x00, 0xE0,
-
-       0x00, 0xCC, 0xC0, 0xCD,
-       0xD1, 0x49, 0xC0, 0xEC,
-
-       0x8A, 0x1F, 0x20, 0xE9,
-       0x8B, 0x3F, 0x20, 0xE9,
-
-       0x41, 0x3C, 0x41, 0xAD,
-       0x49, 0x3C, 0x49, 0xAD,
-
-       0x10, 0xCC, 0x10, 0xCD,
-       0x08, 0xCC, 0x08, 0xCD,
-
-       0xB9, 0x41, 0x49, 0xBB,
-       0x1F, 0xF0, 0x41, 0xCD,
-
-       0x51, 0x3C, 0x51, 0xAD,
-       0x00, 0x98, 0x80, 0xE9,
-
-       0x7F, 0x80, 0x07, 0xEA,
-       0x24, 0x1F, 0x20, 0xE9,
-
-       0x21, 0x45, 0x80, 0xE8,
-       0x1A, 0x4D, 0x80, 0xE8,
-
-       0x31, 0x55, 0x80, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0x41, 0x49, 0xBD,
-       0x1D, 0x41, 0x51, 0xBD,
-
-       0x2E, 0x41, 0x2A, 0xB8,
-       0x34, 0x53, 0xA0, 0xE8,
-
-       0x15, 0x30,
-       0x1D, 0x30,
-       0x58, 0xE3,
-       0x00, 0xE0,
-
-       0xB5, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x24, 0x43, 0xA0, 0xE8,
-       0x2C, 0x4B, 0xA0, 0xE8,
-
-       0x15, 0x72,
-       0x09, 0xE3,
-       0x00, 0xE0,
-       0x1D, 0x72,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0x97, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x6C, 0x64, 0xC8, 0xEC,
-       0x98, 0xE1,
-       0xB5, 0x05,
-
-       0xBD, 0x05,
-       0x2E, 0x30,
-       0x32, 0xC0, 0xA0, 0xE8,
-
-       0x33, 0xC0, 0xA0, 0xE8,
-       0x74, 0x64, 0xC8, 0xEC,
-
-       0x40, 0x3C, 0x40, 0xAD,
-       0x32, 0x6A,
-       0x2A, 0x30,
-
-       0x20, 0x73,
-       0x33, 0x6A,
-       0x00, 0xE0,
-       0x28, 0x73,
-
-       0x1C, 0x72,
-       0x83, 0xE2,
-       0x6B, 0x80, 0x15, 0xEA,
-
-       0xB8, 0x3D, 0x28, 0xDF,
-       0x30, 0x35, 0x20, 0xDF,
-
-       0x40, 0x30,
-       0x00, 0xE0,
-       0xCC, 0xE2,
-       0x64, 0x72,
-
-       0x25, 0x42, 0x52, 0xBF,
-       0x2D, 0x42, 0x4A, 0xBF,
-
-       0x30, 0x2E, 0x30, 0xDF,
-       0x38, 0x2E, 0x38, 0xDF,
-
-       0x18, 0x1D, 0x45, 0xE9,
-       0x1E, 0x15, 0x45, 0xE9,
-
-       0x2B, 0x49, 0x51, 0xBD,
-       0x00, 0xE0,
-       0x1F, 0x73,
-
-       0x38, 0x38, 0x40, 0xAF,
-       0x30, 0x30, 0x40, 0xAF,
-
-       0x24, 0x1F, 0x24, 0xDF,
-       0x1D, 0x32, 0x20, 0xE9,
-
-       0x2C, 0x1F, 0x2C, 0xDF,
-       0x1A, 0x33, 0x20, 0xE9,
-
-       0xB0, 0x10,
-       0x08, 0xE3,
-       0x40, 0x10,
-       0xB8, 0x10,
-
-       0x26, 0xF0, 0x30, 0xCD,
-       0x2F, 0xF0, 0x38, 0xCD,
-
-       0x2B, 0x80, 0x20, 0xE9,
-       0x2A, 0x80, 0x20, 0xE9,
-
-       0xA6, 0x20,
-       0x88, 0xE2,
-       0x00, 0xE0,
-       0xAF, 0x20,
-
-       0x28, 0x2A, 0x26, 0xAF,
-       0x20, 0x2A, 0xC0, 0xAF,
-
-       0x34, 0x1F, 0x34, 0xDF,
-       0x46, 0x24, 0x46, 0xDF,
-
-       0x28, 0x30, 0x80, 0xBF,
-       0x20, 0x38, 0x80, 0xBF,
-
-       0x47, 0x24, 0x47, 0xDF,
-       0x4E, 0x2C, 0x4E, 0xDF,
-
-       0x4F, 0x2C, 0x4F, 0xDF,
-       0x56, 0x34, 0x56, 0xDF,
-
-       0x28, 0x15, 0x28, 0xDF,
-       0x20, 0x1D, 0x20, 0xDF,
-
-       0x57, 0x34, 0x57, 0xDF,
-       0x00, 0xE0,
-       0x1D, 0x05,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x89, 0xE2,
-       0x2B, 0x30,
-
-       0x3F, 0xC1, 0x1D, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA0, 0x68,
-       0xBF, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x20, 0xC0, 0x20, 0xAF,
-       0x28, 0x05,
-       0x97, 0x74,
-
-       0x00, 0xE0,
-       0x2A, 0x10,
-       0x16, 0xC0, 0x20, 0xE9,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x8C, 0xE2,
-       0x95, 0x05,
-
-       0x28, 0xC1, 0x28, 0xAD,
-       0x1F, 0xC1, 0x15, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA8, 0x67,
-       0x9F, 0x6B,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x28, 0xC0, 0x28, 0xAD,
-       0x1D, 0x25,
-       0x20, 0x05,
-
-       0x28, 0x32, 0x80, 0xAD,
-       0x40, 0x2A, 0x40, 0xBD,
-
-       0x1C, 0x80, 0x20, 0xE9,
-       0x20, 0x33, 0x20, 0xAD,
-
-       0x20, 0x73,
-       0x00, 0xE0,
-       0xB6, 0x49, 0x51, 0xBB,
-
-       0x26, 0x2F, 0xB0, 0xE8,
-       0x19, 0x20, 0x20, 0xE9,
-
-       0x35, 0x20, 0x35, 0xDF,
-       0x3D, 0x20, 0x3D, 0xDF,
-
-       0x15, 0x20, 0x15, 0xDF,
-       0x1D, 0x20, 0x1D, 0xDF,
-
-       0x26, 0xD0, 0x26, 0xCD,
-       0x29, 0x49, 0x2A, 0xB8,
-
-       0x26, 0x40, 0x80, 0xBD,
-       0x3B, 0x48, 0x50, 0xBD,
-
-       0x3E, 0x54, 0x57, 0x9F,
-       0x00, 0xE0,
-       0x82, 0xE1,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x26, 0x30,
-       0x29, 0x30,
-       0x48, 0x3C, 0x48, 0xAD,
-
-       0x2B, 0x72,
-       0xC2, 0xE1,
-       0x2C, 0xC0, 0x44, 0xC2,
-
-       0x05, 0x24, 0x34, 0xBF,
-       0x0D, 0x24, 0x2C, 0xBF,
-
-       0x2D, 0x46, 0x4E, 0xBF,
-       0x25, 0x46, 0x56, 0xBF,
-
-       0x20, 0x1D, 0x6F, 0x8F,
-       0x32, 0x3E, 0x5F, 0xE9,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x30,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x33, 0x1E, 0x5F, 0xE9,
-
-       0x05, 0x44, 0x54, 0xB2,
-       0x0D, 0x44, 0x4C, 0xB2,
-
-       0x19, 0xC0, 0xB0, 0xE8,
-       0x34, 0xC0, 0x44, 0xC4,
-
-       0x33, 0x73,
-       0x00, 0xE0,
-       0x3E, 0x62, 0x57, 0x9F,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0xE0,
-       0x0D, 0x20,
-
-       0x84, 0x3E, 0x58, 0xE9,
-       0x28, 0x1D, 0x6F, 0x8F,
-
-       0x05, 0x20,
-       0x00, 0xE0,
-       0x85, 0x1E, 0x58, 0xE9,
-
-       0x9B, 0x3B, 0x33, 0xDF,
-       0x20, 0x20, 0x42, 0xAF,
-
-       0x30, 0x42, 0x56, 0x9F,
-       0x80, 0x3E, 0x57, 0xE9,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x30, 0x80, 0x5F, 0xE9,
-
-       0x28, 0x28, 0x24, 0xAF,
-       0x81, 0x1E, 0x57, 0xE9,
-
-       0x05, 0x47, 0x57, 0xBF,
-       0x0D, 0x47, 0x4F, 0xBF,
-
-       0x88, 0x80, 0x58, 0xE9,
-       0x1B, 0x29, 0x1B, 0xDF,
-
-       0x30, 0x1D, 0x6F, 0x8F,
-       0x3A, 0x30, 0x4F, 0xE9,
-
-       0x1C, 0x30, 0x26, 0xDF,
-       0x09, 0xE3,
-       0x3B, 0x05,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x3B, 0x3F, 0x4F, 0xE9,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x00, 0xE0,
-       0xAC, 0x20,
-
-       0x2D, 0x44, 0x4C, 0xB4,
-       0x2C, 0x1C, 0xC0, 0xAF,
-
-       0x25, 0x44, 0x54, 0xB4,
-       0x00, 0xE0,
-       0xC8, 0x30,
-
-       0x30, 0x46, 0x30, 0xAF,
-       0x1B, 0x1B, 0x48, 0xAF,
-
-       0x00, 0xE0,
-       0x25, 0x20,
-       0x38, 0x2C, 0x4F, 0xE9,
-
-       0x86, 0x80, 0x57, 0xE9,
-       0x38, 0x1D, 0x6F, 0x8F,
-
-       0x28, 0x74,
-       0x00, 0xE0,
-       0x0D, 0x44, 0x4C, 0xB0,
-
-       0x05, 0x44, 0x54, 0xB0,
-       0x2D, 0x20,
-       0x9B, 0x10,
-
-       0x82, 0x3E, 0x57, 0xE9,
-       0x32, 0xF0, 0x1B, 0xCD,
-
-       0x1E, 0xBD, 0x59, 0x9F,
-       0x83, 0x1E, 0x57, 0xE9,
-
-       0x38, 0x47, 0x38, 0xAF,
-       0x34, 0x20,
-       0x2A, 0x30,
-
-       0x00, 0xE0,
-       0x0D, 0x20,
-       0x32, 0x20,
-       0x05, 0x20,
-
-       0x87, 0x80, 0x57, 0xE9,
-       0x1F, 0x54, 0x57, 0x9F,
-
-       0x17, 0x42, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x6A,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x37, 0x1E, 0x4F, 0xE9,
-
-       0x37, 0x32, 0x2A, 0xAF,
-       0x00, 0xE0,
-       0x32, 0x00,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x27, 0xC0, 0x44, 0xC0,
-
-       0x36, 0x1F, 0x4F, 0xE9,
-       0x1F, 0x1F, 0x26, 0xDF,
-
-       0x37, 0x1B, 0x37, 0xBF,
-       0x17, 0x26, 0x17, 0xDF,
-
-       0x3E, 0x17, 0x4F, 0xE9,
-       0x3F, 0x3F, 0x4F, 0xE9,
-
-       0x34, 0x1F, 0x34, 0xAF,
-       0x2B, 0x05,
-       0xA7, 0x20,
-
-       0x33, 0x2B, 0x37, 0xDF,
-       0x27, 0x17, 0xC0, 0xAF,
-
-       0x34, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x0D, 0x21, 0x1A, 0xB6,
-       0x05, 0x21, 0x31, 0xB6,
-
-       0x03, 0x80, 0x2A, 0xEA,
-       0x17, 0xC1, 0x2B, 0xBD,
-
-       0x0D, 0x20,
-       0x05, 0x20,
-       0x2F, 0xC0, 0x21, 0xC6,
-
-       0xB3, 0x68,
-       0x97, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x33, 0xC0, 0x33, 0xAF,
-       0x3C, 0x27, 0x4F, 0xE9,
-
-       0x17, 0x50, 0x56, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x37, 0x0F, 0x5C, 0x9F,
-       0x00, 0xE0,
-       0x2F, 0x20,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x28, 0x19, 0x60, 0xEC,
-
-       0xB3, 0x05,
-       0x00, 0xE0,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x23, 0x3B, 0x33, 0xAD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x17, 0x26, 0x17, 0xDF,
-       0x35, 0x17, 0x4F, 0xE9,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x39, 0x37, 0x4F, 0xE9,
-
-       0x2F, 0x2F, 0x17, 0xAF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x31, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x57, 0x39, 0x20, 0xE9,
-
-       0x16, 0x28, 0x20, 0xE9,
-       0x1D, 0x3B, 0x20, 0xE9,
-
-       0x1E, 0x2B, 0x20, 0xE9,
-       0x2B, 0x32, 0x20, 0xE9,
-
-       0x1C, 0x23, 0x20, 0xE9,
-       0x57, 0x36, 0x20, 0xE9,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x90, 0xE2,
-       0x00, 0xE0,
-
-       0x78, 0xFF, 0x20, 0xEA,
-       0x19, 0xC8, 0xC1, 0xCD,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x9F, 0x41, 0x49, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x25, 0x41, 0x49, 0xBD,
-       0x2D, 0x41, 0x51, 0xBD,
-
-       0x0D, 0x80, 0x07, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x35, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x25, 0x30,
-       0x2D, 0x30,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0xA7, 0x5B, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x77, 0xFF, 0x0A, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC9, 0x41, 0xC8, 0xEC,
-       0x42, 0xE1,
-       0x00, 0xE0,
-
-       0x75, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC8, 0x40, 0xC0, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x72, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-};
-
-static unsigned char warp_g200_tgzs[] = {
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x98, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x81, 0x04,
-       0x89, 0x04,
-       0x01, 0x04,
-       0x09, 0x04,
-
-       0xC9, 0x41, 0xC0, 0xEC,
-       0x11, 0x04,
-       0x00, 0xE0,
-
-       0x41, 0xCC, 0x41, 0xCD,
-       0x49, 0xCC, 0x49, 0xCD,
-
-       0xD1, 0x41, 0xC0, 0xEC,
-       0x51, 0xCC, 0x51, 0xCD,
-
-       0x80, 0x04,
-       0x10, 0x04,
-       0x08, 0x04,
-       0x00, 0xE0,
-
-       0x00, 0xCC, 0xC0, 0xCD,
-       0xD1, 0x49, 0xC0, 0xEC,
-
-       0x8A, 0x1F, 0x20, 0xE9,
-       0x8B, 0x3F, 0x20, 0xE9,
-
-       0x41, 0x3C, 0x41, 0xAD,
-       0x49, 0x3C, 0x49, 0xAD,
-
-       0x10, 0xCC, 0x10, 0xCD,
-       0x08, 0xCC, 0x08, 0xCD,
-
-       0xB9, 0x41, 0x49, 0xBB,
-       0x1F, 0xF0, 0x41, 0xCD,
-
-       0x51, 0x3C, 0x51, 0xAD,
-       0x00, 0x98, 0x80, 0xE9,
-
-       0x8B, 0x80, 0x07, 0xEA,
-       0x24, 0x1F, 0x20, 0xE9,
-
-       0x21, 0x45, 0x80, 0xE8,
-       0x1A, 0x4D, 0x80, 0xE8,
-
-       0x31, 0x55, 0x80, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0x41, 0x49, 0xBD,
-       0x1D, 0x41, 0x51, 0xBD,
-
-       0x2E, 0x41, 0x2A, 0xB8,
-       0x34, 0x53, 0xA0, 0xE8,
-
-       0x15, 0x30,
-       0x1D, 0x30,
-       0x58, 0xE3,
-       0x00, 0xE0,
-
-       0xB5, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x24, 0x43, 0xA0, 0xE8,
-       0x2C, 0x4B, 0xA0, 0xE8,
-
-       0x15, 0x72,
-       0x09, 0xE3,
-       0x00, 0xE0,
-       0x1D, 0x72,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0x97, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x6C, 0x64, 0xC8, 0xEC,
-       0x98, 0xE1,
-       0xB5, 0x05,
-
-       0xBD, 0x05,
-       0x2E, 0x30,
-       0x32, 0xC0, 0xA0, 0xE8,
-
-       0x33, 0xC0, 0xA0, 0xE8,
-       0x74, 0x64, 0xC8, 0xEC,
-
-       0x40, 0x3C, 0x40, 0xAD,
-       0x32, 0x6A,
-       0x2A, 0x30,
-
-       0x20, 0x73,
-       0x33, 0x6A,
-       0x00, 0xE0,
-       0x28, 0x73,
-
-       0x1C, 0x72,
-       0x83, 0xE2,
-       0x77, 0x80, 0x15, 0xEA,
-
-       0xB8, 0x3D, 0x28, 0xDF,
-       0x30, 0x35, 0x20, 0xDF,
-
-       0x40, 0x30,
-       0x00, 0xE0,
-       0xCC, 0xE2,
-       0x64, 0x72,
-
-       0x25, 0x42, 0x52, 0xBF,
-       0x2D, 0x42, 0x4A, 0xBF,
-
-       0x30, 0x2E, 0x30, 0xDF,
-       0x38, 0x2E, 0x38, 0xDF,
-
-       0x18, 0x1D, 0x45, 0xE9,
-       0x1E, 0x15, 0x45, 0xE9,
-
-       0x2B, 0x49, 0x51, 0xBD,
-       0x00, 0xE0,
-       0x1F, 0x73,
-
-       0x38, 0x38, 0x40, 0xAF,
-       0x30, 0x30, 0x40, 0xAF,
-
-       0x24, 0x1F, 0x24, 0xDF,
-       0x1D, 0x32, 0x20, 0xE9,
-
-       0x2C, 0x1F, 0x2C, 0xDF,
-       0x1A, 0x33, 0x20, 0xE9,
-
-       0xB0, 0x10,
-       0x08, 0xE3,
-       0x40, 0x10,
-       0xB8, 0x10,
-
-       0x26, 0xF0, 0x30, 0xCD,
-       0x2F, 0xF0, 0x38, 0xCD,
-
-       0x2B, 0x80, 0x20, 0xE9,
-       0x2A, 0x80, 0x20, 0xE9,
-
-       0xA6, 0x20,
-       0x88, 0xE2,
-       0x00, 0xE0,
-       0xAF, 0x20,
-
-       0x28, 0x2A, 0x26, 0xAF,
-       0x20, 0x2A, 0xC0, 0xAF,
-
-       0x34, 0x1F, 0x34, 0xDF,
-       0x46, 0x24, 0x46, 0xDF,
-
-       0x28, 0x30, 0x80, 0xBF,
-       0x20, 0x38, 0x80, 0xBF,
-
-       0x47, 0x24, 0x47, 0xDF,
-       0x4E, 0x2C, 0x4E, 0xDF,
-
-       0x4F, 0x2C, 0x4F, 0xDF,
-       0x56, 0x34, 0x56, 0xDF,
-
-       0x28, 0x15, 0x28, 0xDF,
-       0x20, 0x1D, 0x20, 0xDF,
-
-       0x57, 0x34, 0x57, 0xDF,
-       0x00, 0xE0,
-       0x1D, 0x05,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x89, 0xE2,
-       0x2B, 0x30,
-
-       0x3F, 0xC1, 0x1D, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA0, 0x68,
-       0xBF, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x20, 0xC0, 0x20, 0xAF,
-       0x28, 0x05,
-       0x97, 0x74,
-
-       0x00, 0xE0,
-       0x2A, 0x10,
-       0x16, 0xC0, 0x20, 0xE9,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x8C, 0xE2,
-       0x95, 0x05,
-
-       0x28, 0xC1, 0x28, 0xAD,
-       0x1F, 0xC1, 0x15, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA8, 0x67,
-       0x9F, 0x6B,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x28, 0xC0, 0x28, 0xAD,
-       0x1D, 0x25,
-       0x20, 0x05,
-
-       0x28, 0x32, 0x80, 0xAD,
-       0x40, 0x2A, 0x40, 0xBD,
-
-       0x1C, 0x80, 0x20, 0xE9,
-       0x20, 0x33, 0x20, 0xAD,
-
-       0x20, 0x73,
-       0x00, 0xE0,
-       0xB6, 0x49, 0x51, 0xBB,
-
-       0x26, 0x2F, 0xB0, 0xE8,
-       0x19, 0x20, 0x20, 0xE9,
-
-       0x35, 0x20, 0x35, 0xDF,
-       0x3D, 0x20, 0x3D, 0xDF,
-
-       0x15, 0x20, 0x15, 0xDF,
-       0x1D, 0x20, 0x1D, 0xDF,
-
-       0x26, 0xD0, 0x26, 0xCD,
-       0x29, 0x49, 0x2A, 0xB8,
-
-       0x26, 0x40, 0x80, 0xBD,
-       0x3B, 0x48, 0x50, 0xBD,
-
-       0x3E, 0x54, 0x57, 0x9F,
-       0x00, 0xE0,
-       0x82, 0xE1,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x26, 0x30,
-       0x29, 0x30,
-       0x48, 0x3C, 0x48, 0xAD,
-
-       0x2B, 0x72,
-       0xC2, 0xE1,
-       0x2C, 0xC0, 0x44, 0xC2,
-
-       0x05, 0x24, 0x34, 0xBF,
-       0x0D, 0x24, 0x2C, 0xBF,
-
-       0x2D, 0x46, 0x4E, 0xBF,
-       0x25, 0x46, 0x56, 0xBF,
-
-       0x20, 0x1D, 0x6F, 0x8F,
-       0x32, 0x3E, 0x5F, 0xE9,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x30,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x33, 0x1E, 0x5F, 0xE9,
-
-       0x05, 0x44, 0x54, 0xB2,
-       0x0D, 0x44, 0x4C, 0xB2,
-
-       0x19, 0xC0, 0xB0, 0xE8,
-       0x34, 0xC0, 0x44, 0xC4,
-
-       0x33, 0x73,
-       0x00, 0xE0,
-       0x3E, 0x62, 0x57, 0x9F,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0xE0,
-       0x0D, 0x20,
-
-       0x84, 0x3E, 0x58, 0xE9,
-       0x28, 0x1D, 0x6F, 0x8F,
-
-       0x05, 0x20,
-       0x00, 0xE0,
-       0x85, 0x1E, 0x58, 0xE9,
-
-       0x9B, 0x3B, 0x33, 0xDF,
-       0x20, 0x20, 0x42, 0xAF,
-
-       0x30, 0x42, 0x56, 0x9F,
-       0x80, 0x3E, 0x57, 0xE9,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x30, 0x80, 0x5F, 0xE9,
-
-       0x28, 0x28, 0x24, 0xAF,
-       0x81, 0x1E, 0x57, 0xE9,
-
-       0x05, 0x47, 0x57, 0xBF,
-       0x0D, 0x47, 0x4F, 0xBF,
-
-       0x88, 0x80, 0x58, 0xE9,
-       0x1B, 0x29, 0x1B, 0xDF,
-
-       0x30, 0x1D, 0x6F, 0x8F,
-       0x3A, 0x30, 0x4F, 0xE9,
-
-       0x1C, 0x30, 0x26, 0xDF,
-       0x09, 0xE3,
-       0x3B, 0x05,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x3B, 0x3F, 0x4F, 0xE9,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x00, 0xE0,
-       0xAC, 0x20,
-
-       0x2D, 0x44, 0x4C, 0xB4,
-       0x2C, 0x1C, 0xC0, 0xAF,
-
-       0x25, 0x44, 0x54, 0xB4,
-       0x00, 0xE0,
-       0xC8, 0x30,
-
-       0x30, 0x46, 0x30, 0xAF,
-       0x1B, 0x1B, 0x48, 0xAF,
-
-       0x00, 0xE0,
-       0x25, 0x20,
-       0x38, 0x2C, 0x4F, 0xE9,
-
-       0x86, 0x80, 0x57, 0xE9,
-       0x38, 0x1D, 0x6F, 0x8F,
-
-       0x28, 0x74,
-       0x00, 0xE0,
-       0x0D, 0x44, 0x4C, 0xB0,
-
-       0x05, 0x44, 0x54, 0xB0,
-       0x2D, 0x20,
-       0x9B, 0x10,
-
-       0x82, 0x3E, 0x57, 0xE9,
-       0x32, 0xF0, 0x1B, 0xCD,
-
-       0x1E, 0xBD, 0x59, 0x9F,
-       0x83, 0x1E, 0x57, 0xE9,
-
-       0x38, 0x47, 0x38, 0xAF,
-       0x34, 0x20,
-       0x2A, 0x30,
-
-       0x00, 0xE0,
-       0x0D, 0x20,
-       0x32, 0x20,
-       0x05, 0x20,
-
-       0x87, 0x80, 0x57, 0xE9,
-       0x1F, 0x54, 0x57, 0x9F,
-
-       0x17, 0x42, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x6A,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x37, 0x1E, 0x4F, 0xE9,
-
-       0x37, 0x32, 0x2A, 0xAF,
-       0x00, 0xE0,
-       0x32, 0x00,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x27, 0xC0, 0x44, 0xC0,
-
-       0x36, 0x1F, 0x4F, 0xE9,
-       0x1F, 0x1F, 0x26, 0xDF,
-
-       0x37, 0x1B, 0x37, 0xBF,
-       0x17, 0x26, 0x17, 0xDF,
-
-       0x3E, 0x17, 0x4F, 0xE9,
-       0x3F, 0x3F, 0x4F, 0xE9,
-
-       0x34, 0x1F, 0x34, 0xAF,
-       0x2B, 0x05,
-       0xA7, 0x20,
-
-       0x33, 0x2B, 0x37, 0xDF,
-       0x27, 0x17, 0xC0, 0xAF,
-
-       0x34, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x2D, 0x21, 0x1A, 0xB0,
-       0x25, 0x21, 0x31, 0xB0,
-
-       0x0D, 0x21, 0x1A, 0xB2,
-       0x05, 0x21, 0x31, 0xB2,
-
-       0x03, 0x80, 0x2A, 0xEA,
-       0x17, 0xC1, 0x2B, 0xBD,
-
-       0x2D, 0x20,
-       0x25, 0x20,
-       0x05, 0x20,
-       0x0D, 0x20,
-
-       0xB3, 0x68,
-       0x97, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x33, 0xC0, 0x33, 0xAF,
-       0x2F, 0xC0, 0x21, 0xC0,
-
-       0x16, 0x42, 0x56, 0x9F,
-       0x3C, 0x27, 0x4F, 0xE9,
-
-       0x1E, 0x62, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x25, 0x21, 0x31, 0xB4,
-       0x2D, 0x21, 0x1A, 0xB4,
-
-       0x3F, 0x2F, 0x5D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x33, 0x05,
-       0x00, 0xE0,
-       0x28, 0x19, 0x60, 0xEC,
-
-       0x37, 0x0F, 0x5C, 0x9F,
-       0x00, 0xE0,
-       0x2F, 0x20,
-
-       0x23, 0x3B, 0x33, 0xAD,
-       0x1E, 0x26, 0x1E, 0xDF,
-
-       0xA7, 0x1E, 0x4F, 0xE9,
-       0x17, 0x26, 0x16, 0xDF,
-
-       0x2D, 0x20,
-       0x00, 0xE0,
-       0xA8, 0x3F, 0x4F, 0xE9,
-
-       0x2F, 0x2F, 0x1E, 0xAF,
-       0x25, 0x20,
-       0x00, 0xE0,
-
-       0xA4, 0x16, 0x4F, 0xE9,
-       0x0F, 0xC0, 0x21, 0xC2,
-
-       0xA6, 0x80, 0x4F, 0xE9,
-       0x1F, 0x62, 0x57, 0x9F,
-
-       0x3F, 0x2F, 0x5D, 0x9F,
-       0x00, 0xE0,
-       0x8F, 0x20,
-
-       0xA5, 0x37, 0x4F, 0xE9,
-       0x0F, 0x17, 0x0F, 0xAF,
-
-       0x06, 0xC0, 0x21, 0xC4,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0xA3, 0x80, 0x4F, 0xE9,
-
-       0x06, 0x20,
-       0x00, 0xE0,
-       0x1F, 0x26, 0x1F, 0xDF,
-
-       0xA1, 0x1F, 0x4F, 0xE9,
-       0xA2, 0x3F, 0x4F, 0xE9,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x06, 0x06, 0x1F, 0xAF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA0, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x57, 0x39, 0x20, 0xE9,
-
-       0x16, 0x28, 0x20, 0xE9,
-       0x1D, 0x3B, 0x20, 0xE9,
-
-       0x1E, 0x2B, 0x20, 0xE9,
-       0x2B, 0x32, 0x20, 0xE9,
-
-       0x1C, 0x23, 0x20, 0xE9,
-       0x57, 0x36, 0x20, 0xE9,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x90, 0xE2,
-       0x00, 0xE0,
-
-       0x6C, 0xFF, 0x20, 0xEA,
-       0x19, 0xC8, 0xC1, 0xCD,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x9F, 0x41, 0x49, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x25, 0x41, 0x49, 0xBD,
-       0x2D, 0x41, 0x51, 0xBD,
-
-       0x0D, 0x80, 0x07, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x35, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x25, 0x30,
-       0x2D, 0x30,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0xA7, 0x5B, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x6B, 0xFF, 0x0A, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC9, 0x41, 0xC8, 0xEC,
-       0x42, 0xE1,
-       0x00, 0xE0,
-
-       0x69, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC8, 0x40, 0xC0, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x66, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-};
-
-static unsigned char warp_g200_tgzsa[] = {
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x98, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x81, 0x04,
-       0x89, 0x04,
-       0x01, 0x04,
-       0x09, 0x04,
-
-       0xC9, 0x41, 0xC0, 0xEC,
-       0x11, 0x04,
-       0x00, 0xE0,
-
-       0x41, 0xCC, 0x41, 0xCD,
-       0x49, 0xCC, 0x49, 0xCD,
-
-       0xD1, 0x41, 0xC0, 0xEC,
-       0x51, 0xCC, 0x51, 0xCD,
-
-       0x80, 0x04,
-       0x10, 0x04,
-       0x08, 0x04,
-       0x00, 0xE0,
-
-       0x00, 0xCC, 0xC0, 0xCD,
-       0xD1, 0x49, 0xC0, 0xEC,
-
-       0x8A, 0x1F, 0x20, 0xE9,
-       0x8B, 0x3F, 0x20, 0xE9,
-
-       0x41, 0x3C, 0x41, 0xAD,
-       0x49, 0x3C, 0x49, 0xAD,
-
-       0x10, 0xCC, 0x10, 0xCD,
-       0x08, 0xCC, 0x08, 0xCD,
-
-       0xB9, 0x41, 0x49, 0xBB,
-       0x1F, 0xF0, 0x41, 0xCD,
-
-       0x51, 0x3C, 0x51, 0xAD,
-       0x00, 0x98, 0x80, 0xE9,
-
-       0x8F, 0x80, 0x07, 0xEA,
-       0x24, 0x1F, 0x20, 0xE9,
-
-       0x21, 0x45, 0x80, 0xE8,
-       0x1A, 0x4D, 0x80, 0xE8,
-
-       0x31, 0x55, 0x80, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0x41, 0x49, 0xBD,
-       0x1D, 0x41, 0x51, 0xBD,
-
-       0x2E, 0x41, 0x2A, 0xB8,
-       0x34, 0x53, 0xA0, 0xE8,
-
-       0x15, 0x30,
-       0x1D, 0x30,
-       0x58, 0xE3,
-       0x00, 0xE0,
-
-       0xB5, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x24, 0x43, 0xA0, 0xE8,
-       0x2C, 0x4B, 0xA0, 0xE8,
-
-       0x15, 0x72,
-       0x09, 0xE3,
-       0x00, 0xE0,
-       0x1D, 0x72,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0x97, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x6C, 0x64, 0xC8, 0xEC,
-       0x98, 0xE1,
-       0xB5, 0x05,
-
-       0xBD, 0x05,
-       0x2E, 0x30,
-       0x32, 0xC0, 0xA0, 0xE8,
-
-       0x33, 0xC0, 0xA0, 0xE8,
-       0x74, 0x64, 0xC8, 0xEC,
-
-       0x40, 0x3C, 0x40, 0xAD,
-       0x32, 0x6A,
-       0x2A, 0x30,
-
-       0x20, 0x73,
-       0x33, 0x6A,
-       0x00, 0xE0,
-       0x28, 0x73,
-
-       0x1C, 0x72,
-       0x83, 0xE2,
-       0x7B, 0x80, 0x15, 0xEA,
-
-       0xB8, 0x3D, 0x28, 0xDF,
-       0x30, 0x35, 0x20, 0xDF,
-
-       0x40, 0x30,
-       0x00, 0xE0,
-       0xCC, 0xE2,
-       0x64, 0x72,
-
-       0x25, 0x42, 0x52, 0xBF,
-       0x2D, 0x42, 0x4A, 0xBF,
-
-       0x30, 0x2E, 0x30, 0xDF,
-       0x38, 0x2E, 0x38, 0xDF,
-
-       0x18, 0x1D, 0x45, 0xE9,
-       0x1E, 0x15, 0x45, 0xE9,
-
-       0x2B, 0x49, 0x51, 0xBD,
-       0x00, 0xE0,
-       0x1F, 0x73,
-
-       0x38, 0x38, 0x40, 0xAF,
-       0x30, 0x30, 0x40, 0xAF,
-
-       0x24, 0x1F, 0x24, 0xDF,
-       0x1D, 0x32, 0x20, 0xE9,
-
-       0x2C, 0x1F, 0x2C, 0xDF,
-       0x1A, 0x33, 0x20, 0xE9,
-
-       0xB0, 0x10,
-       0x08, 0xE3,
-       0x40, 0x10,
-       0xB8, 0x10,
-
-       0x26, 0xF0, 0x30, 0xCD,
-       0x2F, 0xF0, 0x38, 0xCD,
-
-       0x2B, 0x80, 0x20, 0xE9,
-       0x2A, 0x80, 0x20, 0xE9,
-
-       0xA6, 0x20,
-       0x88, 0xE2,
-       0x00, 0xE0,
-       0xAF, 0x20,
-
-       0x28, 0x2A, 0x26, 0xAF,
-       0x20, 0x2A, 0xC0, 0xAF,
-
-       0x34, 0x1F, 0x34, 0xDF,
-       0x46, 0x24, 0x46, 0xDF,
-
-       0x28, 0x30, 0x80, 0xBF,
-       0x20, 0x38, 0x80, 0xBF,
-
-       0x47, 0x24, 0x47, 0xDF,
-       0x4E, 0x2C, 0x4E, 0xDF,
-
-       0x4F, 0x2C, 0x4F, 0xDF,
-       0x56, 0x34, 0x56, 0xDF,
-
-       0x28, 0x15, 0x28, 0xDF,
-       0x20, 0x1D, 0x20, 0xDF,
-
-       0x57, 0x34, 0x57, 0xDF,
-       0x00, 0xE0,
-       0x1D, 0x05,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x89, 0xE2,
-       0x2B, 0x30,
-
-       0x3F, 0xC1, 0x1D, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA0, 0x68,
-       0xBF, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x20, 0xC0, 0x20, 0xAF,
-       0x28, 0x05,
-       0x97, 0x74,
-
-       0x00, 0xE0,
-       0x2A, 0x10,
-       0x16, 0xC0, 0x20, 0xE9,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x8C, 0xE2,
-       0x95, 0x05,
-
-       0x28, 0xC1, 0x28, 0xAD,
-       0x1F, 0xC1, 0x15, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA8, 0x67,
-       0x9F, 0x6B,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x28, 0xC0, 0x28, 0xAD,
-       0x1D, 0x25,
-       0x20, 0x05,
-
-       0x28, 0x32, 0x80, 0xAD,
-       0x40, 0x2A, 0x40, 0xBD,
-
-       0x1C, 0x80, 0x20, 0xE9,
-       0x20, 0x33, 0x20, 0xAD,
-
-       0x20, 0x73,
-       0x00, 0xE0,
-       0xB6, 0x49, 0x51, 0xBB,
-
-       0x26, 0x2F, 0xB0, 0xE8,
-       0x19, 0x20, 0x20, 0xE9,
-
-       0x35, 0x20, 0x35, 0xDF,
-       0x3D, 0x20, 0x3D, 0xDF,
-
-       0x15, 0x20, 0x15, 0xDF,
-       0x1D, 0x20, 0x1D, 0xDF,
-
-       0x26, 0xD0, 0x26, 0xCD,
-       0x29, 0x49, 0x2A, 0xB8,
-
-       0x26, 0x40, 0x80, 0xBD,
-       0x3B, 0x48, 0x50, 0xBD,
-
-       0x3E, 0x54, 0x57, 0x9F,
-       0x00, 0xE0,
-       0x82, 0xE1,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x26, 0x30,
-       0x29, 0x30,
-       0x48, 0x3C, 0x48, 0xAD,
-
-       0x2B, 0x72,
-       0xC2, 0xE1,
-       0x2C, 0xC0, 0x44, 0xC2,
-
-       0x05, 0x24, 0x34, 0xBF,
-       0x0D, 0x24, 0x2C, 0xBF,
-
-       0x2D, 0x46, 0x4E, 0xBF,
-       0x25, 0x46, 0x56, 0xBF,
-
-       0x20, 0x1D, 0x6F, 0x8F,
-       0x32, 0x3E, 0x5F, 0xE9,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x30,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x33, 0x1E, 0x5F, 0xE9,
-
-       0x05, 0x44, 0x54, 0xB2,
-       0x0D, 0x44, 0x4C, 0xB2,
-
-       0x19, 0xC0, 0xB0, 0xE8,
-       0x34, 0xC0, 0x44, 0xC4,
-
-       0x33, 0x73,
-       0x00, 0xE0,
-       0x3E, 0x62, 0x57, 0x9F,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0xE0,
-       0x0D, 0x20,
-
-       0x84, 0x3E, 0x58, 0xE9,
-       0x28, 0x1D, 0x6F, 0x8F,
-
-       0x05, 0x20,
-       0x00, 0xE0,
-       0x85, 0x1E, 0x58, 0xE9,
-
-       0x9B, 0x3B, 0x33, 0xDF,
-       0x20, 0x20, 0x42, 0xAF,
-
-       0x30, 0x42, 0x56, 0x9F,
-       0x80, 0x3E, 0x57, 0xE9,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x30, 0x80, 0x5F, 0xE9,
-
-       0x28, 0x28, 0x24, 0xAF,
-       0x81, 0x1E, 0x57, 0xE9,
-
-       0x05, 0x47, 0x57, 0xBF,
-       0x0D, 0x47, 0x4F, 0xBF,
-
-       0x88, 0x80, 0x58, 0xE9,
-       0x1B, 0x29, 0x1B, 0xDF,
-
-       0x30, 0x1D, 0x6F, 0x8F,
-       0x3A, 0x30, 0x4F, 0xE9,
-
-       0x1C, 0x30, 0x26, 0xDF,
-       0x09, 0xE3,
-       0x3B, 0x05,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x3B, 0x3F, 0x4F, 0xE9,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x00, 0xE0,
-       0xAC, 0x20,
-
-       0x2D, 0x44, 0x4C, 0xB4,
-       0x2C, 0x1C, 0xC0, 0xAF,
-
-       0x25, 0x44, 0x54, 0xB4,
-       0x00, 0xE0,
-       0xC8, 0x30,
-
-       0x30, 0x46, 0x30, 0xAF,
-       0x1B, 0x1B, 0x48, 0xAF,
-
-       0x00, 0xE0,
-       0x25, 0x20,
-       0x38, 0x2C, 0x4F, 0xE9,
-
-       0x86, 0x80, 0x57, 0xE9,
-       0x38, 0x1D, 0x6F, 0x8F,
-
-       0x28, 0x74,
-       0x00, 0xE0,
-       0x0D, 0x44, 0x4C, 0xB0,
-
-       0x05, 0x44, 0x54, 0xB0,
-       0x2D, 0x20,
-       0x9B, 0x10,
-
-       0x82, 0x3E, 0x57, 0xE9,
-       0x32, 0xF0, 0x1B, 0xCD,
-
-       0x1E, 0xBD, 0x59, 0x9F,
-       0x83, 0x1E, 0x57, 0xE9,
-
-       0x38, 0x47, 0x38, 0xAF,
-       0x34, 0x20,
-       0x2A, 0x30,
-
-       0x00, 0xE0,
-       0x0D, 0x20,
-       0x32, 0x20,
-       0x05, 0x20,
-
-       0x87, 0x80, 0x57, 0xE9,
-       0x1F, 0x54, 0x57, 0x9F,
-
-       0x17, 0x42, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x6A,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x37, 0x1E, 0x4F, 0xE9,
-
-       0x37, 0x32, 0x2A, 0xAF,
-       0x00, 0xE0,
-       0x32, 0x00,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x27, 0xC0, 0x44, 0xC0,
-
-       0x36, 0x1F, 0x4F, 0xE9,
-       0x1F, 0x1F, 0x26, 0xDF,
-
-       0x37, 0x1B, 0x37, 0xBF,
-       0x17, 0x26, 0x17, 0xDF,
-
-       0x3E, 0x17, 0x4F, 0xE9,
-       0x3F, 0x3F, 0x4F, 0xE9,
-
-       0x34, 0x1F, 0x34, 0xAF,
-       0x2B, 0x05,
-       0xA7, 0x20,
-
-       0x33, 0x2B, 0x37, 0xDF,
-       0x27, 0x17, 0xC0, 0xAF,
-
-       0x34, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x2D, 0x21, 0x1A, 0xB0,
-       0x25, 0x21, 0x31, 0xB0,
-
-       0x0D, 0x21, 0x1A, 0xB2,
-       0x05, 0x21, 0x31, 0xB2,
-
-       0x03, 0x80, 0x2A, 0xEA,
-       0x17, 0xC1, 0x2B, 0xBD,
-
-       0x2D, 0x20,
-       0x25, 0x20,
-       0x05, 0x20,
-       0x0D, 0x20,
-
-       0xB3, 0x68,
-       0x97, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x33, 0xC0, 0x33, 0xAF,
-       0x2F, 0xC0, 0x21, 0xC0,
-
-       0x16, 0x42, 0x56, 0x9F,
-       0x3C, 0x27, 0x4F, 0xE9,
-
-       0x1E, 0x62, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x25, 0x21, 0x31, 0xB4,
-       0x2D, 0x21, 0x1A, 0xB4,
-
-       0x3F, 0x2F, 0x5D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x33, 0x05,
-       0x00, 0xE0,
-       0x28, 0x19, 0x60, 0xEC,
-
-       0x0D, 0x44, 0x4C, 0xB6,
-       0x05, 0x44, 0x54, 0xB6,
-
-       0x37, 0x0F, 0x5C, 0x9F,
-       0x00, 0xE0,
-       0x2F, 0x20,
-
-       0x23, 0x3B, 0x33, 0xAD,
-       0x1E, 0x26, 0x1E, 0xDF,
-
-       0xA7, 0x1E, 0x4F, 0xE9,
-       0x17, 0x26, 0x16, 0xDF,
-
-       0x2D, 0x20,
-       0x00, 0xE0,
-       0xA8, 0x3F, 0x4F, 0xE9,
-
-       0x2F, 0x2F, 0x1E, 0xAF,
-       0x25, 0x20,
-       0x00, 0xE0,
-
-       0xA4, 0x16, 0x4F, 0xE9,
-       0x0F, 0xC0, 0x21, 0xC2,
-
-       0xA6, 0x80, 0x4F, 0xE9,
-       0x1F, 0x62, 0x57, 0x9F,
-
-       0x0D, 0x20,
-       0x05, 0x20,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x3F, 0x2F, 0x5D, 0x9F,
-       0x00, 0xE0,
-       0x0F, 0x20,
-
-       0x17, 0x50, 0x56, 0x9F,
-       0xA5, 0x37, 0x4F, 0xE9,
-
-       0x06, 0xC0, 0x21, 0xC4,
-       0x0F, 0x17, 0x0F, 0xAF,
-
-       0x37, 0x0F, 0x5C, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x2F, 0xC0, 0x44, 0xC6,
-       0xA3, 0x80, 0x4F, 0xE9,
-
-       0x06, 0x20,
-       0x00, 0xE0,
-       0x1F, 0x26, 0x1F, 0xDF,
-
-       0x17, 0x26, 0x17, 0xDF,
-       0x9D, 0x17, 0x4F, 0xE9,
-
-       0xA1, 0x1F, 0x4F, 0xE9,
-       0xA2, 0x3F, 0x4F, 0xE9,
-
-       0x06, 0x06, 0x1F, 0xAF,
-       0x00, 0xE0,
-       0xAF, 0x20,
-
-       0x9E, 0x37, 0x4F, 0xE9,
-       0x2F, 0x17, 0x2F, 0xAF,
-
-       0xA0, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x9C, 0x80, 0x4F, 0xE9,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x57, 0x39, 0x20, 0xE9,
-
-       0x16, 0x28, 0x20, 0xE9,
-       0x1D, 0x3B, 0x20, 0xE9,
-
-       0x1E, 0x2B, 0x20, 0xE9,
-       0x2B, 0x32, 0x20, 0xE9,
-
-       0x1C, 0x23, 0x20, 0xE9,
-       0x57, 0x36, 0x20, 0xE9,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x90, 0xE2,
-       0x00, 0xE0,
-
-       0x68, 0xFF, 0x20, 0xEA,
-       0x19, 0xC8, 0xC1, 0xCD,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x9F, 0x41, 0x49, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x25, 0x41, 0x49, 0xBD,
-       0x2D, 0x41, 0x51, 0xBD,
-
-       0x0D, 0x80, 0x07, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x35, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x25, 0x30,
-       0x2D, 0x30,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0xA7, 0x5B, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x67, 0xFF, 0x0A, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC9, 0x41, 0xC8, 0xEC,
-       0x42, 0xE1,
-       0x00, 0xE0,
-
-       0x65, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC8, 0x40, 0xC0, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x62, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-};
-
-static unsigned char warp_g200_tgzsaf[] = {
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x98, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x81, 0x04,
-       0x89, 0x04,
-       0x01, 0x04,
-       0x09, 0x04,
-
-       0xC9, 0x41, 0xC0, 0xEC,
-       0x11, 0x04,
-       0x00, 0xE0,
-
-       0x41, 0xCC, 0x41, 0xCD,
-       0x49, 0xCC, 0x49, 0xCD,
-
-       0xD1, 0x41, 0xC0, 0xEC,
-       0x51, 0xCC, 0x51, 0xCD,
-
-       0x80, 0x04,
-       0x10, 0x04,
-       0x08, 0x04,
-       0x00, 0xE0,
-
-       0x00, 0xCC, 0xC0, 0xCD,
-       0xD1, 0x49, 0xC0, 0xEC,
-
-       0x8A, 0x1F, 0x20, 0xE9,
-       0x8B, 0x3F, 0x20, 0xE9,
-
-       0x41, 0x3C, 0x41, 0xAD,
-       0x49, 0x3C, 0x49, 0xAD,
-
-       0x10, 0xCC, 0x10, 0xCD,
-       0x08, 0xCC, 0x08, 0xCD,
-
-       0xB9, 0x41, 0x49, 0xBB,
-       0x1F, 0xF0, 0x41, 0xCD,
-
-       0x51, 0x3C, 0x51, 0xAD,
-       0x00, 0x98, 0x80, 0xE9,
-
-       0x94, 0x80, 0x07, 0xEA,
-       0x24, 0x1F, 0x20, 0xE9,
-
-       0x21, 0x45, 0x80, 0xE8,
-       0x1A, 0x4D, 0x80, 0xE8,
-
-       0x31, 0x55, 0x80, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0x41, 0x49, 0xBD,
-       0x1D, 0x41, 0x51, 0xBD,
-
-       0x2E, 0x41, 0x2A, 0xB8,
-       0x34, 0x53, 0xA0, 0xE8,
-
-       0x15, 0x30,
-       0x1D, 0x30,
-       0x58, 0xE3,
-       0x00, 0xE0,
-
-       0xB5, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x24, 0x43, 0xA0, 0xE8,
-       0x2C, 0x4B, 0xA0, 0xE8,
-
-       0x15, 0x72,
-       0x09, 0xE3,
-       0x00, 0xE0,
-       0x1D, 0x72,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0x97, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x6C, 0x64, 0xC8, 0xEC,
-       0x98, 0xE1,
-       0xB5, 0x05,
-
-       0xBD, 0x05,
-       0x2E, 0x30,
-       0x32, 0xC0, 0xA0, 0xE8,
-
-       0x33, 0xC0, 0xA0, 0xE8,
-       0x74, 0x64, 0xC8, 0xEC,
-
-       0x40, 0x3C, 0x40, 0xAD,
-       0x32, 0x6A,
-       0x2A, 0x30,
-
-       0x20, 0x73,
-       0x33, 0x6A,
-       0x00, 0xE0,
-       0x28, 0x73,
-
-       0x1C, 0x72,
-       0x83, 0xE2,
-       0x80, 0x80, 0x15, 0xEA,
-
-       0xB8, 0x3D, 0x28, 0xDF,
-       0x30, 0x35, 0x20, 0xDF,
-
-       0x40, 0x30,
-       0x00, 0xE0,
-       0xCC, 0xE2,
-       0x64, 0x72,
-
-       0x25, 0x42, 0x52, 0xBF,
-       0x2D, 0x42, 0x4A, 0xBF,
-
-       0x30, 0x2E, 0x30, 0xDF,
-       0x38, 0x2E, 0x38, 0xDF,
-
-       0x18, 0x1D, 0x45, 0xE9,
-       0x1E, 0x15, 0x45, 0xE9,
-
-       0x2B, 0x49, 0x51, 0xBD,
-       0x00, 0xE0,
-       0x1F, 0x73,
-
-       0x38, 0x38, 0x40, 0xAF,
-       0x30, 0x30, 0x40, 0xAF,
-
-       0x24, 0x1F, 0x24, 0xDF,
-       0x1D, 0x32, 0x20, 0xE9,
-
-       0x2C, 0x1F, 0x2C, 0xDF,
-       0x1A, 0x33, 0x20, 0xE9,
-
-       0xB0, 0x10,
-       0x08, 0xE3,
-       0x40, 0x10,
-       0xB8, 0x10,
-
-       0x26, 0xF0, 0x30, 0xCD,
-       0x2F, 0xF0, 0x38, 0xCD,
-
-       0x2B, 0x80, 0x20, 0xE9,
-       0x2A, 0x80, 0x20, 0xE9,
-
-       0xA6, 0x20,
-       0x88, 0xE2,
-       0x00, 0xE0,
-       0xAF, 0x20,
-
-       0x28, 0x2A, 0x26, 0xAF,
-       0x20, 0x2A, 0xC0, 0xAF,
-
-       0x34, 0x1F, 0x34, 0xDF,
-       0x46, 0x24, 0x46, 0xDF,
-
-       0x28, 0x30, 0x80, 0xBF,
-       0x20, 0x38, 0x80, 0xBF,
-
-       0x47, 0x24, 0x47, 0xDF,
-       0x4E, 0x2C, 0x4E, 0xDF,
-
-       0x4F, 0x2C, 0x4F, 0xDF,
-       0x56, 0x34, 0x56, 0xDF,
-
-       0x28, 0x15, 0x28, 0xDF,
-       0x20, 0x1D, 0x20, 0xDF,
-
-       0x57, 0x34, 0x57, 0xDF,
-       0x00, 0xE0,
-       0x1D, 0x05,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x89, 0xE2,
-       0x2B, 0x30,
-
-       0x3F, 0xC1, 0x1D, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA0, 0x68,
-       0xBF, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x20, 0xC0, 0x20, 0xAF,
-       0x28, 0x05,
-       0x97, 0x74,
-
-       0x00, 0xE0,
-       0x2A, 0x10,
-       0x16, 0xC0, 0x20, 0xE9,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x8C, 0xE2,
-       0x95, 0x05,
-
-       0x28, 0xC1, 0x28, 0xAD,
-       0x1F, 0xC1, 0x15, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA8, 0x67,
-       0x9F, 0x6B,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x28, 0xC0, 0x28, 0xAD,
-       0x1D, 0x25,
-       0x20, 0x05,
-
-       0x28, 0x32, 0x80, 0xAD,
-       0x40, 0x2A, 0x40, 0xBD,
-
-       0x1C, 0x80, 0x20, 0xE9,
-       0x20, 0x33, 0x20, 0xAD,
-
-       0x20, 0x73,
-       0x00, 0xE0,
-       0xB6, 0x49, 0x51, 0xBB,
-
-       0x26, 0x2F, 0xB0, 0xE8,
-       0x19, 0x20, 0x20, 0xE9,
-
-       0x35, 0x20, 0x35, 0xDF,
-       0x3D, 0x20, 0x3D, 0xDF,
-
-       0x15, 0x20, 0x15, 0xDF,
-       0x1D, 0x20, 0x1D, 0xDF,
-
-       0x26, 0xD0, 0x26, 0xCD,
-       0x29, 0x49, 0x2A, 0xB8,
-
-       0x26, 0x40, 0x80, 0xBD,
-       0x3B, 0x48, 0x50, 0xBD,
-
-       0x3E, 0x54, 0x57, 0x9F,
-       0x00, 0xE0,
-       0x82, 0xE1,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x26, 0x30,
-       0x29, 0x30,
-       0x48, 0x3C, 0x48, 0xAD,
-
-       0x2B, 0x72,
-       0xC2, 0xE1,
-       0x2C, 0xC0, 0x44, 0xC2,
-
-       0x05, 0x24, 0x34, 0xBF,
-       0x0D, 0x24, 0x2C, 0xBF,
-
-       0x2D, 0x46, 0x4E, 0xBF,
-       0x25, 0x46, 0x56, 0xBF,
-
-       0x20, 0x1D, 0x6F, 0x8F,
-       0x32, 0x3E, 0x5F, 0xE9,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x30,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x33, 0x1E, 0x5F, 0xE9,
-
-       0x05, 0x44, 0x54, 0xB2,
-       0x0D, 0x44, 0x4C, 0xB2,
-
-       0x19, 0xC0, 0xB0, 0xE8,
-       0x34, 0xC0, 0x44, 0xC4,
-
-       0x33, 0x73,
-       0x00, 0xE0,
-       0x3E, 0x62, 0x57, 0x9F,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0xE0,
-       0x0D, 0x20,
-
-       0x84, 0x3E, 0x58, 0xE9,
-       0x28, 0x1D, 0x6F, 0x8F,
-
-       0x05, 0x20,
-       0x00, 0xE0,
-       0x85, 0x1E, 0x58, 0xE9,
-
-       0x9B, 0x3B, 0x33, 0xDF,
-       0x20, 0x20, 0x42, 0xAF,
-
-       0x30, 0x42, 0x56, 0x9F,
-       0x80, 0x3E, 0x57, 0xE9,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x30, 0x80, 0x5F, 0xE9,
-
-       0x28, 0x28, 0x24, 0xAF,
-       0x81, 0x1E, 0x57, 0xE9,
-
-       0x05, 0x47, 0x57, 0xBF,
-       0x0D, 0x47, 0x4F, 0xBF,
-
-       0x88, 0x80, 0x58, 0xE9,
-       0x1B, 0x29, 0x1B, 0xDF,
-
-       0x30, 0x1D, 0x6F, 0x8F,
-       0x3A, 0x30, 0x4F, 0xE9,
-
-       0x1C, 0x30, 0x26, 0xDF,
-       0x09, 0xE3,
-       0x3B, 0x05,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x3B, 0x3F, 0x4F, 0xE9,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x00, 0xE0,
-       0xAC, 0x20,
-
-       0x2D, 0x44, 0x4C, 0xB4,
-       0x2C, 0x1C, 0xC0, 0xAF,
-
-       0x25, 0x44, 0x54, 0xB4,
-       0x00, 0xE0,
-       0xC8, 0x30,
-
-       0x30, 0x46, 0x30, 0xAF,
-       0x1B, 0x1B, 0x48, 0xAF,
-
-       0x00, 0xE0,
-       0x25, 0x20,
-       0x38, 0x2C, 0x4F, 0xE9,
-
-       0x86, 0x80, 0x57, 0xE9,
-       0x38, 0x1D, 0x6F, 0x8F,
-
-       0x28, 0x74,
-       0x00, 0xE0,
-       0x0D, 0x44, 0x4C, 0xB0,
-
-       0x05, 0x44, 0x54, 0xB0,
-       0x2D, 0x20,
-       0x9B, 0x10,
-
-       0x82, 0x3E, 0x57, 0xE9,
-       0x32, 0xF0, 0x1B, 0xCD,
-
-       0x1E, 0xBD, 0x59, 0x9F,
-       0x83, 0x1E, 0x57, 0xE9,
-
-       0x38, 0x47, 0x38, 0xAF,
-       0x34, 0x20,
-       0x2A, 0x30,
-
-       0x00, 0xE0,
-       0x0D, 0x20,
-       0x32, 0x20,
-       0x05, 0x20,
-
-       0x87, 0x80, 0x57, 0xE9,
-       0x1F, 0x54, 0x57, 0x9F,
-
-       0x17, 0x42, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x6A,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x37, 0x1E, 0x4F, 0xE9,
-
-       0x37, 0x32, 0x2A, 0xAF,
-       0x00, 0xE0,
-       0x32, 0x00,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x27, 0xC0, 0x44, 0xC0,
-
-       0x36, 0x1F, 0x4F, 0xE9,
-       0x1F, 0x1F, 0x26, 0xDF,
-
-       0x37, 0x1B, 0x37, 0xBF,
-       0x17, 0x26, 0x17, 0xDF,
-
-       0x3E, 0x17, 0x4F, 0xE9,
-       0x3F, 0x3F, 0x4F, 0xE9,
-
-       0x34, 0x1F, 0x34, 0xAF,
-       0x2B, 0x05,
-       0xA7, 0x20,
-
-       0x33, 0x2B, 0x37, 0xDF,
-       0x27, 0x17, 0xC0, 0xAF,
-
-       0x34, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x2D, 0x21, 0x1A, 0xB0,
-       0x25, 0x21, 0x31, 0xB0,
-
-       0x0D, 0x21, 0x1A, 0xB2,
-       0x05, 0x21, 0x31, 0xB2,
-
-       0x03, 0x80, 0x2A, 0xEA,
-       0x17, 0xC1, 0x2B, 0xBD,
-
-       0x2D, 0x20,
-       0x25, 0x20,
-       0x05, 0x20,
-       0x0D, 0x20,
-
-       0xB3, 0x68,
-       0x97, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x33, 0xC0, 0x33, 0xAF,
-       0x2F, 0xC0, 0x21, 0xC0,
-
-       0x16, 0x42, 0x56, 0x9F,
-       0x3C, 0x27, 0x4F, 0xE9,
-
-       0x1E, 0x62, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x25, 0x21, 0x31, 0xB4,
-       0x2D, 0x21, 0x1A, 0xB4,
-
-       0x3F, 0x2F, 0x5D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x33, 0x05,
-       0x00, 0xE0,
-       0x28, 0x19, 0x60, 0xEC,
-
-       0x0D, 0x21, 0x1A, 0xB6,
-       0x05, 0x21, 0x31, 0xB6,
-
-       0x37, 0x0F, 0x5C, 0x9F,
-       0x00, 0xE0,
-       0x2F, 0x20,
-
-       0x23, 0x3B, 0x33, 0xAD,
-       0x1E, 0x26, 0x1E, 0xDF,
-
-       0xA7, 0x1E, 0x4F, 0xE9,
-       0x17, 0x26, 0x16, 0xDF,
-
-       0x2D, 0x20,
-       0x00, 0xE0,
-       0xA8, 0x3F, 0x4F, 0xE9,
-
-       0x2F, 0x2F, 0x1E, 0xAF,
-       0x25, 0x20,
-       0x00, 0xE0,
-
-       0xA4, 0x16, 0x4F, 0xE9,
-       0x0F, 0xC0, 0x21, 0xC2,
-
-       0xA6, 0x80, 0x4F, 0xE9,
-       0x1F, 0x62, 0x57, 0x9F,
-
-       0x0D, 0x20,
-       0x05, 0x20,
-       0x2F, 0xC0, 0x21, 0xC6,
-
-       0x2D, 0x44, 0x4C, 0xB6,
-       0x25, 0x44, 0x54, 0xB6,
-
-       0x3F, 0x2F, 0x5D, 0x9F,
-       0x00, 0xE0,
-       0x0F, 0x20,
-
-       0x2D, 0x20,
-       0x25, 0x20,
-       0x07, 0xC0, 0x44, 0xC6,
-
-       0x17, 0x50, 0x56, 0x9F,
-       0xA5, 0x37, 0x4F, 0xE9,
-
-       0x06, 0xC0, 0x21, 0xC4,
-       0x0F, 0x17, 0x0F, 0xAF,
-
-       0x37, 0x0F, 0x5C, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x1E, 0x62, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x3E, 0x3D, 0x5D, 0x9F,
-       0x00, 0xE0,
-       0x07, 0x20,
-
-       0x2F, 0x20,
-       0x00, 0xE0,
-       0xA3, 0x0F, 0x4F, 0xE9,
-
-       0x06, 0x20,
-       0x00, 0xE0,
-       0x1F, 0x26, 0x1F, 0xDF,
-
-       0x17, 0x26, 0x17, 0xDF,
-       0xA1, 0x1F, 0x4F, 0xE9,
-
-       0x1E, 0x26, 0x1E, 0xDF,
-       0x9D, 0x1E, 0x4F, 0xE9,
-
-       0x35, 0x17, 0x4F, 0xE9,
-       0xA2, 0x3F, 0x4F, 0xE9,
-
-       0x06, 0x06, 0x1F, 0xAF,
-       0x39, 0x37, 0x4F, 0xE9,
-
-       0x2F, 0x2F, 0x17, 0xAF,
-       0x07, 0x07, 0x1E, 0xAF,
-
-       0xA0, 0x80, 0x4F, 0xE9,
-       0x9E, 0x3E, 0x4F, 0xE9,
-
-       0x31, 0x80, 0x4F, 0xE9,
-       0x9C, 0x80, 0x4F, 0xE9,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x57, 0x39, 0x20, 0xE9,
-
-       0x16, 0x28, 0x20, 0xE9,
-       0x1D, 0x3B, 0x20, 0xE9,
-
-       0x1E, 0x2B, 0x20, 0xE9,
-       0x2B, 0x32, 0x20, 0xE9,
-
-       0x1C, 0x23, 0x20, 0xE9,
-       0x57, 0x36, 0x20, 0xE9,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x90, 0xE2,
-       0x00, 0xE0,
-
-       0x63, 0xFF, 0x20, 0xEA,
-       0x19, 0xC8, 0xC1, 0xCD,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x9F, 0x41, 0x49, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x25, 0x41, 0x49, 0xBD,
-       0x2D, 0x41, 0x51, 0xBD,
-
-       0x0D, 0x80, 0x07, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x35, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x25, 0x30,
-       0x2D, 0x30,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0xA7, 0x5B, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x62, 0xFF, 0x0A, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC9, 0x41, 0xC8, 0xEC,
-       0x42, 0xE1,
-       0x00, 0xE0,
-
-       0x60, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC8, 0x40, 0xC0, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x5D, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-};
-
-static unsigned char warp_g200_tgzsf[] = {
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x98, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x81, 0x04,
-       0x89, 0x04,
-       0x01, 0x04,
-       0x09, 0x04,
-
-       0xC9, 0x41, 0xC0, 0xEC,
-       0x11, 0x04,
-       0x00, 0xE0,
-
-       0x41, 0xCC, 0x41, 0xCD,
-       0x49, 0xCC, 0x49, 0xCD,
-
-       0xD1, 0x41, 0xC0, 0xEC,
-       0x51, 0xCC, 0x51, 0xCD,
-
-       0x80, 0x04,
-       0x10, 0x04,
-       0x08, 0x04,
-       0x00, 0xE0,
-
-       0x00, 0xCC, 0xC0, 0xCD,
-       0xD1, 0x49, 0xC0, 0xEC,
-
-       0x8A, 0x1F, 0x20, 0xE9,
-       0x8B, 0x3F, 0x20, 0xE9,
-
-       0x41, 0x3C, 0x41, 0xAD,
-       0x49, 0x3C, 0x49, 0xAD,
-
-       0x10, 0xCC, 0x10, 0xCD,
-       0x08, 0xCC, 0x08, 0xCD,
-
-       0xB9, 0x41, 0x49, 0xBB,
-       0x1F, 0xF0, 0x41, 0xCD,
-
-       0x51, 0x3C, 0x51, 0xAD,
-       0x00, 0x98, 0x80, 0xE9,
-
-       0x8F, 0x80, 0x07, 0xEA,
-       0x24, 0x1F, 0x20, 0xE9,
-
-       0x21, 0x45, 0x80, 0xE8,
-       0x1A, 0x4D, 0x80, 0xE8,
-
-       0x31, 0x55, 0x80, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0x41, 0x49, 0xBD,
-       0x1D, 0x41, 0x51, 0xBD,
-
-       0x2E, 0x41, 0x2A, 0xB8,
-       0x34, 0x53, 0xA0, 0xE8,
-
-       0x15, 0x30,
-       0x1D, 0x30,
-       0x58, 0xE3,
-       0x00, 0xE0,
-
-       0xB5, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x24, 0x43, 0xA0, 0xE8,
-       0x2C, 0x4B, 0xA0, 0xE8,
-
-       0x15, 0x72,
-       0x09, 0xE3,
-       0x00, 0xE0,
-       0x1D, 0x72,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0x97, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x6C, 0x64, 0xC8, 0xEC,
-       0x98, 0xE1,
-       0xB5, 0x05,
-
-       0xBD, 0x05,
-       0x2E, 0x30,
-       0x32, 0xC0, 0xA0, 0xE8,
-
-       0x33, 0xC0, 0xA0, 0xE8,
-       0x74, 0x64, 0xC8, 0xEC,
-
-       0x40, 0x3C, 0x40, 0xAD,
-       0x32, 0x6A,
-       0x2A, 0x30,
-
-       0x20, 0x73,
-       0x33, 0x6A,
-       0x00, 0xE0,
-       0x28, 0x73,
-
-       0x1C, 0x72,
-       0x83, 0xE2,
-       0x7B, 0x80, 0x15, 0xEA,
-
-       0xB8, 0x3D, 0x28, 0xDF,
-       0x30, 0x35, 0x20, 0xDF,
-
-       0x40, 0x30,
-       0x00, 0xE0,
-       0xCC, 0xE2,
-       0x64, 0x72,
-
-       0x25, 0x42, 0x52, 0xBF,
-       0x2D, 0x42, 0x4A, 0xBF,
-
-       0x30, 0x2E, 0x30, 0xDF,
-       0x38, 0x2E, 0x38, 0xDF,
-
-       0x18, 0x1D, 0x45, 0xE9,
-       0x1E, 0x15, 0x45, 0xE9,
-
-       0x2B, 0x49, 0x51, 0xBD,
-       0x00, 0xE0,
-       0x1F, 0x73,
-
-       0x38, 0x38, 0x40, 0xAF,
-       0x30, 0x30, 0x40, 0xAF,
-
-       0x24, 0x1F, 0x24, 0xDF,
-       0x1D, 0x32, 0x20, 0xE9,
-
-       0x2C, 0x1F, 0x2C, 0xDF,
-       0x1A, 0x33, 0x20, 0xE9,
-
-       0xB0, 0x10,
-       0x08, 0xE3,
-       0x40, 0x10,
-       0xB8, 0x10,
-
-       0x26, 0xF0, 0x30, 0xCD,
-       0x2F, 0xF0, 0x38, 0xCD,
-
-       0x2B, 0x80, 0x20, 0xE9,
-       0x2A, 0x80, 0x20, 0xE9,
-
-       0xA6, 0x20,
-       0x88, 0xE2,
-       0x00, 0xE0,
-       0xAF, 0x20,
-
-       0x28, 0x2A, 0x26, 0xAF,
-       0x20, 0x2A, 0xC0, 0xAF,
-
-       0x34, 0x1F, 0x34, 0xDF,
-       0x46, 0x24, 0x46, 0xDF,
-
-       0x28, 0x30, 0x80, 0xBF,
-       0x20, 0x38, 0x80, 0xBF,
-
-       0x47, 0x24, 0x47, 0xDF,
-       0x4E, 0x2C, 0x4E, 0xDF,
-
-       0x4F, 0x2C, 0x4F, 0xDF,
-       0x56, 0x34, 0x56, 0xDF,
-
-       0x28, 0x15, 0x28, 0xDF,
-       0x20, 0x1D, 0x20, 0xDF,
-
-       0x57, 0x34, 0x57, 0xDF,
-       0x00, 0xE0,
-       0x1D, 0x05,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x89, 0xE2,
-       0x2B, 0x30,
-
-       0x3F, 0xC1, 0x1D, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA0, 0x68,
-       0xBF, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x20, 0xC0, 0x20, 0xAF,
-       0x28, 0x05,
-       0x97, 0x74,
-
-       0x00, 0xE0,
-       0x2A, 0x10,
-       0x16, 0xC0, 0x20, 0xE9,
-
-       0x04, 0x80, 0x10, 0xEA,
-       0x8C, 0xE2,
-       0x95, 0x05,
-
-       0x28, 0xC1, 0x28, 0xAD,
-       0x1F, 0xC1, 0x15, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA8, 0x67,
-       0x9F, 0x6B,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x28, 0xC0, 0x28, 0xAD,
-       0x1D, 0x25,
-       0x20, 0x05,
-
-       0x28, 0x32, 0x80, 0xAD,
-       0x40, 0x2A, 0x40, 0xBD,
-
-       0x1C, 0x80, 0x20, 0xE9,
-       0x20, 0x33, 0x20, 0xAD,
-
-       0x20, 0x73,
-       0x00, 0xE0,
-       0xB6, 0x49, 0x51, 0xBB,
-
-       0x26, 0x2F, 0xB0, 0xE8,
-       0x19, 0x20, 0x20, 0xE9,
-
-       0x35, 0x20, 0x35, 0xDF,
-       0x3D, 0x20, 0x3D, 0xDF,
-
-       0x15, 0x20, 0x15, 0xDF,
-       0x1D, 0x20, 0x1D, 0xDF,
-
-       0x26, 0xD0, 0x26, 0xCD,
-       0x29, 0x49, 0x2A, 0xB8,
-
-       0x26, 0x40, 0x80, 0xBD,
-       0x3B, 0x48, 0x50, 0xBD,
-
-       0x3E, 0x54, 0x57, 0x9F,
-       0x00, 0xE0,
-       0x82, 0xE1,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x26, 0x30,
-       0x29, 0x30,
-       0x48, 0x3C, 0x48, 0xAD,
-
-       0x2B, 0x72,
-       0xC2, 0xE1,
-       0x2C, 0xC0, 0x44, 0xC2,
-
-       0x05, 0x24, 0x34, 0xBF,
-       0x0D, 0x24, 0x2C, 0xBF,
-
-       0x2D, 0x46, 0x4E, 0xBF,
-       0x25, 0x46, 0x56, 0xBF,
-
-       0x20, 0x1D, 0x6F, 0x8F,
-       0x32, 0x3E, 0x5F, 0xE9,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x30,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x33, 0x1E, 0x5F, 0xE9,
-
-       0x05, 0x44, 0x54, 0xB2,
-       0x0D, 0x44, 0x4C, 0xB2,
-
-       0x19, 0xC0, 0xB0, 0xE8,
-       0x34, 0xC0, 0x44, 0xC4,
-
-       0x33, 0x73,
-       0x00, 0xE0,
-       0x3E, 0x62, 0x57, 0x9F,
-
-       0x1E, 0xAF, 0x59, 0x9F,
-       0x00, 0xE0,
-       0x0D, 0x20,
-
-       0x84, 0x3E, 0x58, 0xE9,
-       0x28, 0x1D, 0x6F, 0x8F,
-
-       0x05, 0x20,
-       0x00, 0xE0,
-       0x85, 0x1E, 0x58, 0xE9,
-
-       0x9B, 0x3B, 0x33, 0xDF,
-       0x20, 0x20, 0x42, 0xAF,
-
-       0x30, 0x42, 0x56, 0x9F,
-       0x80, 0x3E, 0x57, 0xE9,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x30, 0x80, 0x5F, 0xE9,
-
-       0x28, 0x28, 0x24, 0xAF,
-       0x81, 0x1E, 0x57, 0xE9,
-
-       0x05, 0x47, 0x57, 0xBF,
-       0x0D, 0x47, 0x4F, 0xBF,
-
-       0x88, 0x80, 0x58, 0xE9,
-       0x1B, 0x29, 0x1B, 0xDF,
-
-       0x30, 0x1D, 0x6F, 0x8F,
-       0x3A, 0x30, 0x4F, 0xE9,
-
-       0x1C, 0x30, 0x26, 0xDF,
-       0x09, 0xE3,
-       0x3B, 0x05,
-
-       0x3E, 0x50, 0x56, 0x9F,
-       0x3B, 0x3F, 0x4F, 0xE9,
-
-       0x1E, 0x8F, 0x51, 0x9F,
-       0x00, 0xE0,
-       0xAC, 0x20,
-
-       0x2D, 0x44, 0x4C, 0xB4,
-       0x2C, 0x1C, 0xC0, 0xAF,
-
-       0x25, 0x44, 0x54, 0xB4,
-       0x00, 0xE0,
-       0xC8, 0x30,
-
-       0x30, 0x46, 0x30, 0xAF,
-       0x1B, 0x1B, 0x48, 0xAF,
-
-       0x00, 0xE0,
-       0x25, 0x20,
-       0x38, 0x2C, 0x4F, 0xE9,
-
-       0x86, 0x80, 0x57, 0xE9,
-       0x38, 0x1D, 0x6F, 0x8F,
-
-       0x28, 0x74,
-       0x00, 0xE0,
-       0x0D, 0x44, 0x4C, 0xB0,
-
-       0x05, 0x44, 0x54, 0xB0,
-       0x2D, 0x20,
-       0x9B, 0x10,
-
-       0x82, 0x3E, 0x57, 0xE9,
-       0x32, 0xF0, 0x1B, 0xCD,
-
-       0x1E, 0xBD, 0x59, 0x9F,
-       0x83, 0x1E, 0x57, 0xE9,
-
-       0x38, 0x47, 0x38, 0xAF,
-       0x34, 0x20,
-       0x2A, 0x30,
-
-       0x00, 0xE0,
-       0x0D, 0x20,
-       0x32, 0x20,
-       0x05, 0x20,
-
-       0x87, 0x80, 0x57, 0xE9,
-       0x1F, 0x54, 0x57, 0x9F,
-
-       0x17, 0x42, 0x56, 0x9F,
-       0x00, 0xE0,
-       0x3B, 0x6A,
-
-       0x3F, 0x8F, 0x51, 0x9F,
-       0x37, 0x1E, 0x4F, 0xE9,
-
-       0x37, 0x32, 0x2A, 0xAF,
-       0x00, 0xE0,
-       0x32, 0x00,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x27, 0xC0, 0x44, 0xC0,
-
-       0x36, 0x1F, 0x4F, 0xE9,
-       0x1F, 0x1F, 0x26, 0xDF,
-
-       0x37, 0x1B, 0x37, 0xBF,
-       0x17, 0x26, 0x17, 0xDF,
-
-       0x3E, 0x17, 0x4F, 0xE9,
-       0x3F, 0x3F, 0x4F, 0xE9,
-
-       0x34, 0x1F, 0x34, 0xAF,
-       0x2B, 0x05,
-       0xA7, 0x20,
-
-       0x33, 0x2B, 0x37, 0xDF,
-       0x27, 0x17, 0xC0, 0xAF,
-
-       0x34, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x2D, 0x21, 0x1A, 0xB0,
-       0x25, 0x21, 0x31, 0xB0,
-
-       0x0D, 0x21, 0x1A, 0xB2,
-       0x05, 0x21, 0x31, 0xB2,
-
-       0x03, 0x80, 0x2A, 0xEA,
-       0x17, 0xC1, 0x2B, 0xBD,
-
-       0x2D, 0x20,
-       0x25, 0x20,
-       0x05, 0x20,
-       0x0D, 0x20,
-
-       0xB3, 0x68,
-       0x97, 0x25,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x33, 0xC0, 0x33, 0xAF,
-       0x2F, 0xC0, 0x21, 0xC0,
-
-       0x16, 0x42, 0x56, 0x9F,
-       0x3C, 0x27, 0x4F, 0xE9,
-
-       0x1E, 0x62, 0x57, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x25, 0x21, 0x31, 0xB4,
-       0x2D, 0x21, 0x1A, 0xB4,
-
-       0x3F, 0x2F, 0x5D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x33, 0x05,
-       0x00, 0xE0,
-       0x28, 0x19, 0x60, 0xEC,
-
-       0x0D, 0x21, 0x1A, 0xB6,
-       0x05, 0x21, 0x31, 0xB6,
-
-       0x37, 0x0F, 0x5C, 0x9F,
-       0x00, 0xE0,
-       0x2F, 0x20,
-
-       0x23, 0x3B, 0x33, 0xAD,
-       0x1E, 0x26, 0x1E, 0xDF,
-
-       0xA7, 0x1E, 0x4F, 0xE9,
-       0x17, 0x26, 0x16, 0xDF,
-
-       0x2D, 0x20,
-       0x00, 0xE0,
-       0xA8, 0x3F, 0x4F, 0xE9,
-
-       0x2F, 0x2F, 0x1E, 0xAF,
-       0x25, 0x20,
-       0x00, 0xE0,
-
-       0xA4, 0x16, 0x4F, 0xE9,
-       0x0F, 0xC0, 0x21, 0xC2,
-
-       0xA6, 0x80, 0x4F, 0xE9,
-       0x1F, 0x62, 0x57, 0x9F,
-
-       0x0D, 0x20,
-       0x05, 0x20,
-       0x2F, 0xC0, 0x21, 0xC6,
-
-       0x3F, 0x2F, 0x5D, 0x9F,
-       0x00, 0xE0,
-       0x0F, 0x20,
-
-       0x17, 0x50, 0x56, 0x9F,
-       0xA5, 0x37, 0x4F, 0xE9,
-
-       0x06, 0xC0, 0x21, 0xC4,
-       0x0F, 0x17, 0x0F, 0xAF,
-
-       0x37, 0x0F, 0x5C, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x2F, 0x20,
-       0x00, 0xE0,
-       0xA3, 0x80, 0x4F, 0xE9,
-
-       0x06, 0x20,
-       0x00, 0xE0,
-       0x1F, 0x26, 0x1F, 0xDF,
-
-       0x17, 0x26, 0x17, 0xDF,
-       0x35, 0x17, 0x4F, 0xE9,
-
-       0xA1, 0x1F, 0x4F, 0xE9,
-       0xA2, 0x3F, 0x4F, 0xE9,
-
-       0x06, 0x06, 0x1F, 0xAF,
-       0x39, 0x37, 0x4F, 0xE9,
-
-       0x2F, 0x2F, 0x17, 0xAF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xA0, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x31, 0x80, 0x4F, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x57, 0x39, 0x20, 0xE9,
-
-       0x16, 0x28, 0x20, 0xE9,
-       0x1D, 0x3B, 0x20, 0xE9,
-
-       0x1E, 0x2B, 0x20, 0xE9,
-       0x2B, 0x32, 0x20, 0xE9,
-
-       0x1C, 0x23, 0x20, 0xE9,
-       0x57, 0x36, 0x20, 0xE9,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x40, 0x40, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x90, 0xE2,
-       0x00, 0xE0,
-
-       0x68, 0xFF, 0x20, 0xEA,
-       0x19, 0xC8, 0xC1, 0xCD,
-
-       0x1F, 0xD7, 0x18, 0xBD,
-       0x3F, 0xD7, 0x22, 0xBD,
-
-       0x9F, 0x41, 0x49, 0xBD,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x25, 0x41, 0x49, 0xBD,
-       0x2D, 0x41, 0x51, 0xBD,
-
-       0x0D, 0x80, 0x07, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x35, 0x40, 0x48, 0xBD,
-       0x3D, 0x40, 0x50, 0xBD,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x25, 0x30,
-       0x2D, 0x30,
-
-       0x35, 0x30,
-       0xB5, 0x30,
-       0xBD, 0x30,
-       0x3D, 0x30,
-
-       0x9C, 0xA7, 0x5B, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x67, 0xFF, 0x0A, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC9, 0x41, 0xC8, 0xEC,
-       0x42, 0xE1,
-       0x00, 0xE0,
-
-       0x65, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xC8, 0x40, 0xC0, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x62, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-};
-
-static unsigned char warp_g400_t2gz[] = {
-
-       0x00, 0x8A, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x0A, 0x40, 0x50, 0xBF,
-       0x2A, 0x40, 0x60, 0xBF,
-
-       0x32, 0x41, 0x51, 0xBF,
-       0x3A, 0x41, 0x61, 0xBF,
-
-       0xC3, 0x6B,
-       0xD3, 0x6B,
-       0x00, 0x8A, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x23, 0x9F,
-       0x00, 0xE0,
-       0x51, 0x04,
-
-       0x90, 0xE2,
-       0x61, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x51, 0x41, 0xE0, 0xEC,
-       0x39, 0x67, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x63, 0xA0, 0xE8,
-
-       0x61, 0x41, 0xE0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x78, 0x80, 0x15, 0xEA,
-       0x10, 0x04,
-       0x20, 0x04,
-
-       0x61, 0x51, 0xE0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x52, 0xBF,
-       0x0F, 0x52, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x62, 0xBF,
-       0x1E, 0x51, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x0E, 0x61, 0x60, 0xEA,
-
-       0x32, 0x40, 0x50, 0xBD,
-       0x22, 0x40, 0x60, 0xBD,
-
-       0x12, 0x41, 0x51, 0xBD,
-       0x3A, 0x41, 0x61, 0xBD,
-
-       0xBF, 0x2F, 0x0E, 0xBD,
-       0x97, 0xE2,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x35, 0x48, 0xB1, 0xE8,
-       0x3D, 0x59, 0xB1, 0xE8,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x56, 0x31, 0x56, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x66, 0x31, 0x66, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x57, 0x39, 0x57, 0xBF,
-       0x67, 0x39, 0x67, 0xBF,
-
-       0x69, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x35, 0x00,
-       0x3D, 0x00,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0x8D, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x75, 0xF8, 0xEC,
-       0x35, 0x20,
-       0x3D, 0x20,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x53, 0x53, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x0E, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x48, 0x35, 0x48, 0xBF,
-       0x58, 0x35, 0x58, 0xBF,
-
-       0x68, 0x35, 0x68, 0xBF,
-       0x49, 0x3D, 0x49, 0xBF,
-
-       0x59, 0x3D, 0x59, 0xBF,
-       0x69, 0x3D, 0x69, 0xBF,
-
-       0x63, 0x63, 0x2D, 0xDF,
-       0x4D, 0x7D, 0xF8, 0xEC,
-
-       0x59, 0xE3,
-       0x00, 0xE0,
-       0xB8, 0x38, 0x33, 0xBF,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x18, 0x3A, 0x41, 0xE9,
-
-       0x3F, 0x53, 0xA0, 0xE8,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x63, 0xA0, 0xE8,
-
-       0x50, 0x70, 0xF8, 0xEC,
-       0x2B, 0x50, 0x3C, 0xE9,
-
-       0x1F, 0x0F, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x59, 0x78, 0xF8, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x56, 0x3F, 0x56, 0xDF,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x66, 0x3D, 0x66, 0xDF,
-
-       0x1D, 0x32, 0x41, 0xE9,
-       0x67, 0x3D, 0x67, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3F, 0x57, 0xDF,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x59, 0x3F, 0x59, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x69, 0x3D, 0x69, 0xDF,
-
-       0x48, 0x37, 0x48, 0xDF,
-       0x58, 0x3F, 0x58, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x68, 0x3D, 0x68, 0xDF,
-       0x49, 0x37, 0x49, 0xDF,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x34, 0x80, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x0A, 0x44, 0x54, 0xB0,
-       0x02, 0x44, 0x64, 0xB0,
-
-       0x2A, 0x44, 0x54, 0xB2,
-       0x1A, 0x44, 0x64, 0xB2,
-
-       0x25, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x3D, 0xCF, 0x74, 0xC2,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x2A, 0x44, 0x54, 0xB4,
-       0x1A, 0x44, 0x64, 0xB4,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x38, 0x3D, 0x20, 0xE9,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x2A, 0x46, 0x56, 0xBF,
-       0x1A, 0x46, 0x66, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x0A, 0x47, 0x57, 0xBF,
-       0x02, 0x47, 0x67, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x53, 0xBF,
-       0x1A, 0x43, 0x63, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x36, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x37, 0x39, 0x4F, 0xE9,
-
-       0x0A, 0x48, 0x58, 0xBF,
-       0x02, 0x48, 0x68, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x2A, 0x49, 0x59, 0xBF,
-       0x1A, 0x49, 0x69, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x82, 0x30, 0x57, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x83, 0x38, 0x57, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x84, 0x31, 0x5E, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x85, 0x39, 0x5E, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x87, 0x77, 0x57, 0xE9,
-       0x8B, 0x3E, 0xBF, 0xEA,
-
-       0x80, 0x30, 0x57, 0xE9,
-       0x81, 0x38, 0x57, 0xE9,
-
-       0x82, 0x31, 0x57, 0xE9,
-       0x86, 0x78, 0x57, 0xE9,
-
-       0x83, 0x39, 0x57, 0xE9,
-       0x87, 0x79, 0x57, 0xE9,
-
-       0x30, 0x1F, 0x5F, 0xE9,
-       0x8A, 0x34, 0x20, 0xE9,
-
-       0x8B, 0x3C, 0x20, 0xE9,
-       0x37, 0x50, 0x60, 0xBD,
-
-       0x57, 0x0D, 0x20, 0xE9,
-       0x35, 0x51, 0x61, 0xBD,
-
-       0x2B, 0x50, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x0E, 0x77,
-
-       0x24, 0x51, 0x20, 0xE9,
-       0x9F, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x0E, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x0B, 0x46, 0xA0, 0xE8,
-       0x1B, 0x56, 0xA0, 0xE8,
-
-       0x2B, 0x66, 0xA0, 0xE8,
-       0x0C, 0x47, 0xA0, 0xE8,
-
-       0x1C, 0x57, 0xA0, 0xE8,
-       0x2C, 0x67, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x57, 0x80, 0x57, 0xCF,
-
-       0x66, 0x33, 0x66, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x67, 0x3B, 0x67, 0xCF,
-
-       0x0B, 0x48, 0xA0, 0xE8,
-       0x1B, 0x58, 0xA0, 0xE8,
-
-       0x2B, 0x68, 0xA0, 0xE8,
-       0x0C, 0x49, 0xA0, 0xE8,
-
-       0x1C, 0x59, 0xA0, 0xE8,
-       0x2C, 0x69, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x34, 0xD7, 0x34, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3C, 0xD7, 0x3C, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x34, 0x80, 0x34, 0xBD,
-       0x3C, 0x80, 0x3C, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x48, 0x80, 0x48, 0xCF,
-       0x59, 0x80, 0x59, 0xCF,
-
-       0x68, 0x33, 0x68, 0xCF,
-       0x49, 0x3B, 0x49, 0xCF,
-
-       0xBE, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x58, 0x33, 0x58, 0xCF,
-       0x69, 0x3B, 0x69, 0xCF,
-
-       0x7D, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_t2gza[] = {
-
-       0x00, 0x8A, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x0A, 0x40, 0x50, 0xBF,
-       0x2A, 0x40, 0x60, 0xBF,
-
-       0x32, 0x41, 0x51, 0xBF,
-       0x3A, 0x41, 0x61, 0xBF,
-
-       0xC3, 0x6B,
-       0xD3, 0x6B,
-       0x00, 0x8A, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x23, 0x9F,
-       0x00, 0xE0,
-       0x51, 0x04,
-
-       0x90, 0xE2,
-       0x61, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x51, 0x41, 0xE0, 0xEC,
-       0x39, 0x67, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x63, 0xA0, 0xE8,
-
-       0x61, 0x41, 0xE0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x7C, 0x80, 0x15, 0xEA,
-       0x10, 0x04,
-       0x20, 0x04,
-
-       0x61, 0x51, 0xE0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x52, 0xBF,
-       0x0F, 0x52, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x62, 0xBF,
-       0x1E, 0x51, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x0E, 0x61, 0x60, 0xEA,
-
-       0x32, 0x40, 0x50, 0xBD,
-       0x22, 0x40, 0x60, 0xBD,
-
-       0x12, 0x41, 0x51, 0xBD,
-       0x3A, 0x41, 0x61, 0xBD,
-
-       0xBF, 0x2F, 0x0E, 0xBD,
-       0x97, 0xE2,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x35, 0x48, 0xB1, 0xE8,
-       0x3D, 0x59, 0xB1, 0xE8,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x56, 0x31, 0x56, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x66, 0x31, 0x66, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x57, 0x39, 0x57, 0xBF,
-       0x67, 0x39, 0x67, 0xBF,
-
-       0x6D, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x35, 0x00,
-       0x3D, 0x00,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0x8D, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x75, 0xF8, 0xEC,
-       0x35, 0x20,
-       0x3D, 0x20,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x53, 0x53, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x0E, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x48, 0x35, 0x48, 0xBF,
-       0x58, 0x35, 0x58, 0xBF,
-
-       0x68, 0x35, 0x68, 0xBF,
-       0x49, 0x3D, 0x49, 0xBF,
-
-       0x59, 0x3D, 0x59, 0xBF,
-       0x69, 0x3D, 0x69, 0xBF,
-
-       0x63, 0x63, 0x2D, 0xDF,
-       0x4D, 0x7D, 0xF8, 0xEC,
-
-       0x59, 0xE3,
-       0x00, 0xE0,
-       0xB8, 0x38, 0x33, 0xBF,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x18, 0x3A, 0x41, 0xE9,
-
-       0x3F, 0x53, 0xA0, 0xE8,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x63, 0xA0, 0xE8,
-
-       0x50, 0x70, 0xF8, 0xEC,
-       0x2B, 0x50, 0x3C, 0xE9,
-
-       0x1F, 0x0F, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x59, 0x78, 0xF8, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x56, 0x3F, 0x56, 0xDF,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x66, 0x3D, 0x66, 0xDF,
-
-       0x1D, 0x32, 0x41, 0xE9,
-       0x67, 0x3D, 0x67, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3F, 0x57, 0xDF,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x59, 0x3F, 0x59, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x69, 0x3D, 0x69, 0xDF,
-
-       0x48, 0x37, 0x48, 0xDF,
-       0x58, 0x3F, 0x58, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x68, 0x3D, 0x68, 0xDF,
-       0x49, 0x37, 0x49, 0xDF,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x34, 0x80, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x0A, 0x44, 0x54, 0xB0,
-       0x02, 0x44, 0x64, 0xB0,
-
-       0x2A, 0x44, 0x54, 0xB2,
-       0x1A, 0x44, 0x64, 0xB2,
-
-       0x29, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x0F, 0xCF, 0x74, 0xC6,
-       0x3D, 0xCF, 0x74, 0xC2,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x9C, 0x0F, 0x20, 0xE9,
-
-       0x0A, 0x44, 0x54, 0xB4,
-       0x02, 0x44, 0x64, 0xB4,
-
-       0x2A, 0x44, 0x54, 0xB6,
-       0x1A, 0x44, 0x64, 0xB6,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x38, 0x3D, 0x20, 0xE9,
-
-       0x0A, 0x20,
-       0x02, 0x20,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x0A, 0x47, 0x57, 0xBF,
-       0x02, 0x47, 0x67, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x46, 0x56, 0xBF,
-       0x1A, 0x46, 0x66, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x36, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x37, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x53, 0xBF,
-       0x1A, 0x43, 0x63, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x9D, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x9E, 0x39, 0x4F, 0xE9,
-
-       0x0A, 0x48, 0x58, 0xBF,
-       0x02, 0x48, 0x68, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x2A, 0x49, 0x59, 0xBF,
-       0x1A, 0x49, 0x69, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x82, 0x30, 0x57, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x83, 0x38, 0x57, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x84, 0x31, 0x5E, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x85, 0x39, 0x5E, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x87, 0x77, 0x57, 0xE9,
-       0x8B, 0x3E, 0xBF, 0xEA,
-
-       0x80, 0x30, 0x57, 0xE9,
-       0x81, 0x38, 0x57, 0xE9,
-
-       0x82, 0x31, 0x57, 0xE9,
-       0x86, 0x78, 0x57, 0xE9,
-
-       0x83, 0x39, 0x57, 0xE9,
-       0x87, 0x79, 0x57, 0xE9,
-
-       0x30, 0x1F, 0x5F, 0xE9,
-       0x8A, 0x34, 0x20, 0xE9,
-
-       0x8B, 0x3C, 0x20, 0xE9,
-       0x37, 0x50, 0x60, 0xBD,
-
-       0x57, 0x0D, 0x20, 0xE9,
-       0x35, 0x51, 0x61, 0xBD,
-
-       0x2B, 0x50, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x0E, 0x77,
-
-       0x24, 0x51, 0x20, 0xE9,
-       0x9B, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x0E, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x0B, 0x46, 0xA0, 0xE8,
-       0x1B, 0x56, 0xA0, 0xE8,
-
-       0x2B, 0x66, 0xA0, 0xE8,
-       0x0C, 0x47, 0xA0, 0xE8,
-
-       0x1C, 0x57, 0xA0, 0xE8,
-       0x2C, 0x67, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x57, 0x80, 0x57, 0xCF,
-
-       0x66, 0x33, 0x66, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x67, 0x3B, 0x67, 0xCF,
-
-       0x0B, 0x48, 0xA0, 0xE8,
-       0x1B, 0x58, 0xA0, 0xE8,
-
-       0x2B, 0x68, 0xA0, 0xE8,
-       0x0C, 0x49, 0xA0, 0xE8,
-
-       0x1C, 0x59, 0xA0, 0xE8,
-       0x2C, 0x69, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x34, 0xD7, 0x34, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3C, 0xD7, 0x3C, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x34, 0x80, 0x34, 0xBD,
-       0x3C, 0x80, 0x3C, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x48, 0x80, 0x48, 0xCF,
-       0x59, 0x80, 0x59, 0xCF,
-
-       0x68, 0x33, 0x68, 0xCF,
-       0x49, 0x3B, 0x49, 0xCF,
-
-       0xBA, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x58, 0x33, 0x58, 0xCF,
-       0x69, 0x3B, 0x69, 0xCF,
-
-       0x79, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_t2gzaf[] = {
-
-       0x00, 0x8A, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x0A, 0x40, 0x50, 0xBF,
-       0x2A, 0x40, 0x60, 0xBF,
-
-       0x32, 0x41, 0x51, 0xBF,
-       0x3A, 0x41, 0x61, 0xBF,
-
-       0xC3, 0x6B,
-       0xD3, 0x6B,
-       0x00, 0x8A, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x23, 0x9F,
-       0x00, 0xE0,
-       0x51, 0x04,
-
-       0x90, 0xE2,
-       0x61, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x51, 0x41, 0xE0, 0xEC,
-       0x39, 0x67, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x63, 0xA0, 0xE8,
-
-       0x61, 0x41, 0xE0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x81, 0x80, 0x15, 0xEA,
-       0x10, 0x04,
-       0x20, 0x04,
-
-       0x61, 0x51, 0xE0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x52, 0xBF,
-       0x0F, 0x52, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x62, 0xBF,
-       0x1E, 0x51, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x0E, 0x61, 0x60, 0xEA,
-
-       0x32, 0x40, 0x50, 0xBD,
-       0x22, 0x40, 0x60, 0xBD,
-
-       0x12, 0x41, 0x51, 0xBD,
-       0x3A, 0x41, 0x61, 0xBD,
-
-       0xBF, 0x2F, 0x0E, 0xBD,
-       0x97, 0xE2,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x35, 0x48, 0xB1, 0xE8,
-       0x3D, 0x59, 0xB1, 0xE8,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x56, 0x31, 0x56, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x66, 0x31, 0x66, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x57, 0x39, 0x57, 0xBF,
-       0x67, 0x39, 0x67, 0xBF,
-
-       0x72, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x35, 0x00,
-       0x3D, 0x00,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0x8D, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x75, 0xF8, 0xEC,
-       0x35, 0x20,
-       0x3D, 0x20,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x53, 0x53, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x0E, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x48, 0x35, 0x48, 0xBF,
-       0x58, 0x35, 0x58, 0xBF,
-
-       0x68, 0x35, 0x68, 0xBF,
-       0x49, 0x3D, 0x49, 0xBF,
-
-       0x59, 0x3D, 0x59, 0xBF,
-       0x69, 0x3D, 0x69, 0xBF,
-
-       0x63, 0x63, 0x2D, 0xDF,
-       0x4D, 0x7D, 0xF8, 0xEC,
-
-       0x59, 0xE3,
-       0x00, 0xE0,
-       0xB8, 0x38, 0x33, 0xBF,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x18, 0x3A, 0x41, 0xE9,
-
-       0x3F, 0x53, 0xA0, 0xE8,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x63, 0xA0, 0xE8,
-
-       0x50, 0x70, 0xF8, 0xEC,
-       0x2B, 0x50, 0x3C, 0xE9,
-
-       0x1F, 0x0F, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x59, 0x78, 0xF8, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x56, 0x3F, 0x56, 0xDF,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x66, 0x3D, 0x66, 0xDF,
-
-       0x1D, 0x32, 0x41, 0xE9,
-       0x67, 0x3D, 0x67, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3F, 0x57, 0xDF,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x59, 0x3F, 0x59, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x69, 0x3D, 0x69, 0xDF,
-
-       0x48, 0x37, 0x48, 0xDF,
-       0x58, 0x3F, 0x58, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x68, 0x3D, 0x68, 0xDF,
-       0x49, 0x37, 0x49, 0xDF,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x0A, 0x44, 0x54, 0xB0,
-       0x02, 0x44, 0x64, 0xB0,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x34, 0x37, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x54, 0xB2,
-       0x1A, 0x44, 0x64, 0xB2,
-
-       0x2E, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x3D, 0xCF, 0x74, 0xC2,
-       0x0F, 0xCF, 0x74, 0xC6,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x9C, 0x0F, 0x20, 0xE9,
-
-       0x0A, 0x44, 0x54, 0xB4,
-       0x02, 0x44, 0x64, 0xB4,
-
-       0x2A, 0x44, 0x54, 0xB6,
-       0x1A, 0x44, 0x64, 0xB6,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x38, 0x3D, 0x20, 0xE9,
-
-       0x0A, 0x20,
-       0x02, 0x20,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x3D, 0xCF, 0x75, 0xC6,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x0A, 0x45, 0x55, 0xB6,
-       0x02, 0x45, 0x65, 0xB6,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x3D, 0x20, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x2A, 0x46, 0x56, 0xBF,
-       0x1A, 0x46, 0x66, 0xBF,
-
-       0x0A, 0x47, 0x57, 0xBF,
-       0x02, 0x47, 0x67, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x36, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x37, 0x38, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x9D, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x9E, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x53, 0xBF,
-       0x1A, 0x43, 0x63, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x35, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x39, 0x38, 0x4F, 0xE9,
-
-       0x0A, 0x48, 0x58, 0xBF,
-       0x02, 0x48, 0x68, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x2A, 0x49, 0x59, 0xBF,
-       0x1A, 0x49, 0x69, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x82, 0x30, 0x57, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x83, 0x38, 0x57, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x84, 0x31, 0x5E, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x85, 0x39, 0x5E, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x87, 0x77, 0x57, 0xE9,
-       0x8B, 0x3E, 0xBF, 0xEA,
-
-       0x80, 0x30, 0x57, 0xE9,
-       0x81, 0x38, 0x57, 0xE9,
-
-       0x82, 0x31, 0x57, 0xE9,
-       0x86, 0x78, 0x57, 0xE9,
-
-       0x83, 0x39, 0x57, 0xE9,
-       0x87, 0x79, 0x57, 0xE9,
-
-       0x30, 0x1F, 0x5F, 0xE9,
-       0x8A, 0x34, 0x20, 0xE9,
-
-       0x8B, 0x3C, 0x20, 0xE9,
-       0x37, 0x50, 0x60, 0xBD,
-
-       0x57, 0x0D, 0x20, 0xE9,
-       0x35, 0x51, 0x61, 0xBD,
-
-       0x2B, 0x50, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x0E, 0x77,
-
-       0x24, 0x51, 0x20, 0xE9,
-       0x96, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x0E, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x0B, 0x46, 0xA0, 0xE8,
-       0x1B, 0x56, 0xA0, 0xE8,
-
-       0x2B, 0x66, 0xA0, 0xE8,
-       0x0C, 0x47, 0xA0, 0xE8,
-
-       0x1C, 0x57, 0xA0, 0xE8,
-       0x2C, 0x67, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x57, 0x80, 0x57, 0xCF,
-
-       0x66, 0x33, 0x66, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x67, 0x3B, 0x67, 0xCF,
-
-       0x0B, 0x48, 0xA0, 0xE8,
-       0x1B, 0x58, 0xA0, 0xE8,
-
-       0x2B, 0x68, 0xA0, 0xE8,
-       0x0C, 0x49, 0xA0, 0xE8,
-
-       0x1C, 0x59, 0xA0, 0xE8,
-       0x2C, 0x69, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x34, 0xD7, 0x34, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3C, 0xD7, 0x3C, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x34, 0x80, 0x34, 0xBD,
-       0x3C, 0x80, 0x3C, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x48, 0x80, 0x48, 0xCF,
-       0x59, 0x80, 0x59, 0xCF,
-
-       0x68, 0x33, 0x68, 0xCF,
-       0x49, 0x3B, 0x49, 0xCF,
-
-       0xB5, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x58, 0x33, 0x58, 0xCF,
-       0x69, 0x3B, 0x69, 0xCF,
-
-       0x74, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_t2gzf[] = {
-
-       0x00, 0x8A, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x0A, 0x40, 0x50, 0xBF,
-       0x2A, 0x40, 0x60, 0xBF,
-
-       0x32, 0x41, 0x51, 0xBF,
-       0x3A, 0x41, 0x61, 0xBF,
-
-       0xC3, 0x6B,
-       0xD3, 0x6B,
-       0x00, 0x8A, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x23, 0x9F,
-       0x00, 0xE0,
-       0x51, 0x04,
-
-       0x90, 0xE2,
-       0x61, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x51, 0x41, 0xE0, 0xEC,
-       0x39, 0x67, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x63, 0xA0, 0xE8,
-
-       0x61, 0x41, 0xE0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x7D, 0x80, 0x15, 0xEA,
-       0x10, 0x04,
-       0x20, 0x04,
-
-       0x61, 0x51, 0xE0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x52, 0xBF,
-       0x0F, 0x52, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x62, 0xBF,
-       0x1E, 0x51, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x0E, 0x61, 0x60, 0xEA,
-
-       0x32, 0x40, 0x50, 0xBD,
-       0x22, 0x40, 0x60, 0xBD,
-
-       0x12, 0x41, 0x51, 0xBD,
-       0x3A, 0x41, 0x61, 0xBD,
-
-       0xBF, 0x2F, 0x0E, 0xBD,
-       0x97, 0xE2,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x35, 0x48, 0xB1, 0xE8,
-       0x3D, 0x59, 0xB1, 0xE8,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x56, 0x31, 0x56, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x66, 0x31, 0x66, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x57, 0x39, 0x57, 0xBF,
-       0x67, 0x39, 0x67, 0xBF,
-
-       0x6E, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x35, 0x00,
-       0x3D, 0x00,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0x8D, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x75, 0xF8, 0xEC,
-       0x35, 0x20,
-       0x3D, 0x20,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x53, 0x53, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x0E, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x48, 0x35, 0x48, 0xBF,
-       0x58, 0x35, 0x58, 0xBF,
-
-       0x68, 0x35, 0x68, 0xBF,
-       0x49, 0x3D, 0x49, 0xBF,
-
-       0x59, 0x3D, 0x59, 0xBF,
-       0x69, 0x3D, 0x69, 0xBF,
-
-       0x63, 0x63, 0x2D, 0xDF,
-       0x4D, 0x7D, 0xF8, 0xEC,
-
-       0x59, 0xE3,
-       0x00, 0xE0,
-       0xB8, 0x38, 0x33, 0xBF,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x18, 0x3A, 0x41, 0xE9,
-
-       0x3F, 0x53, 0xA0, 0xE8,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x63, 0xA0, 0xE8,
-
-       0x50, 0x70, 0xF8, 0xEC,
-       0x2B, 0x50, 0x3C, 0xE9,
-
-       0x1F, 0x0F, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x59, 0x78, 0xF8, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x56, 0x3F, 0x56, 0xDF,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x66, 0x3D, 0x66, 0xDF,
-
-       0x1D, 0x32, 0x41, 0xE9,
-       0x67, 0x3D, 0x67, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3F, 0x57, 0xDF,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x59, 0x3F, 0x59, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x69, 0x3D, 0x69, 0xDF,
-
-       0x48, 0x37, 0x48, 0xDF,
-       0x58, 0x3F, 0x58, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x68, 0x3D, 0x68, 0xDF,
-       0x49, 0x37, 0x49, 0xDF,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x34, 0x80, 0x20, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x0F, 0xCF, 0x75, 0xC6,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x0A, 0x44, 0x54, 0xB0,
-       0x02, 0x44, 0x64, 0xB0,
-
-       0x2A, 0x44, 0x54, 0xB2,
-       0x1A, 0x44, 0x64, 0xB2,
-
-       0x28, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x3D, 0xCF, 0x74, 0xC2,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x31, 0x0F, 0x20, 0xE9,
-
-       0x0A, 0x44, 0x54, 0xB4,
-       0x02, 0x44, 0x64, 0xB4,
-
-       0x2A, 0x45, 0x55, 0xB6,
-       0x1A, 0x45, 0x65, 0xB6,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x38, 0x3D, 0x20, 0xE9,
-
-       0x0A, 0x20,
-       0x02, 0x20,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x0A, 0x47, 0x57, 0xBF,
-       0x02, 0x47, 0x67, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x46, 0x56, 0xBF,
-       0x1A, 0x46, 0x66, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x36, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x37, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x53, 0xBF,
-       0x1A, 0x43, 0x63, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x35, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x39, 0x39, 0x4F, 0xE9,
-
-       0x0A, 0x48, 0x58, 0xBF,
-       0x02, 0x48, 0x68, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x2A, 0x49, 0x59, 0xBF,
-       0x1A, 0x49, 0x69, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x82, 0x30, 0x57, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x83, 0x38, 0x57, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x84, 0x31, 0x5E, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x85, 0x39, 0x5E, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x87, 0x77, 0x57, 0xE9,
-       0x8B, 0x3E, 0xBF, 0xEA,
-
-       0x80, 0x30, 0x57, 0xE9,
-       0x81, 0x38, 0x57, 0xE9,
-
-       0x82, 0x31, 0x57, 0xE9,
-       0x86, 0x78, 0x57, 0xE9,
-
-       0x83, 0x39, 0x57, 0xE9,
-       0x87, 0x79, 0x57, 0xE9,
-
-       0x30, 0x1F, 0x5F, 0xE9,
-       0x8A, 0x34, 0x20, 0xE9,
-
-       0x8B, 0x3C, 0x20, 0xE9,
-       0x37, 0x50, 0x60, 0xBD,
-
-       0x57, 0x0D, 0x20, 0xE9,
-       0x35, 0x51, 0x61, 0xBD,
-
-       0x2B, 0x50, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x0E, 0x77,
-
-       0x24, 0x51, 0x20, 0xE9,
-       0x9A, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x0E, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x0B, 0x46, 0xA0, 0xE8,
-       0x1B, 0x56, 0xA0, 0xE8,
-
-       0x2B, 0x66, 0xA0, 0xE8,
-       0x0C, 0x47, 0xA0, 0xE8,
-
-       0x1C, 0x57, 0xA0, 0xE8,
-       0x2C, 0x67, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x57, 0x80, 0x57, 0xCF,
-
-       0x66, 0x33, 0x66, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x67, 0x3B, 0x67, 0xCF,
-
-       0x0B, 0x48, 0xA0, 0xE8,
-       0x1B, 0x58, 0xA0, 0xE8,
-
-       0x2B, 0x68, 0xA0, 0xE8,
-       0x0C, 0x49, 0xA0, 0xE8,
-
-       0x1C, 0x59, 0xA0, 0xE8,
-       0x2C, 0x69, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x34, 0xD7, 0x34, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3C, 0xD7, 0x3C, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x34, 0x80, 0x34, 0xBD,
-       0x3C, 0x80, 0x3C, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x48, 0x80, 0x48, 0xCF,
-       0x59, 0x80, 0x59, 0xCF,
-
-       0x68, 0x33, 0x68, 0xCF,
-       0x49, 0x3B, 0x49, 0xCF,
-
-       0xBB, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x58, 0x33, 0x58, 0xCF,
-       0x69, 0x3B, 0x69, 0xCF,
-
-       0x78, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_t2gzs[] = {
-
-       0x00, 0x8A, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x0A, 0x40, 0x50, 0xBF,
-       0x2A, 0x40, 0x60, 0xBF,
-
-       0x32, 0x41, 0x51, 0xBF,
-       0x3A, 0x41, 0x61, 0xBF,
-
-       0xC3, 0x6B,
-       0xD3, 0x6B,
-       0x00, 0x8A, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x23, 0x9F,
-       0x00, 0xE0,
-       0x51, 0x04,
-
-       0x90, 0xE2,
-       0x61, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x51, 0x41, 0xE0, 0xEC,
-       0x39, 0x67, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x63, 0xA0, 0xE8,
-
-       0x61, 0x41, 0xE0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x85, 0x80, 0x15, 0xEA,
-       0x10, 0x04,
-       0x20, 0x04,
-
-       0x61, 0x51, 0xE0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x52, 0xBF,
-       0x0F, 0x52, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x62, 0xBF,
-       0x1E, 0x51, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x0E, 0x61, 0x60, 0xEA,
-
-       0x32, 0x40, 0x50, 0xBD,
-       0x22, 0x40, 0x60, 0xBD,
-
-       0x12, 0x41, 0x51, 0xBD,
-       0x3A, 0x41, 0x61, 0xBD,
-
-       0xBF, 0x2F, 0x0E, 0xBD,
-       0x97, 0xE2,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x35, 0x48, 0xB1, 0xE8,
-       0x3D, 0x59, 0xB1, 0xE8,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x56, 0x31, 0x56, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x66, 0x31, 0x66, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x57, 0x39, 0x57, 0xBF,
-       0x67, 0x39, 0x67, 0xBF,
-
-       0x76, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x35, 0x00,
-       0x3D, 0x00,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0x8D, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x75, 0xF8, 0xEC,
-       0x35, 0x20,
-       0x3D, 0x20,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x53, 0x53, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x0E, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x48, 0x35, 0x48, 0xBF,
-       0x58, 0x35, 0x58, 0xBF,
-
-       0x68, 0x35, 0x68, 0xBF,
-       0x49, 0x3D, 0x49, 0xBF,
-
-       0x59, 0x3D, 0x59, 0xBF,
-       0x69, 0x3D, 0x69, 0xBF,
-
-       0x63, 0x63, 0x2D, 0xDF,
-       0x4D, 0x7D, 0xF8, 0xEC,
-
-       0x59, 0xE3,
-       0x00, 0xE0,
-       0xB8, 0x38, 0x33, 0xBF,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x18, 0x3A, 0x41, 0xE9,
-
-       0x3F, 0x53, 0xA0, 0xE8,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x63, 0xA0, 0xE8,
-
-       0x50, 0x70, 0xF8, 0xEC,
-       0x2B, 0x50, 0x3C, 0xE9,
-
-       0x1F, 0x0F, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x59, 0x78, 0xF8, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x56, 0x3F, 0x56, 0xDF,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x66, 0x3D, 0x66, 0xDF,
-
-       0x1D, 0x32, 0x41, 0xE9,
-       0x67, 0x3D, 0x67, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3F, 0x57, 0xDF,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x59, 0x3F, 0x59, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x69, 0x3D, 0x69, 0xDF,
-
-       0x48, 0x37, 0x48, 0xDF,
-       0x58, 0x3F, 0x58, 0xDF,
-
-       0x68, 0x3D, 0x68, 0xDF,
-       0x49, 0x37, 0x49, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x0F, 0xCF, 0x74, 0xC2,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x0A, 0x44, 0x54, 0xB0,
-       0x02, 0x44, 0x64, 0xB0,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x34, 0x37, 0x20, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x38, 0x0F, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x54, 0xB2,
-       0x1A, 0x44, 0x64, 0xB2,
-
-       0x31, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x0F, 0xCF, 0x75, 0xC0,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x3D, 0xCF, 0x75, 0xC2,
-       0x37, 0xCF, 0x75, 0xC4,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA6, 0x0F, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA3, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x54, 0xB4,
-       0x1A, 0x44, 0x64, 0xB4,
-
-       0x0A, 0x45, 0x55, 0xB0,
-       0x02, 0x45, 0x65, 0xB0,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA0, 0x37, 0x20, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x2A, 0x45, 0x55, 0xB2,
-       0x1A, 0x45, 0x65, 0xB2,
-
-       0x0A, 0x45, 0x55, 0xB4,
-       0x02, 0x45, 0x65, 0xB4,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x20,
-       0x1A, 0x20,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x2A, 0x46, 0x56, 0xBF,
-       0x1A, 0x46, 0x66, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x36, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x37, 0x39, 0x4F, 0xE9,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0xA7, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0xA8, 0x38, 0x4F, 0xE9,
-
-       0x0A, 0x47, 0x57, 0xBF,
-       0x02, 0x47, 0x67, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA4, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA5, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x53, 0xBF,
-       0x1A, 0x43, 0x63, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0xA1, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0xA2, 0x38, 0x4F, 0xE9,
-
-       0x0A, 0x48, 0x58, 0xBF,
-       0x02, 0x48, 0x68, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x2A, 0x49, 0x59, 0xBF,
-       0x1A, 0x49, 0x69, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x82, 0x30, 0x57, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x83, 0x38, 0x57, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x84, 0x31, 0x5E, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x85, 0x39, 0x5E, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x87, 0x77, 0x57, 0xE9,
-       0x8B, 0x3E, 0xBF, 0xEA,
-
-       0x80, 0x30, 0x57, 0xE9,
-       0x81, 0x38, 0x57, 0xE9,
-
-       0x82, 0x31, 0x57, 0xE9,
-       0x86, 0x78, 0x57, 0xE9,
-
-       0x83, 0x39, 0x57, 0xE9,
-       0x87, 0x79, 0x57, 0xE9,
-
-       0x30, 0x1F, 0x5F, 0xE9,
-       0x8A, 0x34, 0x20, 0xE9,
-
-       0x8B, 0x3C, 0x20, 0xE9,
-       0x37, 0x50, 0x60, 0xBD,
-
-       0x57, 0x0D, 0x20, 0xE9,
-       0x35, 0x51, 0x61, 0xBD,
-
-       0x2B, 0x50, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x0E, 0x77,
-
-       0x24, 0x51, 0x20, 0xE9,
-       0x92, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x0E, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x0B, 0x46, 0xA0, 0xE8,
-       0x1B, 0x56, 0xA0, 0xE8,
-
-       0x2B, 0x66, 0xA0, 0xE8,
-       0x0C, 0x47, 0xA0, 0xE8,
-
-       0x1C, 0x57, 0xA0, 0xE8,
-       0x2C, 0x67, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x57, 0x80, 0x57, 0xCF,
-
-       0x66, 0x33, 0x66, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x67, 0x3B, 0x67, 0xCF,
-
-       0x0B, 0x48, 0xA0, 0xE8,
-       0x1B, 0x58, 0xA0, 0xE8,
-
-       0x2B, 0x68, 0xA0, 0xE8,
-       0x0C, 0x49, 0xA0, 0xE8,
-
-       0x1C, 0x59, 0xA0, 0xE8,
-       0x2C, 0x69, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x34, 0xD7, 0x34, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3C, 0xD7, 0x3C, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x34, 0x80, 0x34, 0xBD,
-       0x3C, 0x80, 0x3C, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x48, 0x80, 0x48, 0xCF,
-       0x59, 0x80, 0x59, 0xCF,
-
-       0x68, 0x33, 0x68, 0xCF,
-       0x49, 0x3B, 0x49, 0xCF,
-
-       0xB2, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x58, 0x33, 0x58, 0xCF,
-       0x69, 0x3B, 0x69, 0xCF,
-
-       0x70, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_t2gzsa[] = {
-
-       0x00, 0x8A, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x0A, 0x40, 0x50, 0xBF,
-       0x2A, 0x40, 0x60, 0xBF,
-
-       0x32, 0x41, 0x51, 0xBF,
-       0x3A, 0x41, 0x61, 0xBF,
-
-       0xC3, 0x6B,
-       0xD3, 0x6B,
-       0x00, 0x8A, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x23, 0x9F,
-       0x00, 0xE0,
-       0x51, 0x04,
-
-       0x90, 0xE2,
-       0x61, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x51, 0x41, 0xE0, 0xEC,
-       0x39, 0x67, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x63, 0xA0, 0xE8,
-
-       0x61, 0x41, 0xE0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x8A, 0x80, 0x15, 0xEA,
-       0x10, 0x04,
-       0x20, 0x04,
-
-       0x61, 0x51, 0xE0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x52, 0xBF,
-       0x0F, 0x52, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x62, 0xBF,
-       0x1E, 0x51, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x0E, 0x61, 0x60, 0xEA,
-
-       0x32, 0x40, 0x50, 0xBD,
-       0x22, 0x40, 0x60, 0xBD,
-
-       0x12, 0x41, 0x51, 0xBD,
-       0x3A, 0x41, 0x61, 0xBD,
-
-       0xBF, 0x2F, 0x0E, 0xBD,
-       0x97, 0xE2,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x35, 0x48, 0xB1, 0xE8,
-       0x3D, 0x59, 0xB1, 0xE8,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x56, 0x31, 0x56, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x66, 0x31, 0x66, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x57, 0x39, 0x57, 0xBF,
-       0x67, 0x39, 0x67, 0xBF,
-
-       0x7B, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x35, 0x00,
-       0x3D, 0x00,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0x8D, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x75, 0xF8, 0xEC,
-       0x35, 0x20,
-       0x3D, 0x20,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x53, 0x53, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x0E, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x48, 0x35, 0x48, 0xBF,
-       0x58, 0x35, 0x58, 0xBF,
-
-       0x68, 0x35, 0x68, 0xBF,
-       0x49, 0x3D, 0x49, 0xBF,
-
-       0x59, 0x3D, 0x59, 0xBF,
-       0x69, 0x3D, 0x69, 0xBF,
-
-       0x63, 0x63, 0x2D, 0xDF,
-       0x4D, 0x7D, 0xF8, 0xEC,
-
-       0x59, 0xE3,
-       0x00, 0xE0,
-       0xB8, 0x38, 0x33, 0xBF,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x18, 0x3A, 0x41, 0xE9,
-
-       0x3F, 0x53, 0xA0, 0xE8,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x63, 0xA0, 0xE8,
-
-       0x50, 0x70, 0xF8, 0xEC,
-       0x2B, 0x50, 0x3C, 0xE9,
-
-       0x1F, 0x0F, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x59, 0x78, 0xF8, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x56, 0x3F, 0x56, 0xDF,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x66, 0x3D, 0x66, 0xDF,
-
-       0x1D, 0x32, 0x41, 0xE9,
-       0x67, 0x3D, 0x67, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3F, 0x57, 0xDF,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x59, 0x3F, 0x59, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x69, 0x3D, 0x69, 0xDF,
-
-       0x48, 0x37, 0x48, 0xDF,
-       0x58, 0x3F, 0x58, 0xDF,
-
-       0x68, 0x3D, 0x68, 0xDF,
-       0x49, 0x37, 0x49, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x0F, 0xCF, 0x74, 0xC2,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x0A, 0x44, 0x54, 0xB0,
-       0x02, 0x44, 0x64, 0xB0,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x34, 0x37, 0x20, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x38, 0x0F, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x54, 0xB2,
-       0x1A, 0x44, 0x64, 0xB2,
-
-       0x36, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x0F, 0xCF, 0x75, 0xC0,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x3D, 0xCF, 0x75, 0xC2,
-       0x37, 0xCF, 0x75, 0xC4,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA6, 0x0F, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA3, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x54, 0xB4,
-       0x1A, 0x44, 0x64, 0xB4,
-
-       0x0A, 0x45, 0x55, 0xB0,
-       0x02, 0x45, 0x65, 0xB0,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA0, 0x37, 0x20, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x45, 0x55, 0xB2,
-       0x1A, 0x45, 0x65, 0xB2,
-
-       0x0A, 0x45, 0x55, 0xB4,
-       0x02, 0x45, 0x65, 0xB4,
-
-       0x0F, 0xCF, 0x74, 0xC6,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA7, 0x30, 0x4F, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x9C, 0x0F, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA8, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x44, 0x54, 0xB6,
-       0x1A, 0x44, 0x64, 0xB6,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x36, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x37, 0x39, 0x4F, 0xE9,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x2A, 0x46, 0x56, 0xBF,
-       0x1A, 0x46, 0x66, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA4, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA5, 0x39, 0x4F, 0xE9,
-
-       0x0A, 0x47, 0x57, 0xBF,
-       0x02, 0x47, 0x67, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA1, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA2, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x53, 0xBF,
-       0x1A, 0x43, 0x63, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x9D, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x9E, 0x39, 0x4F, 0xE9,
-
-       0x0A, 0x48, 0x58, 0xBF,
-       0x02, 0x48, 0x68, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x2A, 0x49, 0x59, 0xBF,
-       0x1A, 0x49, 0x69, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x82, 0x30, 0x57, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x83, 0x38, 0x57, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x84, 0x31, 0x5E, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x85, 0x39, 0x5E, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x87, 0x77, 0x57, 0xE9,
-       0x8B, 0x3E, 0xBF, 0xEA,
-
-       0x80, 0x30, 0x57, 0xE9,
-       0x81, 0x38, 0x57, 0xE9,
-
-       0x82, 0x31, 0x57, 0xE9,
-       0x86, 0x78, 0x57, 0xE9,
-
-       0x83, 0x39, 0x57, 0xE9,
-       0x87, 0x79, 0x57, 0xE9,
-
-       0x30, 0x1F, 0x5F, 0xE9,
-       0x8A, 0x34, 0x20, 0xE9,
-
-       0x8B, 0x3C, 0x20, 0xE9,
-       0x37, 0x50, 0x60, 0xBD,
-
-       0x57, 0x0D, 0x20, 0xE9,
-       0x35, 0x51, 0x61, 0xBD,
-
-       0x2B, 0x50, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x0E, 0x77,
-
-       0x24, 0x51, 0x20, 0xE9,
-       0x8D, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x0E, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x0B, 0x46, 0xA0, 0xE8,
-       0x1B, 0x56, 0xA0, 0xE8,
-
-       0x2B, 0x66, 0xA0, 0xE8,
-       0x0C, 0x47, 0xA0, 0xE8,
-
-       0x1C, 0x57, 0xA0, 0xE8,
-       0x2C, 0x67, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x57, 0x80, 0x57, 0xCF,
-
-       0x66, 0x33, 0x66, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x67, 0x3B, 0x67, 0xCF,
-
-       0x0B, 0x48, 0xA0, 0xE8,
-       0x1B, 0x58, 0xA0, 0xE8,
-
-       0x2B, 0x68, 0xA0, 0xE8,
-       0x0C, 0x49, 0xA0, 0xE8,
-
-       0x1C, 0x59, 0xA0, 0xE8,
-       0x2C, 0x69, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x34, 0xD7, 0x34, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3C, 0xD7, 0x3C, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x34, 0x80, 0x34, 0xBD,
-       0x3C, 0x80, 0x3C, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x48, 0x80, 0x48, 0xCF,
-       0x59, 0x80, 0x59, 0xCF,
-
-       0x68, 0x33, 0x68, 0xCF,
-       0x49, 0x3B, 0x49, 0xCF,
-
-       0xAD, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x58, 0x33, 0x58, 0xCF,
-       0x69, 0x3B, 0x69, 0xCF,
-
-       0x6B, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_t2gzsaf[] = {
-
-       0x00, 0x8A, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x0A, 0x40, 0x50, 0xBF,
-       0x2A, 0x40, 0x60, 0xBF,
-
-       0x32, 0x41, 0x51, 0xBF,
-       0x3A, 0x41, 0x61, 0xBF,
-
-       0xC3, 0x6B,
-       0xD3, 0x6B,
-       0x00, 0x8A, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x23, 0x9F,
-       0x00, 0xE0,
-       0x51, 0x04,
-
-       0x90, 0xE2,
-       0x61, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x51, 0x41, 0xE0, 0xEC,
-       0x39, 0x67, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x63, 0xA0, 0xE8,
-
-       0x61, 0x41, 0xE0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x8E, 0x80, 0x15, 0xEA,
-       0x10, 0x04,
-       0x20, 0x04,
-
-       0x61, 0x51, 0xE0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x52, 0xBF,
-       0x0F, 0x52, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x62, 0xBF,
-       0x1E, 0x51, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x0E, 0x61, 0x60, 0xEA,
-
-       0x32, 0x40, 0x50, 0xBD,
-       0x22, 0x40, 0x60, 0xBD,
-
-       0x12, 0x41, 0x51, 0xBD,
-       0x3A, 0x41, 0x61, 0xBD,
-
-       0xBF, 0x2F, 0x0E, 0xBD,
-       0x97, 0xE2,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x35, 0x48, 0xB1, 0xE8,
-       0x3D, 0x59, 0xB1, 0xE8,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x56, 0x31, 0x56, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x66, 0x31, 0x66, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x57, 0x39, 0x57, 0xBF,
-       0x67, 0x39, 0x67, 0xBF,
-
-       0x7F, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x35, 0x00,
-       0x3D, 0x00,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0x8D, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x75, 0xF8, 0xEC,
-       0x35, 0x20,
-       0x3D, 0x20,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x53, 0x53, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x0E, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x48, 0x35, 0x48, 0xBF,
-       0x58, 0x35, 0x58, 0xBF,
-
-       0x68, 0x35, 0x68, 0xBF,
-       0x49, 0x3D, 0x49, 0xBF,
-
-       0x59, 0x3D, 0x59, 0xBF,
-       0x69, 0x3D, 0x69, 0xBF,
-
-       0x63, 0x63, 0x2D, 0xDF,
-       0x4D, 0x7D, 0xF8, 0xEC,
-
-       0x59, 0xE3,
-       0x00, 0xE0,
-       0xB8, 0x38, 0x33, 0xBF,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x18, 0x3A, 0x41, 0xE9,
-
-       0x3F, 0x53, 0xA0, 0xE8,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x63, 0xA0, 0xE8,
-
-       0x50, 0x70, 0xF8, 0xEC,
-       0x2B, 0x50, 0x3C, 0xE9,
-
-       0x1F, 0x0F, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x59, 0x78, 0xF8, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x56, 0x3F, 0x56, 0xDF,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x66, 0x3D, 0x66, 0xDF,
-
-       0x1D, 0x32, 0x41, 0xE9,
-       0x67, 0x3D, 0x67, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3F, 0x57, 0xDF,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x59, 0x3F, 0x59, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x69, 0x3D, 0x69, 0xDF,
-
-       0x48, 0x37, 0x48, 0xDF,
-       0x58, 0x3F, 0x58, 0xDF,
-
-       0x68, 0x3D, 0x68, 0xDF,
-       0x49, 0x37, 0x49, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x0F, 0xCF, 0x74, 0xC2,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x0A, 0x44, 0x54, 0xB0,
-       0x02, 0x44, 0x64, 0xB0,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x34, 0x37, 0x20, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x38, 0x0F, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x54, 0xB2,
-       0x1A, 0x44, 0x64, 0xB2,
-
-       0x3A, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x0F, 0xCF, 0x75, 0xC0,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x3D, 0xCF, 0x75, 0xC2,
-       0x37, 0xCF, 0x75, 0xC4,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA6, 0x0F, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA3, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x54, 0xB4,
-       0x1A, 0x44, 0x64, 0xB4,
-
-       0x0A, 0x45, 0x55, 0xB0,
-       0x02, 0x45, 0x65, 0xB0,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA0, 0x37, 0x20, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x45, 0x55, 0xB2,
-       0x1A, 0x45, 0x65, 0xB2,
-
-       0x0A, 0x45, 0x55, 0xB4,
-       0x02, 0x45, 0x65, 0xB4,
-
-       0x0F, 0xCF, 0x74, 0xC6,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA7, 0x30, 0x4F, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x9C, 0x0F, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA8, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x44, 0x54, 0xB6,
-       0x1A, 0x44, 0x64, 0xB6,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x36, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x37, 0x39, 0x4F, 0xE9,
-
-       0x0A, 0x45, 0x55, 0xB6,
-       0x02, 0x45, 0x65, 0xB6,
-
-       0x3D, 0xCF, 0x75, 0xC6,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x2A, 0x46, 0x56, 0xBF,
-       0x1A, 0x46, 0x66, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA4, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA5, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x3D, 0x20, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x0A, 0x47, 0x57, 0xBF,
-       0x02, 0x47, 0x67, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0xA1, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0xA2, 0x38, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x9D, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x9E, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x53, 0xBF,
-       0x1A, 0x43, 0x63, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x35, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x39, 0x38, 0x4F, 0xE9,
-
-       0x0A, 0x48, 0x58, 0xBF,
-       0x02, 0x48, 0x68, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x2A, 0x49, 0x59, 0xBF,
-       0x1A, 0x49, 0x69, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x82, 0x30, 0x57, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x83, 0x38, 0x57, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x84, 0x31, 0x5E, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x85, 0x39, 0x5E, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x87, 0x77, 0x57, 0xE9,
-       0x8B, 0x3E, 0xBF, 0xEA,
-
-       0x80, 0x30, 0x57, 0xE9,
-       0x81, 0x38, 0x57, 0xE9,
-
-       0x82, 0x31, 0x57, 0xE9,
-       0x86, 0x78, 0x57, 0xE9,
-
-       0x83, 0x39, 0x57, 0xE9,
-       0x87, 0x79, 0x57, 0xE9,
-
-       0x30, 0x1F, 0x5F, 0xE9,
-       0x8A, 0x34, 0x20, 0xE9,
-
-       0x8B, 0x3C, 0x20, 0xE9,
-       0x37, 0x50, 0x60, 0xBD,
-
-       0x57, 0x0D, 0x20, 0xE9,
-       0x35, 0x51, 0x61, 0xBD,
-
-       0x2B, 0x50, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x0E, 0x77,
-
-       0x24, 0x51, 0x20, 0xE9,
-       0x89, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x0E, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x0B, 0x46, 0xA0, 0xE8,
-       0x1B, 0x56, 0xA0, 0xE8,
-
-       0x2B, 0x66, 0xA0, 0xE8,
-       0x0C, 0x47, 0xA0, 0xE8,
-
-       0x1C, 0x57, 0xA0, 0xE8,
-       0x2C, 0x67, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x57, 0x80, 0x57, 0xCF,
-
-       0x66, 0x33, 0x66, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x67, 0x3B, 0x67, 0xCF,
-
-       0x0B, 0x48, 0xA0, 0xE8,
-       0x1B, 0x58, 0xA0, 0xE8,
-
-       0x2B, 0x68, 0xA0, 0xE8,
-       0x0C, 0x49, 0xA0, 0xE8,
-
-       0x1C, 0x59, 0xA0, 0xE8,
-       0x2C, 0x69, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x34, 0xD7, 0x34, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3C, 0xD7, 0x3C, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x34, 0x80, 0x34, 0xBD,
-       0x3C, 0x80, 0x3C, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x48, 0x80, 0x48, 0xCF,
-       0x59, 0x80, 0x59, 0xCF,
-
-       0x68, 0x33, 0x68, 0xCF,
-       0x49, 0x3B, 0x49, 0xCF,
-
-       0xA9, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x58, 0x33, 0x58, 0xCF,
-       0x69, 0x3B, 0x69, 0xCF,
-
-       0x67, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_t2gzsf[] = {
-
-       0x00, 0x8A, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x0A, 0x40, 0x50, 0xBF,
-       0x2A, 0x40, 0x60, 0xBF,
-
-       0x32, 0x41, 0x51, 0xBF,
-       0x3A, 0x41, 0x61, 0xBF,
-
-       0xC3, 0x6B,
-       0xD3, 0x6B,
-       0x00, 0x8A, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x23, 0x9F,
-       0x00, 0xE0,
-       0x51, 0x04,
-
-       0x90, 0xE2,
-       0x61, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x51, 0x41, 0xE0, 0xEC,
-       0x39, 0x67, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x63, 0xA0, 0xE8,
-
-       0x61, 0x41, 0xE0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x8A, 0x80, 0x15, 0xEA,
-       0x10, 0x04,
-       0x20, 0x04,
-
-       0x61, 0x51, 0xE0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x52, 0xBF,
-       0x0F, 0x52, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x62, 0xBF,
-       0x1E, 0x51, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x0E, 0x61, 0x60, 0xEA,
-
-       0x32, 0x40, 0x50, 0xBD,
-       0x22, 0x40, 0x60, 0xBD,
-
-       0x12, 0x41, 0x51, 0xBD,
-       0x3A, 0x41, 0x61, 0xBD,
-
-       0xBF, 0x2F, 0x0E, 0xBD,
-       0x97, 0xE2,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x35, 0x48, 0xB1, 0xE8,
-       0x3D, 0x59, 0xB1, 0xE8,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x56, 0x31, 0x56, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x66, 0x31, 0x66, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x57, 0x39, 0x57, 0xBF,
-       0x67, 0x39, 0x67, 0xBF,
-
-       0x7B, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x35, 0x00,
-       0x3D, 0x00,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0x8D, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x75, 0xF8, 0xEC,
-       0x35, 0x20,
-       0x3D, 0x20,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x53, 0x53, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x0E, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x48, 0x35, 0x48, 0xBF,
-       0x58, 0x35, 0x58, 0xBF,
-
-       0x68, 0x35, 0x68, 0xBF,
-       0x49, 0x3D, 0x49, 0xBF,
-
-       0x59, 0x3D, 0x59, 0xBF,
-       0x69, 0x3D, 0x69, 0xBF,
-
-       0x63, 0x63, 0x2D, 0xDF,
-       0x4D, 0x7D, 0xF8, 0xEC,
-
-       0x59, 0xE3,
-       0x00, 0xE0,
-       0xB8, 0x38, 0x33, 0xBF,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x18, 0x3A, 0x41, 0xE9,
-
-       0x3F, 0x53, 0xA0, 0xE8,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x63, 0xA0, 0xE8,
-
-       0x50, 0x70, 0xF8, 0xEC,
-       0x2B, 0x50, 0x3C, 0xE9,
-
-       0x1F, 0x0F, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x59, 0x78, 0xF8, 0xEC,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x56, 0x3F, 0x56, 0xDF,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x66, 0x3D, 0x66, 0xDF,
-
-       0x1D, 0x32, 0x41, 0xE9,
-       0x67, 0x3D, 0x67, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3F, 0x57, 0xDF,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x59, 0x3F, 0x59, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x69, 0x3D, 0x69, 0xDF,
-
-       0x48, 0x37, 0x48, 0xDF,
-       0x58, 0x3F, 0x58, 0xDF,
-
-       0x68, 0x3D, 0x68, 0xDF,
-       0x49, 0x37, 0x49, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x0F, 0xCF, 0x74, 0xC2,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x0A, 0x44, 0x54, 0xB0,
-       0x02, 0x44, 0x64, 0xB0,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x34, 0x37, 0x20, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x38, 0x0F, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x54, 0xB2,
-       0x1A, 0x44, 0x64, 0xB2,
-
-       0x36, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x0F, 0xCF, 0x75, 0xC0,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x3D, 0xCF, 0x75, 0xC2,
-       0x37, 0xCF, 0x75, 0xC4,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA6, 0x0F, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA3, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x54, 0xB4,
-       0x1A, 0x44, 0x64, 0xB4,
-
-       0x0A, 0x45, 0x55, 0xB0,
-       0x02, 0x45, 0x65, 0xB0,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA0, 0x37, 0x20, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x45, 0x55, 0xB2,
-       0x1A, 0x45, 0x65, 0xB2,
-
-       0x0A, 0x45, 0x55, 0xB4,
-       0x02, 0x45, 0x65, 0xB4,
-
-       0x0F, 0xCF, 0x75, 0xC6,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA7, 0x30, 0x4F, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x31, 0x0F, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA8, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x45, 0x55, 0xB6,
-       0x1A, 0x45, 0x65, 0xB6,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x36, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x37, 0x39, 0x4F, 0xE9,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x2A, 0x46, 0x56, 0xBF,
-       0x1A, 0x46, 0x66, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA4, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA5, 0x39, 0x4F, 0xE9,
-
-       0x0A, 0x47, 0x57, 0xBF,
-       0x02, 0x47, 0x67, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA1, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA2, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x53, 0xBF,
-       0x1A, 0x43, 0x63, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x35, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x39, 0x39, 0x4F, 0xE9,
-
-       0x0A, 0x48, 0x58, 0xBF,
-       0x02, 0x48, 0x68, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x2A, 0x49, 0x59, 0xBF,
-       0x1A, 0x49, 0x69, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x82, 0x30, 0x57, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x83, 0x38, 0x57, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x84, 0x31, 0x5E, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x85, 0x39, 0x5E, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x87, 0x77, 0x57, 0xE9,
-       0x8B, 0x3E, 0xBF, 0xEA,
-
-       0x80, 0x30, 0x57, 0xE9,
-       0x81, 0x38, 0x57, 0xE9,
-
-       0x82, 0x31, 0x57, 0xE9,
-       0x86, 0x78, 0x57, 0xE9,
-
-       0x83, 0x39, 0x57, 0xE9,
-       0x87, 0x79, 0x57, 0xE9,
-
-       0x30, 0x1F, 0x5F, 0xE9,
-       0x8A, 0x34, 0x20, 0xE9,
-
-       0x8B, 0x3C, 0x20, 0xE9,
-       0x37, 0x50, 0x60, 0xBD,
-
-       0x57, 0x0D, 0x20, 0xE9,
-       0x35, 0x51, 0x61, 0xBD,
-
-       0x2B, 0x50, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x0E, 0x77,
-
-       0x24, 0x51, 0x20, 0xE9,
-       0x8D, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x0E, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x0B, 0x46, 0xA0, 0xE8,
-       0x1B, 0x56, 0xA0, 0xE8,
-
-       0x2B, 0x66, 0xA0, 0xE8,
-       0x0C, 0x47, 0xA0, 0xE8,
-
-       0x1C, 0x57, 0xA0, 0xE8,
-       0x2C, 0x67, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x57, 0x80, 0x57, 0xCF,
-
-       0x66, 0x33, 0x66, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x67, 0x3B, 0x67, 0xCF,
-
-       0x0B, 0x48, 0xA0, 0xE8,
-       0x1B, 0x58, 0xA0, 0xE8,
-
-       0x2B, 0x68, 0xA0, 0xE8,
-       0x0C, 0x49, 0xA0, 0xE8,
-
-       0x1C, 0x59, 0xA0, 0xE8,
-       0x2C, 0x69, 0xA0, 0xE8,
-
-       0x0B, 0x00,
-       0x1B, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x0C, 0x00,
-       0x1C, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x0B, 0x65,
-       0x1B, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x0C, 0x65,
-       0x1C, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x0B, 0x1B, 0x60, 0xEC,
-       0x34, 0xD7, 0x34, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x0C, 0x1C, 0x60, 0xEC,
-
-       0x3C, 0xD7, 0x3C, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x0B, 0x2B, 0xDE, 0xE8,
-       0x1B, 0x80, 0xDE, 0xE8,
-
-       0x34, 0x80, 0x34, 0xBD,
-       0x3C, 0x80, 0x3C, 0xBD,
-
-       0x33, 0xD7, 0x0B, 0xBD,
-       0x3B, 0xD7, 0x1B, 0xBD,
-
-       0x48, 0x80, 0x48, 0xCF,
-       0x59, 0x80, 0x59, 0xCF,
-
-       0x68, 0x33, 0x68, 0xCF,
-       0x49, 0x3B, 0x49, 0xCF,
-
-       0xAD, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x58, 0x33, 0x58, 0xCF,
-       0x69, 0x3B, 0x69, 0xCF,
-
-       0x6B, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_tgz[] = {
-
-       0x00, 0x88, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x22, 0x40, 0x48, 0xBF,
-       0x2A, 0x40, 0x50, 0xBF,
-
-       0x32, 0x41, 0x49, 0xBF,
-       0x3A, 0x41, 0x51, 0xBF,
-
-       0xC3, 0x6B,
-       0xCB, 0x6B,
-       0x00, 0x88, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x4B, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x29, 0x9F,
-       0x00, 0xE0,
-       0x49, 0x04,
-
-       0x90, 0xE2,
-       0x51, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x49, 0x41, 0xC0, 0xEC,
-       0x39, 0x57, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0x51, 0x41, 0xC0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x58, 0x80, 0x15, 0xEA,
-       0x08, 0x04,
-       0x10, 0x04,
-
-       0x51, 0x49, 0xC0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x4A, 0xBF,
-       0x27, 0x4A, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x52, 0xBF,
-       0x1E, 0x49, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x26, 0x51, 0x60, 0xEA,
-
-       0x32, 0x40, 0x48, 0xBD,
-       0x22, 0x40, 0x50, 0xBD,
-
-       0x12, 0x41, 0x49, 0xBD,
-       0x3A, 0x41, 0x51, 0xBD,
-
-       0xBF, 0x2F, 0x26, 0xBD,
-       0x00, 0xE0,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x4E, 0x31, 0x4E, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x56, 0x31, 0x56, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x4F, 0x39, 0x4F, 0xBF,
-       0x57, 0x39, 0x57, 0xBF,
-
-       0x4A, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x42, 0x73, 0xF8, 0xEC,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0xA5, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x4B, 0x4B, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x26, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x53, 0x53, 0x2D, 0xDF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xB8, 0x38, 0x33, 0xBF,
-       0x00, 0xE0,
-       0x59, 0xE3,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x3F, 0x4B, 0xA0, 0xE8,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x53, 0xA0, 0xE8,
-
-       0x48, 0x70, 0xF8, 0xEC,
-       0x2B, 0x48, 0x3C, 0xE9,
-
-       0x1F, 0x27, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x18, 0x3A, 0x41, 0xE9,
-       0x1D, 0x32, 0x41, 0xE9,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x56, 0x3D, 0x56, 0xDF,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x4E, 0x3F, 0x4E, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x4F, 0x3F, 0x4F, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3D, 0x57, 0xDF,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x34, 0x80, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x0A, 0x44, 0x4C, 0xB0,
-       0x02, 0x44, 0x54, 0xB0,
-
-       0x2A, 0x44, 0x4C, 0xB2,
-       0x1A, 0x44, 0x54, 0xB2,
-
-       0x1D, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x3D, 0xCF, 0x74, 0xC2,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x2A, 0x44, 0x4C, 0xB4,
-       0x1A, 0x44, 0x54, 0xB4,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x38, 0x3D, 0x20, 0xE9,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x2A, 0x46, 0x4E, 0xBF,
-       0x1A, 0x46, 0x56, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x0A, 0x47, 0x4F, 0xBF,
-       0x02, 0x47, 0x57, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x4B, 0xBF,
-       0x1A, 0x43, 0x53, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x36, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x37, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x37, 0x48, 0x50, 0xBD,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8B, 0x3E, 0x20, 0xE9,
-
-       0x82, 0x30, 0x57, 0xE9,
-       0x87, 0x77, 0x57, 0xE9,
-
-       0x83, 0x38, 0x57, 0xE9,
-       0x35, 0x49, 0x51, 0xBD,
-
-       0x84, 0x31, 0x5E, 0xE9,
-       0x30, 0x1F, 0x5F, 0xE9,
-
-       0x85, 0x39, 0x5E, 0xE9,
-       0x57, 0x25, 0x20, 0xE9,
-
-       0x2B, 0x48, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x26, 0x77,
-
-       0x24, 0x49, 0x20, 0xE9,
-       0xAF, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x26, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x1C, 0x46, 0xA0, 0xE8,
-       0x23, 0x4E, 0xA0, 0xE8,
-
-       0x2B, 0x56, 0xA0, 0xE8,
-       0x1D, 0x47, 0xA0, 0xE8,
-
-       0x24, 0x4F, 0xA0, 0xE8,
-       0x2C, 0x57, 0xA0, 0xE8,
-
-       0x1C, 0x00,
-       0x23, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x1D, 0x00,
-       0x24, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x1C, 0x65,
-       0x23, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x1D, 0x65,
-       0x24, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x1C, 0x23, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x1D, 0x24, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x1C, 0x2B, 0xDE, 0xE8,
-       0x23, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x1C, 0xBD,
-       0x3B, 0xD7, 0x23, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x4F, 0x80, 0x4F, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0xD6, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x4E, 0x33, 0x4E, 0xCF,
-       0x57, 0x3B, 0x57, 0xCF,
-
-       0x9D, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_tgza[] = {
-
-       0x00, 0x88, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x22, 0x40, 0x48, 0xBF,
-       0x2A, 0x40, 0x50, 0xBF,
-
-       0x32, 0x41, 0x49, 0xBF,
-       0x3A, 0x41, 0x51, 0xBF,
-
-       0xC3, 0x6B,
-       0xCB, 0x6B,
-       0x00, 0x88, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x4B, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x29, 0x9F,
-       0x00, 0xE0,
-       0x49, 0x04,
-
-       0x90, 0xE2,
-       0x51, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x49, 0x41, 0xC0, 0xEC,
-       0x39, 0x57, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0x51, 0x41, 0xC0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x5C, 0x80, 0x15, 0xEA,
-       0x08, 0x04,
-       0x10, 0x04,
-
-       0x51, 0x49, 0xC0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x4A, 0xBF,
-       0x27, 0x4A, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x52, 0xBF,
-       0x1E, 0x49, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x26, 0x51, 0x60, 0xEA,
-
-       0x32, 0x40, 0x48, 0xBD,
-       0x22, 0x40, 0x50, 0xBD,
-
-       0x12, 0x41, 0x49, 0xBD,
-       0x3A, 0x41, 0x51, 0xBD,
-
-       0xBF, 0x2F, 0x26, 0xBD,
-       0x00, 0xE0,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x4E, 0x31, 0x4E, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x56, 0x31, 0x56, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x4F, 0x39, 0x4F, 0xBF,
-       0x57, 0x39, 0x57, 0xBF,
-
-       0x4E, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x42, 0x73, 0xF8, 0xEC,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0xA5, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x4B, 0x4B, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x26, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x53, 0x53, 0x2D, 0xDF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xB8, 0x38, 0x33, 0xBF,
-       0x00, 0xE0,
-       0x59, 0xE3,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x3F, 0x4B, 0xA0, 0xE8,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x53, 0xA0, 0xE8,
-
-       0x48, 0x70, 0xF8, 0xEC,
-       0x2B, 0x48, 0x3C, 0xE9,
-
-       0x1F, 0x27, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x18, 0x3A, 0x41, 0xE9,
-       0x1D, 0x32, 0x41, 0xE9,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x56, 0x3D, 0x56, 0xDF,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x4E, 0x3F, 0x4E, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x4F, 0x3F, 0x4F, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3D, 0x57, 0xDF,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x34, 0x80, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x27, 0xCF, 0x74, 0xC6,
-       0x3D, 0xCF, 0x74, 0xC2,
-
-       0x0A, 0x44, 0x4C, 0xB0,
-       0x02, 0x44, 0x54, 0xB0,
-
-       0x2A, 0x44, 0x4C, 0xB2,
-       0x1A, 0x44, 0x54, 0xB2,
-
-       0x20, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x9C, 0x27, 0x20, 0xE9,
-
-       0x0A, 0x44, 0x4C, 0xB4,
-       0x02, 0x44, 0x54, 0xB4,
-
-       0x2A, 0x44, 0x4C, 0xB6,
-       0x1A, 0x44, 0x54, 0xB6,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x38, 0x3D, 0x20, 0xE9,
-
-       0x0A, 0x20,
-       0x02, 0x20,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x0A, 0x47, 0x4F, 0xBF,
-       0x02, 0x47, 0x57, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x46, 0x4E, 0xBF,
-       0x1A, 0x46, 0x56, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x36, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x37, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x4B, 0xBF,
-       0x1A, 0x43, 0x53, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x9D, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x9E, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x37, 0x48, 0x50, 0xBD,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8B, 0x3E, 0x20, 0xE9,
-
-       0x82, 0x30, 0x57, 0xE9,
-       0x87, 0x77, 0x57, 0xE9,
-
-       0x83, 0x38, 0x57, 0xE9,
-       0x35, 0x49, 0x51, 0xBD,
-
-       0x84, 0x31, 0x5E, 0xE9,
-       0x30, 0x1F, 0x5F, 0xE9,
-
-       0x85, 0x39, 0x5E, 0xE9,
-       0x57, 0x25, 0x20, 0xE9,
-
-       0x2B, 0x48, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x26, 0x77,
-
-       0x24, 0x49, 0x20, 0xE9,
-       0xAB, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x26, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x1C, 0x46, 0xA0, 0xE8,
-       0x23, 0x4E, 0xA0, 0xE8,
-
-       0x2B, 0x56, 0xA0, 0xE8,
-       0x1D, 0x47, 0xA0, 0xE8,
-
-       0x24, 0x4F, 0xA0, 0xE8,
-       0x2C, 0x57, 0xA0, 0xE8,
-
-       0x1C, 0x00,
-       0x23, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x1D, 0x00,
-       0x24, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x1C, 0x65,
-       0x23, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x1D, 0x65,
-       0x24, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x1C, 0x23, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x1D, 0x24, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x1C, 0x2B, 0xDE, 0xE8,
-       0x23, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x1C, 0xBD,
-       0x3B, 0xD7, 0x23, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x4F, 0x80, 0x4F, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0xD3, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x4E, 0x33, 0x4E, 0xCF,
-       0x57, 0x3B, 0x57, 0xCF,
-
-       0x99, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_tgzaf[] = {
-
-       0x00, 0x88, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x22, 0x40, 0x48, 0xBF,
-       0x2A, 0x40, 0x50, 0xBF,
-
-       0x32, 0x41, 0x49, 0xBF,
-       0x3A, 0x41, 0x51, 0xBF,
-
-       0xC3, 0x6B,
-       0xCB, 0x6B,
-       0x00, 0x88, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x4B, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x29, 0x9F,
-       0x00, 0xE0,
-       0x49, 0x04,
-
-       0x90, 0xE2,
-       0x51, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x49, 0x41, 0xC0, 0xEC,
-       0x39, 0x57, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0x51, 0x41, 0xC0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x61, 0x80, 0x15, 0xEA,
-       0x08, 0x04,
-       0x10, 0x04,
-
-       0x51, 0x49, 0xC0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x4A, 0xBF,
-       0x27, 0x4A, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x52, 0xBF,
-       0x1E, 0x49, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x26, 0x51, 0x60, 0xEA,
-
-       0x32, 0x40, 0x48, 0xBD,
-       0x22, 0x40, 0x50, 0xBD,
-
-       0x12, 0x41, 0x49, 0xBD,
-       0x3A, 0x41, 0x51, 0xBD,
-
-       0xBF, 0x2F, 0x26, 0xBD,
-       0x00, 0xE0,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x4E, 0x31, 0x4E, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x56, 0x31, 0x56, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x4F, 0x39, 0x4F, 0xBF,
-       0x57, 0x39, 0x57, 0xBF,
-
-       0x53, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x42, 0x73, 0xF8, 0xEC,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0xA5, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x4B, 0x4B, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x26, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x53, 0x53, 0x2D, 0xDF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xB8, 0x38, 0x33, 0xBF,
-       0x00, 0xE0,
-       0x59, 0xE3,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x3F, 0x4B, 0xA0, 0xE8,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x53, 0xA0, 0xE8,
-
-       0x48, 0x70, 0xF8, 0xEC,
-       0x2B, 0x48, 0x3C, 0xE9,
-
-       0x1F, 0x27, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x18, 0x3A, 0x41, 0xE9,
-       0x1D, 0x32, 0x41, 0xE9,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x56, 0x3D, 0x56, 0xDF,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x4E, 0x3F, 0x4E, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x4F, 0x3F, 0x4F, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3D, 0x57, 0xDF,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x0A, 0x44, 0x4C, 0xB0,
-       0x02, 0x44, 0x54, 0xB0,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x34, 0x37, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x4C, 0xB2,
-       0x1A, 0x44, 0x54, 0xB2,
-
-       0x26, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x3D, 0xCF, 0x74, 0xC2,
-       0x27, 0xCF, 0x74, 0xC6,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x9C, 0x27, 0x20, 0xE9,
-
-       0x0A, 0x44, 0x4C, 0xB4,
-       0x02, 0x44, 0x54, 0xB4,
-
-       0x2A, 0x44, 0x4C, 0xB6,
-       0x1A, 0x44, 0x54, 0xB6,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x38, 0x3D, 0x20, 0xE9,
-
-       0x0A, 0x20,
-       0x02, 0x20,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x3D, 0xCF, 0x75, 0xC6,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x0A, 0x45, 0x4D, 0xB6,
-       0x02, 0x45, 0x55, 0xB6,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x3D, 0x20, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x2A, 0x46, 0x4E, 0xBF,
-       0x1A, 0x46, 0x56, 0xBF,
-
-       0x0A, 0x47, 0x4F, 0xBF,
-       0x02, 0x47, 0x57, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x36, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x37, 0x38, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x9D, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x9E, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x4B, 0xBF,
-       0x1A, 0x43, 0x53, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x35, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x39, 0x38, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x37, 0x48, 0x50, 0xBD,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8B, 0x3E, 0x20, 0xE9,
-
-       0x82, 0x30, 0x57, 0xE9,
-       0x87, 0x77, 0x57, 0xE9,
-
-       0x83, 0x38, 0x57, 0xE9,
-       0x35, 0x49, 0x51, 0xBD,
-
-       0x84, 0x31, 0x5E, 0xE9,
-       0x30, 0x1F, 0x5F, 0xE9,
-
-       0x85, 0x39, 0x5E, 0xE9,
-       0x57, 0x25, 0x20, 0xE9,
-
-       0x2B, 0x48, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x26, 0x77,
-
-       0x24, 0x49, 0x20, 0xE9,
-       0xA6, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x26, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x1C, 0x46, 0xA0, 0xE8,
-       0x23, 0x4E, 0xA0, 0xE8,
-
-       0x2B, 0x56, 0xA0, 0xE8,
-       0x1D, 0x47, 0xA0, 0xE8,
-
-       0x24, 0x4F, 0xA0, 0xE8,
-       0x2C, 0x57, 0xA0, 0xE8,
-
-       0x1C, 0x00,
-       0x23, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x1D, 0x00,
-       0x24, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x1C, 0x65,
-       0x23, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x1D, 0x65,
-       0x24, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x1C, 0x23, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x1D, 0x24, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x1C, 0x2B, 0xDE, 0xE8,
-       0x23, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x1C, 0xBD,
-       0x3B, 0xD7, 0x23, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x4F, 0x80, 0x4F, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0xCD, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x4E, 0x33, 0x4E, 0xCF,
-       0x57, 0x3B, 0x57, 0xCF,
-
-       0x94, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_tgzf[] = {
-
-       0x00, 0x88, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x22, 0x40, 0x48, 0xBF,
-       0x2A, 0x40, 0x50, 0xBF,
-
-       0x32, 0x41, 0x49, 0xBF,
-       0x3A, 0x41, 0x51, 0xBF,
-
-       0xC3, 0x6B,
-       0xCB, 0x6B,
-       0x00, 0x88, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x4B, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x29, 0x9F,
-       0x00, 0xE0,
-       0x49, 0x04,
-
-       0x90, 0xE2,
-       0x51, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x49, 0x41, 0xC0, 0xEC,
-       0x39, 0x57, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0x51, 0x41, 0xC0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x5D, 0x80, 0x15, 0xEA,
-       0x08, 0x04,
-       0x10, 0x04,
-
-       0x51, 0x49, 0xC0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x4A, 0xBF,
-       0x27, 0x4A, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x52, 0xBF,
-       0x1E, 0x49, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x26, 0x51, 0x60, 0xEA,
-
-       0x32, 0x40, 0x48, 0xBD,
-       0x22, 0x40, 0x50, 0xBD,
-
-       0x12, 0x41, 0x49, 0xBD,
-       0x3A, 0x41, 0x51, 0xBD,
-
-       0xBF, 0x2F, 0x26, 0xBD,
-       0x00, 0xE0,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x4E, 0x31, 0x4E, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x56, 0x31, 0x56, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x4F, 0x39, 0x4F, 0xBF,
-       0x57, 0x39, 0x57, 0xBF,
-
-       0x4F, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x42, 0x73, 0xF8, 0xEC,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0xA5, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x4B, 0x4B, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x26, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x53, 0x53, 0x2D, 0xDF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xB8, 0x38, 0x33, 0xBF,
-       0x00, 0xE0,
-       0x59, 0xE3,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x3F, 0x4B, 0xA0, 0xE8,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x53, 0xA0, 0xE8,
-
-       0x48, 0x70, 0xF8, 0xEC,
-       0x2B, 0x48, 0x3C, 0xE9,
-
-       0x1F, 0x27, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x18, 0x3A, 0x41, 0xE9,
-       0x1D, 0x32, 0x41, 0xE9,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x56, 0x3D, 0x56, 0xDF,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x4E, 0x3F, 0x4E, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x4F, 0x3F, 0x4F, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3D, 0x57, 0xDF,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x34, 0x80, 0x20, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x27, 0xCF, 0x75, 0xC6,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x0A, 0x44, 0x4C, 0xB0,
-       0x02, 0x44, 0x54, 0xB0,
-
-       0x2A, 0x44, 0x4C, 0xB2,
-       0x1A, 0x44, 0x54, 0xB2,
-
-       0x20, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x3D, 0xCF, 0x74, 0xC2,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x31, 0x27, 0x20, 0xE9,
-
-       0x0A, 0x44, 0x4C, 0xB4,
-       0x02, 0x44, 0x54, 0xB4,
-
-       0x2A, 0x45, 0x4D, 0xB6,
-       0x1A, 0x45, 0x55, 0xB6,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x38, 0x3D, 0x20, 0xE9,
-
-       0x0A, 0x20,
-       0x02, 0x20,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x0A, 0x47, 0x4F, 0xBF,
-       0x02, 0x47, 0x57, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x46, 0x4E, 0xBF,
-       0x1A, 0x46, 0x56, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x36, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x37, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x4B, 0xBF,
-       0x1A, 0x43, 0x53, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x35, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x39, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x37, 0x48, 0x50, 0xBD,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8B, 0x3E, 0x20, 0xE9,
-
-       0x82, 0x30, 0x57, 0xE9,
-       0x87, 0x77, 0x57, 0xE9,
-
-       0x83, 0x38, 0x57, 0xE9,
-       0x35, 0x49, 0x51, 0xBD,
-
-       0x84, 0x31, 0x5E, 0xE9,
-       0x30, 0x1F, 0x5F, 0xE9,
-
-       0x85, 0x39, 0x5E, 0xE9,
-       0x57, 0x25, 0x20, 0xE9,
-
-       0x2B, 0x48, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x26, 0x77,
-
-       0x24, 0x49, 0x20, 0xE9,
-       0xAA, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x26, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x1C, 0x46, 0xA0, 0xE8,
-       0x23, 0x4E, 0xA0, 0xE8,
-
-       0x2B, 0x56, 0xA0, 0xE8,
-       0x1D, 0x47, 0xA0, 0xE8,
-
-       0x24, 0x4F, 0xA0, 0xE8,
-       0x2C, 0x57, 0xA0, 0xE8,
-
-       0x1C, 0x00,
-       0x23, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x1D, 0x00,
-       0x24, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x1C, 0x65,
-       0x23, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x1D, 0x65,
-       0x24, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x1C, 0x23, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x1D, 0x24, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x1C, 0x2B, 0xDE, 0xE8,
-       0x23, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x1C, 0xBD,
-       0x3B, 0xD7, 0x23, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x4F, 0x80, 0x4F, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0xD3, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x4E, 0x33, 0x4E, 0xCF,
-       0x57, 0x3B, 0x57, 0xCF,
-
-       0x98, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_tgzs[] = {
-
-       0x00, 0x88, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x22, 0x40, 0x48, 0xBF,
-       0x2A, 0x40, 0x50, 0xBF,
-
-       0x32, 0x41, 0x49, 0xBF,
-       0x3A, 0x41, 0x51, 0xBF,
-
-       0xC3, 0x6B,
-       0xCB, 0x6B,
-       0x00, 0x88, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x4B, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x29, 0x9F,
-       0x00, 0xE0,
-       0x49, 0x04,
-
-       0x90, 0xE2,
-       0x51, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x49, 0x41, 0xC0, 0xEC,
-       0x39, 0x57, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0x51, 0x41, 0xC0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x65, 0x80, 0x15, 0xEA,
-       0x08, 0x04,
-       0x10, 0x04,
-
-       0x51, 0x49, 0xC0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x4A, 0xBF,
-       0x27, 0x4A, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x52, 0xBF,
-       0x1E, 0x49, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x26, 0x51, 0x60, 0xEA,
-
-       0x32, 0x40, 0x48, 0xBD,
-       0x22, 0x40, 0x50, 0xBD,
-
-       0x12, 0x41, 0x49, 0xBD,
-       0x3A, 0x41, 0x51, 0xBD,
-
-       0xBF, 0x2F, 0x26, 0xBD,
-       0x00, 0xE0,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x4E, 0x31, 0x4E, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x56, 0x31, 0x56, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x4F, 0x39, 0x4F, 0xBF,
-       0x57, 0x39, 0x57, 0xBF,
-
-       0x57, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x42, 0x73, 0xF8, 0xEC,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0xA5, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x4B, 0x4B, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x26, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x53, 0x53, 0x2D, 0xDF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xB8, 0x38, 0x33, 0xBF,
-       0x00, 0xE0,
-       0x59, 0xE3,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x3F, 0x4B, 0xA0, 0xE8,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x53, 0xA0, 0xE8,
-
-       0x48, 0x70, 0xF8, 0xEC,
-       0x2B, 0x48, 0x3C, 0xE9,
-
-       0x1F, 0x27, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x18, 0x3A, 0x41, 0xE9,
-       0x1D, 0x32, 0x41, 0xE9,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x56, 0x3D, 0x56, 0xDF,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x4E, 0x3F, 0x4E, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x4F, 0x3F, 0x4F, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3D, 0x57, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x27, 0xCF, 0x74, 0xC2,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x0A, 0x44, 0x4C, 0xB0,
-       0x02, 0x44, 0x54, 0xB0,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x34, 0x37, 0x20, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x38, 0x27, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x4C, 0xB2,
-       0x1A, 0x44, 0x54, 0xB2,
-
-       0x29, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x27, 0xCF, 0x75, 0xC0,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x3D, 0xCF, 0x75, 0xC2,
-       0x37, 0xCF, 0x75, 0xC4,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA6, 0x27, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA3, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x4C, 0xB4,
-       0x1A, 0x44, 0x54, 0xB4,
-
-       0x0A, 0x45, 0x4D, 0xB0,
-       0x02, 0x45, 0x55, 0xB0,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA0, 0x37, 0x20, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x2A, 0x45, 0x4D, 0xB2,
-       0x1A, 0x45, 0x55, 0xB2,
-
-       0x0A, 0x45, 0x4D, 0xB4,
-       0x02, 0x45, 0x55, 0xB4,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x0A, 0x20,
-       0x02, 0x20,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x2A, 0x46, 0x4E, 0xBF,
-       0x1A, 0x46, 0x56, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x36, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x37, 0x39, 0x4F, 0xE9,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0xA7, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0xA8, 0x38, 0x4F, 0xE9,
-
-       0x0A, 0x47, 0x4F, 0xBF,
-       0x02, 0x47, 0x57, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA4, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA5, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x4B, 0xBF,
-       0x1A, 0x43, 0x53, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0xA1, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0xA2, 0x38, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x37, 0x48, 0x50, 0xBD,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8B, 0x3E, 0x20, 0xE9,
-
-       0x82, 0x30, 0x57, 0xE9,
-       0x87, 0x77, 0x57, 0xE9,
-
-       0x83, 0x38, 0x57, 0xE9,
-       0x35, 0x49, 0x51, 0xBD,
-
-       0x84, 0x31, 0x5E, 0xE9,
-       0x30, 0x1F, 0x5F, 0xE9,
-
-       0x85, 0x39, 0x5E, 0xE9,
-       0x57, 0x25, 0x20, 0xE9,
-
-       0x2B, 0x48, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x26, 0x77,
-
-       0x24, 0x49, 0x20, 0xE9,
-       0xA2, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x26, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x1C, 0x46, 0xA0, 0xE8,
-       0x23, 0x4E, 0xA0, 0xE8,
-
-       0x2B, 0x56, 0xA0, 0xE8,
-       0x1D, 0x47, 0xA0, 0xE8,
-
-       0x24, 0x4F, 0xA0, 0xE8,
-       0x2C, 0x57, 0xA0, 0xE8,
-
-       0x1C, 0x00,
-       0x23, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x1D, 0x00,
-       0x24, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x1C, 0x65,
-       0x23, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x1D, 0x65,
-       0x24, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x1C, 0x23, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x1D, 0x24, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x1C, 0x2B, 0xDE, 0xE8,
-       0x23, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x1C, 0xBD,
-       0x3B, 0xD7, 0x23, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x4F, 0x80, 0x4F, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0xCA, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x4E, 0x33, 0x4E, 0xCF,
-       0x57, 0x3B, 0x57, 0xCF,
-
-       0x90, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_tgzsa[] = {
-
-       0x00, 0x88, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x22, 0x40, 0x48, 0xBF,
-       0x2A, 0x40, 0x50, 0xBF,
-
-       0x32, 0x41, 0x49, 0xBF,
-       0x3A, 0x41, 0x51, 0xBF,
-
-       0xC3, 0x6B,
-       0xCB, 0x6B,
-       0x00, 0x88, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x4B, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x29, 0x9F,
-       0x00, 0xE0,
-       0x49, 0x04,
-
-       0x90, 0xE2,
-       0x51, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x49, 0x41, 0xC0, 0xEC,
-       0x39, 0x57, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0x51, 0x41, 0xC0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x6A, 0x80, 0x15, 0xEA,
-       0x08, 0x04,
-       0x10, 0x04,
-
-       0x51, 0x49, 0xC0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x4A, 0xBF,
-       0x27, 0x4A, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x52, 0xBF,
-       0x1E, 0x49, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x26, 0x51, 0x60, 0xEA,
-
-       0x32, 0x40, 0x48, 0xBD,
-       0x22, 0x40, 0x50, 0xBD,
-
-       0x12, 0x41, 0x49, 0xBD,
-       0x3A, 0x41, 0x51, 0xBD,
-
-       0xBF, 0x2F, 0x26, 0xBD,
-       0x00, 0xE0,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x4E, 0x31, 0x4E, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x56, 0x31, 0x56, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x4F, 0x39, 0x4F, 0xBF,
-       0x57, 0x39, 0x57, 0xBF,
-
-       0x5C, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x42, 0x73, 0xF8, 0xEC,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0xA5, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x4B, 0x4B, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x26, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x53, 0x53, 0x2D, 0xDF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xB8, 0x38, 0x33, 0xBF,
-       0x00, 0xE0,
-       0x59, 0xE3,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x3F, 0x4B, 0xA0, 0xE8,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x53, 0xA0, 0xE8,
-
-       0x48, 0x70, 0xF8, 0xEC,
-       0x2B, 0x48, 0x3C, 0xE9,
-
-       0x1F, 0x27, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x18, 0x3A, 0x41, 0xE9,
-       0x1D, 0x32, 0x41, 0xE9,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x56, 0x3D, 0x56, 0xDF,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x4E, 0x3F, 0x4E, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x4F, 0x3F, 0x4F, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3D, 0x57, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x27, 0xCF, 0x74, 0xC2,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x0A, 0x44, 0x4C, 0xB0,
-       0x02, 0x44, 0x54, 0xB0,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x34, 0x37, 0x20, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x38, 0x27, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x4C, 0xB2,
-       0x1A, 0x44, 0x54, 0xB2,
-
-       0x2E, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x27, 0xCF, 0x75, 0xC0,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x3D, 0xCF, 0x75, 0xC2,
-       0x37, 0xCF, 0x75, 0xC4,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA6, 0x27, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA3, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x4C, 0xB4,
-       0x1A, 0x44, 0x54, 0xB4,
-
-       0x0A, 0x45, 0x4D, 0xB0,
-       0x02, 0x45, 0x55, 0xB0,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA0, 0x37, 0x20, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x45, 0x4D, 0xB2,
-       0x1A, 0x45, 0x55, 0xB2,
-
-       0x0A, 0x45, 0x4D, 0xB4,
-       0x02, 0x45, 0x55, 0xB4,
-
-       0x27, 0xCF, 0x74, 0xC6,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA7, 0x30, 0x4F, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x9C, 0x27, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA8, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x44, 0x4C, 0xB6,
-       0x1A, 0x44, 0x54, 0xB6,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x36, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x37, 0x39, 0x4F, 0xE9,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x2A, 0x46, 0x4E, 0xBF,
-       0x1A, 0x46, 0x56, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA4, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA5, 0x39, 0x4F, 0xE9,
-
-       0x0A, 0x47, 0x4F, 0xBF,
-       0x02, 0x47, 0x57, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA1, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA2, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x4B, 0xBF,
-       0x1A, 0x43, 0x53, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x9D, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x9E, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x37, 0x48, 0x50, 0xBD,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8B, 0x3E, 0x20, 0xE9,
-
-       0x82, 0x30, 0x57, 0xE9,
-       0x87, 0x77, 0x57, 0xE9,
-
-       0x83, 0x38, 0x57, 0xE9,
-       0x35, 0x49, 0x51, 0xBD,
-
-       0x84, 0x31, 0x5E, 0xE9,
-       0x30, 0x1F, 0x5F, 0xE9,
-
-       0x85, 0x39, 0x5E, 0xE9,
-       0x57, 0x25, 0x20, 0xE9,
-
-       0x2B, 0x48, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x26, 0x77,
-
-       0x24, 0x49, 0x20, 0xE9,
-       0x9D, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x26, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x1C, 0x46, 0xA0, 0xE8,
-       0x23, 0x4E, 0xA0, 0xE8,
-
-       0x2B, 0x56, 0xA0, 0xE8,
-       0x1D, 0x47, 0xA0, 0xE8,
-
-       0x24, 0x4F, 0xA0, 0xE8,
-       0x2C, 0x57, 0xA0, 0xE8,
-
-       0x1C, 0x00,
-       0x23, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x1D, 0x00,
-       0x24, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x1C, 0x65,
-       0x23, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x1D, 0x65,
-       0x24, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x1C, 0x23, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x1D, 0x24, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x1C, 0x2B, 0xDE, 0xE8,
-       0x23, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x1C, 0xBD,
-       0x3B, 0xD7, 0x23, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x4F, 0x80, 0x4F, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0xC5, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x4E, 0x33, 0x4E, 0xCF,
-       0x57, 0x3B, 0x57, 0xCF,
-
-       0x8B, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_tgzsaf[] = {
-
-       0x00, 0x88, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x22, 0x40, 0x48, 0xBF,
-       0x2A, 0x40, 0x50, 0xBF,
-
-       0x32, 0x41, 0x49, 0xBF,
-       0x3A, 0x41, 0x51, 0xBF,
-
-       0xC3, 0x6B,
-       0xCB, 0x6B,
-       0x00, 0x88, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x4B, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x29, 0x9F,
-       0x00, 0xE0,
-       0x49, 0x04,
-
-       0x90, 0xE2,
-       0x51, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x49, 0x41, 0xC0, 0xEC,
-       0x39, 0x57, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0x51, 0x41, 0xC0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x6E, 0x80, 0x15, 0xEA,
-       0x08, 0x04,
-       0x10, 0x04,
-
-       0x51, 0x49, 0xC0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x4A, 0xBF,
-       0x27, 0x4A, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x52, 0xBF,
-       0x1E, 0x49, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x26, 0x51, 0x60, 0xEA,
-
-       0x32, 0x40, 0x48, 0xBD,
-       0x22, 0x40, 0x50, 0xBD,
-
-       0x12, 0x41, 0x49, 0xBD,
-       0x3A, 0x41, 0x51, 0xBD,
-
-       0xBF, 0x2F, 0x26, 0xBD,
-       0x00, 0xE0,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x4E, 0x31, 0x4E, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x56, 0x31, 0x56, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x4F, 0x39, 0x4F, 0xBF,
-       0x57, 0x39, 0x57, 0xBF,
-
-       0x60, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x42, 0x73, 0xF8, 0xEC,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0xA5, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x4B, 0x4B, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x26, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x53, 0x53, 0x2D, 0xDF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xB8, 0x38, 0x33, 0xBF,
-       0x00, 0xE0,
-       0x59, 0xE3,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x3F, 0x4B, 0xA0, 0xE8,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x53, 0xA0, 0xE8,
-
-       0x48, 0x70, 0xF8, 0xEC,
-       0x2B, 0x48, 0x3C, 0xE9,
-
-       0x1F, 0x27, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x18, 0x3A, 0x41, 0xE9,
-       0x1D, 0x32, 0x41, 0xE9,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x56, 0x3D, 0x56, 0xDF,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x4E, 0x3F, 0x4E, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x4F, 0x3F, 0x4F, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3D, 0x57, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x27, 0xCF, 0x74, 0xC2,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x0A, 0x44, 0x4C, 0xB0,
-       0x02, 0x44, 0x54, 0xB0,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x34, 0x37, 0x20, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x38, 0x27, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x4C, 0xB2,
-       0x1A, 0x44, 0x54, 0xB2,
-
-       0x32, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x27, 0xCF, 0x75, 0xC0,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x3D, 0xCF, 0x75, 0xC2,
-       0x37, 0xCF, 0x75, 0xC4,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA6, 0x27, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA3, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x4C, 0xB4,
-       0x1A, 0x44, 0x54, 0xB4,
-
-       0x0A, 0x45, 0x4D, 0xB0,
-       0x02, 0x45, 0x55, 0xB0,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA0, 0x37, 0x20, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x45, 0x4D, 0xB2,
-       0x1A, 0x45, 0x55, 0xB2,
-
-       0x0A, 0x45, 0x4D, 0xB4,
-       0x02, 0x45, 0x55, 0xB4,
-
-       0x27, 0xCF, 0x74, 0xC6,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA7, 0x30, 0x4F, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x9C, 0x27, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA8, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x44, 0x4C, 0xB6,
-       0x1A, 0x44, 0x54, 0xB6,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x36, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x37, 0x39, 0x4F, 0xE9,
-
-       0x0A, 0x45, 0x4D, 0xB6,
-       0x02, 0x45, 0x55, 0xB6,
-
-       0x3D, 0xCF, 0x75, 0xC6,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x2A, 0x46, 0x4E, 0xBF,
-       0x1A, 0x46, 0x56, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA4, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA5, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x3D, 0x20, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x0A, 0x47, 0x4F, 0xBF,
-       0x02, 0x47, 0x57, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0xA1, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0xA2, 0x38, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x9D, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x9E, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x4B, 0xBF,
-       0x1A, 0x43, 0x53, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x35, 0x30, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x39, 0x38, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x37, 0x48, 0x50, 0xBD,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8B, 0x3E, 0x20, 0xE9,
-
-       0x82, 0x30, 0x57, 0xE9,
-       0x87, 0x77, 0x57, 0xE9,
-
-       0x83, 0x38, 0x57, 0xE9,
-       0x35, 0x49, 0x51, 0xBD,
-
-       0x84, 0x31, 0x5E, 0xE9,
-       0x30, 0x1F, 0x5F, 0xE9,
-
-       0x85, 0x39, 0x5E, 0xE9,
-       0x57, 0x25, 0x20, 0xE9,
-
-       0x2B, 0x48, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x26, 0x77,
-
-       0x24, 0x49, 0x20, 0xE9,
-       0x99, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x26, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x1C, 0x46, 0xA0, 0xE8,
-       0x23, 0x4E, 0xA0, 0xE8,
-
-       0x2B, 0x56, 0xA0, 0xE8,
-       0x1D, 0x47, 0xA0, 0xE8,
-
-       0x24, 0x4F, 0xA0, 0xE8,
-       0x2C, 0x57, 0xA0, 0xE8,
-
-       0x1C, 0x00,
-       0x23, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x1D, 0x00,
-       0x24, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x1C, 0x65,
-       0x23, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x1D, 0x65,
-       0x24, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x1C, 0x23, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x1D, 0x24, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x1C, 0x2B, 0xDE, 0xE8,
-       0x23, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x1C, 0xBD,
-       0x3B, 0xD7, 0x23, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x4F, 0x80, 0x4F, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0xC1, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x4E, 0x33, 0x4E, 0xCF,
-       0x57, 0x3B, 0x57, 0xCF,
-
-       0x87, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
-
-static unsigned char warp_g400_tgzsf[] = {
-
-       0x00, 0x88, 0x98, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-       0xFF, 0x80, 0xC0, 0xE9,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x22, 0x40, 0x48, 0xBF,
-       0x2A, 0x40, 0x50, 0xBF,
-
-       0x32, 0x41, 0x49, 0xBF,
-       0x3A, 0x41, 0x51, 0xBF,
-
-       0xC3, 0x6B,
-       0xCB, 0x6B,
-       0x00, 0x88, 0x98, 0xE9,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x96, 0xE2,
-       0x41, 0x04,
-
-       0x7B, 0x43, 0xA0, 0xE8,
-       0x73, 0x4B, 0xA0, 0xE8,
-
-       0xAD, 0xEE, 0x29, 0x9F,
-       0x00, 0xE0,
-       0x49, 0x04,
-
-       0x90, 0xE2,
-       0x51, 0x04,
-       0x31, 0x46, 0xB1, 0xE8,
-
-       0x49, 0x41, 0xC0, 0xEC,
-       0x39, 0x57, 0xB1, 0xE8,
-
-       0x00, 0x04,
-       0x46, 0xE2,
-       0x73, 0x53, 0xA0, 0xE8,
-
-       0x51, 0x41, 0xC0, 0xEC,
-       0x31, 0x00,
-       0x39, 0x00,
-
-       0x6A, 0x80, 0x15, 0xEA,
-       0x08, 0x04,
-       0x10, 0x04,
-
-       0x51, 0x49, 0xC0, 0xEC,
-       0x2F, 0x41, 0x60, 0xEA,
-
-       0x31, 0x20,
-       0x39, 0x20,
-       0x1F, 0x42, 0xA0, 0xE8,
-
-       0x2A, 0x42, 0x4A, 0xBF,
-       0x27, 0x4A, 0xA0, 0xE8,
-
-       0x1A, 0x42, 0x52, 0xBF,
-       0x1E, 0x49, 0x60, 0xEA,
-
-       0x73, 0x7B, 0xC8, 0xEC,
-       0x26, 0x51, 0x60, 0xEA,
-
-       0x32, 0x40, 0x48, 0xBD,
-       0x22, 0x40, 0x50, 0xBD,
-
-       0x12, 0x41, 0x49, 0xBD,
-       0x3A, 0x41, 0x51, 0xBD,
-
-       0xBF, 0x2F, 0x26, 0xBD,
-       0x00, 0xE0,
-       0x7B, 0x72,
-
-       0x32, 0x20,
-       0x22, 0x20,
-       0x12, 0x20,
-       0x3A, 0x20,
-
-       0x46, 0x31, 0x46, 0xBF,
-       0x4E, 0x31, 0x4E, 0xBF,
-
-       0xB3, 0xE2, 0x2D, 0x9F,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x56, 0x31, 0x56, 0xBF,
-       0x47, 0x39, 0x47, 0xBF,
-
-       0x4F, 0x39, 0x4F, 0xBF,
-       0x57, 0x39, 0x57, 0xBF,
-
-       0x5C, 0x80, 0x07, 0xEA,
-       0x24, 0x41, 0x20, 0xE9,
-
-       0x42, 0x73, 0xF8, 0xEC,
-       0x00, 0xE0,
-       0x2D, 0x73,
-
-       0x33, 0x72,
-       0x0C, 0xE3,
-       0xA5, 0x2F, 0x1E, 0xBD,
-
-       0x43, 0x43, 0x2D, 0xDF,
-       0x4B, 0x4B, 0x2D, 0xDF,
-
-       0xAE, 0x1E, 0x26, 0xBD,
-       0x58, 0xE3,
-       0x33, 0x66,
-
-       0x53, 0x53, 0x2D, 0xDF,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0xB8, 0x38, 0x33, 0xBF,
-       0x00, 0xE0,
-       0x59, 0xE3,
-
-       0x1E, 0x12, 0x41, 0xE9,
-       0x1A, 0x22, 0x41, 0xE9,
-
-       0x2B, 0x40, 0x3D, 0xE9,
-       0x3F, 0x4B, 0xA0, 0xE8,
-
-       0x2D, 0x73,
-       0x30, 0x76,
-       0x05, 0x80, 0x3D, 0xEA,
-
-       0x37, 0x43, 0xA0, 0xE8,
-       0x3D, 0x53, 0xA0, 0xE8,
-
-       0x48, 0x70, 0xF8, 0xEC,
-       0x2B, 0x48, 0x3C, 0xE9,
-
-       0x1F, 0x27, 0xBC, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x15, 0xC0, 0x20, 0xE9,
-       0x15, 0xC0, 0x20, 0xE9,
-
-       0x18, 0x3A, 0x41, 0xE9,
-       0x1D, 0x32, 0x41, 0xE9,
-
-       0x2A, 0x40, 0x20, 0xE9,
-       0x56, 0x3D, 0x56, 0xDF,
-
-       0x46, 0x37, 0x46, 0xDF,
-       0x4E, 0x3F, 0x4E, 0xDF,
-
-       0x16, 0x30, 0x20, 0xE9,
-       0x4F, 0x3F, 0x4F, 0xDF,
-
-       0x47, 0x37, 0x47, 0xDF,
-       0x57, 0x3D, 0x57, 0xDF,
-
-       0x32, 0x32, 0x2D, 0xDF,
-       0x22, 0x22, 0x2D, 0xDF,
-
-       0x12, 0x12, 0x2D, 0xDF,
-       0x3A, 0x3A, 0x2D, 0xDF,
-
-       0x27, 0xCF, 0x74, 0xC2,
-       0x37, 0xCF, 0x74, 0xC4,
-
-       0x0A, 0x44, 0x4C, 0xB0,
-       0x02, 0x44, 0x54, 0xB0,
-
-       0x3D, 0xCF, 0x74, 0xC0,
-       0x34, 0x37, 0x20, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x38, 0x27, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3C, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x4C, 0xB2,
-       0x1A, 0x44, 0x54, 0xB2,
-
-       0x2E, 0x80, 0x3A, 0xEA,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x27, 0xCF, 0x75, 0xC0,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x32, 0x31, 0x5F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x33, 0x39, 0x5F, 0xE9,
-
-       0x3D, 0xCF, 0x75, 0xC2,
-       0x37, 0xCF, 0x75, 0xC4,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA6, 0x27, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA3, 0x3D, 0x20, 0xE9,
-
-       0x2A, 0x44, 0x4C, 0xB4,
-       0x1A, 0x44, 0x54, 0xB4,
-
-       0x0A, 0x45, 0x4D, 0xB0,
-       0x02, 0x45, 0x55, 0xB0,
-
-       0x88, 0x73, 0x5E, 0xE9,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA0, 0x37, 0x20, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x3E, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x3F, 0x38, 0x4F, 0xE9,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x3A, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x3B, 0x39, 0x4F, 0xE9,
-
-       0x2A, 0x45, 0x4D, 0xB2,
-       0x1A, 0x45, 0x55, 0xB2,
-
-       0x0A, 0x45, 0x4D, 0xB4,
-       0x02, 0x45, 0x55, 0xB4,
-
-       0x27, 0xCF, 0x75, 0xC6,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0xA7, 0x30, 0x4F, 0xE9,
-       0x0A, 0x20,
-       0x02, 0x20,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x31, 0x27, 0x20, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA8, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x45, 0x4D, 0xB6,
-       0x1A, 0x45, 0x55, 0xB6,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x36, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x37, 0x39, 0x4F, 0xE9,
-
-       0x00, 0x80, 0x00, 0xE8,
-       0x2A, 0x20,
-       0x1A, 0x20,
-
-       0x2A, 0x46, 0x4E, 0xBF,
-       0x1A, 0x46, 0x56, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA4, 0x31, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA5, 0x39, 0x4F, 0xE9,
-
-       0x0A, 0x47, 0x4F, 0xBF,
-       0x02, 0x47, 0x57, 0xBF,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0xA1, 0x30, 0x4F, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0xA2, 0x38, 0x4F, 0xE9,
-
-       0x2A, 0x43, 0x4B, 0xBF,
-       0x1A, 0x43, 0x53, 0xBF,
-
-       0x30, 0x50, 0x2E, 0x9F,
-       0x35, 0x31, 0x4F, 0xE9,
-
-       0x38, 0x21, 0x2C, 0x9F,
-       0x39, 0x39, 0x4F, 0xE9,
-
-       0x31, 0x53, 0x2F, 0x9F,
-       0x80, 0x31, 0x57, 0xE9,
-
-       0x39, 0xE5, 0x2C, 0x9F,
-       0x81, 0x39, 0x57, 0xE9,
-
-       0x37, 0x48, 0x50, 0xBD,
-       0x8A, 0x36, 0x20, 0xE9,
-
-       0x86, 0x76, 0x57, 0xE9,
-       0x8B, 0x3E, 0x20, 0xE9,
-
-       0x82, 0x30, 0x57, 0xE9,
-       0x87, 0x77, 0x57, 0xE9,
-
-       0x83, 0x38, 0x57, 0xE9,
-       0x35, 0x49, 0x51, 0xBD,
-
-       0x84, 0x31, 0x5E, 0xE9,
-       0x30, 0x1F, 0x5F, 0xE9,
-
-       0x85, 0x39, 0x5E, 0xE9,
-       0x57, 0x25, 0x20, 0xE9,
-
-       0x2B, 0x48, 0x20, 0xE9,
-       0x1D, 0x37, 0xE1, 0xEA,
-
-       0x1E, 0x35, 0xE1, 0xEA,
-       0x00, 0xE0,
-       0x26, 0x77,
-
-       0x24, 0x49, 0x20, 0xE9,
-       0x9D, 0xFF, 0x20, 0xEA,
-
-       0x16, 0x26, 0x20, 0xE9,
-       0x57, 0x2E, 0xBF, 0xEA,
-
-       0x1C, 0x46, 0xA0, 0xE8,
-       0x23, 0x4E, 0xA0, 0xE8,
-
-       0x2B, 0x56, 0xA0, 0xE8,
-       0x1D, 0x47, 0xA0, 0xE8,
-
-       0x24, 0x4F, 0xA0, 0xE8,
-       0x2C, 0x57, 0xA0, 0xE8,
-
-       0x1C, 0x00,
-       0x23, 0x00,
-       0x2B, 0x00,
-       0x00, 0xE0,
-
-       0x1D, 0x00,
-       0x24, 0x00,
-       0x2C, 0x00,
-       0x00, 0xE0,
-
-       0x1C, 0x65,
-       0x23, 0x65,
-       0x2B, 0x65,
-       0x00, 0xE0,
-
-       0x1D, 0x65,
-       0x24, 0x65,
-       0x2C, 0x65,
-       0x00, 0xE0,
-
-       0x1C, 0x23, 0x60, 0xEC,
-       0x36, 0xD7, 0x36, 0xAD,
-
-       0x2B, 0x80, 0x60, 0xEC,
-       0x1D, 0x24, 0x60, 0xEC,
-
-       0x3E, 0xD7, 0x3E, 0xAD,
-       0x2C, 0x80, 0x60, 0xEC,
-
-       0x1C, 0x2B, 0xDE, 0xE8,
-       0x23, 0x80, 0xDE, 0xE8,
-
-       0x36, 0x80, 0x36, 0xBD,
-       0x3E, 0x80, 0x3E, 0xBD,
-
-       0x33, 0xD7, 0x1C, 0xBD,
-       0x3B, 0xD7, 0x23, 0xBD,
-
-       0x46, 0x80, 0x46, 0xCF,
-       0x4F, 0x80, 0x4F, 0xCF,
-
-       0x56, 0x33, 0x56, 0xCF,
-       0x47, 0x3B, 0x47, 0xCF,
-
-       0xC5, 0xFF, 0x20, 0xEA,
-       0x00, 0x80, 0x00, 0xE8,
-
-       0x4E, 0x33, 0x4E, 0xCF,
-       0x57, 0x3B, 0x57, 0xCF,
-
-       0x8B, 0xFF, 0x20, 0xEA,
-       0x57, 0xC0, 0xBF, 0xEA,
-
-       0x00, 0x80, 0xA0, 0xE9,
-       0x00, 0x00, 0xD8, 0xEC,
-
-};
diff --git a/drivers/char/drm/mga_warp.c b/drivers/char/drm/mga_warp.c
deleted file mode 100644 (file)
index 651b93c..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/* mga_warp.c -- Matrox G200/G400 WARP engine management -*- linux-c -*-
- * Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com
- *
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "mga_drm.h"
-#include "mga_drv.h"
-#include "mga_ucode.h"
-
-#define MGA_WARP_CODE_ALIGN            256     /* in bytes */
-
-#define WARP_UCODE_SIZE( which )                                       \
-       ((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN)
-
-#define WARP_UCODE_INSTALL( which, where )                             \
-do {                                                                   \
-       DRM_DEBUG( " pcbase = 0x%08lx  vcbase = %p\n", pcbase, vcbase );\
-       dev_priv->warp_pipe_phys[where] = pcbase;                       \
-       memcpy( vcbase, which, sizeof(which) );                         \
-       pcbase += WARP_UCODE_SIZE( which );                             \
-       vcbase += WARP_UCODE_SIZE( which );                             \
-} while (0)
-
-static const unsigned int mga_warp_g400_microcode_size =
-    (WARP_UCODE_SIZE(warp_g400_tgz) +
-     WARP_UCODE_SIZE(warp_g400_tgza) +
-     WARP_UCODE_SIZE(warp_g400_tgzaf) +
-     WARP_UCODE_SIZE(warp_g400_tgzf) +
-     WARP_UCODE_SIZE(warp_g400_tgzs) +
-     WARP_UCODE_SIZE(warp_g400_tgzsa) +
-     WARP_UCODE_SIZE(warp_g400_tgzsaf) +
-     WARP_UCODE_SIZE(warp_g400_tgzsf) +
-     WARP_UCODE_SIZE(warp_g400_t2gz) +
-     WARP_UCODE_SIZE(warp_g400_t2gza) +
-     WARP_UCODE_SIZE(warp_g400_t2gzaf) +
-     WARP_UCODE_SIZE(warp_g400_t2gzf) +
-     WARP_UCODE_SIZE(warp_g400_t2gzs) +
-     WARP_UCODE_SIZE(warp_g400_t2gzsa) +
-     WARP_UCODE_SIZE(warp_g400_t2gzsaf) + WARP_UCODE_SIZE(warp_g400_t2gzsf));
-
-static const unsigned int mga_warp_g200_microcode_size =
-    (WARP_UCODE_SIZE(warp_g200_tgz) +
-     WARP_UCODE_SIZE(warp_g200_tgza) +
-     WARP_UCODE_SIZE(warp_g200_tgzaf) +
-     WARP_UCODE_SIZE(warp_g200_tgzf) +
-     WARP_UCODE_SIZE(warp_g200_tgzs) +
-     WARP_UCODE_SIZE(warp_g200_tgzsa) +
-     WARP_UCODE_SIZE(warp_g200_tgzsaf) + WARP_UCODE_SIZE(warp_g200_tgzsf));
-
-unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv)
-{
-       switch (dev_priv->chipset) {
-       case MGA_CARD_TYPE_G400:
-       case MGA_CARD_TYPE_G550:
-               return PAGE_ALIGN(mga_warp_g400_microcode_size);
-       case MGA_CARD_TYPE_G200:
-               return PAGE_ALIGN(mga_warp_g200_microcode_size);
-       default:
-               return 0;
-       }
-}
-
-static int mga_warp_install_g400_microcode(drm_mga_private_t * dev_priv)
-{
-       unsigned char *vcbase = dev_priv->warp->handle;
-       unsigned long pcbase = dev_priv->warp->offset;
-
-       memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
-
-       WARP_UCODE_INSTALL(warp_g400_tgz, MGA_WARP_TGZ);
-       WARP_UCODE_INSTALL(warp_g400_tgzf, MGA_WARP_TGZF);
-       WARP_UCODE_INSTALL(warp_g400_tgza, MGA_WARP_TGZA);
-       WARP_UCODE_INSTALL(warp_g400_tgzaf, MGA_WARP_TGZAF);
-       WARP_UCODE_INSTALL(warp_g400_tgzs, MGA_WARP_TGZS);
-       WARP_UCODE_INSTALL(warp_g400_tgzsf, MGA_WARP_TGZSF);
-       WARP_UCODE_INSTALL(warp_g400_tgzsa, MGA_WARP_TGZSA);
-       WARP_UCODE_INSTALL(warp_g400_tgzsaf, MGA_WARP_TGZSAF);
-
-       WARP_UCODE_INSTALL(warp_g400_t2gz, MGA_WARP_T2GZ);
-       WARP_UCODE_INSTALL(warp_g400_t2gzf, MGA_WARP_T2GZF);
-       WARP_UCODE_INSTALL(warp_g400_t2gza, MGA_WARP_T2GZA);
-       WARP_UCODE_INSTALL(warp_g400_t2gzaf, MGA_WARP_T2GZAF);
-       WARP_UCODE_INSTALL(warp_g400_t2gzs, MGA_WARP_T2GZS);
-       WARP_UCODE_INSTALL(warp_g400_t2gzsf, MGA_WARP_T2GZSF);
-       WARP_UCODE_INSTALL(warp_g400_t2gzsa, MGA_WARP_T2GZSA);
-       WARP_UCODE_INSTALL(warp_g400_t2gzsaf, MGA_WARP_T2GZSAF);
-
-       return 0;
-}
-
-static int mga_warp_install_g200_microcode(drm_mga_private_t * dev_priv)
-{
-       unsigned char *vcbase = dev_priv->warp->handle;
-       unsigned long pcbase = dev_priv->warp->offset;
-
-       memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
-
-       WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ);
-       WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF);
-       WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA);
-       WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF);
-       WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS);
-       WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF);
-       WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA);
-       WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF);
-
-       return 0;
-}
-
-int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
-{
-       const unsigned int size = mga_warp_microcode_size(dev_priv);
-
-       DRM_DEBUG("MGA ucode size = %d bytes\n", size);
-       if (size > dev_priv->warp->size) {
-               DRM_ERROR("microcode too large! (%u > %lu)\n",
-                         size, dev_priv->warp->size);
-               return -ENOMEM;
-       }
-
-       switch (dev_priv->chipset) {
-       case MGA_CARD_TYPE_G400:
-       case MGA_CARD_TYPE_G550:
-               return mga_warp_install_g400_microcode(dev_priv);
-       case MGA_CARD_TYPE_G200:
-               return mga_warp_install_g200_microcode(dev_priv);
-       default:
-               return -EINVAL;
-       }
-}
-
-#define WMISC_EXPECTED         (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
-
-int mga_warp_init(drm_mga_private_t * dev_priv)
-{
-       u32 wmisc;
-
-       /* FIXME: Get rid of these damned magic numbers...
-        */
-       switch (dev_priv->chipset) {
-       case MGA_CARD_TYPE_G400:
-       case MGA_CARD_TYPE_G550:
-               MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND);
-               MGA_WRITE(MGA_WGETMSB, 0x00000E00);
-               MGA_WRITE(MGA_WVRTXSZ, 0x00001807);
-               MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000);
-               break;
-       case MGA_CARD_TYPE_G200:
-               MGA_WRITE(MGA_WIADDR, MGA_WMODE_SUSPEND);
-               MGA_WRITE(MGA_WGETMSB, 0x1606);
-               MGA_WRITE(MGA_WVRTXSZ, 7);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
-                             MGA_WMASTER_ENABLE | MGA_WCACHEFLUSH_ENABLE));
-       wmisc = MGA_READ(MGA_WMISC);
-       if (wmisc != WMISC_EXPECTED) {
-               DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n",
-                         wmisc, WMISC_EXPECTED);
-               return -EINVAL;
-       }
-
-       return 0;
-}
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
deleted file mode 100644 (file)
index c31afbd..0000000
+++ /dev/null
@@ -1,935 +0,0 @@
-/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-
- * Created: Wed Apr  5 19:24:19 2000 by kevin@precisioninsight.com
- */
-/*
- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "r128_drm.h"
-#include "r128_drv.h"
-
-#define R128_FIFO_DEBUG                0
-
-/* CCE microcode (from ATI) */
-static u32 r128_cce_microcode[] = {
-       0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0,
-       1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0,
-       599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1,
-       11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11,
-       262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28,
-       1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9,
-       30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656,
-       1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1,
-       15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071,
-       12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2,
-       46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1,
-       459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1,
-       18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1,
-       15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2,
-       268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1,
-       15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82,
-       1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729,
-       3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008,
-       1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0,
-       15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1,
-       180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1,
-       114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0,
-       33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370,
-       1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1,
-       14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793,
-       1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1,
-       198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1,
-       114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1,
-       1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1,
-       1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894,
-       16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14,
-       174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1,
-       33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1,
-       33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1,
-       409611, 9, 188, 0, 10240, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static int R128_READ_PLL(struct drm_device * dev, int addr)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-
-       R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
-       return R128_READ(R128_CLOCK_CNTL_DATA);
-}
-
-#if R128_FIFO_DEBUG
-static void r128_status(drm_r128_private_t * dev_priv)
-{
-       printk("GUI_STAT           = 0x%08x\n",
-              (unsigned int)R128_READ(R128_GUI_STAT));
-       printk("PM4_STAT           = 0x%08x\n",
-              (unsigned int)R128_READ(R128_PM4_STAT));
-       printk("PM4_BUFFER_DL_WPTR = 0x%08x\n",
-              (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR));
-       printk("PM4_BUFFER_DL_RPTR = 0x%08x\n",
-              (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR));
-       printk("PM4_MICRO_CNTL     = 0x%08x\n",
-              (unsigned int)R128_READ(R128_PM4_MICRO_CNTL));
-       printk("PM4_BUFFER_CNTL    = 0x%08x\n",
-              (unsigned int)R128_READ(R128_PM4_BUFFER_CNTL));
-}
-#endif
-
-/* ================================================================
- * Engine, FIFO control
- */
-
-static int r128_do_pixcache_flush(drm_r128_private_t * dev_priv)
-{
-       u32 tmp;
-       int i;
-
-       tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL;
-       R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp);
-
-       for (i = 0; i < dev_priv->usec_timeout; i++) {
-               if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) {
-                       return 0;
-               }
-               DRM_UDELAY(1);
-       }
-
-#if R128_FIFO_DEBUG
-       DRM_ERROR("failed!\n");
-#endif
-       return -EBUSY;
-}
-
-static int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries)
-{
-       int i;
-
-       for (i = 0; i < dev_priv->usec_timeout; i++) {
-               int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
-               if (slots >= entries)
-                       return 0;
-               DRM_UDELAY(1);
-       }
-
-#if R128_FIFO_DEBUG
-       DRM_ERROR("failed!\n");
-#endif
-       return -EBUSY;
-}
-
-static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv)
-{
-       int i, ret;
-
-       ret = r128_do_wait_for_fifo(dev_priv, 64);
-       if (ret)
-               return ret;
-
-       for (i = 0; i < dev_priv->usec_timeout; i++) {
-               if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
-                       r128_do_pixcache_flush(dev_priv);
-                       return 0;
-               }
-               DRM_UDELAY(1);
-       }
-
-#if R128_FIFO_DEBUG
-       DRM_ERROR("failed!\n");
-#endif
-       return -EBUSY;
-}
-
-/* ================================================================
- * CCE control, initialization
- */
-
-/* Load the microcode for the CCE */
-static void r128_cce_load_microcode(drm_r128_private_t * dev_priv)
-{
-       int i;
-
-       DRM_DEBUG("\n");
-
-       r128_do_wait_for_idle(dev_priv);
-
-       R128_WRITE(R128_PM4_MICROCODE_ADDR, 0);
-       for (i = 0; i < 256; i++) {
-               R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]);
-               R128_WRITE(R128_PM4_MICROCODE_DATAL,
-                          r128_cce_microcode[i * 2 + 1]);
-       }
-}
-
-/* Flush any pending commands to the CCE.  This should only be used just
- * prior to a wait for idle, as it informs the engine that the command
- * stream is ending.
- */
-static void r128_do_cce_flush(drm_r128_private_t * dev_priv)
-{
-       u32 tmp;
-
-       tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR) | R128_PM4_BUFFER_DL_DONE;
-       R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp);
-}
-
-/* Wait for the CCE to go idle.
- */
-int r128_do_cce_idle(drm_r128_private_t * dev_priv)
-{
-       int i;
-
-       for (i = 0; i < dev_priv->usec_timeout; i++) {
-               if (GET_RING_HEAD(dev_priv) == dev_priv->ring.tail) {
-                       int pm4stat = R128_READ(R128_PM4_STAT);
-                       if (((pm4stat & R128_PM4_FIFOCNT_MASK) >=
-                            dev_priv->cce_fifo_size) &&
-                           !(pm4stat & (R128_PM4_BUSY |
-                                        R128_PM4_GUI_ACTIVE))) {
-                               return r128_do_pixcache_flush(dev_priv);
-                       }
-               }
-               DRM_UDELAY(1);
-       }
-
-#if R128_FIFO_DEBUG
-       DRM_ERROR("failed!\n");
-       r128_status(dev_priv);
-#endif
-       return -EBUSY;
-}
-
-/* Start the Concurrent Command Engine.
- */
-static void r128_do_cce_start(drm_r128_private_t * dev_priv)
-{
-       r128_do_wait_for_idle(dev_priv);
-
-       R128_WRITE(R128_PM4_BUFFER_CNTL,
-                  dev_priv->cce_mode | dev_priv->ring.size_l2qw
-                  | R128_PM4_BUFFER_CNTL_NOUPDATE);
-       R128_READ(R128_PM4_BUFFER_ADDR);        /* as per the sample code */
-       R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN);
-
-       dev_priv->cce_running = 1;
-}
-
-/* Reset the Concurrent Command Engine.  This will not flush any pending
- * commands, so you must wait for the CCE command stream to complete
- * before calling this routine.
- */
-static void r128_do_cce_reset(drm_r128_private_t * dev_priv)
-{
-       R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
-       R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
-       dev_priv->ring.tail = 0;
-}
-
-/* Stop the Concurrent Command Engine.  This will not flush any pending
- * commands, so you must flush the command stream and wait for the CCE
- * to go idle before calling this routine.
- */
-static void r128_do_cce_stop(drm_r128_private_t * dev_priv)
-{
-       R128_WRITE(R128_PM4_MICRO_CNTL, 0);
-       R128_WRITE(R128_PM4_BUFFER_CNTL,
-                  R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE);
-
-       dev_priv->cce_running = 0;
-}
-
-/* Reset the engine.  This will stop the CCE if it is running.
- */
-static int r128_do_engine_reset(struct drm_device * dev)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
-
-       r128_do_pixcache_flush(dev_priv);
-
-       clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX);
-       mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL);
-
-       R128_WRITE_PLL(R128_MCLK_CNTL,
-                      mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP);
-
-       gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL);
-
-       /* Taken from the sample code - do not change */
-       R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI);
-       R128_READ(R128_GEN_RESET_CNTL);
-       R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI);
-       R128_READ(R128_GEN_RESET_CNTL);
-
-       R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl);
-       R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
-       R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl);
-
-       /* Reset the CCE ring */
-       r128_do_cce_reset(dev_priv);
-
-       /* The CCE is no longer running after an engine reset */
-       dev_priv->cce_running = 0;
-
-       /* Reset any pending vertex, indirect buffers */
-       r128_freelist_reset(dev);
-
-       return 0;
-}
-
-static void r128_cce_init_ring_buffer(struct drm_device * dev,
-                                     drm_r128_private_t * dev_priv)
-{
-       u32 ring_start;
-       u32 tmp;
-
-       DRM_DEBUG("\n");
-
-       /* The manual (p. 2) says this address is in "VM space".  This
-        * means it's an offset from the start of AGP space.
-        */
-#if __OS_HAS_AGP
-       if (!dev_priv->is_pci)
-               ring_start = dev_priv->cce_ring->offset - dev->agp->base;
-       else
-#endif
-               ring_start = dev_priv->cce_ring->offset -
-                   (unsigned long)dev->sg->virtual;
-
-       R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET);
-
-       R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
-       R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
-
-       /* Set watermark control */
-       R128_WRITE(R128_PM4_BUFFER_WM_CNTL,
-                  ((R128_WATERMARK_L / 4) << R128_WMA_SHIFT)
-                  | ((R128_WATERMARK_M / 4) << R128_WMB_SHIFT)
-                  | ((R128_WATERMARK_N / 4) << R128_WMC_SHIFT)
-                  | ((R128_WATERMARK_K / 64) << R128_WB_WM_SHIFT));
-
-       /* Force read.  Why?  Because it's in the examples... */
-       R128_READ(R128_PM4_BUFFER_ADDR);
-
-       /* Turn on bus mastering */
-       tmp = R128_READ(R128_BUS_CNTL) & ~R128_BUS_MASTER_DIS;
-       R128_WRITE(R128_BUS_CNTL, tmp);
-}
-
-static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
-{
-       drm_r128_private_t *dev_priv;
-
-       DRM_DEBUG("\n");
-
-       dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
-       if (dev_priv == NULL)
-               return -ENOMEM;
-
-       memset(dev_priv, 0, sizeof(drm_r128_private_t));
-
-       dev_priv->is_pci = init->is_pci;
-
-       if (dev_priv->is_pci && !dev->sg) {
-               DRM_ERROR("PCI GART memory not allocated!\n");
-               dev->dev_private = (void *)dev_priv;
-               r128_do_cleanup_cce(dev);
-               return -EINVAL;
-       }
-
-       dev_priv->usec_timeout = init->usec_timeout;
-       if (dev_priv->usec_timeout < 1 ||
-           dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) {
-               DRM_DEBUG("TIMEOUT problem!\n");
-               dev->dev_private = (void *)dev_priv;
-               r128_do_cleanup_cce(dev);
-               return -EINVAL;
-       }
-
-       dev_priv->cce_mode = init->cce_mode;
-
-       /* GH: Simple idle check.
-        */
-       atomic_set(&dev_priv->idle_count, 0);
-
-       /* We don't support anything other than bus-mastering ring mode,
-        * but the ring can be in either AGP or PCI space for the ring
-        * read pointer.
-        */
-       if ((init->cce_mode != R128_PM4_192BM) &&
-           (init->cce_mode != R128_PM4_128BM_64INDBM) &&
-           (init->cce_mode != R128_PM4_64BM_128INDBM) &&
-           (init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM)) {
-               DRM_DEBUG("Bad cce_mode!\n");
-               dev->dev_private = (void *)dev_priv;
-               r128_do_cleanup_cce(dev);
-               return -EINVAL;
-       }
-
-       switch (init->cce_mode) {
-       case R128_PM4_NONPM4:
-               dev_priv->cce_fifo_size = 0;
-               break;
-       case R128_PM4_192PIO:
-       case R128_PM4_192BM:
-               dev_priv->cce_fifo_size = 192;
-               break;
-       case R128_PM4_128PIO_64INDBM:
-       case R128_PM4_128BM_64INDBM:
-               dev_priv->cce_fifo_size = 128;
-               break;
-       case R128_PM4_64PIO_128INDBM:
-       case R128_PM4_64BM_128INDBM:
-       case R128_PM4_64PIO_64VCBM_64INDBM:
-       case R128_PM4_64BM_64VCBM_64INDBM:
-       case R128_PM4_64PIO_64VCPIO_64INDPIO:
-               dev_priv->cce_fifo_size = 64;
-               break;
-       }
-
-       switch (init->fb_bpp) {
-       case 16:
-               dev_priv->color_fmt = R128_DATATYPE_RGB565;
-               break;
-       case 32:
-       default:
-               dev_priv->color_fmt = R128_DATATYPE_ARGB8888;
-               break;
-       }
-       dev_priv->front_offset = init->front_offset;
-       dev_priv->front_pitch = init->front_pitch;
-       dev_priv->back_offset = init->back_offset;
-       dev_priv->back_pitch = init->back_pitch;
-
-       switch (init->depth_bpp) {
-       case 16:
-               dev_priv->depth_fmt = R128_DATATYPE_RGB565;
-               break;
-       case 24:
-       case 32:
-       default:
-               dev_priv->depth_fmt = R128_DATATYPE_ARGB8888;
-               break;
-       }
-       dev_priv->depth_offset = init->depth_offset;
-       dev_priv->depth_pitch = init->depth_pitch;
-       dev_priv->span_offset = init->span_offset;
-
-       dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch / 8) << 21) |
-                                         (dev_priv->front_offset >> 5));
-       dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch / 8) << 21) |
-                                        (dev_priv->back_offset >> 5));
-       dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
-                                         (dev_priv->depth_offset >> 5) |
-                                         R128_DST_TILE);
-       dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
-                                        (dev_priv->span_offset >> 5));
-
-       dev_priv->sarea = drm_getsarea(dev);
-       if (!dev_priv->sarea) {
-               DRM_ERROR("could not find sarea!\n");
-               dev->dev_private = (void *)dev_priv;
-               r128_do_cleanup_cce(dev);
-               return -EINVAL;
-       }
-
-       dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
-       if (!dev_priv->mmio) {
-               DRM_ERROR("could not find mmio region!\n");
-               dev->dev_private = (void *)dev_priv;
-               r128_do_cleanup_cce(dev);
-               return -EINVAL;
-       }
-       dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset);
-       if (!dev_priv->cce_ring) {
-               DRM_ERROR("could not find cce ring region!\n");
-               dev->dev_private = (void *)dev_priv;
-               r128_do_cleanup_cce(dev);
-               return -EINVAL;
-       }
-       dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
-       if (!dev_priv->ring_rptr) {
-               DRM_ERROR("could not find ring read pointer!\n");
-               dev->dev_private = (void *)dev_priv;
-               r128_do_cleanup_cce(dev);
-               return -EINVAL;
-       }
-       dev->agp_buffer_token = init->buffers_offset;
-       dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
-       if (!dev->agp_buffer_map) {
-               DRM_ERROR("could not find dma buffer region!\n");
-               dev->dev_private = (void *)dev_priv;
-               r128_do_cleanup_cce(dev);
-               return -EINVAL;
-       }
-
-       if (!dev_priv->is_pci) {
-               dev_priv->agp_textures =
-                   drm_core_findmap(dev, init->agp_textures_offset);
-               if (!dev_priv->agp_textures) {
-                       DRM_ERROR("could not find agp texture region!\n");
-                       dev->dev_private = (void *)dev_priv;
-                       r128_do_cleanup_cce(dev);
-                       return -EINVAL;
-               }
-       }
-
-       dev_priv->sarea_priv =
-           (drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->handle +
-                                 init->sarea_priv_offset);
-
-#if __OS_HAS_AGP
-       if (!dev_priv->is_pci) {
-               drm_core_ioremap(dev_priv->cce_ring, dev);
-               drm_core_ioremap(dev_priv->ring_rptr, dev);
-               drm_core_ioremap(dev->agp_buffer_map, dev);
-               if (!dev_priv->cce_ring->handle ||
-                   !dev_priv->ring_rptr->handle ||
-                   !dev->agp_buffer_map->handle) {
-                       DRM_ERROR("Could not ioremap agp regions!\n");
-                       dev->dev_private = (void *)dev_priv;
-                       r128_do_cleanup_cce(dev);
-                       return -ENOMEM;
-               }
-       } else
-#endif
-       {
-               dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset;
-               dev_priv->ring_rptr->handle =
-                   (void *)dev_priv->ring_rptr->offset;
-               dev->agp_buffer_map->handle =
-                   (void *)dev->agp_buffer_map->offset;
-       }
-
-#if __OS_HAS_AGP
-       if (!dev_priv->is_pci)
-               dev_priv->cce_buffers_offset = dev->agp->base;
-       else
-#endif
-               dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual;
-
-       dev_priv->ring.start = (u32 *) dev_priv->cce_ring->handle;
-       dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle
-                             + init->ring_size / sizeof(u32));
-       dev_priv->ring.size = init->ring_size;
-       dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
-
-       dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
-
-       dev_priv->ring.high_mark = 128;
-
-       dev_priv->sarea_priv->last_frame = 0;
-       R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
-
-       dev_priv->sarea_priv->last_dispatch = 0;
-       R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch);
-
-#if __OS_HAS_AGP
-       if (dev_priv->is_pci) {
-#endif
-               dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
-               dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
-               dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE;
-               dev_priv->gart_info.addr = NULL;
-               dev_priv->gart_info.bus_addr = 0;
-               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
-               if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
-                       DRM_ERROR("failed to init PCI GART!\n");
-                       dev->dev_private = (void *)dev_priv;
-                       r128_do_cleanup_cce(dev);
-                       return -ENOMEM;
-               }
-               R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);
-#if __OS_HAS_AGP
-       }
-#endif
-
-       r128_cce_init_ring_buffer(dev, dev_priv);
-       r128_cce_load_microcode(dev_priv);
-
-       dev->dev_private = (void *)dev_priv;
-
-       r128_do_engine_reset(dev);
-
-       return 0;
-}
-
-int r128_do_cleanup_cce(struct drm_device * dev)
-{
-
-       /* Make sure interrupts are disabled here because the uninstall ioctl
-        * may not have been called from userspace and after dev_private
-        * is freed, it's too late.
-        */
-       if (dev->irq_enabled)
-               drm_irq_uninstall(dev);
-
-       if (dev->dev_private) {
-               drm_r128_private_t *dev_priv = dev->dev_private;
-
-#if __OS_HAS_AGP
-               if (!dev_priv->is_pci) {
-                       if (dev_priv->cce_ring != NULL)
-                               drm_core_ioremapfree(dev_priv->cce_ring, dev);
-                       if (dev_priv->ring_rptr != NULL)
-                               drm_core_ioremapfree(dev_priv->ring_rptr, dev);
-                       if (dev->agp_buffer_map != NULL) {
-                               drm_core_ioremapfree(dev->agp_buffer_map, dev);
-                               dev->agp_buffer_map = NULL;
-                       }
-               } else
-#endif
-               {
-                       if (dev_priv->gart_info.bus_addr)
-                               if (!drm_ati_pcigart_cleanup(dev,
-                                                       &dev_priv->gart_info))
-                                       DRM_ERROR
-                                           ("failed to cleanup PCI GART!\n");
-               }
-
-               drm_free(dev->dev_private, sizeof(drm_r128_private_t),
-                        DRM_MEM_DRIVER);
-               dev->dev_private = NULL;
-       }
-
-       return 0;
-}
-
-int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_init_t *init = data;
-
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       switch (init->func) {
-       case R128_INIT_CCE:
-               return r128_do_init_cce(dev, init);
-       case R128_CLEANUP_CCE:
-               return r128_do_cleanup_cce(dev);
-       }
-
-       return -EINVAL;
-}
-
-int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
-               DRM_DEBUG("while CCE running\n");
-               return 0;
-       }
-
-       r128_do_cce_start(dev_priv);
-
-       return 0;
-}
-
-/* Stop the CCE.  The engine must have been idled before calling this
- * routine.
- */
-int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_cce_stop_t *stop = data;
-       int ret;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       /* Flush any pending CCE commands.  This ensures any outstanding
-        * commands are exectuted by the engine before we turn it off.
-        */
-       if (stop->flush) {
-               r128_do_cce_flush(dev_priv);
-       }
-
-       /* If we fail to make the engine go idle, we return an error
-        * code so that the DRM ioctl wrapper can try again.
-        */
-       if (stop->idle) {
-               ret = r128_do_cce_idle(dev_priv);
-               if (ret)
-                       return ret;
-       }
-
-       /* Finally, we can turn off the CCE.  If the engine isn't idle,
-        * we will get some dropped triangles as they won't be fully
-        * rendered before the CCE is shut down.
-        */
-       r128_do_cce_stop(dev_priv);
-
-       /* Reset the engine */
-       r128_do_engine_reset(dev);
-
-       return 0;
-}
-
-/* Just reset the CCE ring.  Called as part of an X Server engine reset.
- */
-int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (!dev_priv) {
-               DRM_DEBUG("called before init done\n");
-               return -EINVAL;
-       }
-
-       r128_do_cce_reset(dev_priv);
-
-       /* The CCE is no longer running after an engine reset */
-       dev_priv->cce_running = 0;
-
-       return 0;
-}
-
-int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (dev_priv->cce_running) {
-               r128_do_cce_flush(dev_priv);
-       }
-
-       return r128_do_cce_idle(dev_priv);
-}
-
-int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       return r128_do_engine_reset(dev);
-}
-
-int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       return -EINVAL;
-}
-
-/* ================================================================
- * Freelist management
- */
-#define R128_BUFFER_USED       0xffffffff
-#define R128_BUFFER_FREE       0
-
-#if 0
-static int r128_freelist_init(struct drm_device * dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       struct drm_buf *buf;
-       drm_r128_buf_priv_t *buf_priv;
-       drm_r128_freelist_t *entry;
-       int i;
-
-       dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
-       if (dev_priv->head == NULL)
-               return -ENOMEM;
-
-       memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t));
-       dev_priv->head->age = R128_BUFFER_USED;
-
-       for (i = 0; i < dma->buf_count; i++) {
-               buf = dma->buflist[i];
-               buf_priv = buf->dev_private;
-
-               entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
-               if (!entry)
-                       return -ENOMEM;
-
-               entry->age = R128_BUFFER_FREE;
-               entry->buf = buf;
-               entry->prev = dev_priv->head;
-               entry->next = dev_priv->head->next;
-               if (!entry->next)
-                       dev_priv->tail = entry;
-
-               buf_priv->discard = 0;
-               buf_priv->dispatched = 0;
-               buf_priv->list_entry = entry;
-
-               dev_priv->head->next = entry;
-
-               if (dev_priv->head->next)
-                       dev_priv->head->next->prev = entry;
-       }
-
-       return 0;
-
-}
-#endif
-
-static struct drm_buf *r128_freelist_get(struct drm_device * dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_buf_priv_t *buf_priv;
-       struct drm_buf *buf;
-       int i, t;
-
-       /* FIXME: Optimize -- use freelist code */
-
-       for (i = 0; i < dma->buf_count; i++) {
-               buf = dma->buflist[i];
-               buf_priv = buf->dev_private;
-               if (!buf->file_priv)
-                       return buf;
-       }
-
-       for (t = 0; t < dev_priv->usec_timeout; t++) {
-               u32 done_age = R128_READ(R128_LAST_DISPATCH_REG);
-
-               for (i = 0; i < dma->buf_count; i++) {
-                       buf = dma->buflist[i];
-                       buf_priv = buf->dev_private;
-                       if (buf->pending && buf_priv->age <= done_age) {
-                               /* The buffer has been processed, so it
-                                * can now be used.
-                                */
-                               buf->pending = 0;
-                               return buf;
-                       }
-               }
-               DRM_UDELAY(1);
-       }
-
-       DRM_DEBUG("returning NULL!\n");
-       return NULL;
-}
-
-void r128_freelist_reset(struct drm_device * dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int i;
-
-       for (i = 0; i < dma->buf_count; i++) {
-               struct drm_buf *buf = dma->buflist[i];
-               drm_r128_buf_priv_t *buf_priv = buf->dev_private;
-               buf_priv->age = 0;
-       }
-}
-
-/* ================================================================
- * CCE command submission
- */
-
-int r128_wait_ring(drm_r128_private_t * dev_priv, int n)
-{
-       drm_r128_ring_buffer_t *ring = &dev_priv->ring;
-       int i;
-
-       for (i = 0; i < dev_priv->usec_timeout; i++) {
-               r128_update_ring_snapshot(dev_priv);
-               if (ring->space >= n)
-                       return 0;
-               DRM_UDELAY(1);
-       }
-
-       /* FIXME: This is being ignored... */
-       DRM_ERROR("failed!\n");
-       return -EBUSY;
-}
-
-static int r128_cce_get_buffers(struct drm_device * dev,
-                               struct drm_file *file_priv,
-                               struct drm_dma * d)
-{
-       int i;
-       struct drm_buf *buf;
-
-       for (i = d->granted_count; i < d->request_count; i++) {
-               buf = r128_freelist_get(dev);
-               if (!buf)
-                       return -EAGAIN;
-
-               buf->file_priv = file_priv;
-
-               if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
-                                    sizeof(buf->idx)))
-                       return -EFAULT;
-               if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
-                                    sizeof(buf->total)))
-                       return -EFAULT;
-
-               d->granted_count++;
-       }
-       return 0;
-}
-
-int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int ret = 0;
-       struct drm_dma *d = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       /* Please don't send us buffers.
-        */
-       if (d->send_count != 0) {
-               DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-                         DRM_CURRENTPID, d->send_count);
-               return -EINVAL;
-       }
-
-       /* We'll send you buffers.
-        */
-       if (d->request_count < 0 || d->request_count > dma->buf_count) {
-               DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         DRM_CURRENTPID, d->request_count, dma->buf_count);
-               return -EINVAL;
-       }
-
-       d->granted_count = 0;
-
-       if (d->request_count) {
-               ret = r128_cce_get_buffers(dev, file_priv, d);
-       }
-
-       return ret;
-}
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
deleted file mode 100644 (file)
index 8d8878b..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-
- * Created: Wed Apr  5 19:24:19 2000 by kevin@precisioninsight.com
- */
-/*
- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Gareth Hughes <gareth@valinux.com>
- *    Kevin E. Martin <martin@valinux.com>
- */
-
-#ifndef __R128_DRM_H__
-#define __R128_DRM_H__
-
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the X server file (r128_sarea.h)
- */
-#ifndef __R128_SAREA_DEFINES__
-#define __R128_SAREA_DEFINES__
-
-/* What needs to be changed for the current vertex buffer?
- */
-#define R128_UPLOAD_CONTEXT            0x001
-#define R128_UPLOAD_SETUP              0x002
-#define R128_UPLOAD_TEX0               0x004
-#define R128_UPLOAD_TEX1               0x008
-#define R128_UPLOAD_TEX0IMAGES         0x010
-#define R128_UPLOAD_TEX1IMAGES         0x020
-#define R128_UPLOAD_CORE               0x040
-#define R128_UPLOAD_MASKS              0x080
-#define R128_UPLOAD_WINDOW             0x100
-#define R128_UPLOAD_CLIPRECTS          0x200   /* handled client-side */
-#define R128_REQUIRE_QUIESCENCE                0x400
-#define R128_UPLOAD_ALL                        0x7ff
-
-#define R128_FRONT                     0x1
-#define R128_BACK                      0x2
-#define R128_DEPTH                     0x4
-
-/* Primitive types
- */
-#define R128_POINTS                    0x1
-#define R128_LINES                     0x2
-#define R128_LINE_STRIP                        0x3
-#define R128_TRIANGLES                 0x4
-#define R128_TRIANGLE_FAN              0x5
-#define R128_TRIANGLE_STRIP            0x6
-
-/* Vertex/indirect buffer size
- */
-#define R128_BUFFER_SIZE               16384
-
-/* Byte offsets for indirect buffer data
- */
-#define R128_INDEX_PRIM_OFFSET         20
-#define R128_HOSTDATA_BLIT_OFFSET      32
-
-/* Keep these small for testing.
- */
-#define R128_NR_SAREA_CLIPRECTS                12
-
-/* There are 2 heaps (local/AGP).  Each region within a heap is a
- *  minimum of 64k, and there are at most 64 of them per heap.
- */
-#define R128_LOCAL_TEX_HEAP            0
-#define R128_AGP_TEX_HEAP              1
-#define R128_NR_TEX_HEAPS              2
-#define R128_NR_TEX_REGIONS            64
-#define R128_LOG_TEX_GRANULARITY       16
-
-#define R128_NR_CONTEXT_REGS           12
-
-#define R128_MAX_TEXTURE_LEVELS                11
-#define R128_MAX_TEXTURE_UNITS         2
-
-#endif                         /* __R128_SAREA_DEFINES__ */
-
-typedef struct {
-       /* Context state - can be written in one large chunk */
-       unsigned int dst_pitch_offset_c;
-       unsigned int dp_gui_master_cntl_c;
-       unsigned int sc_top_left_c;
-       unsigned int sc_bottom_right_c;
-       unsigned int z_offset_c;
-       unsigned int z_pitch_c;
-       unsigned int z_sten_cntl_c;
-       unsigned int tex_cntl_c;
-       unsigned int misc_3d_state_cntl_reg;
-       unsigned int texture_clr_cmp_clr_c;
-       unsigned int texture_clr_cmp_msk_c;
-       unsigned int fog_color_c;
-
-       /* Texture state */
-       unsigned int tex_size_pitch_c;
-       unsigned int constant_color_c;
-
-       /* Setup state */
-       unsigned int pm4_vc_fpu_setup;
-       unsigned int setup_cntl;
-
-       /* Mask state */
-       unsigned int dp_write_mask;
-       unsigned int sten_ref_mask_c;
-       unsigned int plane_3d_mask_c;
-
-       /* Window state */
-       unsigned int window_xy_offset;
-
-       /* Core state */
-       unsigned int scale_3d_cntl;
-} drm_r128_context_regs_t;
-
-/* Setup registers for each texture unit
- */
-typedef struct {
-       unsigned int tex_cntl;
-       unsigned int tex_combine_cntl;
-       unsigned int tex_size_pitch;
-       unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS];
-       unsigned int tex_border_color;
-} drm_r128_texture_regs_t;
-
-typedef struct drm_r128_sarea {
-       /* The channel for communication of state information to the kernel
-        * on firing a vertex buffer.
-        */
-       drm_r128_context_regs_t context_state;
-       drm_r128_texture_regs_t tex_state[R128_MAX_TEXTURE_UNITS];
-       unsigned int dirty;
-       unsigned int vertsize;
-       unsigned int vc_format;
-
-       /* The current cliprects, or a subset thereof.
-        */
-       struct drm_clip_rect boxes[R128_NR_SAREA_CLIPRECTS];
-       unsigned int nbox;
-
-       /* Counters for client-side throttling of rendering clients.
-        */
-       unsigned int last_frame;
-       unsigned int last_dispatch;
-
-       struct drm_tex_region tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1];
-       unsigned int tex_age[R128_NR_TEX_HEAPS];
-       int ctx_owner;
-       int pfAllowPageFlip;    /* number of 3d windows (0,1,2 or more) */
-       int pfCurrentPage;      /* which buffer is being displayed? */
-} drm_r128_sarea_t;
-
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the Xserver file (xf86drmR128.h)
- */
-
-/* Rage 128 specific ioctls
- * The device specific ioctl range is 0x40 to 0x79.
- */
-#define DRM_R128_INIT       0x00
-#define DRM_R128_CCE_START  0x01
-#define DRM_R128_CCE_STOP   0x02
-#define DRM_R128_CCE_RESET  0x03
-#define DRM_R128_CCE_IDLE   0x04
-/* 0x05 not used */
-#define DRM_R128_RESET      0x06
-#define DRM_R128_SWAP       0x07
-#define DRM_R128_CLEAR      0x08
-#define DRM_R128_VERTEX     0x09
-#define DRM_R128_INDICES    0x0a
-#define DRM_R128_BLIT       0x0b
-#define DRM_R128_DEPTH      0x0c
-#define DRM_R128_STIPPLE    0x0d
-/* 0x0e not used */
-#define DRM_R128_INDIRECT   0x0f
-#define DRM_R128_FULLSCREEN 0x10
-#define DRM_R128_CLEAR2     0x11
-#define DRM_R128_GETPARAM   0x12
-#define DRM_R128_FLIP       0x13
-
-#define DRM_IOCTL_R128_INIT       DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INIT, drm_r128_init_t)
-#define DRM_IOCTL_R128_CCE_START  DRM_IO(  DRM_COMMAND_BASE + DRM_R128_CCE_START)
-#define DRM_IOCTL_R128_CCE_STOP   DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CCE_STOP, drm_r128_cce_stop_t)
-#define DRM_IOCTL_R128_CCE_RESET  DRM_IO(  DRM_COMMAND_BASE + DRM_R128_CCE_RESET)
-#define DRM_IOCTL_R128_CCE_IDLE   DRM_IO(  DRM_COMMAND_BASE + DRM_R128_CCE_IDLE)
-/* 0x05 not used */
-#define DRM_IOCTL_R128_RESET      DRM_IO(  DRM_COMMAND_BASE + DRM_R128_RESET)
-#define DRM_IOCTL_R128_SWAP       DRM_IO(  DRM_COMMAND_BASE + DRM_R128_SWAP)
-#define DRM_IOCTL_R128_CLEAR      DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR, drm_r128_clear_t)
-#define DRM_IOCTL_R128_VERTEX     DRM_IOW( DRM_COMMAND_BASE + DRM_R128_VERTEX, drm_r128_vertex_t)
-#define DRM_IOCTL_R128_INDICES    DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INDICES, drm_r128_indices_t)
-#define DRM_IOCTL_R128_BLIT       DRM_IOW( DRM_COMMAND_BASE + DRM_R128_BLIT, drm_r128_blit_t)
-#define DRM_IOCTL_R128_DEPTH      DRM_IOW( DRM_COMMAND_BASE + DRM_R128_DEPTH, drm_r128_depth_t)
-#define DRM_IOCTL_R128_STIPPLE    DRM_IOW( DRM_COMMAND_BASE + DRM_R128_STIPPLE, drm_r128_stipple_t)
-/* 0x0e not used */
-#define DRM_IOCTL_R128_INDIRECT   DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t)
-#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t)
-#define DRM_IOCTL_R128_CLEAR2     DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t)
-#define DRM_IOCTL_R128_GETPARAM   DRM_IOWR( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t)
-#define DRM_IOCTL_R128_FLIP       DRM_IO(  DRM_COMMAND_BASE + DRM_R128_FLIP)
-
-typedef struct drm_r128_init {
-       enum {
-               R128_INIT_CCE = 0x01,
-               R128_CLEANUP_CCE = 0x02
-       } func;
-       unsigned long sarea_priv_offset;
-       int is_pci;
-       int cce_mode;
-       int cce_secure;
-       int ring_size;
-       int usec_timeout;
-
-       unsigned int fb_bpp;
-       unsigned int front_offset, front_pitch;
-       unsigned int back_offset, back_pitch;
-       unsigned int depth_bpp;
-       unsigned int depth_offset, depth_pitch;
-       unsigned int span_offset;
-
-       unsigned long fb_offset;
-       unsigned long mmio_offset;
-       unsigned long ring_offset;
-       unsigned long ring_rptr_offset;
-       unsigned long buffers_offset;
-       unsigned long agp_textures_offset;
-} drm_r128_init_t;
-
-typedef struct drm_r128_cce_stop {
-       int flush;
-       int idle;
-} drm_r128_cce_stop_t;
-
-typedef struct drm_r128_clear {
-       unsigned int flags;
-       unsigned int clear_color;
-       unsigned int clear_depth;
-       unsigned int color_mask;
-       unsigned int depth_mask;
-} drm_r128_clear_t;
-
-typedef struct drm_r128_vertex {
-       int prim;
-       int idx;                /* Index of vertex buffer */
-       int count;              /* Number of vertices in buffer */
-       int discard;            /* Client finished with buffer? */
-} drm_r128_vertex_t;
-
-typedef struct drm_r128_indices {
-       int prim;
-       int idx;
-       int start;
-       int end;
-       int discard;            /* Client finished with buffer? */
-} drm_r128_indices_t;
-
-typedef struct drm_r128_blit {
-       int idx;
-       int pitch;
-       int offset;
-       int format;
-       unsigned short x, y;
-       unsigned short width, height;
-} drm_r128_blit_t;
-
-typedef struct drm_r128_depth {
-       enum {
-               R128_WRITE_SPAN = 0x01,
-               R128_WRITE_PIXELS = 0x02,
-               R128_READ_SPAN = 0x03,
-               R128_READ_PIXELS = 0x04
-       } func;
-       int n;
-       int __user *x;
-       int __user *y;
-       unsigned int __user *buffer;
-       unsigned char __user *mask;
-} drm_r128_depth_t;
-
-typedef struct drm_r128_stipple {
-       unsigned int __user *mask;
-} drm_r128_stipple_t;
-
-typedef struct drm_r128_indirect {
-       int idx;
-       int start;
-       int end;
-       int discard;
-} drm_r128_indirect_t;
-
-typedef struct drm_r128_fullscreen {
-       enum {
-               R128_INIT_FULLSCREEN = 0x01,
-               R128_CLEANUP_FULLSCREEN = 0x02
-       } func;
-} drm_r128_fullscreen_t;
-
-/* 2.3: An ioctl to get parameters that aren't available to the 3d
- * client any other way.
- */
-#define R128_PARAM_IRQ_NR            1
-
-typedef struct drm_r128_getparam {
-       int param;
-       void __user *value;
-} drm_r128_getparam_t;
-
-#endif
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
deleted file mode 100644 (file)
index 6108e75..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*-
- * Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "r128_drm.h"
-#include "r128_drv.h"
-
-#include "drm_pciids.h"
-
-static struct pci_device_id pciidlist[] = {
-       r128_PCI_IDS
-};
-
-static struct drm_driver driver = {
-       .driver_features =
-           DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
-           DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
-           DRIVER_IRQ_VBL,
-       .dev_priv_size = sizeof(drm_r128_buf_priv_t),
-       .preclose = r128_driver_preclose,
-       .lastclose = r128_driver_lastclose,
-       .vblank_wait = r128_driver_vblank_wait,
-       .irq_preinstall = r128_driver_irq_preinstall,
-       .irq_postinstall = r128_driver_irq_postinstall,
-       .irq_uninstall = r128_driver_irq_uninstall,
-       .irq_handler = r128_driver_irq_handler,
-       .reclaim_buffers = drm_core_reclaim_buffers,
-       .get_map_ofs = drm_core_get_map_ofs,
-       .get_reg_ofs = drm_core_get_reg_ofs,
-       .ioctls = r128_ioctls,
-       .dma_ioctl = r128_cce_buffers,
-       .fops = {
-                .owner = THIS_MODULE,
-                .open = drm_open,
-                .release = drm_release,
-                .ioctl = drm_ioctl,
-                .mmap = drm_mmap,
-                .poll = drm_poll,
-                .fasync = drm_fasync,
-#ifdef CONFIG_COMPAT
-                .compat_ioctl = r128_compat_ioctl,
-#endif
-       },
-
-       .pci_driver = {
-                .name = DRIVER_NAME,
-                .id_table = pciidlist,
-       },
-
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int __init r128_init(void)
-{
-       driver.num_ioctls = r128_max_ioctl;
-       return drm_init(&driver);
-}
-
-static void __exit r128_exit(void)
-{
-       drm_exit(&driver);
-}
-
-module_init(r128_init);
-module_exit(r128_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
deleted file mode 100644 (file)
index 011105e..0000000
+++ /dev/null
@@ -1,522 +0,0 @@
-/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-
- * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com
- */
-/*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Kevin E. Martin <martin@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- *    Michel Dänzer <daenzerm@student.ethz.ch>
- */
-
-#ifndef __R128_DRV_H__
-#define __R128_DRV_H__
-
-/* General customization:
- */
-#define DRIVER_AUTHOR          "Gareth Hughes, VA Linux Systems Inc."
-
-#define DRIVER_NAME            "r128"
-#define DRIVER_DESC            "ATI Rage 128"
-#define DRIVER_DATE            "20030725"
-
-/* Interface history:
- *
- * ??  - ??
- * 2.4 - Add support for ycbcr textures (no new ioctls)
- * 2.5 - Add FLIP ioctl, disable FULLSCREEN.
- */
-#define DRIVER_MAJOR           2
-#define DRIVER_MINOR           5
-#define DRIVER_PATCHLEVEL      0
-
-#define GET_RING_HEAD(dev_priv)                R128_READ( R128_PM4_BUFFER_DL_RPTR )
-
-typedef struct drm_r128_freelist {
-       unsigned int age;
-       struct drm_buf *buf;
-       struct drm_r128_freelist *next;
-       struct drm_r128_freelist *prev;
-} drm_r128_freelist_t;
-
-typedef struct drm_r128_ring_buffer {
-       u32 *start;
-       u32 *end;
-       int size;
-       int size_l2qw;
-
-       u32 tail;
-       u32 tail_mask;
-       int space;
-
-       int high_mark;
-} drm_r128_ring_buffer_t;
-
-typedef struct drm_r128_private {
-       drm_r128_ring_buffer_t ring;
-       drm_r128_sarea_t *sarea_priv;
-
-       int cce_mode;
-       int cce_fifo_size;
-       int cce_running;
-
-       drm_r128_freelist_t *head;
-       drm_r128_freelist_t *tail;
-
-       int usec_timeout;
-       int is_pci;
-       unsigned long cce_buffers_offset;
-
-       atomic_t idle_count;
-
-       int page_flipping;
-       int current_page;
-       u32 crtc_offset;
-       u32 crtc_offset_cntl;
-
-       u32 color_fmt;
-       unsigned int front_offset;
-       unsigned int front_pitch;
-       unsigned int back_offset;
-       unsigned int back_pitch;
-
-       u32 depth_fmt;
-       unsigned int depth_offset;
-       unsigned int depth_pitch;
-       unsigned int span_offset;
-
-       u32 front_pitch_offset_c;
-       u32 back_pitch_offset_c;
-       u32 depth_pitch_offset_c;
-       u32 span_pitch_offset_c;
-
-       drm_local_map_t *sarea;
-       drm_local_map_t *mmio;
-       drm_local_map_t *cce_ring;
-       drm_local_map_t *ring_rptr;
-       drm_local_map_t *agp_textures;
-       struct drm_ati_pcigart_info gart_info;
-} drm_r128_private_t;
-
-typedef struct drm_r128_buf_priv {
-       u32 age;
-       int prim;
-       int discard;
-       int dispatched;
-       drm_r128_freelist_t *list_entry;
-} drm_r128_buf_priv_t;
-
-extern struct drm_ioctl_desc r128_ioctls[];
-extern int r128_max_ioctl;
-
-                               /* r128_cce.c */
-extern int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
-
-extern void r128_freelist_reset(struct drm_device * dev);
-
-extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
-
-extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
-extern int r128_do_cleanup_cce(struct drm_device * dev);
-
-extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
-
-extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
-extern void r128_driver_irq_preinstall(struct drm_device * dev);
-extern void r128_driver_irq_postinstall(struct drm_device * dev);
-extern void r128_driver_irq_uninstall(struct drm_device * dev);
-extern void r128_driver_lastclose(struct drm_device * dev);
-extern void r128_driver_preclose(struct drm_device * dev,
-                                struct drm_file *file_priv);
-
-extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
-                             unsigned long arg);
-
-/* Register definitions, register access macros and drmAddMap constants
- * for Rage 128 kernel driver.
- */
-
-#define R128_AUX_SC_CNTL               0x1660
-#      define R128_AUX1_SC_EN                  (1 << 0)
-#      define R128_AUX1_SC_MODE_OR             (0 << 1)
-#      define R128_AUX1_SC_MODE_NAND           (1 << 1)
-#      define R128_AUX2_SC_EN                  (1 << 2)
-#      define R128_AUX2_SC_MODE_OR             (0 << 3)
-#      define R128_AUX2_SC_MODE_NAND           (1 << 3)
-#      define R128_AUX3_SC_EN                  (1 << 4)
-#      define R128_AUX3_SC_MODE_OR             (0 << 5)
-#      define R128_AUX3_SC_MODE_NAND           (1 << 5)
-#define R128_AUX1_SC_LEFT              0x1664
-#define R128_AUX1_SC_RIGHT             0x1668
-#define R128_AUX1_SC_TOP               0x166c
-#define R128_AUX1_SC_BOTTOM            0x1670
-#define R128_AUX2_SC_LEFT              0x1674
-#define R128_AUX2_SC_RIGHT             0x1678
-#define R128_AUX2_SC_TOP               0x167c
-#define R128_AUX2_SC_BOTTOM            0x1680
-#define R128_AUX3_SC_LEFT              0x1684
-#define R128_AUX3_SC_RIGHT             0x1688
-#define R128_AUX3_SC_TOP               0x168c
-#define R128_AUX3_SC_BOTTOM            0x1690
-
-#define R128_BRUSH_DATA0               0x1480
-#define R128_BUS_CNTL                  0x0030
-#      define R128_BUS_MASTER_DIS              (1 << 6)
-
-#define R128_CLOCK_CNTL_INDEX          0x0008
-#define R128_CLOCK_CNTL_DATA           0x000c
-#      define R128_PLL_WR_EN                   (1 << 7)
-#define R128_CONSTANT_COLOR_C          0x1d34
-#define R128_CRTC_OFFSET               0x0224
-#define R128_CRTC_OFFSET_CNTL          0x0228
-#      define R128_CRTC_OFFSET_FLIP_CNTL       (1 << 16)
-
-#define R128_DP_GUI_MASTER_CNTL                0x146c
-#       define R128_GMC_SRC_PITCH_OFFSET_CNTL  (1    <<  0)
-#       define R128_GMC_DST_PITCH_OFFSET_CNTL  (1    <<  1)
-#      define R128_GMC_BRUSH_SOLID_COLOR       (13   <<  4)
-#      define R128_GMC_BRUSH_NONE              (15   <<  4)
-#      define R128_GMC_DST_16BPP               (4    <<  8)
-#      define R128_GMC_DST_24BPP               (5    <<  8)
-#      define R128_GMC_DST_32BPP               (6    <<  8)
-#       define R128_GMC_DST_DATATYPE_SHIFT     8
-#      define R128_GMC_SRC_DATATYPE_COLOR      (3    << 12)
-#      define R128_DP_SRC_SOURCE_MEMORY        (2    << 24)
-#      define R128_DP_SRC_SOURCE_HOST_DATA     (3    << 24)
-#      define R128_GMC_CLR_CMP_CNTL_DIS        (1    << 28)
-#      define R128_GMC_AUX_CLIP_DIS            (1    << 29)
-#      define R128_GMC_WR_MSK_DIS              (1    << 30)
-#      define R128_ROP3_S                      0x00cc0000
-#      define R128_ROP3_P                      0x00f00000
-#define R128_DP_WRITE_MASK             0x16cc
-#define R128_DST_PITCH_OFFSET_C                0x1c80
-#      define R128_DST_TILE                    (1 << 31)
-
-#define R128_GEN_INT_CNTL              0x0040
-#      define R128_CRTC_VBLANK_INT_EN          (1 <<  0)
-#define R128_GEN_INT_STATUS            0x0044
-#      define R128_CRTC_VBLANK_INT             (1 <<  0)
-#      define R128_CRTC_VBLANK_INT_AK          (1 <<  0)
-#define R128_GEN_RESET_CNTL            0x00f0
-#      define R128_SOFT_RESET_GUI              (1 <<  0)
-
-#define R128_GUI_SCRATCH_REG0          0x15e0
-#define R128_GUI_SCRATCH_REG1          0x15e4
-#define R128_GUI_SCRATCH_REG2          0x15e8
-#define R128_GUI_SCRATCH_REG3          0x15ec
-#define R128_GUI_SCRATCH_REG4          0x15f0
-#define R128_GUI_SCRATCH_REG5          0x15f4
-
-#define R128_GUI_STAT                  0x1740
-#      define R128_GUI_FIFOCNT_MASK            0x0fff
-#      define R128_GUI_ACTIVE                  (1 << 31)
-
-#define R128_MCLK_CNTL                 0x000f
-#      define R128_FORCE_GCP                   (1 << 16)
-#      define R128_FORCE_PIPE3D_CP             (1 << 17)
-#      define R128_FORCE_RCP                   (1 << 18)
-
-#define R128_PC_GUI_CTLSTAT            0x1748
-#define R128_PC_NGUI_CTLSTAT           0x0184
-#      define R128_PC_FLUSH_GUI                (3 << 0)
-#      define R128_PC_RI_GUI                   (1 << 2)
-#      define R128_PC_FLUSH_ALL                0x00ff
-#      define R128_PC_BUSY                     (1 << 31)
-
-#define R128_PCI_GART_PAGE             0x017c
-#define R128_PRIM_TEX_CNTL_C           0x1cb0
-
-#define R128_SCALE_3D_CNTL             0x1a00
-#define R128_SEC_TEX_CNTL_C            0x1d00
-#define R128_SEC_TEXTURE_BORDER_COLOR_C        0x1d3c
-#define R128_SETUP_CNTL                        0x1bc4
-#define R128_STEN_REF_MASK_C           0x1d40
-
-#define R128_TEX_CNTL_C                        0x1c9c
-#      define R128_TEX_CACHE_FLUSH             (1 << 23)
-
-#define R128_WAIT_UNTIL                        0x1720
-#      define R128_EVENT_CRTC_OFFSET           (1 << 0)
-#define R128_WINDOW_XY_OFFSET          0x1bcc
-
-/* CCE registers
- */
-#define R128_PM4_BUFFER_OFFSET         0x0700
-#define R128_PM4_BUFFER_CNTL           0x0704
-#      define R128_PM4_MASK                    (15 << 28)
-#      define R128_PM4_NONPM4                  (0  << 28)
-#      define R128_PM4_192PIO                  (1  << 28)
-#      define R128_PM4_192BM                   (2  << 28)
-#      define R128_PM4_128PIO_64INDBM          (3  << 28)
-#      define R128_PM4_128BM_64INDBM           (4  << 28)
-#      define R128_PM4_64PIO_128INDBM          (5  << 28)
-#      define R128_PM4_64BM_128INDBM           (6  << 28)
-#      define R128_PM4_64PIO_64VCBM_64INDBM    (7  << 28)
-#      define R128_PM4_64BM_64VCBM_64INDBM     (8  << 28)
-#      define R128_PM4_64PIO_64VCPIO_64INDPIO  (15 << 28)
-#      define R128_PM4_BUFFER_CNTL_NOUPDATE    (1  << 27)
-
-#define R128_PM4_BUFFER_WM_CNTL                0x0708
-#      define R128_WMA_SHIFT                   0
-#      define R128_WMB_SHIFT                   8
-#      define R128_WMC_SHIFT                   16
-#      define R128_WB_WM_SHIFT                 24
-
-#define R128_PM4_BUFFER_DL_RPTR_ADDR   0x070c
-#define R128_PM4_BUFFER_DL_RPTR                0x0710
-#define R128_PM4_BUFFER_DL_WPTR                0x0714
-#      define R128_PM4_BUFFER_DL_DONE          (1 << 31)
-
-#define R128_PM4_VC_FPU_SETUP          0x071c
-
-#define R128_PM4_IW_INDOFF             0x0738
-#define R128_PM4_IW_INDSIZE            0x073c
-
-#define R128_PM4_STAT                  0x07b8
-#      define R128_PM4_FIFOCNT_MASK            0x0fff
-#      define R128_PM4_BUSY                    (1 << 16)
-#      define R128_PM4_GUI_ACTIVE              (1 << 31)
-
-#define R128_PM4_MICROCODE_ADDR                0x07d4
-#define R128_PM4_MICROCODE_RADDR       0x07d8
-#define R128_PM4_MICROCODE_DATAH       0x07dc
-#define R128_PM4_MICROCODE_DATAL       0x07e0
-
-#define R128_PM4_BUFFER_ADDR           0x07f0
-#define R128_PM4_MICRO_CNTL            0x07fc
-#      define R128_PM4_MICRO_FREERUN           (1 << 30)
-
-#define R128_PM4_FIFO_DATA_EVEN                0x1000
-#define R128_PM4_FIFO_DATA_ODD         0x1004
-
-/* CCE command packets
- */
-#define R128_CCE_PACKET0               0x00000000
-#define R128_CCE_PACKET1               0x40000000
-#define R128_CCE_PACKET2               0x80000000
-#define R128_CCE_PACKET3               0xC0000000
-#      define R128_CNTL_HOSTDATA_BLT           0x00009400
-#      define R128_CNTL_PAINT_MULTI            0x00009A00
-#      define R128_CNTL_BITBLT_MULTI           0x00009B00
-#      define R128_3D_RNDR_GEN_INDX_PRIM       0x00002300
-
-#define R128_CCE_PACKET_MASK           0xC0000000
-#define R128_CCE_PACKET_COUNT_MASK     0x3fff0000
-#define R128_CCE_PACKET0_REG_MASK      0x000007ff
-#define R128_CCE_PACKET1_REG0_MASK     0x000007ff
-#define R128_CCE_PACKET1_REG1_MASK     0x003ff800
-
-#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE                0x00000000
-#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT       0x00000001
-#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE                0x00000002
-#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE   0x00000003
-#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST    0x00000004
-#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN     0x00000005
-#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP   0x00000006
-#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2   0x00000007
-#define R128_CCE_VC_CNTL_PRIM_WALK_IND         0x00000010
-#define R128_CCE_VC_CNTL_PRIM_WALK_LIST                0x00000020
-#define R128_CCE_VC_CNTL_PRIM_WALK_RING                0x00000030
-#define R128_CCE_VC_CNTL_NUM_SHIFT             16
-
-#define R128_DATATYPE_VQ               0
-#define R128_DATATYPE_CI4              1
-#define R128_DATATYPE_CI8              2
-#define R128_DATATYPE_ARGB1555         3
-#define R128_DATATYPE_RGB565           4
-#define R128_DATATYPE_RGB888           5
-#define R128_DATATYPE_ARGB8888         6
-#define R128_DATATYPE_RGB332           7
-#define R128_DATATYPE_Y8               8
-#define R128_DATATYPE_RGB8             9
-#define R128_DATATYPE_CI16             10
-#define R128_DATATYPE_YVYU422          11
-#define R128_DATATYPE_VYUY422          12
-#define R128_DATATYPE_AYUV444          14
-#define R128_DATATYPE_ARGB4444         15
-
-/* Constants */
-#define R128_AGP_OFFSET                        0x02000000
-
-#define R128_WATERMARK_L               16
-#define R128_WATERMARK_M               8
-#define R128_WATERMARK_N               8
-#define R128_WATERMARK_K               128
-
-#define R128_MAX_USEC_TIMEOUT          100000  /* 100 ms */
-
-#define R128_LAST_FRAME_REG            R128_GUI_SCRATCH_REG0
-#define R128_LAST_DISPATCH_REG         R128_GUI_SCRATCH_REG1
-#define R128_MAX_VB_AGE                        0x7fffffff
-#define R128_MAX_VB_VERTS              (0xffff)
-
-#define R128_RING_HIGH_MARK            128
-
-#define R128_PERFORMANCE_BOXES         0
-
-#define R128_PCIGART_TABLE_SIZE         32768
-
-#define R128_READ(reg)         DRM_READ32(  dev_priv->mmio, (reg) )
-#define R128_WRITE(reg,val)    DRM_WRITE32( dev_priv->mmio, (reg), (val) )
-#define R128_READ8(reg)                DRM_READ8(   dev_priv->mmio, (reg) )
-#define R128_WRITE8(reg,val)   DRM_WRITE8(  dev_priv->mmio, (reg), (val) )
-
-#define R128_WRITE_PLL(addr,val)                                       \
-do {                                                                   \
-       R128_WRITE8(R128_CLOCK_CNTL_INDEX,                              \
-                   ((addr) & 0x1f) | R128_PLL_WR_EN);                  \
-       R128_WRITE(R128_CLOCK_CNTL_DATA, (val));                        \
-} while (0)
-
-#define CCE_PACKET0( reg, n )          (R128_CCE_PACKET0 |             \
-                                        ((n) << 16) | ((reg) >> 2))
-#define CCE_PACKET1( reg0, reg1 )      (R128_CCE_PACKET1 |             \
-                                        (((reg1) >> 2) << 11) | ((reg0) >> 2))
-#define CCE_PACKET2()                  (R128_CCE_PACKET2)
-#define CCE_PACKET3( pkt, n )          (R128_CCE_PACKET3 |             \
-                                        (pkt) | ((n) << 16))
-
-static __inline__ void r128_update_ring_snapshot(drm_r128_private_t * dev_priv)
-{
-       drm_r128_ring_buffer_t *ring = &dev_priv->ring;
-       ring->space = (GET_RING_HEAD(dev_priv) - ring->tail) * sizeof(u32);
-       if (ring->space <= 0)
-               ring->space += ring->size;
-}
-
-/* ================================================================
- * Misc helper macros
- */
-
-#define RING_SPACE_TEST_WITH_RETURN( dev_priv )                                \
-do {                                                                   \
-       drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i;          \
-       if ( ring->space < ring->high_mark ) {                          \
-               for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {      \
-                       r128_update_ring_snapshot( dev_priv );          \
-                       if ( ring->space >= ring->high_mark )           \
-                               goto __ring_space_done;                 \
-                       DRM_UDELAY(1);                          \
-               }                                                       \
-               DRM_ERROR( "ring space check failed!\n" );              \
-               return -EBUSY;                          \
-       }                                                               \
- __ring_space_done:                                                    \
-       ;                                                               \
-} while (0)
-
-#define VB_AGE_TEST_WITH_RETURN( dev_priv )                            \
-do {                                                                   \
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;            \
-       if ( sarea_priv->last_dispatch >= R128_MAX_VB_AGE ) {           \
-               int __ret = r128_do_cce_idle( dev_priv );               \
-               if ( __ret ) return __ret;                              \
-               sarea_priv->last_dispatch = 0;                          \
-               r128_freelist_reset( dev );                             \
-       }                                                               \
-} while (0)
-
-#define R128_WAIT_UNTIL_PAGE_FLIPPED() do {                            \
-       OUT_RING( CCE_PACKET0( R128_WAIT_UNTIL, 0 ) );                  \
-       OUT_RING( R128_EVENT_CRTC_OFFSET );                             \
-} while (0)
-
-/* ================================================================
- * Ring control
- */
-
-#define R128_VERBOSE   0
-
-#define RING_LOCALS                                                    \
-       int write, _nr; unsigned int tail_mask; volatile u32 *ring;
-
-#define BEGIN_RING( n ) do {                                           \
-       if ( R128_VERBOSE ) {                                           \
-               DRM_INFO( "BEGIN_RING( %d )\n", (n));                   \
-       }                                                               \
-       if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {              \
-               COMMIT_RING();                                          \
-               r128_wait_ring( dev_priv, (n) * sizeof(u32) );          \
-       }                                                               \
-       _nr = n; dev_priv->ring.space -= (n) * sizeof(u32);             \
-       ring = dev_priv->ring.start;                                    \
-       write = dev_priv->ring.tail;                                    \
-       tail_mask = dev_priv->ring.tail_mask;                           \
-} while (0)
-
-/* You can set this to zero if you want.  If the card locks up, you'll
- * need to keep this set.  It works around a bug in early revs of the
- * Rage 128 chipset, where the CCE would read 32 dwords past the end of
- * the ring buffer before wrapping around.
- */
-#define R128_BROKEN_CCE        1
-
-#define ADVANCE_RING() do {                                            \
-       if ( R128_VERBOSE ) {                                           \
-               DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",     \
-                         write, dev_priv->ring.tail );                 \
-       }                                                               \
-       if ( R128_BROKEN_CCE && write < 32 ) {                          \
-               memcpy( dev_priv->ring.end,                             \
-                       dev_priv->ring.start,                           \
-                       write * sizeof(u32) );                          \
-       }                                                               \
-       if (((dev_priv->ring.tail + _nr) & tail_mask) != write) {       \
-               DRM_ERROR(                                              \
-                       "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n",        \
-                       ((dev_priv->ring.tail + _nr) & tail_mask),      \
-                       write, __LINE__);                               \
-       } else                                                          \
-               dev_priv->ring.tail = write;                            \
-} while (0)
-
-#define COMMIT_RING() do {                                             \
-       if ( R128_VERBOSE ) {                                           \
-               DRM_INFO( "COMMIT_RING() tail=0x%06x\n",                \
-                       dev_priv->ring.tail );                          \
-       }                                                               \
-       DRM_MEMORYBARRIER();                                            \
-       R128_WRITE( R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail );     \
-       R128_READ( R128_PM4_BUFFER_DL_WPTR );                           \
-} while (0)
-
-#define OUT_RING( x ) do {                                             \
-       if ( R128_VERBOSE ) {                                           \
-               DRM_INFO( "   OUT_RING( 0x%08x ) at 0x%x\n",            \
-                          (unsigned int)(x), write );                  \
-       }                                                               \
-       ring[write++] = cpu_to_le32( x );                               \
-       write &= tail_mask;                                             \
-} while (0)
-
-#endif                         /* __R128_DRV_H__ */
diff --git a/drivers/char/drm/r128_ioc32.c b/drivers/char/drm/r128_ioc32.c
deleted file mode 100644 (file)
index d3cb676..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/**
- * \file r128_ioc32.c
- *
- * 32-bit ioctl compatibility routines for the R128 DRM.
- *
- * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich
- *
- * Copyright (C) Paul Mackerras 2005
- * Copyright (C) Egbert Eich 2003,2004
- * Copyright (C) Dave Airlie 2005
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <linux/compat.h>
-
-#include "drmP.h"
-#include "drm.h"
-#include "r128_drm.h"
-
-typedef struct drm_r128_init32 {
-       int func;
-       unsigned int sarea_priv_offset;
-       int is_pci;
-       int cce_mode;
-       int cce_secure;
-       int ring_size;
-       int usec_timeout;
-
-       unsigned int fb_bpp;
-       unsigned int front_offset, front_pitch;
-       unsigned int back_offset, back_pitch;
-       unsigned int depth_bpp;
-       unsigned int depth_offset, depth_pitch;
-       unsigned int span_offset;
-
-       unsigned int fb_offset;
-       unsigned int mmio_offset;
-       unsigned int ring_offset;
-       unsigned int ring_rptr_offset;
-       unsigned int buffers_offset;
-       unsigned int agp_textures_offset;
-} drm_r128_init32_t;
-
-static int compat_r128_init(struct file *file, unsigned int cmd,
-                           unsigned long arg)
-{
-       drm_r128_init32_t init32;
-       drm_r128_init_t __user *init;
-
-       if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
-               return -EFAULT;
-
-       init = compat_alloc_user_space(sizeof(*init));
-       if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
-           || __put_user(init32.func, &init->func)
-           || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
-           || __put_user(init32.is_pci, &init->is_pci)
-           || __put_user(init32.cce_mode, &init->cce_mode)
-           || __put_user(init32.cce_secure, &init->cce_secure)
-           || __put_user(init32.ring_size, &init->ring_size)
-           || __put_user(init32.usec_timeout, &init->usec_timeout)
-           || __put_user(init32.fb_bpp, &init->fb_bpp)
-           || __put_user(init32.front_offset, &init->front_offset)
-           || __put_user(init32.front_pitch, &init->front_pitch)
-           || __put_user(init32.back_offset, &init->back_offset)
-           || __put_user(init32.back_pitch, &init->back_pitch)
-           || __put_user(init32.depth_bpp, &init->depth_bpp)
-           || __put_user(init32.depth_offset, &init->depth_offset)
-           || __put_user(init32.depth_pitch, &init->depth_pitch)
-           || __put_user(init32.span_offset, &init->span_offset)
-           || __put_user(init32.fb_offset, &init->fb_offset)
-           || __put_user(init32.mmio_offset, &init->mmio_offset)
-           || __put_user(init32.ring_offset, &init->ring_offset)
-           || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
-           || __put_user(init32.buffers_offset, &init->buffers_offset)
-           || __put_user(init32.agp_textures_offset,
-                         &init->agp_textures_offset))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_R128_INIT, (unsigned long)init);
-}
-
-typedef struct drm_r128_depth32 {
-       int func;
-       int n;
-       u32 x;
-       u32 y;
-       u32 buffer;
-       u32 mask;
-} drm_r128_depth32_t;
-
-static int compat_r128_depth(struct file *file, unsigned int cmd,
-                            unsigned long arg)
-{
-       drm_r128_depth32_t depth32;
-       drm_r128_depth_t __user *depth;
-
-       if (copy_from_user(&depth32, (void __user *)arg, sizeof(depth32)))
-               return -EFAULT;
-
-       depth = compat_alloc_user_space(sizeof(*depth));
-       if (!access_ok(VERIFY_WRITE, depth, sizeof(*depth))
-           || __put_user(depth32.func, &depth->func)
-           || __put_user(depth32.n, &depth->n)
-           || __put_user((int __user *)(unsigned long)depth32.x, &depth->x)
-           || __put_user((int __user *)(unsigned long)depth32.y, &depth->y)
-           || __put_user((unsigned int __user *)(unsigned long)depth32.buffer,
-                         &depth->buffer)
-           || __put_user((unsigned char __user *)(unsigned long)depth32.mask,
-                         &depth->mask))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
-
-}
-
-typedef struct drm_r128_stipple32 {
-       u32 mask;
-} drm_r128_stipple32_t;
-
-static int compat_r128_stipple(struct file *file, unsigned int cmd,
-                              unsigned long arg)
-{
-       drm_r128_stipple32_t stipple32;
-       drm_r128_stipple_t __user *stipple;
-
-       if (copy_from_user(&stipple32, (void __user *)arg, sizeof(stipple32)))
-               return -EFAULT;
-
-       stipple = compat_alloc_user_space(sizeof(*stipple));
-       if (!access_ok(VERIFY_WRITE, stipple, sizeof(*stipple))
-           || __put_user((unsigned int __user *)(unsigned long)stipple32.mask,
-                         &stipple->mask))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
-}
-
-typedef struct drm_r128_getparam32 {
-       int param;
-       u32 value;
-} drm_r128_getparam32_t;
-
-static int compat_r128_getparam(struct file *file, unsigned int cmd,
-                               unsigned long arg)
-{
-       drm_r128_getparam32_t getparam32;
-       drm_r128_getparam_t __user *getparam;
-
-       if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
-               return -EFAULT;
-
-       getparam = compat_alloc_user_space(sizeof(*getparam));
-       if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
-           || __put_user(getparam32.param, &getparam->param)
-           || __put_user((void __user *)(unsigned long)getparam32.value,
-                         &getparam->value))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
-}
-
-drm_ioctl_compat_t *r128_compat_ioctls[] = {
-       [DRM_R128_INIT] = compat_r128_init,
-       [DRM_R128_DEPTH] = compat_r128_depth,
-       [DRM_R128_STIPPLE] = compat_r128_stipple,
-       [DRM_R128_GETPARAM] = compat_r128_getparam,
-};
-
-/**
- * Called whenever a 32-bit process running under a 64-bit kernel
- * performs an ioctl on /dev/dri/card<n>.
- *
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
- */
-long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       unsigned int nr = DRM_IOCTL_NR(cmd);
-       drm_ioctl_compat_t *fn = NULL;
-       int ret;
-
-       if (nr < DRM_COMMAND_BASE)
-               return drm_compat_ioctl(filp, cmd, arg);
-
-       if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(r128_compat_ioctls))
-               fn = r128_compat_ioctls[nr - DRM_COMMAND_BASE];
-
-       lock_kernel();          /* XXX for now */
-       if (fn != NULL)
-               ret = (*fn) (filp, cmd, arg);
-       else
-               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
-
-       return ret;
-}
diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
deleted file mode 100644 (file)
index c76fdca..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- */
-/*
- * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
- *
- * The Weather Channel (TM) funded Tungsten Graphics to develop the
- * initial release of the Radeon 8500 driver under the XFree86 license.
- * This notice must be preserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- *    Eric Anholt <anholt@FreeBSD.org>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "r128_drm.h"
-#include "r128_drv.h"
-
-irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
-{
-       struct drm_device *dev = (struct drm_device *) arg;
-       drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
-       int status;
-
-       status = R128_READ(R128_GEN_INT_STATUS);
-
-       /* VBLANK interrupt */
-       if (status & R128_CRTC_VBLANK_INT) {
-               R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
-               atomic_inc(&dev->vbl_received);
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
-               return IRQ_HANDLED;
-       }
-       return IRQ_NONE;
-}
-
-int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
-{
-       unsigned int cur_vblank;
-       int ret = 0;
-
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using vertical blanks...
-        */
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(&dev->vbl_received))
-                     - *sequence) <= (1 << 23)));
-
-       *sequence = cur_vblank;
-
-       return ret;
-}
-
-void r128_driver_irq_preinstall(struct drm_device * dev)
-{
-       drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
-
-       /* Disable *all* interrupts */
-       R128_WRITE(R128_GEN_INT_CNTL, 0);
-       /* Clear vblank bit if it's already high */
-       R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
-}
-
-void r128_driver_irq_postinstall(struct drm_device * dev)
-{
-       drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
-
-       /* Turn on VBL interrupt */
-       R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
-}
-
-void r128_driver_irq_uninstall(struct drm_device * dev)
-{
-       drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
-       if (!dev_priv)
-               return;
-
-       /* Disable *all* interrupts */
-       R128_WRITE(R128_GEN_INT_CNTL, 0);
-}
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
deleted file mode 100644 (file)
index 51a9afc..0000000
+++ /dev/null
@@ -1,1681 +0,0 @@
-/* r128_state.c -- State support for r128 -*- linux-c -*-
- * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
- */
-/*
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "r128_drm.h"
-#include "r128_drv.h"
-
-/* ================================================================
- * CCE hardware state programming functions
- */
-
-static void r128_emit_clip_rects(drm_r128_private_t * dev_priv,
-                                struct drm_clip_rect * boxes, int count)
-{
-       u32 aux_sc_cntl = 0x00000000;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_RING((count < 3 ? count : 3) * 5 + 2);
-
-       if (count >= 1) {
-               OUT_RING(CCE_PACKET0(R128_AUX1_SC_LEFT, 3));
-               OUT_RING(boxes[0].x1);
-               OUT_RING(boxes[0].x2 - 1);
-               OUT_RING(boxes[0].y1);
-               OUT_RING(boxes[0].y2 - 1);
-
-               aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
-       }
-       if (count >= 2) {
-               OUT_RING(CCE_PACKET0(R128_AUX2_SC_LEFT, 3));
-               OUT_RING(boxes[1].x1);
-               OUT_RING(boxes[1].x2 - 1);
-               OUT_RING(boxes[1].y1);
-               OUT_RING(boxes[1].y2 - 1);
-
-               aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
-       }
-       if (count >= 3) {
-               OUT_RING(CCE_PACKET0(R128_AUX3_SC_LEFT, 3));
-               OUT_RING(boxes[2].x1);
-               OUT_RING(boxes[2].x2 - 1);
-               OUT_RING(boxes[2].y1);
-               OUT_RING(boxes[2].y2 - 1);
-
-               aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
-       }
-
-       OUT_RING(CCE_PACKET0(R128_AUX_SC_CNTL, 0));
-       OUT_RING(aux_sc_cntl);
-
-       ADVANCE_RING();
-}
-
-static __inline__ void r128_emit_core(drm_r128_private_t * dev_priv)
-{
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_RING(2);
-
-       OUT_RING(CCE_PACKET0(R128_SCALE_3D_CNTL, 0));
-       OUT_RING(ctx->scale_3d_cntl);
-
-       ADVANCE_RING();
-}
-
-static __inline__ void r128_emit_context(drm_r128_private_t * dev_priv)
-{
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_RING(13);
-
-       OUT_RING(CCE_PACKET0(R128_DST_PITCH_OFFSET_C, 11));
-       OUT_RING(ctx->dst_pitch_offset_c);
-       OUT_RING(ctx->dp_gui_master_cntl_c);
-       OUT_RING(ctx->sc_top_left_c);
-       OUT_RING(ctx->sc_bottom_right_c);
-       OUT_RING(ctx->z_offset_c);
-       OUT_RING(ctx->z_pitch_c);
-       OUT_RING(ctx->z_sten_cntl_c);
-       OUT_RING(ctx->tex_cntl_c);
-       OUT_RING(ctx->misc_3d_state_cntl_reg);
-       OUT_RING(ctx->texture_clr_cmp_clr_c);
-       OUT_RING(ctx->texture_clr_cmp_msk_c);
-       OUT_RING(ctx->fog_color_c);
-
-       ADVANCE_RING();
-}
-
-static __inline__ void r128_emit_setup(drm_r128_private_t * dev_priv)
-{
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_RING(3);
-
-       OUT_RING(CCE_PACKET1(R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP));
-       OUT_RING(ctx->setup_cntl);
-       OUT_RING(ctx->pm4_vc_fpu_setup);
-
-       ADVANCE_RING();
-}
-
-static __inline__ void r128_emit_masks(drm_r128_private_t * dev_priv)
-{
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_RING(5);
-
-       OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
-       OUT_RING(ctx->dp_write_mask);
-
-       OUT_RING(CCE_PACKET0(R128_STEN_REF_MASK_C, 1));
-       OUT_RING(ctx->sten_ref_mask_c);
-       OUT_RING(ctx->plane_3d_mask_c);
-
-       ADVANCE_RING();
-}
-
-static __inline__ void r128_emit_window(drm_r128_private_t * dev_priv)
-{
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_RING(2);
-
-       OUT_RING(CCE_PACKET0(R128_WINDOW_XY_OFFSET, 0));
-       OUT_RING(ctx->window_xy_offset);
-
-       ADVANCE_RING();
-}
-
-static __inline__ void r128_emit_tex0(drm_r128_private_t * dev_priv)
-{
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
-       drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
-       int i;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS);
-
-       OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C,
-                            2 + R128_MAX_TEXTURE_LEVELS));
-       OUT_RING(tex->tex_cntl);
-       OUT_RING(tex->tex_combine_cntl);
-       OUT_RING(ctx->tex_size_pitch_c);
-       for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
-               OUT_RING(tex->tex_offset[i]);
-       }
-
-       OUT_RING(CCE_PACKET0(R128_CONSTANT_COLOR_C, 1));
-       OUT_RING(ctx->constant_color_c);
-       OUT_RING(tex->tex_border_color);
-
-       ADVANCE_RING();
-}
-
-static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv)
-{
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
-       int i;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS);
-
-       OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS));
-       OUT_RING(tex->tex_cntl);
-       OUT_RING(tex->tex_combine_cntl);
-       for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
-               OUT_RING(tex->tex_offset[i]);
-       }
-
-       OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0));
-       OUT_RING(tex->tex_border_color);
-
-       ADVANCE_RING();
-}
-
-static void r128_emit_state(drm_r128_private_t * dev_priv)
-{
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       unsigned int dirty = sarea_priv->dirty;
-
-       DRM_DEBUG("dirty=0x%08x\n", dirty);
-
-       if (dirty & R128_UPLOAD_CORE) {
-               r128_emit_core(dev_priv);
-               sarea_priv->dirty &= ~R128_UPLOAD_CORE;
-       }
-
-       if (dirty & R128_UPLOAD_CONTEXT) {
-               r128_emit_context(dev_priv);
-               sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
-       }
-
-       if (dirty & R128_UPLOAD_SETUP) {
-               r128_emit_setup(dev_priv);
-               sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
-       }
-
-       if (dirty & R128_UPLOAD_MASKS) {
-               r128_emit_masks(dev_priv);
-               sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
-       }
-
-       if (dirty & R128_UPLOAD_WINDOW) {
-               r128_emit_window(dev_priv);
-               sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
-       }
-
-       if (dirty & R128_UPLOAD_TEX0) {
-               r128_emit_tex0(dev_priv);
-               sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
-       }
-
-       if (dirty & R128_UPLOAD_TEX1) {
-               r128_emit_tex1(dev_priv);
-               sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
-       }
-
-       /* Turn off the texture cache flushing */
-       sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
-
-       sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
-}
-
-#if R128_PERFORMANCE_BOXES
-/* ================================================================
- * Performance monitoring functions
- */
-
-static void r128_clear_box(drm_r128_private_t * dev_priv,
-                          int x, int y, int w, int h, int r, int g, int b)
-{
-       u32 pitch, offset;
-       u32 fb_bpp, color;
-       RING_LOCALS;
-
-       switch (dev_priv->fb_bpp) {
-       case 16:
-               fb_bpp = R128_GMC_DST_16BPP;
-               color = (((r & 0xf8) << 8) |
-                        ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
-               break;
-       case 24:
-               fb_bpp = R128_GMC_DST_24BPP;
-               color = ((r << 16) | (g << 8) | b);
-               break;
-       case 32:
-               fb_bpp = R128_GMC_DST_32BPP;
-               color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
-               break;
-       default:
-               return;
-       }
-
-       offset = dev_priv->back_offset;
-       pitch = dev_priv->back_pitch >> 3;
-
-       BEGIN_RING(6);
-
-       OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
-       OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
-                R128_GMC_BRUSH_SOLID_COLOR |
-                fb_bpp |
-                R128_GMC_SRC_DATATYPE_COLOR |
-                R128_ROP3_P |
-                R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS);
-
-       OUT_RING((pitch << 21) | (offset >> 5));
-       OUT_RING(color);
-
-       OUT_RING((x << 16) | y);
-       OUT_RING((w << 16) | h);
-
-       ADVANCE_RING();
-}
-
-static void r128_cce_performance_boxes(drm_r128_private_t * dev_priv)
-{
-       if (atomic_read(&dev_priv->idle_count) == 0) {
-               r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
-       } else {
-               atomic_set(&dev_priv->idle_count, 0);
-       }
-}
-
-#endif
-
-/* ================================================================
- * CCE command dispatch functions
- */
-
-static void r128_print_dirty(const char *msg, unsigned int flags)
-{
-       DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
-                msg,
-                flags,
-                (flags & R128_UPLOAD_CORE) ? "core, " : "",
-                (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
-                (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
-                (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
-                (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
-                (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
-                (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
-                (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
-                (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
-}
-
-static void r128_cce_dispatch_clear(struct drm_device * dev,
-                                   drm_r128_clear_t * clear)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int nbox = sarea_priv->nbox;
-       struct drm_clip_rect *pbox = sarea_priv->boxes;
-       unsigned int flags = clear->flags;
-       int i;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       if (dev_priv->page_flipping && dev_priv->current_page == 1) {
-               unsigned int tmp = flags;
-
-               flags &= ~(R128_FRONT | R128_BACK);
-               if (tmp & R128_FRONT)
-                       flags |= R128_BACK;
-               if (tmp & R128_BACK)
-                       flags |= R128_FRONT;
-       }
-
-       for (i = 0; i < nbox; i++) {
-               int x = pbox[i].x1;
-               int y = pbox[i].y1;
-               int w = pbox[i].x2 - x;
-               int h = pbox[i].y2 - y;
-
-               DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
-                         pbox[i].x1, pbox[i].y1, pbox[i].x2,
-                         pbox[i].y2, flags);
-
-               if (flags & (R128_FRONT | R128_BACK)) {
-                       BEGIN_RING(2);
-
-                       OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
-                       OUT_RING(clear->color_mask);
-
-                       ADVANCE_RING();
-               }
-
-               if (flags & R128_FRONT) {
-                       BEGIN_RING(6);
-
-                       OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
-                       OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
-                                R128_GMC_BRUSH_SOLID_COLOR |
-                                (dev_priv->color_fmt << 8) |
-                                R128_GMC_SRC_DATATYPE_COLOR |
-                                R128_ROP3_P |
-                                R128_GMC_CLR_CMP_CNTL_DIS |
-                                R128_GMC_AUX_CLIP_DIS);
-
-                       OUT_RING(dev_priv->front_pitch_offset_c);
-                       OUT_RING(clear->clear_color);
-
-                       OUT_RING((x << 16) | y);
-                       OUT_RING((w << 16) | h);
-
-                       ADVANCE_RING();
-               }
-
-               if (flags & R128_BACK) {
-                       BEGIN_RING(6);
-
-                       OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
-                       OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
-                                R128_GMC_BRUSH_SOLID_COLOR |
-                                (dev_priv->color_fmt << 8) |
-                                R128_GMC_SRC_DATATYPE_COLOR |
-                                R128_ROP3_P |
-                                R128_GMC_CLR_CMP_CNTL_DIS |
-                                R128_GMC_AUX_CLIP_DIS);
-
-                       OUT_RING(dev_priv->back_pitch_offset_c);
-                       OUT_RING(clear->clear_color);
-
-                       OUT_RING((x << 16) | y);
-                       OUT_RING((w << 16) | h);
-
-                       ADVANCE_RING();
-               }
-
-               if (flags & R128_DEPTH) {
-                       BEGIN_RING(6);
-
-                       OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
-                       OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
-                                R128_GMC_BRUSH_SOLID_COLOR |
-                                (dev_priv->depth_fmt << 8) |
-                                R128_GMC_SRC_DATATYPE_COLOR |
-                                R128_ROP3_P |
-                                R128_GMC_CLR_CMP_CNTL_DIS |
-                                R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
-
-                       OUT_RING(dev_priv->depth_pitch_offset_c);
-                       OUT_RING(clear->clear_depth);
-
-                       OUT_RING((x << 16) | y);
-                       OUT_RING((w << 16) | h);
-
-                       ADVANCE_RING();
-               }
-       }
-}
-
-static void r128_cce_dispatch_swap(struct drm_device * dev)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int nbox = sarea_priv->nbox;
-       struct drm_clip_rect *pbox = sarea_priv->boxes;
-       int i;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-#if R128_PERFORMANCE_BOXES
-       /* Do some trivial performance monitoring...
-        */
-       r128_cce_performance_boxes(dev_priv);
-#endif
-
-       for (i = 0; i < nbox; i++) {
-               int x = pbox[i].x1;
-               int y = pbox[i].y1;
-               int w = pbox[i].x2 - x;
-               int h = pbox[i].y2 - y;
-
-               BEGIN_RING(7);
-
-               OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
-               OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
-                        R128_GMC_DST_PITCH_OFFSET_CNTL |
-                        R128_GMC_BRUSH_NONE |
-                        (dev_priv->color_fmt << 8) |
-                        R128_GMC_SRC_DATATYPE_COLOR |
-                        R128_ROP3_S |
-                        R128_DP_SRC_SOURCE_MEMORY |
-                        R128_GMC_CLR_CMP_CNTL_DIS |
-                        R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
-
-               /* Make this work even if front & back are flipped:
-                */
-               if (dev_priv->current_page == 0) {
-                       OUT_RING(dev_priv->back_pitch_offset_c);
-                       OUT_RING(dev_priv->front_pitch_offset_c);
-               } else {
-                       OUT_RING(dev_priv->front_pitch_offset_c);
-                       OUT_RING(dev_priv->back_pitch_offset_c);
-               }
-
-               OUT_RING((x << 16) | y);
-               OUT_RING((x << 16) | y);
-               OUT_RING((w << 16) | h);
-
-               ADVANCE_RING();
-       }
-
-       /* Increment the frame counter.  The client-side 3D driver must
-        * throttle the framerate by waiting for this value before
-        * performing the swapbuffer ioctl.
-        */
-       dev_priv->sarea_priv->last_frame++;
-
-       BEGIN_RING(2);
-
-       OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
-       OUT_RING(dev_priv->sarea_priv->last_frame);
-
-       ADVANCE_RING();
-}
-
-static void r128_cce_dispatch_flip(struct drm_device * dev)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-       DRM_DEBUG("page=%d pfCurrentPage=%d\n",
-                 dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
-
-#if R128_PERFORMANCE_BOXES
-       /* Do some trivial performance monitoring...
-        */
-       r128_cce_performance_boxes(dev_priv);
-#endif
-
-       BEGIN_RING(4);
-
-       R128_WAIT_UNTIL_PAGE_FLIPPED();
-       OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0));
-
-       if (dev_priv->current_page == 0) {
-               OUT_RING(dev_priv->back_offset);
-       } else {
-               OUT_RING(dev_priv->front_offset);
-       }
-
-       ADVANCE_RING();
-
-       /* Increment the frame counter.  The client-side 3D driver must
-        * throttle the framerate by waiting for this value before
-        * performing the swapbuffer ioctl.
-        */
-       dev_priv->sarea_priv->last_frame++;
-       dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
-           1 - dev_priv->current_page;
-
-       BEGIN_RING(2);
-
-       OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
-       OUT_RING(dev_priv->sarea_priv->last_frame);
-
-       ADVANCE_RING();
-}
-
-static void r128_cce_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_buf_priv_t *buf_priv = buf->dev_private;
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int format = sarea_priv->vc_format;
-       int offset = buf->bus_address;
-       int size = buf->used;
-       int prim = buf_priv->prim;
-       int i = 0;
-       RING_LOCALS;
-       DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox);
-
-       if (0)
-               r128_print_dirty("dispatch_vertex", sarea_priv->dirty);
-
-       if (buf->used) {
-               buf_priv->dispatched = 1;
-
-               if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
-                       r128_emit_state(dev_priv);
-               }
-
-               do {
-                       /* Emit the next set of up to three cliprects */
-                       if (i < sarea_priv->nbox) {
-                               r128_emit_clip_rects(dev_priv,
-                                                    &sarea_priv->boxes[i],
-                                                    sarea_priv->nbox - i);
-                       }
-
-                       /* Emit the vertex buffer rendering commands */
-                       BEGIN_RING(5);
-
-                       OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3));
-                       OUT_RING(offset);
-                       OUT_RING(size);
-                       OUT_RING(format);
-                       OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
-                                (size << R128_CCE_VC_CNTL_NUM_SHIFT));
-
-                       ADVANCE_RING();
-
-                       i += 3;
-               } while (i < sarea_priv->nbox);
-       }
-
-       if (buf_priv->discard) {
-               buf_priv->age = dev_priv->sarea_priv->last_dispatch;
-
-               /* Emit the vertex buffer age */
-               BEGIN_RING(2);
-
-               OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
-               OUT_RING(buf_priv->age);
-
-               ADVANCE_RING();
-
-               buf->pending = 1;
-               buf->used = 0;
-               /* FIXME: Check dispatched field */
-               buf_priv->dispatched = 0;
-       }
-
-       dev_priv->sarea_priv->last_dispatch++;
-
-       sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
-       sarea_priv->nbox = 0;
-}
-
-static void r128_cce_dispatch_indirect(struct drm_device * dev,
-                                      struct drm_buf * buf, int start, int end)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_buf_priv_t *buf_priv = buf->dev_private;
-       RING_LOCALS;
-       DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
-
-       if (start != end) {
-               int offset = buf->bus_address + start;
-               int dwords = (end - start + 3) / sizeof(u32);
-
-               /* Indirect buffer data must be an even number of
-                * dwords, so if we've been given an odd number we must
-                * pad the data with a Type-2 CCE packet.
-                */
-               if (dwords & 1) {
-                       u32 *data = (u32 *)
-                           ((char *)dev->agp_buffer_map->handle
-                            + buf->offset + start);
-                       data[dwords++] = cpu_to_le32(R128_CCE_PACKET2);
-               }
-
-               buf_priv->dispatched = 1;
-
-               /* Fire off the indirect buffer */
-               BEGIN_RING(3);
-
-               OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1));
-               OUT_RING(offset);
-               OUT_RING(dwords);
-
-               ADVANCE_RING();
-       }
-
-       if (buf_priv->discard) {
-               buf_priv->age = dev_priv->sarea_priv->last_dispatch;
-
-               /* Emit the indirect buffer age */
-               BEGIN_RING(2);
-
-               OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
-               OUT_RING(buf_priv->age);
-
-               ADVANCE_RING();
-
-               buf->pending = 1;
-               buf->used = 0;
-               /* FIXME: Check dispatched field */
-               buf_priv->dispatched = 0;
-       }
-
-       dev_priv->sarea_priv->last_dispatch++;
-}
-
-static void r128_cce_dispatch_indices(struct drm_device * dev,
-                                     struct drm_buf * buf,
-                                     int start, int end, int count)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_buf_priv_t *buf_priv = buf->dev_private;
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int format = sarea_priv->vc_format;
-       int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset;
-       int prim = buf_priv->prim;
-       u32 *data;
-       int dwords;
-       int i = 0;
-       RING_LOCALS;
-       DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count);
-
-       if (0)
-               r128_print_dirty("dispatch_indices", sarea_priv->dirty);
-
-       if (start != end) {
-               buf_priv->dispatched = 1;
-
-               if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
-                       r128_emit_state(dev_priv);
-               }
-
-               dwords = (end - start + 3) / sizeof(u32);
-
-               data = (u32 *) ((char *)dev->agp_buffer_map->handle
-                               + buf->offset + start);
-
-               data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM,
-                                                 dwords - 2));
-
-               data[1] = cpu_to_le32(offset);
-               data[2] = cpu_to_le32(R128_MAX_VB_VERTS);
-               data[3] = cpu_to_le32(format);
-               data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
-                                      (count << 16)));
-
-               if (count & 0x1) {
-#ifdef __LITTLE_ENDIAN
-                       data[dwords - 1] &= 0x0000ffff;
-#else
-                       data[dwords - 1] &= 0xffff0000;
-#endif
-               }
-
-               do {
-                       /* Emit the next set of up to three cliprects */
-                       if (i < sarea_priv->nbox) {
-                               r128_emit_clip_rects(dev_priv,
-                                                    &sarea_priv->boxes[i],
-                                                    sarea_priv->nbox - i);
-                       }
-
-                       r128_cce_dispatch_indirect(dev, buf, start, end);
-
-                       i += 3;
-               } while (i < sarea_priv->nbox);
-       }
-
-       if (buf_priv->discard) {
-               buf_priv->age = dev_priv->sarea_priv->last_dispatch;
-
-               /* Emit the vertex buffer age */
-               BEGIN_RING(2);
-
-               OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
-               OUT_RING(buf_priv->age);
-
-               ADVANCE_RING();
-
-               buf->pending = 1;
-               /* FIXME: Check dispatched field */
-               buf_priv->dispatched = 0;
-       }
-
-       dev_priv->sarea_priv->last_dispatch++;
-
-       sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
-       sarea_priv->nbox = 0;
-}
-
-static int r128_cce_dispatch_blit(struct drm_device * dev,
-                                 struct drm_file *file_priv,
-                                 drm_r128_blit_t * blit)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_r128_buf_priv_t *buf_priv;
-       u32 *data;
-       int dword_shift, dwords;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       /* The compiler won't optimize away a division by a variable,
-        * even if the only legal values are powers of two.  Thus, we'll
-        * use a shift instead.
-        */
-       switch (blit->format) {
-       case R128_DATATYPE_ARGB8888:
-               dword_shift = 0;
-               break;
-       case R128_DATATYPE_ARGB1555:
-       case R128_DATATYPE_RGB565:
-       case R128_DATATYPE_ARGB4444:
-       case R128_DATATYPE_YVYU422:
-       case R128_DATATYPE_VYUY422:
-               dword_shift = 1;
-               break;
-       case R128_DATATYPE_CI8:
-       case R128_DATATYPE_RGB8:
-               dword_shift = 2;
-               break;
-       default:
-               DRM_ERROR("invalid blit format %d\n", blit->format);
-               return -EINVAL;
-       }
-
-       /* Flush the pixel cache, and mark the contents as Read Invalid.
-        * This ensures no pixel data gets mixed up with the texture
-        * data from the host data blit, otherwise part of the texture
-        * image may be corrupted.
-        */
-       BEGIN_RING(2);
-
-       OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
-       OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI);
-
-       ADVANCE_RING();
-
-       /* Dispatch the indirect buffer.
-        */
-       buf = dma->buflist[blit->idx];
-       buf_priv = buf->dev_private;
-
-       if (buf->file_priv != file_priv) {
-               DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->file_priv);
-               return -EINVAL;
-       }
-       if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", blit->idx);
-               return -EINVAL;
-       }
-
-       buf_priv->discard = 1;
-
-       dwords = (blit->width * blit->height) >> dword_shift;
-
-       data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
-
-       data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6));
-       data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL |
-                              R128_GMC_BRUSH_NONE |
-                              (blit->format << 8) |
-                              R128_GMC_SRC_DATATYPE_COLOR |
-                              R128_ROP3_S |
-                              R128_DP_SRC_SOURCE_HOST_DATA |
-                              R128_GMC_CLR_CMP_CNTL_DIS |
-                              R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS));
-
-       data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5));
-       data[3] = cpu_to_le32(0xffffffff);
-       data[4] = cpu_to_le32(0xffffffff);
-       data[5] = cpu_to_le32((blit->y << 16) | blit->x);
-       data[6] = cpu_to_le32((blit->height << 16) | blit->width);
-       data[7] = cpu_to_le32(dwords);
-
-       buf->used = (dwords + 8) * sizeof(u32);
-
-       r128_cce_dispatch_indirect(dev, buf, 0, buf->used);
-
-       /* Flush the pixel cache after the blit completes.  This ensures
-        * the texture data is written out to memory before rendering
-        * continues.
-        */
-       BEGIN_RING(2);
-
-       OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
-       OUT_RING(R128_PC_FLUSH_GUI);
-
-       ADVANCE_RING();
-
-       return 0;
-}
-
-/* ================================================================
- * Tiled depth buffer management
- *
- * FIXME: These should all set the destination write mask for when we
- * have hardware stencil support.
- */
-
-static int r128_cce_dispatch_write_span(struct drm_device * dev,
-                                       drm_r128_depth_t * depth)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       int count, x, y;
-       u32 *buffer;
-       u8 *mask;
-       int i, buffer_size, mask_size;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       count = depth->n;
-       if (count > 4096 || count <= 0)
-               return -EMSGSIZE;
-
-       if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
-               return -EFAULT;
-       }
-       if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
-               return -EFAULT;
-       }
-
-       buffer_size = depth->n * sizeof(u32);
-       buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
-       if (buffer == NULL)
-               return -ENOMEM;
-       if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
-               drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-               return -EFAULT;
-       }
-
-       mask_size = depth->n * sizeof(u8);
-       if (depth->mask) {
-               mask = drm_alloc(mask_size, DRM_MEM_BUFS);
-               if (mask == NULL) {
-                       drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-                       return -ENOMEM;
-               }
-               if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
-                       drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-                       drm_free(mask, mask_size, DRM_MEM_BUFS);
-                       return -EFAULT;
-               }
-
-               for (i = 0; i < count; i++, x++) {
-                       if (mask[i]) {
-                               BEGIN_RING(6);
-
-                               OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
-                               OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
-                                        R128_GMC_BRUSH_SOLID_COLOR |
-                                        (dev_priv->depth_fmt << 8) |
-                                        R128_GMC_SRC_DATATYPE_COLOR |
-                                        R128_ROP3_P |
-                                        R128_GMC_CLR_CMP_CNTL_DIS |
-                                        R128_GMC_WR_MSK_DIS);
-
-                               OUT_RING(dev_priv->depth_pitch_offset_c);
-                               OUT_RING(buffer[i]);
-
-                               OUT_RING((x << 16) | y);
-                               OUT_RING((1 << 16) | 1);
-
-                               ADVANCE_RING();
-                       }
-               }
-
-               drm_free(mask, mask_size, DRM_MEM_BUFS);
-       } else {
-               for (i = 0; i < count; i++, x++) {
-                       BEGIN_RING(6);
-
-                       OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
-                       OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
-                                R128_GMC_BRUSH_SOLID_COLOR |
-                                (dev_priv->depth_fmt << 8) |
-                                R128_GMC_SRC_DATATYPE_COLOR |
-                                R128_ROP3_P |
-                                R128_GMC_CLR_CMP_CNTL_DIS |
-                                R128_GMC_WR_MSK_DIS);
-
-                       OUT_RING(dev_priv->depth_pitch_offset_c);
-                       OUT_RING(buffer[i]);
-
-                       OUT_RING((x << 16) | y);
-                       OUT_RING((1 << 16) | 1);
-
-                       ADVANCE_RING();
-               }
-       }
-
-       drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-
-       return 0;
-}
-
-static int r128_cce_dispatch_write_pixels(struct drm_device * dev,
-                                         drm_r128_depth_t * depth)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       int count, *x, *y;
-       u32 *buffer;
-       u8 *mask;
-       int i, xbuf_size, ybuf_size, buffer_size, mask_size;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       count = depth->n;
-       if (count > 4096 || count <= 0)
-               return -EMSGSIZE;
-
-       xbuf_size = count * sizeof(*x);
-       ybuf_size = count * sizeof(*y);
-       x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
-       if (x == NULL) {
-               return -ENOMEM;
-       }
-       y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
-       if (y == NULL) {
-               drm_free(x, xbuf_size, DRM_MEM_BUFS);
-               return -ENOMEM;
-       }
-       if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
-               drm_free(x, xbuf_size, DRM_MEM_BUFS);
-               drm_free(y, ybuf_size, DRM_MEM_BUFS);
-               return -EFAULT;
-       }
-       if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {
-               drm_free(x, xbuf_size, DRM_MEM_BUFS);
-               drm_free(y, ybuf_size, DRM_MEM_BUFS);
-               return -EFAULT;
-       }
-
-       buffer_size = depth->n * sizeof(u32);
-       buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
-       if (buffer == NULL) {
-               drm_free(x, xbuf_size, DRM_MEM_BUFS);
-               drm_free(y, ybuf_size, DRM_MEM_BUFS);
-               return -ENOMEM;
-       }
-       if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
-               drm_free(x, xbuf_size, DRM_MEM_BUFS);
-               drm_free(y, ybuf_size, DRM_MEM_BUFS);
-               drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-               return -EFAULT;
-       }
-
-       if (depth->mask) {
-               mask_size = depth->n * sizeof(u8);
-               mask = drm_alloc(mask_size, DRM_MEM_BUFS);
-               if (mask == NULL) {
-                       drm_free(x, xbuf_size, DRM_MEM_BUFS);
-                       drm_free(y, ybuf_size, DRM_MEM_BUFS);
-                       drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-                       return -ENOMEM;
-               }
-               if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
-                       drm_free(x, xbuf_size, DRM_MEM_BUFS);
-                       drm_free(y, ybuf_size, DRM_MEM_BUFS);
-                       drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-                       drm_free(mask, mask_size, DRM_MEM_BUFS);
-                       return -EFAULT;
-               }
-
-               for (i = 0; i < count; i++) {
-                       if (mask[i]) {
-                               BEGIN_RING(6);
-
-                               OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
-                               OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
-                                        R128_GMC_BRUSH_SOLID_COLOR |
-                                        (dev_priv->depth_fmt << 8) |
-                                        R128_GMC_SRC_DATATYPE_COLOR |
-                                        R128_ROP3_P |
-                                        R128_GMC_CLR_CMP_CNTL_DIS |
-                                        R128_GMC_WR_MSK_DIS);
-
-                               OUT_RING(dev_priv->depth_pitch_offset_c);
-                               OUT_RING(buffer[i]);
-
-                               OUT_RING((x[i] << 16) | y[i]);
-                               OUT_RING((1 << 16) | 1);
-
-                               ADVANCE_RING();
-                       }
-               }
-
-               drm_free(mask, mask_size, DRM_MEM_BUFS);
-       } else {
-               for (i = 0; i < count; i++) {
-                       BEGIN_RING(6);
-
-                       OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
-                       OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
-                                R128_GMC_BRUSH_SOLID_COLOR |
-                                (dev_priv->depth_fmt << 8) |
-                                R128_GMC_SRC_DATATYPE_COLOR |
-                                R128_ROP3_P |
-                                R128_GMC_CLR_CMP_CNTL_DIS |
-                                R128_GMC_WR_MSK_DIS);
-
-                       OUT_RING(dev_priv->depth_pitch_offset_c);
-                       OUT_RING(buffer[i]);
-
-                       OUT_RING((x[i] << 16) | y[i]);
-                       OUT_RING((1 << 16) | 1);
-
-                       ADVANCE_RING();
-               }
-       }
-
-       drm_free(x, xbuf_size, DRM_MEM_BUFS);
-       drm_free(y, ybuf_size, DRM_MEM_BUFS);
-       drm_free(buffer, buffer_size, DRM_MEM_BUFS);
-
-       return 0;
-}
-
-static int r128_cce_dispatch_read_span(struct drm_device * dev,
-                                      drm_r128_depth_t * depth)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       int count, x, y;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       count = depth->n;
-       if (count > 4096 || count <= 0)
-               return -EMSGSIZE;
-
-       if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
-               return -EFAULT;
-       }
-       if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
-               return -EFAULT;
-       }
-
-       BEGIN_RING(7);
-
-       OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
-       OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
-                R128_GMC_DST_PITCH_OFFSET_CNTL |
-                R128_GMC_BRUSH_NONE |
-                (dev_priv->depth_fmt << 8) |
-                R128_GMC_SRC_DATATYPE_COLOR |
-                R128_ROP3_S |
-                R128_DP_SRC_SOURCE_MEMORY |
-                R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
-
-       OUT_RING(dev_priv->depth_pitch_offset_c);
-       OUT_RING(dev_priv->span_pitch_offset_c);
-
-       OUT_RING((x << 16) | y);
-       OUT_RING((0 << 16) | 0);
-       OUT_RING((count << 16) | 1);
-
-       ADVANCE_RING();
-
-       return 0;
-}
-
-static int r128_cce_dispatch_read_pixels(struct drm_device * dev,
-                                        drm_r128_depth_t * depth)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       int count, *x, *y;
-       int i, xbuf_size, ybuf_size;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       count = depth->n;
-       if (count > 4096 || count <= 0)
-               return -EMSGSIZE;
-
-       if (count > dev_priv->depth_pitch) {
-               count = dev_priv->depth_pitch;
-       }
-
-       xbuf_size = count * sizeof(*x);
-       ybuf_size = count * sizeof(*y);
-       x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
-       if (x == NULL) {
-               return -ENOMEM;
-       }
-       y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
-       if (y == NULL) {
-               drm_free(x, xbuf_size, DRM_MEM_BUFS);
-               return -ENOMEM;
-       }
-       if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
-               drm_free(x, xbuf_size, DRM_MEM_BUFS);
-               drm_free(y, ybuf_size, DRM_MEM_BUFS);
-               return -EFAULT;
-       }
-       if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {
-               drm_free(x, xbuf_size, DRM_MEM_BUFS);
-               drm_free(y, ybuf_size, DRM_MEM_BUFS);
-               return -EFAULT;
-       }
-
-       for (i = 0; i < count; i++) {
-               BEGIN_RING(7);
-
-               OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
-               OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
-                        R128_GMC_DST_PITCH_OFFSET_CNTL |
-                        R128_GMC_BRUSH_NONE |
-                        (dev_priv->depth_fmt << 8) |
-                        R128_GMC_SRC_DATATYPE_COLOR |
-                        R128_ROP3_S |
-                        R128_DP_SRC_SOURCE_MEMORY |
-                        R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
-
-               OUT_RING(dev_priv->depth_pitch_offset_c);
-               OUT_RING(dev_priv->span_pitch_offset_c);
-
-               OUT_RING((x[i] << 16) | y[i]);
-               OUT_RING((i << 16) | 0);
-               OUT_RING((1 << 16) | 1);
-
-               ADVANCE_RING();
-       }
-
-       drm_free(x, xbuf_size, DRM_MEM_BUFS);
-       drm_free(y, ybuf_size, DRM_MEM_BUFS);
-
-       return 0;
-}
-
-/* ================================================================
- * Polygon stipple
- */
-
-static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       int i;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_RING(33);
-
-       OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31));
-       for (i = 0; i < 32; i++) {
-               OUT_RING(stipple[i]);
-       }
-
-       ADVANCE_RING();
-}
-
-/* ================================================================
- * IOCTL functions
- */
-
-static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_r128_clear_t *clear = data;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-       if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
-               sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
-
-       r128_cce_dispatch_clear(dev, clear);
-       COMMIT_RING();
-
-       /* Make sure we restore the 3D state next time.
-        */
-       dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
-
-       return 0;
-}
-
-static int r128_do_init_pageflip(struct drm_device * dev)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET);
-       dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL);
-
-       R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset);
-       R128_WRITE(R128_CRTC_OFFSET_CNTL,
-                  dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL);
-
-       dev_priv->page_flipping = 1;
-       dev_priv->current_page = 0;
-       dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
-
-       return 0;
-}
-
-static int r128_do_cleanup_pageflip(struct drm_device * dev)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset);
-       R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl);
-
-       if (dev_priv->current_page != 0) {
-               r128_cce_dispatch_flip(dev);
-               COMMIT_RING();
-       }
-
-       dev_priv->page_flipping = 0;
-       return 0;
-}
-
-/* Swapping and flipping are different operations, need different ioctls.
- * They can & should be intermixed to support multiple 3d windows.
- */
-
-static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-       if (!dev_priv->page_flipping)
-               r128_do_init_pageflip(dev);
-
-       r128_cce_dispatch_flip(dev);
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-       if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
-               sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
-
-       r128_cce_dispatch_swap(dev);
-       dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
-                                       R128_UPLOAD_MASKS);
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_r128_buf_priv_t *buf_priv;
-       drm_r128_vertex_t *vertex = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
-                 DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
-
-       if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
-               DRM_ERROR("buffer index %d (of %d max)\n",
-                         vertex->idx, dma->buf_count - 1);
-               return -EINVAL;
-       }
-       if (vertex->prim < 0 ||
-           vertex->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
-               DRM_ERROR("buffer prim %d\n", vertex->prim);
-               return -EINVAL;
-       }
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-       VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-       buf = dma->buflist[vertex->idx];
-       buf_priv = buf->dev_private;
-
-       if (buf->file_priv != file_priv) {
-               DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->file_priv);
-               return -EINVAL;
-       }
-       if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", vertex->idx);
-               return -EINVAL;
-       }
-
-       buf->used = vertex->count;
-       buf_priv->prim = vertex->prim;
-       buf_priv->discard = vertex->discard;
-
-       r128_cce_dispatch_vertex(dev, buf);
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_r128_buf_priv_t *buf_priv;
-       drm_r128_indices_t *elts = data;
-       int count;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
-                 elts->idx, elts->start, elts->end, elts->discard);
-
-       if (elts->idx < 0 || elts->idx >= dma->buf_count) {
-               DRM_ERROR("buffer index %d (of %d max)\n",
-                         elts->idx, dma->buf_count - 1);
-               return -EINVAL;
-       }
-       if (elts->prim < 0 ||
-           elts->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
-               DRM_ERROR("buffer prim %d\n", elts->prim);
-               return -EINVAL;
-       }
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-       VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-       buf = dma->buflist[elts->idx];
-       buf_priv = buf->dev_private;
-
-       if (buf->file_priv != file_priv) {
-               DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->file_priv);
-               return -EINVAL;
-       }
-       if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", elts->idx);
-               return -EINVAL;
-       }
-
-       count = (elts->end - elts->start) / sizeof(u16);
-       elts->start -= R128_INDEX_PRIM_OFFSET;
-
-       if (elts->start & 0x7) {
-               DRM_ERROR("misaligned buffer 0x%x\n", elts->start);
-               return -EINVAL;
-       }
-       if (elts->start < buf->used) {
-               DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);
-               return -EINVAL;
-       }
-
-       buf->used = elts->end;
-       buf_priv->prim = elts->prim;
-       buf_priv->discard = elts->discard;
-
-       r128_cce_dispatch_indices(dev, buf, elts->start, elts->end, count);
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_blit_t *blit = data;
-       int ret;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx);
-
-       if (blit->idx < 0 || blit->idx >= dma->buf_count) {
-               DRM_ERROR("buffer index %d (of %d max)\n",
-                         blit->idx, dma->buf_count - 1);
-               return -EINVAL;
-       }
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-       VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-       ret = r128_cce_dispatch_blit(dev, file_priv, blit);
-
-       COMMIT_RING();
-       return ret;
-}
-
-static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_depth_t *depth = data;
-       int ret;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-       ret = -EINVAL;
-       switch (depth->func) {
-       case R128_WRITE_SPAN:
-               ret = r128_cce_dispatch_write_span(dev, depth);
-               break;
-       case R128_WRITE_PIXELS:
-               ret = r128_cce_dispatch_write_pixels(dev, depth);
-               break;
-       case R128_READ_SPAN:
-               ret = r128_cce_dispatch_read_span(dev, depth);
-               break;
-       case R128_READ_PIXELS:
-               ret = r128_cce_dispatch_read_pixels(dev, depth);
-               break;
-       }
-
-       COMMIT_RING();
-       return ret;
-}
-
-static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_stipple_t *stipple = data;
-       u32 mask[32];
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
-               return -EFAULT;
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-       r128_cce_dispatch_stipple(dev, mask);
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_r128_buf_priv_t *buf_priv;
-       drm_r128_indirect_t *indirect = data;
-#if 0
-       RING_LOCALS;
-#endif
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
-                 indirect->idx, indirect->start, indirect->end,
-                 indirect->discard);
-
-       if (indirect->idx < 0 || indirect->idx >= dma->buf_count) {
-               DRM_ERROR("buffer index %d (of %d max)\n",
-                         indirect->idx, dma->buf_count - 1);
-               return -EINVAL;
-       }
-
-       buf = dma->buflist[indirect->idx];
-       buf_priv = buf->dev_private;
-
-       if (buf->file_priv != file_priv) {
-               DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->file_priv);
-               return -EINVAL;
-       }
-       if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", indirect->idx);
-               return -EINVAL;
-       }
-
-       if (indirect->start < buf->used) {
-               DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
-                         indirect->start, buf->used);
-               return -EINVAL;
-       }
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-       VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-       buf->used = indirect->end;
-       buf_priv->discard = indirect->discard;
-
-#if 0
-       /* Wait for the 3D stream to idle before the indirect buffer
-        * containing 2D acceleration commands is processed.
-        */
-       BEGIN_RING(2);
-       RADEON_WAIT_UNTIL_3D_IDLE();
-       ADVANCE_RING();
-#endif
-
-       /* Dispatch the indirect buffer full of commands from the
-        * X server.  This is insecure and is thus only available to
-        * privileged clients.
-        */
-       r128_cce_dispatch_indirect(dev, buf, indirect->start, indirect->end);
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_r128_private_t *dev_priv = dev->dev_private;
-       drm_r128_getparam_t *param = data;
-       int value;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
-
-       switch (param->param) {
-       case R128_PARAM_IRQ_NR:
-               value = dev->irq;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
-               DRM_ERROR("copy_to_user\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-void r128_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
-{
-       if (dev->dev_private) {
-               drm_r128_private_t *dev_priv = dev->dev_private;
-               if (dev_priv->page_flipping) {
-                       r128_do_cleanup_pageflip(dev);
-               }
-       }
-}
-
-void r128_driver_lastclose(struct drm_device * dev)
-{
-       r128_do_cleanup_cce(dev);
-}
-
-struct drm_ioctl_desc r128_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_R128_CCE_IDLE, r128_cce_idle, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_RESET, r128_engine_reset, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_FULLSCREEN, r128_fullscreen, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_SWAP, r128_cce_swap, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_FLIP, r128_cce_flip, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_CLEAR, r128_cce_clear, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_VERTEX, r128_cce_vertex, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_INDICES, r128_cce_indices, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_BLIT, r128_cce_blit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_DEPTH, r128_cce_depth, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_STIPPLE, r128_cce_stipple, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_R128_GETPARAM, r128_getparam, DRM_AUTH),
-};
-
-int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
deleted file mode 100644 (file)
index 702df45..0000000
+++ /dev/null
@@ -1,1071 +0,0 @@
-/* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*-
- *
- * Copyright (C) The Weather Channel, Inc.  2002.
- * Copyright (C) 2004 Nicolai Haehnle.
- * All Rights Reserved.
- *
- * The Weather Channel (TM) funded Tungsten Graphics to develop the
- * initial release of the Radeon 8500 driver under the XFree86 license.
- * This notice must be preserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Nicolai Haehnle <prefect_@gmx.net>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "radeon_drm.h"
-#include "radeon_drv.h"
-#include "r300_reg.h"
-
-#define R300_SIMULTANEOUS_CLIPRECTS            4
-
-/* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects
- */
-static const int r300_cliprect_cntl[4] = {
-       0xAAAA,
-       0xEEEE,
-       0xFEFE,
-       0xFFFE
-};
-
-/**
- * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
- * buffer, starting with index n.
- */
-static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
-                              drm_radeon_kcmd_buffer_t *cmdbuf, int n)
-{
-       struct drm_clip_rect box;
-       int nr;
-       int i;
-       RING_LOCALS;
-
-       nr = cmdbuf->nbox - n;
-       if (nr > R300_SIMULTANEOUS_CLIPRECTS)
-               nr = R300_SIMULTANEOUS_CLIPRECTS;
-
-       DRM_DEBUG("%i cliprects\n", nr);
-
-       if (nr) {
-               BEGIN_RING(6 + nr * 2);
-               OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
-
-               for (i = 0; i < nr; ++i) {
-                       if (DRM_COPY_FROM_USER_UNCHECKED
-                           (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
-                               DRM_ERROR("copy cliprect faulted\n");
-                               return -EFAULT;
-                       }
-
-                       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
-                               box.x1 = (box.x1) &
-                                       R300_CLIPRECT_MASK;
-                               box.y1 = (box.y1) &
-                                       R300_CLIPRECT_MASK;
-                               box.x2 = (box.x2) &
-                                       R300_CLIPRECT_MASK;
-                               box.y2 = (box.y2) &
-                                       R300_CLIPRECT_MASK;
-                       } else {
-                               box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) &
-                                       R300_CLIPRECT_MASK;
-                               box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) &
-                                       R300_CLIPRECT_MASK;
-                               box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) &
-                                       R300_CLIPRECT_MASK;
-                               box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
-                                       R300_CLIPRECT_MASK;
-
-                       }
-                       OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
-                                (box.y1 << R300_CLIPRECT_Y_SHIFT));
-                       OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
-                                (box.y2 << R300_CLIPRECT_Y_SHIFT));
-
-               }
-
-               OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]);
-
-               /* TODO/SECURITY: Force scissors to a safe value, otherwise the
-                * client might be able to trample over memory.
-                * The impact should be very limited, but I'd rather be safe than
-                * sorry.
-                */
-               OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1));
-               OUT_RING(0);
-               OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK);
-               ADVANCE_RING();
-       } else {
-               /* Why we allow zero cliprect rendering:
-                * There are some commands in a command buffer that must be submitted
-                * even when there are no cliprects, e.g. DMA buffer discard
-                * or state setting (though state setting could be avoided by
-                * simulating a loss of context).
-                *
-                * Now since the cmdbuf interface is so chaotic right now (and is
-                * bound to remain that way for a bit until things settle down),
-                * it is basically impossible to filter out the commands that are
-                * necessary and those that aren't.
-                *
-                * So I choose the safe way and don't do any filtering at all;
-                * instead, I simply set up the engine so that all rendering
-                * can't produce any fragments.
-                */
-               BEGIN_RING(2);
-               OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0);
-               ADVANCE_RING();
-       }
-
-       return 0;
-}
-
-static u8 r300_reg_flags[0x10000 >> 2];
-
-void r300_init_reg_flags(struct drm_device *dev)
-{
-       int i;
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-
-       memset(r300_reg_flags, 0, 0x10000 >> 2);
-#define ADD_RANGE_MARK(reg, count,mark) \
-               for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
-                       r300_reg_flags[i]|=(mark);
-
-#define MARK_SAFE              1
-#define MARK_CHECK_OFFSET      2
-
-#define ADD_RANGE(reg, count)  ADD_RANGE_MARK(reg, count, MARK_SAFE)
-
-       /* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
-       ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
-       ADD_RANGE(R300_VAP_CNTL, 1);
-       ADD_RANGE(R300_SE_VTE_CNTL, 2);
-       ADD_RANGE(0x2134, 2);
-       ADD_RANGE(R300_VAP_CNTL_STATUS, 1);
-       ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
-       ADD_RANGE(0x21DC, 1);
-       ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
-       ADD_RANGE(R300_VAP_CLIP_X_0, 4);
-       ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1);
-       ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
-       ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
-       ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
-       ADD_RANGE(R300_GB_ENABLE, 1);
-       ADD_RANGE(R300_GB_MSPOS0, 5);
-       ADD_RANGE(R300_TX_CNTL, 1);
-       ADD_RANGE(R300_TX_ENABLE, 1);
-       ADD_RANGE(0x4200, 4);
-       ADD_RANGE(0x4214, 1);
-       ADD_RANGE(R300_RE_POINTSIZE, 1);
-       ADD_RANGE(0x4230, 3);
-       ADD_RANGE(R300_RE_LINE_CNT, 1);
-       ADD_RANGE(R300_RE_UNK4238, 1);
-       ADD_RANGE(0x4260, 3);
-       ADD_RANGE(R300_RE_SHADE, 4);
-       ADD_RANGE(R300_RE_POLYGON_MODE, 5);
-       ADD_RANGE(R300_RE_ZBIAS_CNTL, 1);
-       ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
-       ADD_RANGE(R300_RE_OCCLUSION_CNTL, 1);
-       ADD_RANGE(R300_RE_CULL_CNTL, 1);
-       ADD_RANGE(0x42C0, 2);
-       ADD_RANGE(R300_RS_CNTL_0, 2);
-
-       ADD_RANGE(R300_SC_HYPERZ, 2);
-       ADD_RANGE(0x43E8, 1);
-
-       ADD_RANGE(0x46A4, 5);
-
-       ADD_RANGE(R300_RE_FOG_STATE, 1);
-       ADD_RANGE(R300_FOG_COLOR_R, 3);
-       ADD_RANGE(R300_PP_ALPHA_TEST, 2);
-       ADD_RANGE(0x4BD8, 1);
-       ADD_RANGE(R300_PFS_PARAM_0_X, 64);
-       ADD_RANGE(0x4E00, 1);
-       ADD_RANGE(R300_RB3D_CBLEND, 2);
-       ADD_RANGE(R300_RB3D_COLORMASK, 1);
-       ADD_RANGE(R300_RB3D_BLEND_COLOR, 3);
-       ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET);   /* check offset */
-       ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
-       ADD_RANGE(0x4E50, 9);
-       ADD_RANGE(0x4E88, 1);
-       ADD_RANGE(0x4EA0, 2);
-       ADD_RANGE(R300_ZB_CNTL, 3);
-       ADD_RANGE(R300_ZB_FORMAT, 4);
-       ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET);      /* check offset */
-       ADD_RANGE(R300_ZB_DEPTHPITCH, 1);
-       ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1);
-       ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13);
-
-       ADD_RANGE(R300_TX_FILTER_0, 16);
-       ADD_RANGE(R300_TX_FILTER1_0, 16);
-       ADD_RANGE(R300_TX_SIZE_0, 16);
-       ADD_RANGE(R300_TX_FORMAT_0, 16);
-       ADD_RANGE(R300_TX_PITCH_0, 16);
-       /* Texture offset is dangerous and needs more checking */
-       ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
-       ADD_RANGE(R300_TX_CHROMA_KEY_0, 16);
-       ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
-
-       /* Sporadic registers used as primitives are emitted */
-       ADD_RANGE(R300_ZB_ZCACHE_CTLSTAT, 1);
-       ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
-       ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
-       ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
-
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
-               ADD_RANGE(R500_VAP_INDEX_OFFSET, 1);
-               ADD_RANGE(R500_US_CONFIG, 2);
-               ADD_RANGE(R500_US_CODE_ADDR, 3);
-               ADD_RANGE(R500_US_FC_CTRL, 1);
-               ADD_RANGE(R500_RS_IP_0, 16);
-               ADD_RANGE(R500_RS_INST_0, 16);
-               ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2);
-               ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2);
-               ADD_RANGE(R500_ZB_FIFO_SIZE, 2);
-       } else {
-               ADD_RANGE(R300_PFS_CNTL_0, 3);
-               ADD_RANGE(R300_PFS_NODE_0, 4);
-               ADD_RANGE(R300_PFS_TEXI_0, 64);
-               ADD_RANGE(R300_PFS_INSTR0_0, 64);
-               ADD_RANGE(R300_PFS_INSTR1_0, 64);
-               ADD_RANGE(R300_PFS_INSTR2_0, 64);
-               ADD_RANGE(R300_PFS_INSTR3_0, 64);
-               ADD_RANGE(R300_RS_INTERP_0, 8);
-               ADD_RANGE(R300_RS_ROUTE_0, 8);
-
-       }
-}
-
-static __inline__ int r300_check_range(unsigned reg, int count)
-{
-       int i;
-       if (reg & ~0xffff)
-               return -1;
-       for (i = (reg >> 2); i < (reg >> 2) + count; i++)
-               if (r300_reg_flags[i] != MARK_SAFE)
-                       return 1;
-       return 0;
-}
-
-static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
-                                                         dev_priv,
-                                                         drm_radeon_kcmd_buffer_t
-                                                         * cmdbuf,
-                                                         drm_r300_cmd_header_t
-                                                         header)
-{
-       int reg;
-       int sz;
-       int i;
-       int values[64];
-       RING_LOCALS;
-
-       sz = header.packet0.count;
-       reg = (header.packet0.reghi << 8) | header.packet0.reglo;
-
-       if ((sz > 64) || (sz < 0)) {
-               DRM_ERROR
-                   ("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
-                    reg, sz);
-               return -EINVAL;
-       }
-       for (i = 0; i < sz; i++) {
-               values[i] = ((int *)cmdbuf->buf)[i];
-               switch (r300_reg_flags[(reg >> 2) + i]) {
-               case MARK_SAFE:
-                       break;
-               case MARK_CHECK_OFFSET:
-                       if (!radeon_check_offset(dev_priv, (u32) values[i])) {
-                               DRM_ERROR
-                                   ("Offset failed range check (reg=%04x sz=%d)\n",
-                                    reg, sz);
-                               return -EINVAL;
-                       }
-                       break;
-               default:
-                       DRM_ERROR("Register %04x failed check as flag=%02x\n",
-                                 reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
-                       return -EINVAL;
-               }
-       }
-
-       BEGIN_RING(1 + sz);
-       OUT_RING(CP_PACKET0(reg, sz - 1));
-       OUT_RING_TABLE(values, sz);
-       ADVANCE_RING();
-
-       cmdbuf->buf += sz * 4;
-       cmdbuf->bufsz -= sz * 4;
-
-       return 0;
-}
-
-/**
- * Emits a packet0 setting arbitrary registers.
- * Called by r300_do_cp_cmdbuf.
- *
- * Note that checks are performed on contents and addresses of the registers
- */
-static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
-                                       drm_radeon_kcmd_buffer_t *cmdbuf,
-                                       drm_r300_cmd_header_t header)
-{
-       int reg;
-       int sz;
-       RING_LOCALS;
-
-       sz = header.packet0.count;
-       reg = (header.packet0.reghi << 8) | header.packet0.reglo;
-
-       if (!sz)
-               return 0;
-
-       if (sz * 4 > cmdbuf->bufsz)
-               return -EINVAL;
-
-       if (reg + sz * 4 >= 0x10000) {
-               DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg,
-                         sz);
-               return -EINVAL;
-       }
-
-       if (r300_check_range(reg, sz)) {
-               /* go and check everything */
-               return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf,
-                                                          header);
-       }
-       /* the rest of the data is safe to emit, whatever the values the user passed */
-
-       BEGIN_RING(1 + sz);
-       OUT_RING(CP_PACKET0(reg, sz - 1));
-       OUT_RING_TABLE((int *)cmdbuf->buf, sz);
-       ADVANCE_RING();
-
-       cmdbuf->buf += sz * 4;
-       cmdbuf->bufsz -= sz * 4;
-
-       return 0;
-}
-
-/**
- * Uploads user-supplied vertex program instructions or parameters onto
- * the graphics card.
- * Called by r300_do_cp_cmdbuf.
- */
-static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
-                                   drm_radeon_kcmd_buffer_t *cmdbuf,
-                                   drm_r300_cmd_header_t header)
-{
-       int sz;
-       int addr;
-       RING_LOCALS;
-
-       sz = header.vpu.count;
-       addr = (header.vpu.adrhi << 8) | header.vpu.adrlo;
-
-       if (!sz)
-               return 0;
-       if (sz * 16 > cmdbuf->bufsz)
-               return -EINVAL;
-
-       BEGIN_RING(5 + sz * 4);
-       /* Wait for VAP to come to senses.. */
-       /* there is no need to emit it multiple times, (only once before VAP is programmed,
-          but this optimization is for later */
-       OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0);
-       OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
-       OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
-       OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
-
-       ADVANCE_RING();
-
-       cmdbuf->buf += sz * 16;
-       cmdbuf->bufsz -= sz * 16;
-
-       return 0;
-}
-
-/**
- * Emit a clear packet from userspace.
- * Called by r300_emit_packet3.
- */
-static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
-                                     drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-       RING_LOCALS;
-
-       if (8 * 4 > cmdbuf->bufsz)
-               return -EINVAL;
-
-       BEGIN_RING(10);
-       OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
-       OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
-                (1 << R300_PRIM_NUM_VERTICES_SHIFT));
-       OUT_RING_TABLE((int *)cmdbuf->buf, 8);
-       ADVANCE_RING();
-
-       cmdbuf->buf += 8 * 4;
-       cmdbuf->bufsz -= 8 * 4;
-
-       return 0;
-}
-
-static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
-                                              drm_radeon_kcmd_buffer_t *cmdbuf,
-                                              u32 header)
-{
-       int count, i, k;
-#define MAX_ARRAY_PACKET  64
-       u32 payload[MAX_ARRAY_PACKET];
-       u32 narrays;
-       RING_LOCALS;
-
-       count = (header >> 16) & 0x3fff;
-
-       if ((count + 1) > MAX_ARRAY_PACKET) {
-               DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
-                         count);
-               return -EINVAL;
-       }
-       memset(payload, 0, MAX_ARRAY_PACKET * 4);
-       memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4);
-
-       /* carefully check packet contents */
-
-       narrays = payload[0];
-       k = 0;
-       i = 1;
-       while ((k < narrays) && (i < (count + 1))) {
-               i++;            /* skip attribute field */
-               if (!radeon_check_offset(dev_priv, payload[i])) {
-                       DRM_ERROR
-                           ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
-                            k, i);
-                       return -EINVAL;
-               }
-               k++;
-               i++;
-               if (k == narrays)
-                       break;
-               /* have one more to process, they come in pairs */
-               if (!radeon_check_offset(dev_priv, payload[i])) {
-                       DRM_ERROR
-                           ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
-                            k, i);
-                       return -EINVAL;
-               }
-               k++;
-               i++;
-       }
-       /* do the counts match what we expect ? */
-       if ((k != narrays) || (i != (count + 1))) {
-               DRM_ERROR
-                   ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
-                    k, i, narrays, count + 1);
-               return -EINVAL;
-       }
-
-       /* all clear, output packet */
-
-       BEGIN_RING(count + 2);
-       OUT_RING(header);
-       OUT_RING_TABLE(payload, count + 1);
-       ADVANCE_RING();
-
-       cmdbuf->buf += (count + 2) * 4;
-       cmdbuf->bufsz -= (count + 2) * 4;
-
-       return 0;
-}
-
-static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
-                                            drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-       u32 *cmd = (u32 *) cmdbuf->buf;
-       int count, ret;
-       RING_LOCALS;
-
-       count=(cmd[0]>>16) & 0x3fff;
-
-       if (cmd[0] & 0x8000) {
-               u32 offset;
-
-               if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
-                             | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-                       offset = cmd[2] << 10;
-                       ret = !radeon_check_offset(dev_priv, offset);
-                       if (ret) {
-                               DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
-                               return -EINVAL;
-                       }
-               }
-
-               if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
-                   (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-                       offset = cmd[3] << 10;
-                       ret = !radeon_check_offset(dev_priv, offset);
-                       if (ret) {
-                               DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
-                               return -EINVAL;
-                       }
-
-               }
-       }
-
-       BEGIN_RING(count+2);
-       OUT_RING(cmd[0]);
-       OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
-       ADVANCE_RING();
-
-       cmdbuf->buf += (count+2)*4;
-       cmdbuf->bufsz -= (count+2)*4;
-
-       return 0;
-}
-
-static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
-                                            drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-       u32 *cmd = (u32 *) cmdbuf->buf;
-       int count, ret;
-       RING_LOCALS;
-
-       count=(cmd[0]>>16) & 0x3fff;
-
-       if ((cmd[1] & 0x8000ffff) != 0x80000810) {
-               DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
-               return -EINVAL;
-       }
-       ret = !radeon_check_offset(dev_priv, cmd[2]);
-       if (ret) {
-               DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
-               return -EINVAL;
-       }
-
-       BEGIN_RING(count+2);
-       OUT_RING(cmd[0]);
-       OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
-       ADVANCE_RING();
-
-       cmdbuf->buf += (count+2)*4;
-       cmdbuf->bufsz -= (count+2)*4;
-
-       return 0;
-}
-
-static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
-                                           drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-       u32 header;
-       int count;
-       RING_LOCALS;
-
-       if (4 > cmdbuf->bufsz)
-               return -EINVAL;
-
-       /* Fixme !! This simply emits a packet without much checking.
-          We need to be smarter. */
-
-       /* obtain first word - actual packet3 header */
-       header = *(u32 *) cmdbuf->buf;
-
-       /* Is it packet 3 ? */
-       if ((header >> 30) != 0x3) {
-               DRM_ERROR("Not a packet3 header (0x%08x)\n", header);
-               return -EINVAL;
-       }
-
-       count = (header >> 16) & 0x3fff;
-
-       /* Check again now that we know how much data to expect */
-       if ((count + 2) * 4 > cmdbuf->bufsz) {
-               DRM_ERROR
-                   ("Expected packet3 of length %d but have only %d bytes left\n",
-                    (count + 2) * 4, cmdbuf->bufsz);
-               return -EINVAL;
-       }
-
-       /* Is it a packet type we know about ? */
-       switch (header & 0xff00) {
-       case RADEON_3D_LOAD_VBPNTR:     /* load vertex array pointers */
-               return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header);
-
-       case RADEON_CNTL_BITBLT_MULTI:
-               return r300_emit_bitblt_multi(dev_priv, cmdbuf);
-
-       case RADEON_CP_INDX_BUFFER:     /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */
-               return r300_emit_indx_buffer(dev_priv, cmdbuf);
-       case RADEON_CP_3D_DRAW_IMMD_2:  /* triggers drawing using in-packet vertex data */
-       case RADEON_CP_3D_DRAW_VBUF_2:  /* triggers drawing of vertex buffers setup elsewhere */
-       case RADEON_CP_3D_DRAW_INDX_2:  /* triggers drawing using indices to vertex buffer */
-       case RADEON_WAIT_FOR_IDLE:
-       case RADEON_CP_NOP:
-               /* these packets are safe */
-               break;
-       default:
-               DRM_ERROR("Unknown packet3 header (0x%08x)\n", header);
-               return -EINVAL;
-       }
-
-       BEGIN_RING(count + 2);
-       OUT_RING(header);
-       OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
-       ADVANCE_RING();
-
-       cmdbuf->buf += (count + 2) * 4;
-       cmdbuf->bufsz -= (count + 2) * 4;
-
-       return 0;
-}
-
-/**
- * Emit a rendering packet3 from userspace.
- * Called by r300_do_cp_cmdbuf.
- */
-static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
-                                       drm_radeon_kcmd_buffer_t *cmdbuf,
-                                       drm_r300_cmd_header_t header)
-{
-       int n;
-       int ret;
-       char *orig_buf = cmdbuf->buf;
-       int orig_bufsz = cmdbuf->bufsz;
-
-       /* This is a do-while-loop so that we run the interior at least once,
-        * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale.
-        */
-       n = 0;
-       do {
-               if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) {
-                       ret = r300_emit_cliprects(dev_priv, cmdbuf, n);
-                       if (ret)
-                               return ret;
-
-                       cmdbuf->buf = orig_buf;
-                       cmdbuf->bufsz = orig_bufsz;
-               }
-
-               switch (header.packet3.packet) {
-               case R300_CMD_PACKET3_CLEAR:
-                       DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n");
-                       ret = r300_emit_clear(dev_priv, cmdbuf);
-                       if (ret) {
-                               DRM_ERROR("r300_emit_clear failed\n");
-                               return ret;
-                       }
-                       break;
-
-               case R300_CMD_PACKET3_RAW:
-                       DRM_DEBUG("R300_CMD_PACKET3_RAW\n");
-                       ret = r300_emit_raw_packet3(dev_priv, cmdbuf);
-                       if (ret) {
-                               DRM_ERROR("r300_emit_raw_packet3 failed\n");
-                               return ret;
-                       }
-                       break;
-
-               default:
-                       DRM_ERROR("bad packet3 type %i at %p\n",
-                                 header.packet3.packet,
-                                 cmdbuf->buf - sizeof(header));
-                       return -EINVAL;
-               }
-
-               n += R300_SIMULTANEOUS_CLIPRECTS;
-       } while (n < cmdbuf->nbox);
-
-       return 0;
-}
-
-/* Some of the R300 chips seem to be extremely touchy about the two registers
- * that are configured in r300_pacify.
- * Among the worst offenders seems to be the R300 ND (0x4E44): When userspace
- * sends a command buffer that contains only state setting commands and a
- * vertex program/parameter upload sequence, this will eventually lead to a
- * lockup, unless the sequence is bracketed by calls to r300_pacify.
- * So we should take great care to *always* call r300_pacify before
- * *anything* 3D related, and again afterwards. This is what the
- * call bracket in r300_do_cp_cmdbuf is for.
- */
-
-/**
- * Emit the sequence to pacify R300.
- */
-static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
-{
-       RING_LOCALS;
-
-       BEGIN_RING(6);
-       OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
-       OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A);
-       OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));
-       OUT_RING(R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE|
-                R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
-       OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
-       OUT_RING(0x0);
-       ADVANCE_RING();
-}
-
-/**
- * Called by r300_do_cp_cmdbuf to update the internal buffer age and state.
- * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
- * be careful about how this function is called.
- */
-static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
-
-       buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
-       buf->pending = 1;
-       buf->used = 0;
-}
-
-static void r300_cmd_wait(drm_radeon_private_t * dev_priv,
-                         drm_r300_cmd_header_t header)
-{
-       u32 wait_until;
-       RING_LOCALS;
-
-       if (!header.wait.flags)
-               return;
-
-       wait_until = 0;
-
-       switch(header.wait.flags) {
-       case R300_WAIT_2D:
-               wait_until = RADEON_WAIT_2D_IDLE;
-               break;
-       case R300_WAIT_3D:
-               wait_until = RADEON_WAIT_3D_IDLE;
-               break;
-       case R300_NEW_WAIT_2D_3D:
-               wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE;
-               break;
-       case R300_NEW_WAIT_2D_2D_CLEAN:
-               wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
-               break;
-       case R300_NEW_WAIT_3D_3D_CLEAN:
-               wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
-               break;
-       case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN:
-               wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
-               wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
-               break;
-       default:
-               return;
-       }
-
-       BEGIN_RING(2);
-       OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
-       OUT_RING(wait_until);
-       ADVANCE_RING();
-}
-
-static int r300_scratch(drm_radeon_private_t *dev_priv,
-                       drm_radeon_kcmd_buffer_t *cmdbuf,
-                       drm_r300_cmd_header_t header)
-{
-       u32 *ref_age_base;
-       u32 i, buf_idx, h_pending;
-       RING_LOCALS;
-
-       if (cmdbuf->bufsz <
-           (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) {
-               return -EINVAL;
-       }
-
-       if (header.scratch.reg >= 5) {
-               return -EINVAL;
-       }
-
-       dev_priv->scratch_ages[header.scratch.reg]++;
-
-       ref_age_base =  (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf);
-
-       cmdbuf->buf += sizeof(u64);
-       cmdbuf->bufsz -= sizeof(u64);
-
-       for (i=0; i < header.scratch.n_bufs; i++) {
-               buf_idx = *(u32 *)cmdbuf->buf;
-               buf_idx *= 2; /* 8 bytes per buf */
-
-               if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
-                       return -EINVAL;
-               }
-
-               if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
-                       return -EINVAL;
-               }
-
-               if (h_pending == 0) {
-                       return -EINVAL;
-               }
-
-               h_pending--;
-
-               if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
-                       return -EINVAL;
-               }
-
-               cmdbuf->buf += sizeof(buf_idx);
-               cmdbuf->bufsz -= sizeof(buf_idx);
-       }
-
-       BEGIN_RING(2);
-       OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) );
-       OUT_RING( dev_priv->scratch_ages[header.scratch.reg] );
-       ADVANCE_RING();
-
-       return 0;
-}
-
-/**
- * Uploads user-supplied vertex program instructions or parameters onto
- * the graphics card.
- * Called by r300_do_cp_cmdbuf.
- */
-static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv,
-                                      drm_radeon_kcmd_buffer_t *cmdbuf,
-                                      drm_r300_cmd_header_t header)
-{
-       int sz;
-       int addr;
-       int type;
-       int clamp;
-       int stride;
-       RING_LOCALS;
-
-       sz = header.r500fp.count;
-       /* address is 9 bits 0 - 8, bit 1 of flags is part of address */
-       addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo;
-
-       type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE);
-       clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
-
-       addr |= (type << 16);
-       addr |= (clamp << 17);
-
-       stride = type ? 4 : 6;
-
-       DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type);
-       if (!sz)
-               return 0;
-       if (sz * stride * 4 > cmdbuf->bufsz)
-               return -EINVAL;
-
-       BEGIN_RING(3 + sz * stride);
-       OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr);
-       OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1));
-       OUT_RING_TABLE((int *)cmdbuf->buf, sz * stride);
-
-       ADVANCE_RING();
-
-       cmdbuf->buf += sz * stride * 4;
-       cmdbuf->bufsz -= sz * stride * 4;
-
-       return 0;
-}
-
-
-/**
- * Parses and validates a user-supplied command buffer and emits appropriate
- * commands on the DMA ring buffer.
- * Called by the ioctl handler function radeon_cp_cmdbuf.
- */
-int r300_do_cp_cmdbuf(struct drm_device *dev,
-                     struct drm_file *file_priv,
-                     drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf = NULL;
-       int emit_dispatch_age = 0;
-       int ret = 0;
-
-       DRM_DEBUG("\n");
-
-       /* See the comment above r300_emit_begin3d for why this call must be here,
-        * and what the cleanup gotos are for. */
-       r300_pacify(dev_priv);
-
-       if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
-               ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
-               if (ret)
-                       goto cleanup;
-       }
-
-       while (cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
-               int idx;
-               drm_r300_cmd_header_t header;
-
-               header.u = *(unsigned int *)cmdbuf->buf;
-
-               cmdbuf->buf += sizeof(header);
-               cmdbuf->bufsz -= sizeof(header);
-
-               switch (header.header.cmd_type) {
-               case R300_CMD_PACKET0:
-                       DRM_DEBUG("R300_CMD_PACKET0\n");
-                       ret = r300_emit_packet0(dev_priv, cmdbuf, header);
-                       if (ret) {
-                               DRM_ERROR("r300_emit_packet0 failed\n");
-                               goto cleanup;
-                       }
-                       break;
-
-               case R300_CMD_VPU:
-                       DRM_DEBUG("R300_CMD_VPU\n");
-                       ret = r300_emit_vpu(dev_priv, cmdbuf, header);
-                       if (ret) {
-                               DRM_ERROR("r300_emit_vpu failed\n");
-                               goto cleanup;
-                       }
-                       break;
-
-               case R300_CMD_PACKET3:
-                       DRM_DEBUG("R300_CMD_PACKET3\n");
-                       ret = r300_emit_packet3(dev_priv, cmdbuf, header);
-                       if (ret) {
-                               DRM_ERROR("r300_emit_packet3 failed\n");
-                               goto cleanup;
-                       }
-                       break;
-
-               case R300_CMD_END3D:
-                       DRM_DEBUG("R300_CMD_END3D\n");
-                       /* TODO:
-                          Ideally userspace driver should not need to issue this call,
-                          i.e. the drm driver should issue it automatically and prevent
-                          lockups.
-
-                          In practice, we do not understand why this call is needed and what
-                          it does (except for some vague guesses that it has to do with cache
-                          coherence) and so the user space driver does it.
-
-                          Once we are sure which uses prevent lockups the code could be moved
-                          into the kernel and the userspace driver will not
-                          need to use this command.
-
-                          Note that issuing this command does not hurt anything
-                          except, possibly, performance */
-                       r300_pacify(dev_priv);
-                       break;
-
-               case R300_CMD_CP_DELAY:
-                       /* simple enough, we can do it here */
-                       DRM_DEBUG("R300_CMD_CP_DELAY\n");
-                       {
-                               int i;
-                               RING_LOCALS;
-
-                               BEGIN_RING(header.delay.count);
-                               for (i = 0; i < header.delay.count; i++)
-                                       OUT_RING(RADEON_CP_PACKET2);
-                               ADVANCE_RING();
-                       }
-                       break;
-
-               case R300_CMD_DMA_DISCARD:
-                       DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
-                       idx = header.dma.buf_idx;
-                       if (idx < 0 || idx >= dma->buf_count) {
-                               DRM_ERROR("buffer index %d (of %d max)\n",
-                                         idx, dma->buf_count - 1);
-                               ret = -EINVAL;
-                               goto cleanup;
-                       }
-
-                       buf = dma->buflist[idx];
-                       if (buf->file_priv != file_priv || buf->pending) {
-                               DRM_ERROR("bad buffer %p %p %d\n",
-                                         buf->file_priv, file_priv,
-                                         buf->pending);
-                               ret = -EINVAL;
-                               goto cleanup;
-                       }
-
-                       emit_dispatch_age = 1;
-                       r300_discard_buffer(dev, buf);
-                       break;
-
-               case R300_CMD_WAIT:
-                       DRM_DEBUG("R300_CMD_WAIT\n");
-                       r300_cmd_wait(dev_priv, header);
-                       break;
-
-               case R300_CMD_SCRATCH:
-                       DRM_DEBUG("R300_CMD_SCRATCH\n");
-                       ret = r300_scratch(dev_priv, cmdbuf, header);
-                       if (ret) {
-                               DRM_ERROR("r300_scratch failed\n");
-                               goto cleanup;
-                       }
-                       break;
-
-               case R300_CMD_R500FP:
-                       if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) {
-                               DRM_ERROR("Calling r500 command on r300 card\n");
-                               ret = -EINVAL;
-                               goto cleanup;
-                       }
-                       DRM_DEBUG("R300_CMD_R500FP\n");
-                       ret = r300_emit_r500fp(dev_priv, cmdbuf, header);
-                       if (ret) {
-                               DRM_ERROR("r300_emit_r500fp failed\n");
-                               goto cleanup;
-                       }
-                       break;
-               default:
-                       DRM_ERROR("bad cmd_type %i at %p\n",
-                                 header.header.cmd_type,
-                                 cmdbuf->buf - sizeof(header));
-                       ret = -EINVAL;
-                       goto cleanup;
-               }
-       }
-
-       DRM_DEBUG("END\n");
-
-      cleanup:
-       r300_pacify(dev_priv);
-
-       /* We emit the vertex buffer age here, outside the pacifier "brackets"
-        * for two reasons:
-        *  (1) This may coalesce multiple age emissions into a single one and
-        *  (2) more importantly, some chips lock up hard when scratch registers
-        *      are written inside the pacifier bracket.
-        */
-       if (emit_dispatch_age) {
-               RING_LOCALS;
-
-               /* Emit the vertex buffer age */
-               BEGIN_RING(2);
-               RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch);
-               ADVANCE_RING();
-       }
-
-       COMMIT_RING();
-
-       return ret;
-}
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
deleted file mode 100644 (file)
index a6802f2..0000000
+++ /dev/null
@@ -1,1772 +0,0 @@
-/**************************************************************************
-
-Copyright (C) 2004-2005 Nicolai Haehnle et al.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-#ifndef _R300_REG_H
-#define _R300_REG_H
-
-#define R300_MC_INIT_MISC_LAT_TIMER    0x180
-#      define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT      0
-#      define R300_MC_MISC__MC_VF_INIT_LAT_SHIFT       4
-#      define R300_MC_MISC__MC_DISP0R_INIT_LAT_SHIFT   8
-#      define R300_MC_MISC__MC_DISP1R_INIT_LAT_SHIFT   12
-#      define R300_MC_MISC__MC_FIXED_INIT_LAT_SHIFT    16
-#      define R300_MC_MISC__MC_E2R_INIT_LAT_SHIFT      20
-#      define R300_MC_MISC__MC_SAME_PAGE_PRIO_SHIFT    24
-#      define R300_MC_MISC__MC_GLOBW_INIT_LAT_SHIFT    28
-
-#define R300_MC_INIT_GFX_LAT_TIMER     0x154
-#      define R300_MC_MISC__MC_G3D0R_INIT_LAT_SHIFT    0
-#      define R300_MC_MISC__MC_G3D1R_INIT_LAT_SHIFT    4
-#      define R300_MC_MISC__MC_G3D2R_INIT_LAT_SHIFT    8
-#      define R300_MC_MISC__MC_G3D3R_INIT_LAT_SHIFT    12
-#      define R300_MC_MISC__MC_TX0R_INIT_LAT_SHIFT     16
-#      define R300_MC_MISC__MC_TX1R_INIT_LAT_SHIFT     20
-#      define R300_MC_MISC__MC_GLOBR_INIT_LAT_SHIFT    24
-#      define R300_MC_MISC__MC_GLOBW_FULL_LAT_SHIFT    28
-
-/*
- * This file contains registers and constants for the R300. They have been
- * found mostly by examining command buffers captured using glxtest, as well
- * as by extrapolating some known registers and constants from the R200.
- * I am fairly certain that they are correct unless stated otherwise
- * in comments.
- */
-
-#define R300_SE_VPORT_XSCALE                0x1D98
-#define R300_SE_VPORT_XOFFSET               0x1D9C
-#define R300_SE_VPORT_YSCALE                0x1DA0
-#define R300_SE_VPORT_YOFFSET               0x1DA4
-#define R300_SE_VPORT_ZSCALE                0x1DA8
-#define R300_SE_VPORT_ZOFFSET               0x1DAC
-
-
-/*
- * Vertex Array Processing (VAP) Control
- * Stolen from r200 code from Christoph Brill (It's a guess!)
- */
-#define R300_VAP_CNTL  0x2080
-
-/* This register is written directly and also starts data section
- * in many 3d CP_PACKET3's
- */
-#define R300_VAP_VF_CNTL       0x2084
-#      define  R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT              0
-#      define  R300_VAP_VF_CNTL__PRIM_NONE                     (0<<0)
-#      define  R300_VAP_VF_CNTL__PRIM_POINTS                   (1<<0)
-#      define  R300_VAP_VF_CNTL__PRIM_LINES                    (2<<0)
-#      define  R300_VAP_VF_CNTL__PRIM_LINE_STRIP               (3<<0)
-#      define  R300_VAP_VF_CNTL__PRIM_TRIANGLES                (4<<0)
-#      define  R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN             (5<<0)
-#      define  R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP           (6<<0)
-#      define  R300_VAP_VF_CNTL__PRIM_LINE_LOOP                (12<<0)
-#      define  R300_VAP_VF_CNTL__PRIM_QUADS                    (13<<0)
-#      define  R300_VAP_VF_CNTL__PRIM_QUAD_STRIP               (14<<0)
-#      define  R300_VAP_VF_CNTL__PRIM_POLYGON                  (15<<0)
-
-#      define  R300_VAP_VF_CNTL__PRIM_WALK__SHIFT              4
-       /* State based - direct writes to registers trigger vertex
-           generation */
-#      define  R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED         (0<<4)
-#      define  R300_VAP_VF_CNTL__PRIM_WALK_INDICES             (1<<4)
-#      define  R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST         (2<<4)
-#      define  R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED     (3<<4)
-
-       /* I don't think I saw these three used.. */
-#      define  R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT            6
-#      define  R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT     9
-#      define  R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT        10
-
-       /* index size - when not set the indices are assumed to be 16 bit */
-#      define  R300_VAP_VF_CNTL__INDEX_SIZE_32bit              (1<<11)
-       /* number of vertices */
-#      define  R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT           16
-
-/* BEGIN: Wild guesses */
-#define R300_VAP_OUTPUT_VTX_FMT_0           0x2090
-#       define R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT     (1<<0)
-#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT   (1<<1)
-#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2)  /* GUESS */
-#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3)  /* GUESS */
-#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4)  /* GUESS */
-#       define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */
-
-#define R300_VAP_OUTPUT_VTX_FMT_1           0x2094
-       /* each of the following is 3 bits wide, specifies number
-          of components */
-#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
-#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
-#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
-#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9
-#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12
-#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15
-#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18
-#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21
-/* END: Wild guesses */
-
-#define R300_SE_VTE_CNTL                  0x20b0
-#      define     R300_VPORT_X_SCALE_ENA                0x00000001
-#      define     R300_VPORT_X_OFFSET_ENA               0x00000002
-#      define     R300_VPORT_Y_SCALE_ENA                0x00000004
-#      define     R300_VPORT_Y_OFFSET_ENA               0x00000008
-#      define     R300_VPORT_Z_SCALE_ENA                0x00000010
-#      define     R300_VPORT_Z_OFFSET_ENA               0x00000020
-#      define     R300_VTX_XY_FMT                       0x00000100
-#      define     R300_VTX_Z_FMT                        0x00000200
-#      define     R300_VTX_W0_FMT                       0x00000400
-#      define     R300_VTX_W0_NORMALIZE                 0x00000800
-#      define     R300_VTX_ST_DENORMALIZED              0x00001000
-
-/* BEGIN: Vertex data assembly - lots of uncertainties */
-
-/* gap */
-
-#define R300_VAP_CNTL_STATUS              0x2140
-#      define R300_VC_NO_SWAP                  (0 << 0)
-#      define R300_VC_16BIT_SWAP               (1 << 0)
-#      define R300_VC_32BIT_SWAP               (2 << 0)
-#      define R300_VAP_TCL_BYPASS              (1 << 8)
-
-/* gap */
-
-/* Where do we get our vertex data?
- *
- * Vertex data either comes either from immediate mode registers or from
- * vertex arrays.
- * There appears to be no mixed mode (though we can force the pitch of
- * vertex arrays to 0, effectively reusing the same element over and over
- * again).
- *
- * Immediate mode is controlled by the INPUT_CNTL registers. I am not sure
- * if these registers influence vertex array processing.
- *
- * Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3.
- *
- * In both cases, vertex attributes are then passed through INPUT_ROUTE.
- *
- * Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data
- * into the vertex processor's input registers.
- * The first word routes the first input, the second word the second, etc.
- * The corresponding input is routed into the register with the given index.
- * The list is ended by a word with INPUT_ROUTE_END set.
- *
- * Always set COMPONENTS_4 in immediate mode.
- */
-
-#define R300_VAP_INPUT_ROUTE_0_0            0x2150
-#       define R300_INPUT_ROUTE_COMPONENTS_1     (0 << 0)
-#       define R300_INPUT_ROUTE_COMPONENTS_2     (1 << 0)
-#       define R300_INPUT_ROUTE_COMPONENTS_3     (2 << 0)
-#       define R300_INPUT_ROUTE_COMPONENTS_4     (3 << 0)
-#       define R300_INPUT_ROUTE_COMPONENTS_RGBA  (4 << 0) /* GUESS */
-#       define R300_VAP_INPUT_ROUTE_IDX_SHIFT    8
-#       define R300_VAP_INPUT_ROUTE_IDX_MASK     (31 << 8) /* GUESS */
-#       define R300_VAP_INPUT_ROUTE_END          (1 << 13)
-#       define R300_INPUT_ROUTE_IMMEDIATE_MODE   (0 << 14) /* GUESS */
-#       define R300_INPUT_ROUTE_FLOAT            (1 << 14) /* GUESS */
-#       define R300_INPUT_ROUTE_UNSIGNED_BYTE    (2 << 14) /* GUESS */
-#       define R300_INPUT_ROUTE_FLOAT_COLOR      (3 << 14) /* GUESS */
-#define R300_VAP_INPUT_ROUTE_0_1            0x2154
-#define R300_VAP_INPUT_ROUTE_0_2            0x2158
-#define R300_VAP_INPUT_ROUTE_0_3            0x215C
-#define R300_VAP_INPUT_ROUTE_0_4            0x2160
-#define R300_VAP_INPUT_ROUTE_0_5            0x2164
-#define R300_VAP_INPUT_ROUTE_0_6            0x2168
-#define R300_VAP_INPUT_ROUTE_0_7            0x216C
-
-/* gap */
-
-/* Notes:
- *  - always set up to produce at least two attributes:
- *    if vertex program uses only position, fglrx will set normal, too
- *  - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal.
- */
-#define R300_VAP_INPUT_CNTL_0               0x2180
-#       define R300_INPUT_CNTL_0_COLOR           0x00000001
-#define R300_VAP_INPUT_CNTL_1               0x2184
-#       define R300_INPUT_CNTL_POS               0x00000001
-#       define R300_INPUT_CNTL_NORMAL            0x00000002
-#       define R300_INPUT_CNTL_COLOR             0x00000004
-#       define R300_INPUT_CNTL_TC0               0x00000400
-#       define R300_INPUT_CNTL_TC1               0x00000800
-#       define R300_INPUT_CNTL_TC2               0x00001000 /* GUESS */
-#       define R300_INPUT_CNTL_TC3               0x00002000 /* GUESS */
-#       define R300_INPUT_CNTL_TC4               0x00004000 /* GUESS */
-#       define R300_INPUT_CNTL_TC5               0x00008000 /* GUESS */
-#       define R300_INPUT_CNTL_TC6               0x00010000 /* GUESS */
-#       define R300_INPUT_CNTL_TC7               0x00020000 /* GUESS */
-
-/* gap */
-
-/* Words parallel to INPUT_ROUTE_0; All words that are active in INPUT_ROUTE_0
- * are set to a swizzling bit pattern, other words are 0.
- *
- * In immediate mode, the pattern is always set to xyzw. In vertex array
- * mode, the swizzling pattern is e.g. used to set zw components in texture
- * coordinates with only tweo components.
- */
-#define R300_VAP_INPUT_ROUTE_1_0            0x21E0
-#       define R300_INPUT_ROUTE_SELECT_X    0
-#       define R300_INPUT_ROUTE_SELECT_Y    1
-#       define R300_INPUT_ROUTE_SELECT_Z    2
-#       define R300_INPUT_ROUTE_SELECT_W    3
-#       define R300_INPUT_ROUTE_SELECT_ZERO 4
-#       define R300_INPUT_ROUTE_SELECT_ONE  5
-#       define R300_INPUT_ROUTE_SELECT_MASK 7
-#       define R300_INPUT_ROUTE_X_SHIFT     0
-#       define R300_INPUT_ROUTE_Y_SHIFT     3
-#       define R300_INPUT_ROUTE_Z_SHIFT     6
-#       define R300_INPUT_ROUTE_W_SHIFT     9
-#       define R300_INPUT_ROUTE_ENABLE      (15 << 12)
-#define R300_VAP_INPUT_ROUTE_1_1            0x21E4
-#define R300_VAP_INPUT_ROUTE_1_2            0x21E8
-#define R300_VAP_INPUT_ROUTE_1_3            0x21EC
-#define R300_VAP_INPUT_ROUTE_1_4            0x21F0
-#define R300_VAP_INPUT_ROUTE_1_5            0x21F4
-#define R300_VAP_INPUT_ROUTE_1_6            0x21F8
-#define R300_VAP_INPUT_ROUTE_1_7            0x21FC
-
-/* END: Vertex data assembly */
-
-/* gap */
-
-/* BEGIN: Upload vertex program and data */
-
-/*
- * The programmable vertex shader unit has a memory bank of unknown size
- * that can be written to in 16 byte units by writing the address into
- * UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs).
- *
- * Pointers into the memory bank are always in multiples of 16 bytes.
- *
- * The memory bank is divided into areas with fixed meaning.
- *
- * Starting at address UPLOAD_PROGRAM: Vertex program instructions.
- * Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB),
- * whereas the difference between known addresses suggests size 512.
- *
- * Starting at address UPLOAD_PARAMETERS: Vertex program parameters.
- * Native reported limits and the VPI layout suggest size 256, whereas
- * difference between known addresses suggests size 512.
- *
- * At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the
- * floating point pointsize. The exact purpose of this state is uncertain,
- * as there is also the R300_RE_POINTSIZE register.
- *
- * Multiple vertex programs and parameter sets can be loaded at once,
- * which could explain the size discrepancy.
- */
-#define R300_VAP_PVS_UPLOAD_ADDRESS         0x2200
-#       define R300_PVS_UPLOAD_PROGRAM           0x00000000
-#       define R300_PVS_UPLOAD_PARAMETERS        0x00000200
-#       define R300_PVS_UPLOAD_POINTSIZE         0x00000406
-
-/* gap */
-
-#define R300_VAP_PVS_UPLOAD_DATA            0x2208
-
-/* END: Upload vertex program and data */
-
-/* gap */
-
-/* I do not know the purpose of this register. However, I do know that
- * it is set to 221C_CLEAR for clear operations and to 221C_NORMAL
- * for normal rendering.
- */
-#define R300_VAP_UNKNOWN_221C               0x221C
-#       define R300_221C_NORMAL                  0x00000000
-#       define R300_221C_CLEAR                   0x0001C000
-
-/* These seem to be per-pixel and per-vertex X and Y clipping planes. The first
- * plane is per-pixel and the second plane is per-vertex.
- *
- * This was determined by experimentation alone but I believe it is correct.
- *
- * These registers are called X_QUAD0_1_FL to X_QUAD0_4_FL by glxtest.
- */
-#define R300_VAP_CLIP_X_0                   0x2220
-#define R300_VAP_CLIP_X_1                   0x2224
-#define R300_VAP_CLIP_Y_0                   0x2228
-#define R300_VAP_CLIP_Y_1                   0x2230
-
-/* gap */
-
-/* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between
- * rendering commands and overwriting vertex program parameters.
- * Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
- * avoids bugs caused by still running shaders reading bad data from memory.
- */
-#define R300_VAP_PVS_WAITIDLE               0x2284 /* GUESS */
-
-/* Absolutely no clue what this register is about. */
-#define R300_VAP_UNKNOWN_2288               0x2288
-#       define R300_2288_R300                    0x00750000 /* -- nh */
-#       define R300_2288_RV350                   0x0000FFFF /* -- Vladimir */
-
-/* gap */
-
-/* Addresses are relative to the vertex program instruction area of the
- * memory bank. PROGRAM_END points to the last instruction of the active
- * program
- *
- * The meaning of the two UNKNOWN fields is obviously not known. However,
- * experiments so far have shown that both *must* point to an instruction
- * inside the vertex program, otherwise the GPU locks up.
- *
- * fglrx usually sets CNTL_3_UNKNOWN to the end of the program and
- * R300_PVS_CNTL_1_POS_END_SHIFT points to instruction where last write to
- * position takes place.
- *
- * Most likely this is used to ignore rest of the program in cases
- * where group of verts arent visible. For some reason this "section"
- * is sometimes accepted other instruction that have no relationship with
- * position calculations.
- */
-#define R300_VAP_PVS_CNTL_1                 0x22D0
-#       define R300_PVS_CNTL_1_PROGRAM_START_SHIFT   0
-#       define R300_PVS_CNTL_1_POS_END_SHIFT         10
-#       define R300_PVS_CNTL_1_PROGRAM_END_SHIFT     20
-/* Addresses are relative the the vertex program parameters area. */
-#define R300_VAP_PVS_CNTL_2                 0x22D4
-#       define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0
-#       define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT  16
-#define R300_VAP_PVS_CNTL_3               0x22D8
-#       define R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT 10
-#       define R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT 0
-
-/* The entire range from 0x2300 to 0x2AC inclusive seems to be used for
- * immediate vertices
- */
-#define R300_VAP_VTX_COLOR_R                0x2464
-#define R300_VAP_VTX_COLOR_G                0x2468
-#define R300_VAP_VTX_COLOR_B                0x246C
-#define R300_VAP_VTX_POS_0_X_1              0x2490 /* used for glVertex2*() */
-#define R300_VAP_VTX_POS_0_Y_1              0x2494
-#define R300_VAP_VTX_COLOR_PKD              0x249C /* RGBA */
-#define R300_VAP_VTX_POS_0_X_2              0x24A0 /* used for glVertex3*() */
-#define R300_VAP_VTX_POS_0_Y_2              0x24A4
-#define R300_VAP_VTX_POS_0_Z_2              0x24A8
-/* write 0 to indicate end of packet? */
-#define R300_VAP_VTX_END_OF_PKT             0x24AC
-
-/* gap */
-
-/* These are values from r300_reg/r300_reg.h - they are known to be correct
- * and are here so we can use one register file instead of several
- * - Vladimir
- */
-#define R300_GB_VAP_RASTER_VTX_FMT_0   0x4000
-#      define R300_GB_VAP_RASTER_VTX_FMT_0__POS_PRESENT        (1<<0)
-#      define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_0_PRESENT    (1<<1)
-#      define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_1_PRESENT    (1<<2)
-#      define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_2_PRESENT    (1<<3)
-#      define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_3_PRESENT    (1<<4)
-#      define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_SPACE        (0xf<<5)
-#      define R300_GB_VAP_RASTER_VTX_FMT_0__PT_SIZE_PRESENT    (0x1<<16)
-
-#define R300_GB_VAP_RASTER_VTX_FMT_1   0x4004
-       /* each of the following is 3 bits wide, specifies number
-          of components */
-#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT       0
-#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT       3
-#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT       6
-#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT       9
-#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT       12
-#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT       15
-#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT       18
-#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT       21
-
-/* UNK30 seems to enables point to quad transformation on textures
- * (or something closely related to that).
- * This bit is rather fatal at the time being due to lackings at pixel
- * shader side
- */
-#define R300_GB_ENABLE 0x4008
-#      define R300_GB_POINT_STUFF_ENABLE       (1<<0)
-#      define R300_GB_LINE_STUFF_ENABLE        (1<<1)
-#      define R300_GB_TRIANGLE_STUFF_ENABLE    (1<<2)
-#      define R300_GB_STENCIL_AUTO_ENABLE      (1<<4)
-#      define R300_GB_UNK31                    (1<<31)
-       /* each of the following is 2 bits wide */
-#define R300_GB_TEX_REPLICATE  0
-#define R300_GB_TEX_ST         1
-#define R300_GB_TEX_STR                2
-#      define R300_GB_TEX0_SOURCE_SHIFT        16
-#      define R300_GB_TEX1_SOURCE_SHIFT        18
-#      define R300_GB_TEX2_SOURCE_SHIFT        20
-#      define R300_GB_TEX3_SOURCE_SHIFT        22
-#      define R300_GB_TEX4_SOURCE_SHIFT        24
-#      define R300_GB_TEX5_SOURCE_SHIFT        26
-#      define R300_GB_TEX6_SOURCE_SHIFT        28
-#      define R300_GB_TEX7_SOURCE_SHIFT        30
-
-/* MSPOS - positions for multisample antialiasing (?) */
-#define R300_GB_MSPOS0 0x4010
-       /* shifts - each of the fields is 4 bits */
-#      define R300_GB_MSPOS0__MS_X0_SHIFT      0
-#      define R300_GB_MSPOS0__MS_Y0_SHIFT      4
-#      define R300_GB_MSPOS0__MS_X1_SHIFT      8
-#      define R300_GB_MSPOS0__MS_Y1_SHIFT      12
-#      define R300_GB_MSPOS0__MS_X2_SHIFT      16
-#      define R300_GB_MSPOS0__MS_Y2_SHIFT      20
-#      define R300_GB_MSPOS0__MSBD0_Y          24
-#      define R300_GB_MSPOS0__MSBD0_X          28
-
-#define R300_GB_MSPOS1 0x4014
-#      define R300_GB_MSPOS1__MS_X3_SHIFT      0
-#      define R300_GB_MSPOS1__MS_Y3_SHIFT      4
-#      define R300_GB_MSPOS1__MS_X4_SHIFT      8
-#      define R300_GB_MSPOS1__MS_Y4_SHIFT      12
-#      define R300_GB_MSPOS1__MS_X5_SHIFT      16
-#      define R300_GB_MSPOS1__MS_Y5_SHIFT      20
-#      define R300_GB_MSPOS1__MSBD1            24
-
-
-#define R300_GB_TILE_CONFIG    0x4018
-#      define R300_GB_TILE_ENABLE      (1<<0)
-#      define R300_GB_TILE_PIPE_COUNT_RV300    0
-#      define R300_GB_TILE_PIPE_COUNT_R300     (3<<1)
-#      define R300_GB_TILE_PIPE_COUNT_R420     (7<<1)
-#      define R300_GB_TILE_PIPE_COUNT_RV410    (3<<1)
-#      define R300_GB_TILE_SIZE_8              0
-#      define R300_GB_TILE_SIZE_16             (1<<4)
-#      define R300_GB_TILE_SIZE_32             (2<<4)
-#      define R300_GB_SUPER_SIZE_1             (0<<6)
-#      define R300_GB_SUPER_SIZE_2             (1<<6)
-#      define R300_GB_SUPER_SIZE_4             (2<<6)
-#      define R300_GB_SUPER_SIZE_8             (3<<6)
-#      define R300_GB_SUPER_SIZE_16            (4<<6)
-#      define R300_GB_SUPER_SIZE_32            (5<<6)
-#      define R300_GB_SUPER_SIZE_64            (6<<6)
-#      define R300_GB_SUPER_SIZE_128           (7<<6)
-#      define R300_GB_SUPER_X_SHIFT            9       /* 3 bits wide */
-#      define R300_GB_SUPER_Y_SHIFT            12      /* 3 bits wide */
-#      define R300_GB_SUPER_TILE_A             0
-#      define R300_GB_SUPER_TILE_B             (1<<15)
-#      define R300_GB_SUBPIXEL_1_12            0
-#      define R300_GB_SUBPIXEL_1_16            (1<<16)
-
-#define R300_GB_FIFO_SIZE      0x4024
-       /* each of the following is 2 bits wide */
-#define R300_GB_FIFO_SIZE_32   0
-#define R300_GB_FIFO_SIZE_64   1
-#define R300_GB_FIFO_SIZE_128  2
-#define R300_GB_FIFO_SIZE_256  3
-#      define R300_SC_IFIFO_SIZE_SHIFT 0
-#      define R300_SC_TZFIFO_SIZE_SHIFT        2
-#      define R300_SC_BFIFO_SIZE_SHIFT 4
-
-#      define R300_US_OFIFO_SIZE_SHIFT 12
-#      define R300_US_WFIFO_SIZE_SHIFT 14
-       /* the following use the same constants as above, but meaning is
-          is times 2 (i.e. instead of 32 words it means 64 */
-#      define R300_RS_TFIFO_SIZE_SHIFT 6
-#      define R300_RS_CFIFO_SIZE_SHIFT 8
-#      define R300_US_RAM_SIZE_SHIFT           10
-       /* watermarks, 3 bits wide */
-#      define R300_RS_HIGHWATER_COL_SHIFT      16
-#      define R300_RS_HIGHWATER_TEX_SHIFT      19
-#      define R300_OFIFO_HIGHWATER_SHIFT       22      /* two bits only */
-#      define R300_CUBE_FIFO_HIGHWATER_COL_SHIFT       24
-
-#define R300_GB_SELECT 0x401C
-#      define R300_GB_FOG_SELECT_C0A           0
-#      define R300_GB_FOG_SELECT_C1A           1
-#      define R300_GB_FOG_SELECT_C2A           2
-#      define R300_GB_FOG_SELECT_C3A           3
-#      define R300_GB_FOG_SELECT_1_1_W 4
-#      define R300_GB_FOG_SELECT_Z             5
-#      define R300_GB_DEPTH_SELECT_Z           0
-#      define R300_GB_DEPTH_SELECT_1_1_W       (1<<3)
-#      define R300_GB_W_SELECT_1_W             0
-#      define R300_GB_W_SELECT_1               (1<<4)
-
-#define R300_GB_AA_CONFIG              0x4020
-#      define R300_AA_DISABLE                  0x00
-#      define R300_AA_ENABLE                   0x01
-#      define R300_AA_SUBSAMPLES_2             0
-#      define R300_AA_SUBSAMPLES_3             (1<<1)
-#      define R300_AA_SUBSAMPLES_4             (2<<1)
-#      define R300_AA_SUBSAMPLES_6             (3<<1)
-
-/* gap */
-
-/* Zero to flush caches. */
-#define R300_TX_CNTL                        0x4100
-#define R300_TX_FLUSH                       0x0
-
-/* The upper enable bits are guessed, based on fglrx reported limits. */
-#define R300_TX_ENABLE                      0x4104
-#       define R300_TX_ENABLE_0                  (1 << 0)
-#       define R300_TX_ENABLE_1                  (1 << 1)
-#       define R300_TX_ENABLE_2                  (1 << 2)
-#       define R300_TX_ENABLE_3                  (1 << 3)
-#       define R300_TX_ENABLE_4                  (1 << 4)
-#       define R300_TX_ENABLE_5                  (1 << 5)
-#       define R300_TX_ENABLE_6                  (1 << 6)
-#       define R300_TX_ENABLE_7                  (1 << 7)
-#       define R300_TX_ENABLE_8                  (1 << 8)
-#       define R300_TX_ENABLE_9                  (1 << 9)
-#       define R300_TX_ENABLE_10                 (1 << 10)
-#       define R300_TX_ENABLE_11                 (1 << 11)
-#       define R300_TX_ENABLE_12                 (1 << 12)
-#       define R300_TX_ENABLE_13                 (1 << 13)
-#       define R300_TX_ENABLE_14                 (1 << 14)
-#       define R300_TX_ENABLE_15                 (1 << 15)
-
-/* The pointsize is given in multiples of 6. The pointsize can be
- * enormous: Clear() renders a single point that fills the entire
- * framebuffer.
- */
-#define R300_RE_POINTSIZE                   0x421C
-#       define R300_POINTSIZE_Y_SHIFT            0
-#       define R300_POINTSIZE_Y_MASK             (0xFFFF << 0) /* GUESS */
-#       define R300_POINTSIZE_X_SHIFT            16
-#       define R300_POINTSIZE_X_MASK             (0xFFFF << 16) /* GUESS */
-#       define R300_POINTSIZE_MAX             (R300_POINTSIZE_Y_MASK / 6)
-
-/* The line width is given in multiples of 6.
- * In default mode lines are classified as vertical lines.
- * HO: horizontal
- * VE: vertical or horizontal
- * HO & VE: no classification
- */
-#define R300_RE_LINE_CNT                      0x4234
-#       define R300_LINESIZE_SHIFT            0
-#       define R300_LINESIZE_MASK             (0xFFFF << 0) /* GUESS */
-#       define R300_LINESIZE_MAX             (R300_LINESIZE_MASK / 6)
-#       define R300_LINE_CNT_HO               (1 << 16)
-#       define R300_LINE_CNT_VE               (1 << 17)
-
-/* Some sort of scale or clamp value for texcoordless textures. */
-#define R300_RE_UNK4238                       0x4238
-
-/* Something shade related */
-#define R300_RE_SHADE                         0x4274
-
-#define R300_RE_SHADE_MODEL                   0x4278
-#      define R300_RE_SHADE_MODEL_SMOOTH     0x3aaaa
-#      define R300_RE_SHADE_MODEL_FLAT       0x39595
-
-/* Dangerous */
-#define R300_RE_POLYGON_MODE                  0x4288
-#      define R300_PM_ENABLED                (1 << 0)
-#      define R300_PM_FRONT_POINT            (0 << 0)
-#      define R300_PM_BACK_POINT             (0 << 0)
-#      define R300_PM_FRONT_LINE             (1 << 4)
-#      define R300_PM_FRONT_FILL             (1 << 5)
-#      define R300_PM_BACK_LINE              (1 << 7)
-#      define R300_PM_BACK_FILL              (1 << 8)
-
-/* Fog parameters */
-#define R300_RE_FOG_SCALE                     0x4294
-#define R300_RE_FOG_START                     0x4298
-
-/* Not sure why there are duplicate of factor and constant values.
- * My best guess so far is that there are separate zbiases for test and write.
- * Ordering might be wrong.
- * Some of the tests indicate that fgl has a fallback implementation of zbias
- * via pixel shaders.
- */
-#define R300_RE_ZBIAS_CNTL                    0x42A0 /* GUESS */
-#define R300_RE_ZBIAS_T_FACTOR                0x42A4
-#define R300_RE_ZBIAS_T_CONSTANT              0x42A8
-#define R300_RE_ZBIAS_W_FACTOR                0x42AC
-#define R300_RE_ZBIAS_W_CONSTANT              0x42B0
-
-/* This register needs to be set to (1<<1) for RV350 to correctly
- * perform depth test (see --vb-triangles in r300_demo)
- * Don't know about other chips. - Vladimir
- * This is set to 3 when GL_POLYGON_OFFSET_FILL is on.
- * My guess is that there are two bits for each zbias primitive
- * (FILL, LINE, POINT).
- *  One to enable depth test and one for depth write.
- * Yet this doesnt explain why depth writes work ...
- */
-#define R300_RE_OCCLUSION_CNTL             0x42B4
-#      define R300_OCCLUSION_ON                (1<<1)
-
-#define R300_RE_CULL_CNTL                   0x42B8
-#       define R300_CULL_FRONT                   (1 << 0)
-#       define R300_CULL_BACK                    (1 << 1)
-#       define R300_FRONT_FACE_CCW               (0 << 2)
-#       define R300_FRONT_FACE_CW                (1 << 2)
-
-
-/* BEGIN: Rasterization / Interpolators - many guesses */
-
-/* 0_UNKNOWN_18 has always been set except for clear operations.
- * TC_CNT is the number of incoming texture coordinate sets (i.e. it depends
- * on the vertex program, *not* the fragment program)
- */
-#define R300_RS_CNTL_0                      0x4300
-#       define R300_RS_CNTL_TC_CNT_SHIFT         2
-#       define R300_RS_CNTL_TC_CNT_MASK          (7 << 2)
-       /* number of color interpolators used */
-#      define R300_RS_CNTL_CI_CNT_SHIFT         7
-#       define R300_RS_CNTL_0_UNKNOWN_18         (1 << 18)
-       /* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n
-          register. */
-#define R300_RS_CNTL_1                      0x4304
-
-/* gap */
-
-/* Only used for texture coordinates.
- * Use the source field to route texture coordinate input from the
- * vertex program to the desired interpolator. Note that the source
- * field is relative to the outputs the vertex program *actually*
- * writes. If a vertex program only writes texcoord[1], this will
- * be source index 0.
- * Set INTERP_USED on all interpolators that produce data used by
- * the fragment program. INTERP_USED looks like a swizzling mask,
- * but I haven't seen it used that way.
- *
- * Note: The _UNKNOWN constants are always set in their respective
- * register. I don't know if this is necessary.
- */
-#define R300_RS_INTERP_0                    0x4310
-#define R300_RS_INTERP_1                    0x4314
-#       define R300_RS_INTERP_1_UNKNOWN          0x40
-#define R300_RS_INTERP_2                    0x4318
-#       define R300_RS_INTERP_2_UNKNOWN          0x80
-#define R300_RS_INTERP_3                    0x431C
-#       define R300_RS_INTERP_3_UNKNOWN          0xC0
-#define R300_RS_INTERP_4                    0x4320
-#define R300_RS_INTERP_5                    0x4324
-#define R300_RS_INTERP_6                    0x4328
-#define R300_RS_INTERP_7                    0x432C
-#       define R300_RS_INTERP_SRC_SHIFT          2
-#       define R300_RS_INTERP_SRC_MASK           (7 << 2)
-#       define R300_RS_INTERP_USED               0x00D10000
-
-/* These DWORDs control how vertex data is routed into fragment program
- * registers, after interpolators.
- */
-#define R300_RS_ROUTE_0                     0x4330
-#define R300_RS_ROUTE_1                     0x4334
-#define R300_RS_ROUTE_2                     0x4338
-#define R300_RS_ROUTE_3                     0x433C /* GUESS */
-#define R300_RS_ROUTE_4                     0x4340 /* GUESS */
-#define R300_RS_ROUTE_5                     0x4344 /* GUESS */
-#define R300_RS_ROUTE_6                     0x4348 /* GUESS */
-#define R300_RS_ROUTE_7                     0x434C /* GUESS */
-#       define R300_RS_ROUTE_SOURCE_INTERP_0     0
-#       define R300_RS_ROUTE_SOURCE_INTERP_1     1
-#       define R300_RS_ROUTE_SOURCE_INTERP_2     2
-#       define R300_RS_ROUTE_SOURCE_INTERP_3     3
-#       define R300_RS_ROUTE_SOURCE_INTERP_4     4
-#       define R300_RS_ROUTE_SOURCE_INTERP_5     5 /* GUESS */
-#       define R300_RS_ROUTE_SOURCE_INTERP_6     6 /* GUESS */
-#       define R300_RS_ROUTE_SOURCE_INTERP_7     7 /* GUESS */
-#       define R300_RS_ROUTE_ENABLE              (1 << 3) /* GUESS */
-#       define R300_RS_ROUTE_DEST_SHIFT          6
-#       define R300_RS_ROUTE_DEST_MASK           (31 << 6) /* GUESS */
-
-/* Special handling for color: When the fragment program uses color,
- * the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the
- * color register index.
- *
- * Apperently you may set the R300_RS_ROUTE_0_COLOR bit, but not provide any
- * R300_RS_ROUTE_0_COLOR_DEST value; this setup is used for clearing the state.
- * See r300_ioctl.c:r300EmitClearState. I'm not sure if this setup is strictly
- * correct or not. - Oliver.
- */
-#       define R300_RS_ROUTE_0_COLOR             (1 << 14)
-#       define R300_RS_ROUTE_0_COLOR_DEST_SHIFT  17
-#       define R300_RS_ROUTE_0_COLOR_DEST_MASK   (31 << 17) /* GUESS */
-/* As above, but for secondary color */
-#              define R300_RS_ROUTE_1_COLOR1            (1 << 14)
-#              define R300_RS_ROUTE_1_COLOR1_DEST_SHIFT 17
-#              define R300_RS_ROUTE_1_COLOR1_DEST_MASK  (31 << 17)
-#              define R300_RS_ROUTE_1_UNKNOWN11         (1 << 11)
-/* END: Rasterization / Interpolators - many guesses */
-
-/* Hierarchical Z Enable */
-#define R300_SC_HYPERZ                   0x43a4
-#      define R300_SC_HYPERZ_DISABLE     (0 << 0)
-#      define R300_SC_HYPERZ_ENABLE      (1 << 0)
-#      define R300_SC_HYPERZ_MIN         (0 << 1)
-#      define R300_SC_HYPERZ_MAX         (1 << 1)
-#      define R300_SC_HYPERZ_ADJ_256     (0 << 2)
-#      define R300_SC_HYPERZ_ADJ_128     (1 << 2)
-#      define R300_SC_HYPERZ_ADJ_64      (2 << 2)
-#      define R300_SC_HYPERZ_ADJ_32      (3 << 2)
-#      define R300_SC_HYPERZ_ADJ_16      (4 << 2)
-#      define R300_SC_HYPERZ_ADJ_8       (5 << 2)
-#      define R300_SC_HYPERZ_ADJ_4       (6 << 2)
-#      define R300_SC_HYPERZ_ADJ_2       (7 << 2)
-#      define R300_SC_HYPERZ_HZ_Z0MIN_NO (0 << 5)
-#      define R300_SC_HYPERZ_HZ_Z0MIN    (1 << 5)
-#      define R300_SC_HYPERZ_HZ_Z0MAX_NO (0 << 6)
-#      define R300_SC_HYPERZ_HZ_Z0MAX    (1 << 6)
-
-#define R300_SC_EDGERULE                 0x43a8
-
-/* BEGIN: Scissors and cliprects */
-
-/* There are four clipping rectangles. Their corner coordinates are inclusive.
- * Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending
- * on whether the pixel is inside cliprects 0-3, respectively. For example,
- * if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned
- * the number 3 (binary 0011).
- * Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set,
- * the pixel is rasterized.
- *
- * In addition to this, there is a scissors rectangle. Only pixels inside the
- * scissors rectangle are drawn. (coordinates are inclusive)
- *
- * For some reason, the top-left corner of the framebuffer is at (1440, 1440)
- * for the purpose of clipping and scissors.
- */
-#define R300_RE_CLIPRECT_TL_0               0x43B0
-#define R300_RE_CLIPRECT_BR_0               0x43B4
-#define R300_RE_CLIPRECT_TL_1               0x43B8
-#define R300_RE_CLIPRECT_BR_1               0x43BC
-#define R300_RE_CLIPRECT_TL_2               0x43C0
-#define R300_RE_CLIPRECT_BR_2               0x43C4
-#define R300_RE_CLIPRECT_TL_3               0x43C8
-#define R300_RE_CLIPRECT_BR_3               0x43CC
-#       define R300_CLIPRECT_OFFSET              1440
-#       define R300_CLIPRECT_MASK                0x1FFF
-#       define R300_CLIPRECT_X_SHIFT             0
-#       define R300_CLIPRECT_X_MASK              (0x1FFF << 0)
-#       define R300_CLIPRECT_Y_SHIFT             13
-#       define R300_CLIPRECT_Y_MASK              (0x1FFF << 13)
-#define R300_RE_CLIPRECT_CNTL               0x43D0
-#       define R300_CLIP_OUT                     (1 << 0)
-#       define R300_CLIP_0                       (1 << 1)
-#       define R300_CLIP_1                       (1 << 2)
-#       define R300_CLIP_10                      (1 << 3)
-#       define R300_CLIP_2                       (1 << 4)
-#       define R300_CLIP_20                      (1 << 5)
-#       define R300_CLIP_21                      (1 << 6)
-#       define R300_CLIP_210                     (1 << 7)
-#       define R300_CLIP_3                       (1 << 8)
-#       define R300_CLIP_30                      (1 << 9)
-#       define R300_CLIP_31                      (1 << 10)
-#       define R300_CLIP_310                     (1 << 11)
-#       define R300_CLIP_32                      (1 << 12)
-#       define R300_CLIP_320                     (1 << 13)
-#       define R300_CLIP_321                     (1 << 14)
-#       define R300_CLIP_3210                    (1 << 15)
-
-/* gap */
-
-#define R300_RE_SCISSORS_TL                 0x43E0
-#define R300_RE_SCISSORS_BR                 0x43E4
-#       define R300_SCISSORS_OFFSET              1440
-#       define R300_SCISSORS_X_SHIFT             0
-#       define R300_SCISSORS_X_MASK              (0x1FFF << 0)
-#       define R300_SCISSORS_Y_SHIFT             13
-#       define R300_SCISSORS_Y_MASK              (0x1FFF << 13)
-/* END: Scissors and cliprects */
-
-/* BEGIN: Texture specification */
-
-/*
- * The texture specification dwords are grouped by meaning and not by texture
- * unit. This means that e.g. the offset for texture image unit N is found in
- * register TX_OFFSET_0 + (4*N)
- */
-#define R300_TX_FILTER_0                    0x4400
-#       define R300_TX_REPEAT                    0
-#       define R300_TX_MIRRORED                  1
-#       define R300_TX_CLAMP                     4
-#       define R300_TX_CLAMP_TO_EDGE             2
-#       define R300_TX_CLAMP_TO_BORDER           6
-#       define R300_TX_WRAP_S_SHIFT              0
-#       define R300_TX_WRAP_S_MASK               (7 << 0)
-#       define R300_TX_WRAP_T_SHIFT              3
-#       define R300_TX_WRAP_T_MASK               (7 << 3)
-#       define R300_TX_WRAP_Q_SHIFT              6
-#       define R300_TX_WRAP_Q_MASK               (7 << 6)
-#       define R300_TX_MAG_FILTER_NEAREST        (1 << 9)
-#       define R300_TX_MAG_FILTER_LINEAR         (2 << 9)
-#       define R300_TX_MAG_FILTER_MASK           (3 << 9)
-#       define R300_TX_MIN_FILTER_NEAREST        (1 << 11)
-#       define R300_TX_MIN_FILTER_LINEAR         (2 << 11)
-#      define R300_TX_MIN_FILTER_NEAREST_MIP_NEAREST       (5  <<  11)
-#      define R300_TX_MIN_FILTER_NEAREST_MIP_LINEAR        (9  <<  11)
-#      define R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST        (6  <<  11)
-#      define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR         (10 <<  11)
-
-/* NOTE: NEAREST doesnt seem to exist.
- * Im not seting MAG_FILTER_MASK and (3 << 11) on for all
- * anisotropy modes because that would void selected mag filter
- */
-#      define R300_TX_MIN_FILTER_ANISO_NEAREST             (0 << 13)
-#      define R300_TX_MIN_FILTER_ANISO_LINEAR              (0 << 13)
-#      define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (1 << 13)
-#      define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR  (2 << 13)
-#       define R300_TX_MIN_FILTER_MASK   ( (15 << 11) | (3 << 13) )
-#      define R300_TX_MAX_ANISO_1_TO_1  (0 << 21)
-#      define R300_TX_MAX_ANISO_2_TO_1  (2 << 21)
-#      define R300_TX_MAX_ANISO_4_TO_1  (4 << 21)
-#      define R300_TX_MAX_ANISO_8_TO_1  (6 << 21)
-#      define R300_TX_MAX_ANISO_16_TO_1 (8 << 21)
-#      define R300_TX_MAX_ANISO_MASK    (14 << 21)
-
-#define R300_TX_FILTER1_0                      0x4440
-#      define R300_CHROMA_KEY_MODE_DISABLE    0
-#      define R300_CHROMA_KEY_FORCE           1
-#      define R300_CHROMA_KEY_BLEND           2
-#      define R300_MC_ROUND_NORMAL            (0<<2)
-#      define R300_MC_ROUND_MPEG4             (1<<2)
-#      define R300_LOD_BIAS_MASK           0x1fff
-#      define R300_EDGE_ANISO_EDGE_DIAG       (0<<13)
-#      define R300_EDGE_ANISO_EDGE_ONLY       (1<<13)
-#      define R300_MC_COORD_TRUNCATE_DISABLE  (0<<14)
-#      define R300_MC_COORD_TRUNCATE_MPEG     (1<<14)
-#      define R300_TX_TRI_PERF_0_8            (0<<15)
-#      define R300_TX_TRI_PERF_1_8            (1<<15)
-#      define R300_TX_TRI_PERF_1_4            (2<<15)
-#      define R300_TX_TRI_PERF_3_8            (3<<15)
-#      define R300_ANISO_THRESHOLD_MASK       (7<<17)
-
-#define R300_TX_SIZE_0                      0x4480
-#       define R300_TX_WIDTHMASK_SHIFT           0
-#       define R300_TX_WIDTHMASK_MASK            (2047 << 0)
-#       define R300_TX_HEIGHTMASK_SHIFT          11
-#       define R300_TX_HEIGHTMASK_MASK           (2047 << 11)
-#       define R300_TX_UNK23                     (1 << 23)
-#       define R300_TX_MAX_MIP_LEVEL_SHIFT       26
-#       define R300_TX_MAX_MIP_LEVEL_MASK        (0xf << 26)
-#       define R300_TX_SIZE_PROJECTED            (1<<30)
-#       define R300_TX_SIZE_TXPITCH_EN           (1<<31)
-#define R300_TX_FORMAT_0                    0x44C0
-       /* The interpretation of the format word by Wladimir van der Laan */
-       /* The X, Y, Z and W refer to the layout of the components.
-          They are given meanings as R, G, B and Alpha by the swizzle
-          specification */
-#      define R300_TX_FORMAT_X8                    0x0
-#      define R300_TX_FORMAT_X16                   0x1
-#      define R300_TX_FORMAT_Y4X4                  0x2
-#      define R300_TX_FORMAT_Y8X8                  0x3
-#      define R300_TX_FORMAT_Y16X16                0x4
-#      define R300_TX_FORMAT_Z3Y3X2                0x5
-#      define R300_TX_FORMAT_Z5Y6X5                0x6
-#      define R300_TX_FORMAT_Z6Y5X5                0x7
-#      define R300_TX_FORMAT_Z11Y11X10             0x8
-#      define R300_TX_FORMAT_Z10Y11X11             0x9
-#      define R300_TX_FORMAT_W4Z4Y4X4              0xA
-#      define R300_TX_FORMAT_W1Z5Y5X5              0xB
-#      define R300_TX_FORMAT_W8Z8Y8X8              0xC
-#      define R300_TX_FORMAT_W2Z10Y10X10           0xD
-#      define R300_TX_FORMAT_W16Z16Y16X16          0xE
-#      define R300_TX_FORMAT_DXT1                  0xF
-#      define R300_TX_FORMAT_DXT3                  0x10
-#      define R300_TX_FORMAT_DXT5                  0x11
-#      define R300_TX_FORMAT_D3DMFT_CxV8U8         0x12     /* no swizzle */
-#      define R300_TX_FORMAT_A8R8G8B8              0x13     /* no swizzle */
-#      define R300_TX_FORMAT_B8G8_B8G8             0x14     /* no swizzle */
-#      define R300_TX_FORMAT_G8R8_G8B8             0x15     /* no swizzle */
-       /* 0x16 - some 16 bit green format.. ?? */
-#      define R300_TX_FORMAT_UNK25                (1 << 25) /* no swizzle */
-#      define R300_TX_FORMAT_CUBIC_MAP            (1 << 26)
-
-       /* gap */
-       /* Floating point formats */
-       /* Note - hardware supports both 16 and 32 bit floating point */
-#      define R300_TX_FORMAT_FL_I16                0x18
-#      define R300_TX_FORMAT_FL_I16A16             0x19
-#      define R300_TX_FORMAT_FL_R16G16B16A16       0x1A
-#      define R300_TX_FORMAT_FL_I32                0x1B
-#      define R300_TX_FORMAT_FL_I32A32             0x1C
-#      define R300_TX_FORMAT_FL_R32G32B32A32       0x1D
-       /* alpha modes, convenience mostly */
-       /* if you have alpha, pick constant appropriate to the
-          number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */
-#      define R300_TX_FORMAT_ALPHA_1CH             0x000
-#      define R300_TX_FORMAT_ALPHA_2CH             0x200
-#      define R300_TX_FORMAT_ALPHA_4CH             0x600
-#      define R300_TX_FORMAT_ALPHA_NONE            0xA00
-       /* Swizzling */
-       /* constants */
-#      define R300_TX_FORMAT_X         0
-#      define R300_TX_FORMAT_Y         1
-#      define R300_TX_FORMAT_Z         2
-#      define R300_TX_FORMAT_W         3
-#      define R300_TX_FORMAT_ZERO      4
-#      define R300_TX_FORMAT_ONE       5
-       /* 2.0*Z, everything above 1.0 is set to 0.0 */
-#      define R300_TX_FORMAT_CUT_Z     6
-       /* 2.0*W, everything above 1.0 is set to 0.0 */
-#      define R300_TX_FORMAT_CUT_W     7
-
-#      define R300_TX_FORMAT_B_SHIFT   18
-#      define R300_TX_FORMAT_G_SHIFT   15
-#      define R300_TX_FORMAT_R_SHIFT   12
-#      define R300_TX_FORMAT_A_SHIFT   9
-       /* Convenience macro to take care of layout and swizzling */
-#      define R300_EASY_TX_FORMAT(B, G, R, A, FMT)     (               \
-               ((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT)          \
-               | ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT)        \
-               | ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT)        \
-               | ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT)        \
-               | (R300_TX_FORMAT_##FMT)                                \
-               )
-       /* These can be ORed with result of R300_EASY_TX_FORMAT()
-          We don't really know what they do. Take values from a
-           constant color ? */
-#      define R300_TX_FORMAT_CONST_X           (1<<5)
-#      define R300_TX_FORMAT_CONST_Y           (2<<5)
-#      define R300_TX_FORMAT_CONST_Z           (4<<5)
-#      define R300_TX_FORMAT_CONST_W           (8<<5)
-
-#      define R300_TX_FORMAT_YUV_MODE          0x00800000
-
-#define R300_TX_PITCH_0                            0x4500 /* obvious missing in gap */
-#define R300_TX_OFFSET_0                    0x4540
-       /* BEGIN: Guess from R200 */
-#       define R300_TXO_ENDIAN_NO_SWAP           (0 << 0)
-#       define R300_TXO_ENDIAN_BYTE_SWAP         (1 << 0)
-#       define R300_TXO_ENDIAN_WORD_SWAP         (2 << 0)
-#       define R300_TXO_ENDIAN_HALFDW_SWAP       (3 << 0)
-#       define R300_TXO_MACRO_TILE               (1 << 2)
-#       define R300_TXO_MICRO_TILE               (1 << 3)
-#       define R300_TXO_OFFSET_MASK              0xffffffe0
-#       define R300_TXO_OFFSET_SHIFT             5
-       /* END: Guess from R200 */
-
-/* 32 bit chroma key */
-#define R300_TX_CHROMA_KEY_0                      0x4580
-/* ff00ff00 == { 0, 1.0, 0, 1.0 } */
-#define R300_TX_BORDER_COLOR_0              0x45C0
-
-/* END: Texture specification */
-
-/* BEGIN: Fragment program instruction set */
-
-/* Fragment programs are written directly into register space.
- * There are separate instruction streams for texture instructions and ALU
- * instructions.
- * In order to synchronize these streams, the program is divided into up
- * to 4 nodes. Each node begins with a number of TEX operations, followed
- * by a number of ALU operations.
- * The first node can have zero TEX ops, all subsequent nodes must have at
- * least
- * one TEX ops.
- * All nodes must have at least one ALU op.
- *
- * The index of the last node is stored in PFS_CNTL_0: A value of 0 means
- * 1 node, a value of 3 means 4 nodes.
- * The total amount of instructions is defined in PFS_CNTL_2. The offsets are
- * offsets into the respective instruction streams, while *_END points to the
- * last instruction relative to this offset.
- */
-#define R300_PFS_CNTL_0                     0x4600
-#       define R300_PFS_CNTL_LAST_NODES_SHIFT    0
-#       define R300_PFS_CNTL_LAST_NODES_MASK     (3 << 0)
-#       define R300_PFS_CNTL_FIRST_NODE_HAS_TEX  (1 << 3)
-#define R300_PFS_CNTL_1                     0x4604
-/* There is an unshifted value here which has so far always been equal to the
- * index of the highest used temporary register.
- */
-#define R300_PFS_CNTL_2                     0x4608
-#       define R300_PFS_CNTL_ALU_OFFSET_SHIFT    0
-#       define R300_PFS_CNTL_ALU_OFFSET_MASK     (63 << 0)
-#       define R300_PFS_CNTL_ALU_END_SHIFT       6
-#       define R300_PFS_CNTL_ALU_END_MASK        (63 << 6)
-#       define R300_PFS_CNTL_TEX_OFFSET_SHIFT    12
-#       define R300_PFS_CNTL_TEX_OFFSET_MASK     (31 << 12) /* GUESS */
-#       define R300_PFS_CNTL_TEX_END_SHIFT       18
-#       define R300_PFS_CNTL_TEX_END_MASK        (31 << 18) /* GUESS */
-
-/* gap */
-
-/* Nodes are stored backwards. The last active node is always stored in
- * PFS_NODE_3.
- * Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The
- * first node is stored in NODE_2, the second node is stored in NODE_3.
- *
- * Offsets are relative to the master offset from PFS_CNTL_2.
- */
-#define R300_PFS_NODE_0                     0x4610
-#define R300_PFS_NODE_1                     0x4614
-#define R300_PFS_NODE_2                     0x4618
-#define R300_PFS_NODE_3                     0x461C
-#       define R300_PFS_NODE_ALU_OFFSET_SHIFT    0
-#       define R300_PFS_NODE_ALU_OFFSET_MASK     (63 << 0)
-#       define R300_PFS_NODE_ALU_END_SHIFT       6
-#       define R300_PFS_NODE_ALU_END_MASK        (63 << 6)
-#       define R300_PFS_NODE_TEX_OFFSET_SHIFT    12
-#       define R300_PFS_NODE_TEX_OFFSET_MASK     (31 << 12)
-#       define R300_PFS_NODE_TEX_END_SHIFT       17
-#       define R300_PFS_NODE_TEX_END_MASK        (31 << 17)
-#              define R300_PFS_NODE_OUTPUT_COLOR        (1 << 22)
-#              define R300_PFS_NODE_OUTPUT_DEPTH        (1 << 23)
-
-/* TEX
- * As far as I can tell, texture instructions cannot write into output
- * registers directly. A subsequent ALU instruction is always necessary,
- * even if it's just MAD o0, r0, 1, 0
- */
-#define R300_PFS_TEXI_0                     0x4620
-#      define R300_FPITX_SRC_SHIFT              0
-#      define R300_FPITX_SRC_MASK               (31 << 0)
-       /* GUESS */
-#      define R300_FPITX_SRC_CONST              (1 << 5)
-#      define R300_FPITX_DST_SHIFT              6
-#      define R300_FPITX_DST_MASK               (31 << 6)
-#      define R300_FPITX_IMAGE_SHIFT            11
-       /* GUESS based on layout and native limits */
-#       define R300_FPITX_IMAGE_MASK             (15 << 11)
-/* Unsure if these are opcodes, or some kind of bitfield, but this is how
- * they were set when I checked
- */
-#      define R300_FPITX_OPCODE_SHIFT          15
-#              define R300_FPITX_OP_TEX        1
-#              define R300_FPITX_OP_KIL        2
-#              define R300_FPITX_OP_TXP        3
-#              define R300_FPITX_OP_TXB        4
-#      define R300_FPITX_OPCODE_MASK           (7 << 15)
-
-/* ALU
- * The ALU instructions register blocks are enumerated according to the order
- * in which fglrx. I assume there is space for 64 instructions, since
- * each block has space for a maximum of 64 DWORDs, and this matches reported
- * native limits.
- *
- * The basic functional block seems to be one MAD for each color and alpha,
- * and an adder that adds all components after the MUL.
- *  - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands
- *  - DP4: Use OUTC_DP4, OUTA_DP4
- *  - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands
- *  - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands
- *  - CMPH: If ARG2 > 0.5, return ARG0, else return ARG1
- *  - CMP: If ARG2 < 0, return ARG1, else return ARG0
- *  - FLR: use FRC+MAD
- *  - XPD: use MAD+MAD
- *  - SGE, SLT: use MAD+CMP
- *  - RSQ: use ABS modifier for argument
- *  - Use OUTC_REPL_ALPHA to write results of an alpha-only operation
- *    (e.g. RCP) into color register
- *  - apparently, there's no quick DST operation
- *  - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2"
- *  - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0"
- *  - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1"
- *
- * Operand selection
- * First stage selects three sources from the available registers and
- * constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha).
- * fglrx sorts the three source fields: Registers before constants,
- * lower indices before higher indices; I do not know whether this is
- * necessary.
- *
- * fglrx fills unused sources with "read constant 0"
- * According to specs, you cannot select more than two different constants.
- *
- * Second stage selects the operands from the sources. This is defined in
- * INSTR0 (color) and INSTR2 (alpha). You can also select the special constants
- * zero and one.
- * Swizzling and negation happens in this stage, as well.
- *
- * Important: Color and alpha seem to be mostly separate, i.e. their sources
- * selection appears to be fully independent (the register storage is probably
- * physically split into a color and an alpha section).
- * However (because of the apparent physical split), there is some interaction
- * WRT swizzling. If, for example, you want to load an R component into an
- * Alpha operand, this R component is taken from a *color* source, not from
- * an alpha source. The corresponding register doesn't even have to appear in
- * the alpha sources list. (I hope this all makes sense to you)
- *
- * Destination selection
- * The destination register index is in FPI1 (color) and FPI3 (alpha)
- * together with enable bits.
- * There are separate enable bits for writing into temporary registers
- * (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_*
- * /DSTA_OUTPUT). You can write to both at once, or not write at all (the
- * same index must be used for both).
- *
- * Note: There is a special form for LRP
- *  - Argument order is the same as in ARB_fragment_program.
- *  - Operation is MAD
- *  - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP
- *  - Set FPI0/FPI2_SPECIAL_LRP
- * Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD
- */
-#define R300_PFS_INSTR1_0                   0x46C0
-#       define R300_FPI1_SRC0C_SHIFT             0
-#       define R300_FPI1_SRC0C_MASK              (31 << 0)
-#       define R300_FPI1_SRC0C_CONST             (1 << 5)
-#       define R300_FPI1_SRC1C_SHIFT             6
-#       define R300_FPI1_SRC1C_MASK              (31 << 6)
-#       define R300_FPI1_SRC1C_CONST             (1 << 11)
-#       define R300_FPI1_SRC2C_SHIFT             12
-#       define R300_FPI1_SRC2C_MASK              (31 << 12)
-#       define R300_FPI1_SRC2C_CONST             (1 << 17)
-#       define R300_FPI1_SRC_MASK                0x0003ffff
-#       define R300_FPI1_DSTC_SHIFT              18
-#       define R300_FPI1_DSTC_MASK               (31 << 18)
-#              define R300_FPI1_DSTC_REG_MASK_SHIFT     23
-#       define R300_FPI1_DSTC_REG_X              (1 << 23)
-#       define R300_FPI1_DSTC_REG_Y              (1 << 24)
-#       define R300_FPI1_DSTC_REG_Z              (1 << 25)
-#              define R300_FPI1_DSTC_OUTPUT_MASK_SHIFT  26
-#       define R300_FPI1_DSTC_OUTPUT_X           (1 << 26)
-#       define R300_FPI1_DSTC_OUTPUT_Y           (1 << 27)
-#       define R300_FPI1_DSTC_OUTPUT_Z           (1 << 28)
-
-#define R300_PFS_INSTR3_0                   0x47C0
-#       define R300_FPI3_SRC0A_SHIFT             0
-#       define R300_FPI3_SRC0A_MASK              (31 << 0)
-#       define R300_FPI3_SRC0A_CONST             (1 << 5)
-#       define R300_FPI3_SRC1A_SHIFT             6
-#       define R300_FPI3_SRC1A_MASK              (31 << 6)
-#       define R300_FPI3_SRC1A_CONST             (1 << 11)
-#       define R300_FPI3_SRC2A_SHIFT             12
-#       define R300_FPI3_SRC2A_MASK              (31 << 12)
-#       define R300_FPI3_SRC2A_CONST             (1 << 17)
-#       define R300_FPI3_SRC_MASK                0x0003ffff
-#       define R300_FPI3_DSTA_SHIFT              18
-#       define R300_FPI3_DSTA_MASK               (31 << 18)
-#       define R300_FPI3_DSTA_REG                (1 << 23)
-#       define R300_FPI3_DSTA_OUTPUT             (1 << 24)
-#              define R300_FPI3_DSTA_DEPTH              (1 << 27)
-
-#define R300_PFS_INSTR0_0                   0x48C0
-#       define R300_FPI0_ARGC_SRC0C_XYZ          0
-#       define R300_FPI0_ARGC_SRC0C_XXX          1
-#       define R300_FPI0_ARGC_SRC0C_YYY          2
-#       define R300_FPI0_ARGC_SRC0C_ZZZ          3
-#       define R300_FPI0_ARGC_SRC1C_XYZ          4
-#       define R300_FPI0_ARGC_SRC1C_XXX          5
-#       define R300_FPI0_ARGC_SRC1C_YYY          6
-#       define R300_FPI0_ARGC_SRC1C_ZZZ          7
-#       define R300_FPI0_ARGC_SRC2C_XYZ          8
-#       define R300_FPI0_ARGC_SRC2C_XXX          9
-#       define R300_FPI0_ARGC_SRC2C_YYY          10
-#       define R300_FPI0_ARGC_SRC2C_ZZZ          11
-#       define R300_FPI0_ARGC_SRC0A              12
-#       define R300_FPI0_ARGC_SRC1A              13
-#       define R300_FPI0_ARGC_SRC2A              14
-#       define R300_FPI0_ARGC_SRC1C_LRP          15
-#       define R300_FPI0_ARGC_ZERO               20
-#       define R300_FPI0_ARGC_ONE                21
-       /* GUESS */
-#       define R300_FPI0_ARGC_HALF               22
-#       define R300_FPI0_ARGC_SRC0C_YZX          23
-#       define R300_FPI0_ARGC_SRC1C_YZX          24
-#       define R300_FPI0_ARGC_SRC2C_YZX          25
-#       define R300_FPI0_ARGC_SRC0C_ZXY          26
-#       define R300_FPI0_ARGC_SRC1C_ZXY          27
-#       define R300_FPI0_ARGC_SRC2C_ZXY          28
-#       define R300_FPI0_ARGC_SRC0CA_WZY         29
-#       define R300_FPI0_ARGC_SRC1CA_WZY         30
-#       define R300_FPI0_ARGC_SRC2CA_WZY         31
-
-#       define R300_FPI0_ARG0C_SHIFT             0
-#       define R300_FPI0_ARG0C_MASK              (31 << 0)
-#       define R300_FPI0_ARG0C_NEG               (1 << 5)
-#       define R300_FPI0_ARG0C_ABS               (1 << 6)
-#       define R300_FPI0_ARG1C_SHIFT             7
-#       define R300_FPI0_ARG1C_MASK              (31 << 7)
-#       define R300_FPI0_ARG1C_NEG               (1 << 12)
-#       define R300_FPI0_ARG1C_ABS               (1 << 13)
-#       define R300_FPI0_ARG2C_SHIFT             14
-#       define R300_FPI0_ARG2C_MASK              (31 << 14)
-#       define R300_FPI0_ARG2C_NEG               (1 << 19)
-#       define R300_FPI0_ARG2C_ABS               (1 << 20)
-#       define R300_FPI0_SPECIAL_LRP             (1 << 21)
-#       define R300_FPI0_OUTC_MAD                (0 << 23)
-#       define R300_FPI0_OUTC_DP3                (1 << 23)
-#       define R300_FPI0_OUTC_DP4                (2 << 23)
-#       define R300_FPI0_OUTC_MIN                (4 << 23)
-#       define R300_FPI0_OUTC_MAX                (5 << 23)
-#       define R300_FPI0_OUTC_CMPH               (7 << 23)
-#       define R300_FPI0_OUTC_CMP                (8 << 23)
-#       define R300_FPI0_OUTC_FRC                (9 << 23)
-#       define R300_FPI0_OUTC_REPL_ALPHA         (10 << 23)
-#       define R300_FPI0_OUTC_SAT                (1 << 30)
-#       define R300_FPI0_INSERT_NOP              (1 << 31)
-
-#define R300_PFS_INSTR2_0                   0x49C0
-#       define R300_FPI2_ARGA_SRC0C_X            0
-#       define R300_FPI2_ARGA_SRC0C_Y            1
-#       define R300_FPI2_ARGA_SRC0C_Z            2
-#       define R300_FPI2_ARGA_SRC1C_X            3
-#       define R300_FPI2_ARGA_SRC1C_Y            4
-#       define R300_FPI2_ARGA_SRC1C_Z            5
-#       define R300_FPI2_ARGA_SRC2C_X            6
-#       define R300_FPI2_ARGA_SRC2C_Y            7
-#       define R300_FPI2_ARGA_SRC2C_Z            8
-#       define R300_FPI2_ARGA_SRC0A              9
-#       define R300_FPI2_ARGA_SRC1A              10
-#       define R300_FPI2_ARGA_SRC2A              11
-#       define R300_FPI2_ARGA_SRC1A_LRP          15
-#       define R300_FPI2_ARGA_ZERO               16
-#       define R300_FPI2_ARGA_ONE                17
-       /* GUESS */
-#       define R300_FPI2_ARGA_HALF               18
-#       define R300_FPI2_ARG0A_SHIFT             0
-#       define R300_FPI2_ARG0A_MASK              (31 << 0)
-#       define R300_FPI2_ARG0A_NEG               (1 << 5)
-       /* GUESS */
-#      define R300_FPI2_ARG0A_ABS               (1 << 6)
-#       define R300_FPI2_ARG1A_SHIFT             7
-#       define R300_FPI2_ARG1A_MASK              (31 << 7)
-#       define R300_FPI2_ARG1A_NEG               (1 << 12)
-       /* GUESS */
-#      define R300_FPI2_ARG1A_ABS               (1 << 13)
-#       define R300_FPI2_ARG2A_SHIFT             14
-#       define R300_FPI2_ARG2A_MASK              (31 << 14)
-#       define R300_FPI2_ARG2A_NEG               (1 << 19)
-       /* GUESS */
-#      define R300_FPI2_ARG2A_ABS               (1 << 20)
-#       define R300_FPI2_SPECIAL_LRP             (1 << 21)
-#       define R300_FPI2_OUTA_MAD                (0 << 23)
-#       define R300_FPI2_OUTA_DP4                (1 << 23)
-#       define R300_FPI2_OUTA_MIN                (2 << 23)
-#       define R300_FPI2_OUTA_MAX                (3 << 23)
-#       define R300_FPI2_OUTA_CMP                (6 << 23)
-#       define R300_FPI2_OUTA_FRC                (7 << 23)
-#       define R300_FPI2_OUTA_EX2                (8 << 23)
-#       define R300_FPI2_OUTA_LG2                (9 << 23)
-#       define R300_FPI2_OUTA_RCP                (10 << 23)
-#       define R300_FPI2_OUTA_RSQ                (11 << 23)
-#       define R300_FPI2_OUTA_SAT                (1 << 30)
-#       define R300_FPI2_UNKNOWN_31              (1 << 31)
-/* END: Fragment program instruction set */
-
-/* Fog state and color */
-#define R300_RE_FOG_STATE                   0x4BC0
-#       define R300_FOG_ENABLE                   (1 << 0)
-#      define R300_FOG_MODE_LINEAR              (0 << 1)
-#      define R300_FOG_MODE_EXP                 (1 << 1)
-#      define R300_FOG_MODE_EXP2                (2 << 1)
-#      define R300_FOG_MODE_MASK                (3 << 1)
-#define R300_FOG_COLOR_R                    0x4BC8
-#define R300_FOG_COLOR_G                    0x4BCC
-#define R300_FOG_COLOR_B                    0x4BD0
-
-#define R300_PP_ALPHA_TEST                  0x4BD4
-#       define R300_REF_ALPHA_MASK               0x000000ff
-#       define R300_ALPHA_TEST_FAIL              (0 << 8)
-#       define R300_ALPHA_TEST_LESS              (1 << 8)
-#       define R300_ALPHA_TEST_LEQUAL            (3 << 8)
-#       define R300_ALPHA_TEST_EQUAL             (2 << 8)
-#       define R300_ALPHA_TEST_GEQUAL            (6 << 8)
-#       define R300_ALPHA_TEST_GREATER           (4 << 8)
-#       define R300_ALPHA_TEST_NEQUAL            (5 << 8)
-#       define R300_ALPHA_TEST_PASS              (7 << 8)
-#       define R300_ALPHA_TEST_OP_MASK           (7 << 8)
-#       define R300_ALPHA_TEST_ENABLE            (1 << 11)
-
-/* gap */
-
-/* Fragment program parameters in 7.16 floating point */
-#define R300_PFS_PARAM_0_X                  0x4C00
-#define R300_PFS_PARAM_0_Y                  0x4C04
-#define R300_PFS_PARAM_0_Z                  0x4C08
-#define R300_PFS_PARAM_0_W                  0x4C0C
-/* GUESS: PARAM_31 is last, based on native limits reported by fglrx */
-#define R300_PFS_PARAM_31_X                 0x4DF0
-#define R300_PFS_PARAM_31_Y                 0x4DF4
-#define R300_PFS_PARAM_31_Z                 0x4DF8
-#define R300_PFS_PARAM_31_W                 0x4DFC
-
-/* Notes:
- * - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in
- *   the application
- * - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND
- *    are set to the same
- *   function (both registers are always set up completely in any case)
- * - Most blend flags are simply copied from R200 and not tested yet
- */
-#define R300_RB3D_CBLEND                    0x4E04
-#define R300_RB3D_ABLEND                    0x4E08
-/* the following only appear in CBLEND */
-#       define R300_BLEND_ENABLE                     (1 << 0)
-#       define R300_BLEND_UNKNOWN                    (3 << 1)
-#       define R300_BLEND_NO_SEPARATE                (1 << 3)
-/* the following are shared between CBLEND and ABLEND */
-#       define R300_FCN_MASK                         (3  << 12)
-#       define R300_COMB_FCN_ADD_CLAMP               (0  << 12)
-#       define R300_COMB_FCN_ADD_NOCLAMP             (1  << 12)
-#       define R300_COMB_FCN_SUB_CLAMP               (2  << 12)
-#       define R300_COMB_FCN_SUB_NOCLAMP             (3  << 12)
-#       define R300_COMB_FCN_MIN                     (4  << 12)
-#       define R300_COMB_FCN_MAX                     (5  << 12)
-#       define R300_COMB_FCN_RSUB_CLAMP              (6  << 12)
-#       define R300_COMB_FCN_RSUB_NOCLAMP            (7  << 12)
-#       define R300_BLEND_GL_ZERO                    (32)
-#       define R300_BLEND_GL_ONE                     (33)
-#       define R300_BLEND_GL_SRC_COLOR               (34)
-#       define R300_BLEND_GL_ONE_MINUS_SRC_COLOR     (35)
-#       define R300_BLEND_GL_DST_COLOR               (36)
-#       define R300_BLEND_GL_ONE_MINUS_DST_COLOR     (37)
-#       define R300_BLEND_GL_SRC_ALPHA               (38)
-#       define R300_BLEND_GL_ONE_MINUS_SRC_ALPHA     (39)
-#       define R300_BLEND_GL_DST_ALPHA               (40)
-#       define R300_BLEND_GL_ONE_MINUS_DST_ALPHA     (41)
-#       define R300_BLEND_GL_SRC_ALPHA_SATURATE      (42)
-#       define R300_BLEND_GL_CONST_COLOR             (43)
-#       define R300_BLEND_GL_ONE_MINUS_CONST_COLOR   (44)
-#       define R300_BLEND_GL_CONST_ALPHA             (45)
-#       define R300_BLEND_GL_ONE_MINUS_CONST_ALPHA   (46)
-#       define R300_BLEND_MASK                       (63)
-#       define R300_SRC_BLEND_SHIFT                  (16)
-#       define R300_DST_BLEND_SHIFT                  (24)
-#define R300_RB3D_BLEND_COLOR               0x4E10
-#define R300_RB3D_COLORMASK                 0x4E0C
-#       define R300_COLORMASK0_B                 (1<<0)
-#       define R300_COLORMASK0_G                 (1<<1)
-#       define R300_COLORMASK0_R                 (1<<2)
-#       define R300_COLORMASK0_A                 (1<<3)
-
-/* gap */
-
-#define R300_RB3D_COLOROFFSET0              0x4E28
-#       define R300_COLOROFFSET_MASK             0xFFFFFFF0 /* GUESS */
-#define R300_RB3D_COLOROFFSET1              0x4E2C /* GUESS */
-#define R300_RB3D_COLOROFFSET2              0x4E30 /* GUESS */
-#define R300_RB3D_COLOROFFSET3              0x4E34 /* GUESS */
-
-/* gap */
-
-/* Bit 16: Larger tiles
- * Bit 17: 4x2 tiles
- * Bit 18: Extremely weird tile like, but some pixels duplicated?
- */
-#define R300_RB3D_COLORPITCH0               0x4E38
-#       define R300_COLORPITCH_MASK              0x00001FF8 /* GUESS */
-#       define R300_COLOR_TILE_ENABLE            (1 << 16) /* GUESS */
-#       define R300_COLOR_MICROTILE_ENABLE       (1 << 17) /* GUESS */
-#       define R300_COLOR_ENDIAN_NO_SWAP         (0 << 18) /* GUESS */
-#       define R300_COLOR_ENDIAN_WORD_SWAP       (1 << 18) /* GUESS */
-#       define R300_COLOR_ENDIAN_DWORD_SWAP      (2 << 18) /* GUESS */
-#       define R300_COLOR_FORMAT_RGB565          (2 << 22)
-#       define R300_COLOR_FORMAT_ARGB8888        (3 << 22)
-#define R300_RB3D_COLORPITCH1               0x4E3C /* GUESS */
-#define R300_RB3D_COLORPITCH2               0x4E40 /* GUESS */
-#define R300_RB3D_COLORPITCH3               0x4E44 /* GUESS */
-
-/* gap */
-
-/* Guess by Vladimir.
- * Set to 0A before 3D operations, set to 02 afterwards.
- */
-/*#define R300_RB3D_DSTCACHE_CTLSTAT          0x4E4C*/
-#       define R300_RB3D_DSTCACHE_UNKNOWN_02             0x00000002
-#       define R300_RB3D_DSTCACHE_UNKNOWN_0A             0x0000000A
-
-/* gap */
-/* There seems to be no "write only" setting, so use Z-test = ALWAYS
- * for this.
- * Bit (1<<8) is the "test" bit. so plain write is 6  - vd
- */
-#define R300_ZB_CNTL                             0x4F00
-#      define R300_STENCIL_ENABLE               (1 << 0)
-#      define R300_Z_ENABLE                     (1 << 1)
-#      define R300_Z_WRITE_ENABLE               (1 << 2)
-#      define R300_Z_SIGNED_COMPARE             (1 << 3)
-#      define R300_STENCIL_FRONT_BACK           (1 << 4)
-
-#define R300_ZB_ZSTENCILCNTL                   0x4f04
-       /* functions */
-#      define R300_ZS_NEVER                    0
-#      define R300_ZS_LESS                     1
-#      define R300_ZS_LEQUAL                   2
-#      define R300_ZS_EQUAL                    3
-#      define R300_ZS_GEQUAL                   4
-#      define R300_ZS_GREATER                  5
-#      define R300_ZS_NOTEQUAL                 6
-#      define R300_ZS_ALWAYS                   7
-#       define R300_ZS_MASK                     7
-       /* operations */
-#      define R300_ZS_KEEP                     0
-#      define R300_ZS_ZERO                     1
-#      define R300_ZS_REPLACE                  2
-#      define R300_ZS_INCR                     3
-#      define R300_ZS_DECR                     4
-#      define R300_ZS_INVERT                   5
-#      define R300_ZS_INCR_WRAP                6
-#      define R300_ZS_DECR_WRAP                7
-#      define R300_Z_FUNC_SHIFT                0
-       /* front and back refer to operations done for front
-          and back faces, i.e. separate stencil function support */
-#      define R300_S_FRONT_FUNC_SHIFT          3
-#      define R300_S_FRONT_SFAIL_OP_SHIFT      6
-#      define R300_S_FRONT_ZPASS_OP_SHIFT      9
-#      define R300_S_FRONT_ZFAIL_OP_SHIFT      12
-#      define R300_S_BACK_FUNC_SHIFT           15
-#      define R300_S_BACK_SFAIL_OP_SHIFT       18
-#      define R300_S_BACK_ZPASS_OP_SHIFT       21
-#      define R300_S_BACK_ZFAIL_OP_SHIFT       24
-
-#define R300_ZB_STENCILREFMASK                        0x4f08
-#      define R300_STENCILREF_SHIFT       0
-#      define R300_STENCILREF_MASK        0x000000ff
-#      define R300_STENCILMASK_SHIFT      8
-#      define R300_STENCILMASK_MASK       0x0000ff00
-#      define R300_STENCILWRITEMASK_SHIFT 16
-#      define R300_STENCILWRITEMASK_MASK  0x00ff0000
-
-/* gap */
-
-#define R300_ZB_FORMAT                             0x4f10
-#      define R300_DEPTHFORMAT_16BIT_INT_Z   (0 << 0)
-#      define R300_DEPTHFORMAT_16BIT_13E3    (1 << 0)
-#      define R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL   (2 << 0)
-/* reserved up to (15 << 0) */
-#      define R300_INVERT_13E3_LEADING_ONES  (0 << 4)
-#      define R300_INVERT_13E3_LEADING_ZEROS (1 << 4)
-
-#define R300_ZB_ZTOP                             0x4F14
-#      define R300_ZTOP_DISABLE                 (0 << 0)
-#      define R300_ZTOP_ENABLE                  (1 << 0)
-
-/* gap */
-
-#define R300_ZB_ZCACHE_CTLSTAT            0x4f18
-#       define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_NO_EFFECT      (0 << 0)
-#       define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE (1 << 0)
-#       define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_NO_EFFECT       (0 << 1)
-#       define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE            (1 << 1)
-#       define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_IDLE            (0 << 31)
-#       define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_BUSY            (1 << 31)
-
-#define R300_ZB_BW_CNTL                     0x4f1c
-#      define R300_HIZ_DISABLE                              (0 << 0)
-#      define R300_HIZ_ENABLE                               (1 << 0)
-#      define R300_HIZ_MIN                                  (0 << 1)
-#      define R300_HIZ_MAX                                  (1 << 1)
-#      define R300_FAST_FILL_DISABLE                        (0 << 2)
-#      define R300_FAST_FILL_ENABLE                         (1 << 2)
-#      define R300_RD_COMP_DISABLE                          (0 << 3)
-#      define R300_RD_COMP_ENABLE                           (1 << 3)
-#      define R300_WR_COMP_DISABLE                          (0 << 4)
-#      define R300_WR_COMP_ENABLE                           (1 << 4)
-#      define R300_ZB_CB_CLEAR_RMW                          (0 << 5)
-#      define R300_ZB_CB_CLEAR_CACHE_LINEAR                 (1 << 5)
-#      define R300_FORCE_COMPRESSED_STENCIL_VALUE_DISABLE   (0 << 6)
-#      define R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE    (1 << 6)
-
-#      define R500_ZEQUAL_OPTIMIZE_ENABLE                   (0 << 7)
-#      define R500_ZEQUAL_OPTIMIZE_DISABLE                  (1 << 7)
-#      define R500_SEQUAL_OPTIMIZE_ENABLE                   (0 << 8)
-#      define R500_SEQUAL_OPTIMIZE_DISABLE                  (1 << 8)
-
-#      define R500_BMASK_ENABLE                             (0 << 10)
-#      define R500_BMASK_DISABLE                            (1 << 10)
-#      define R500_HIZ_EQUAL_REJECT_DISABLE                 (0 << 11)
-#      define R500_HIZ_EQUAL_REJECT_ENABLE                  (1 << 11)
-#      define R500_HIZ_FP_EXP_BITS_DISABLE                  (0 << 12)
-#      define R500_HIZ_FP_EXP_BITS_1                        (1 << 12)
-#      define R500_HIZ_FP_EXP_BITS_2                        (2 << 12)
-#      define R500_HIZ_FP_EXP_BITS_3                        (3 << 12)
-#      define R500_HIZ_FP_EXP_BITS_4                        (4 << 12)
-#      define R500_HIZ_FP_EXP_BITS_5                        (5 << 12)
-#      define R500_HIZ_FP_INVERT_LEADING_ONES               (0 << 15)
-#      define R500_HIZ_FP_INVERT_LEADING_ZEROS              (1 << 15)
-#      define R500_TILE_OVERWRITE_RECOMPRESSION_ENABLE      (0 << 16)
-#      define R500_TILE_OVERWRITE_RECOMPRESSION_DISABLE     (1 << 16)
-#      define R500_CONTIGUOUS_6XAA_SAMPLES_ENABLE           (0 << 17)
-#      define R500_CONTIGUOUS_6XAA_SAMPLES_DISABLE          (1 << 17)
-#      define R500_PEQ_PACKING_DISABLE                      (0 << 18)
-#      define R500_PEQ_PACKING_ENABLE                       (1 << 18)
-#      define R500_COVERED_PTR_MASKING_DISABLE              (0 << 18)
-#      define R500_COVERED_PTR_MASKING_ENABLE               (1 << 18)
-
-
-/* gap */
-
-/* Z Buffer Address Offset.
- * Bits 31 to 5 are used for aligned Z buffer address offset for macro tiles.
- */
-#define R300_ZB_DEPTHOFFSET               0x4f20
-
-/* Z Buffer Pitch and Endian Control */
-#define R300_ZB_DEPTHPITCH                0x4f24
-#       define R300_DEPTHPITCH_MASK              0x00003FFC
-#       define R300_DEPTHMACROTILE_DISABLE      (0 << 16)
-#       define R300_DEPTHMACROTILE_ENABLE       (1 << 16)
-#       define R300_DEPTHMICROTILE_LINEAR       (0 << 17)
-#       define R300_DEPTHMICROTILE_TILED        (1 << 17)
-#       define R300_DEPTHMICROTILE_TILED_SQUARE (2 << 17)
-#       define R300_DEPTHENDIAN_NO_SWAP         (0 << 18)
-#       define R300_DEPTHENDIAN_WORD_SWAP       (1 << 18)
-#       define R300_DEPTHENDIAN_DWORD_SWAP      (2 << 18)
-#       define R300_DEPTHENDIAN_HALF_DWORD_SWAP (3 << 18)
-
-/* Z Buffer Clear Value */
-#define R300_ZB_DEPTHCLEARVALUE                  0x4f28
-
-#define R300_ZB_ZMASK_OFFSET                    0x4f30
-#define R300_ZB_ZMASK_PITCH                     0x4f34
-#define R300_ZB_ZMASK_WRINDEX                   0x4f38
-#define R300_ZB_ZMASK_DWORD                     0x4f3c
-#define R300_ZB_ZMASK_RDINDEX                   0x4f40
-
-/* Hierarchical Z Memory Offset */
-#define R300_ZB_HIZ_OFFSET                       0x4f44
-
-/* Hierarchical Z Write Index */
-#define R300_ZB_HIZ_WRINDEX                      0x4f48
-
-/* Hierarchical Z Data */
-#define R300_ZB_HIZ_DWORD                        0x4f4c
-
-/* Hierarchical Z Read Index */
-#define R300_ZB_HIZ_RDINDEX                      0x4f50
-
-/* Hierarchical Z Pitch */
-#define R300_ZB_HIZ_PITCH                        0x4f54
-
-/* Z Buffer Z Pass Counter Data */
-#define R300_ZB_ZPASS_DATA                       0x4f58
-
-/* Z Buffer Z Pass Counter Address */
-#define R300_ZB_ZPASS_ADDR                       0x4f5c
-
-/* Depth buffer X and Y coordinate offset */
-#define R300_ZB_DEPTHXY_OFFSET                   0x4f60
-#      define R300_DEPTHX_OFFSET_SHIFT  1
-#      define R300_DEPTHX_OFFSET_MASK   0x000007FE
-#      define R300_DEPTHY_OFFSET_SHIFT  17
-#      define R300_DEPTHY_OFFSET_MASK   0x07FE0000
-
-/* Sets the fifo sizes */
-#define R500_ZB_FIFO_SIZE                        0x4fd0
-#      define R500_OP_FIFO_SIZE_FULL   (0 << 0)
-#      define R500_OP_FIFO_SIZE_HALF   (1 << 0)
-#      define R500_OP_FIFO_SIZE_QUATER (2 << 0)
-#      define R500_OP_FIFO_SIZE_EIGTHS (4 << 0)
-
-/* Stencil Reference Value and Mask for backfacing quads */
-/* R300_ZB_STENCILREFMASK handles front face */
-#define R500_ZB_STENCILREFMASK_BF                0x4fd4
-#      define R500_STENCILREF_SHIFT       0
-#      define R500_STENCILREF_MASK        0x000000ff
-#      define R500_STENCILMASK_SHIFT      8
-#      define R500_STENCILMASK_MASK       0x0000ff00
-#      define R500_STENCILWRITEMASK_SHIFT 16
-#      define R500_STENCILWRITEMASK_MASK  0x00ff0000
-
-/* BEGIN: Vertex program instruction set */
-
-/* Every instruction is four dwords long:
- *  DWORD 0: output and opcode
- *  DWORD 1: first argument
- *  DWORD 2: second argument
- *  DWORD 3: third argument
- *
- * Notes:
- *  - ABS r, a is implemented as MAX r, a, -a
- *  - MOV is implemented as ADD to zero
- *  - XPD is implemented as MUL + MAD
- *  - FLR is implemented as FRC + ADD
- *  - apparently, fglrx tries to schedule instructions so that there is at
- *    least one instruction between the write to a temporary and the first
- *    read from said temporary; however, violations of this scheduling are
- *    allowed
- *  - register indices seem to be unrelated with OpenGL aliasing to
- *    conventional state
- *  - only one attribute and one parameter can be loaded at a time; however,
- *    the same attribute/parameter can be used for more than one argument
- *  - the second software argument for POW is the third hardware argument
- *    (no idea why)
- *  - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2
- *
- * There is some magic surrounding LIT:
- *   The single argument is replicated across all three inputs, but swizzled:
- *     First argument: xyzy
- *     Second argument: xyzx
- *     Third argument: xyzw
- *   Whenever the result is used later in the fragment program, fglrx forces
- *   x and w to be 1.0 in the input selection; I don't know whether this is
- *   strictly necessary
- */
-#define R300_VPI_OUT_OP_DOT                     (1 << 0)
-#define R300_VPI_OUT_OP_MUL                     (2 << 0)
-#define R300_VPI_OUT_OP_ADD                     (3 << 0)
-#define R300_VPI_OUT_OP_MAD                     (4 << 0)
-#define R300_VPI_OUT_OP_DST                     (5 << 0)
-#define R300_VPI_OUT_OP_FRC                     (6 << 0)
-#define R300_VPI_OUT_OP_MAX                     (7 << 0)
-#define R300_VPI_OUT_OP_MIN                     (8 << 0)
-#define R300_VPI_OUT_OP_SGE                     (9 << 0)
-#define R300_VPI_OUT_OP_SLT                     (10 << 0)
-       /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */
-#define R300_VPI_OUT_OP_UNK12                   (12 << 0)
-#define R300_VPI_OUT_OP_ARL                     (13 << 0)
-#define R300_VPI_OUT_OP_EXP                     (65 << 0)
-#define R300_VPI_OUT_OP_LOG                     (66 << 0)
-       /* Used in fog computations, scalar(scalar) */
-#define R300_VPI_OUT_OP_UNK67                   (67 << 0)
-#define R300_VPI_OUT_OP_LIT                     (68 << 0)
-#define R300_VPI_OUT_OP_POW                     (69 << 0)
-#define R300_VPI_OUT_OP_RCP                     (70 << 0)
-#define R300_VPI_OUT_OP_RSQ                     (72 << 0)
-       /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */
-#define R300_VPI_OUT_OP_UNK73                   (73 << 0)
-#define R300_VPI_OUT_OP_EX2                     (75 << 0)
-#define R300_VPI_OUT_OP_LG2                     (76 << 0)
-#define R300_VPI_OUT_OP_MAD_2                   (128 << 0)
-       /* all temps, vector(scalar, vector, vector) */
-#define R300_VPI_OUT_OP_UNK129                  (129 << 0)
-
-#define R300_VPI_OUT_REG_CLASS_TEMPORARY        (0 << 8)
-#define R300_VPI_OUT_REG_CLASS_ADDR             (1 << 8)
-#define R300_VPI_OUT_REG_CLASS_RESULT           (2 << 8)
-#define R300_VPI_OUT_REG_CLASS_MASK             (31 << 8)
-
-#define R300_VPI_OUT_REG_INDEX_SHIFT            13
-       /* GUESS based on fglrx native limits */
-#define R300_VPI_OUT_REG_INDEX_MASK             (31 << 13)
-
-#define R300_VPI_OUT_WRITE_X                    (1 << 20)
-#define R300_VPI_OUT_WRITE_Y                    (1 << 21)
-#define R300_VPI_OUT_WRITE_Z                    (1 << 22)
-#define R300_VPI_OUT_WRITE_W                    (1 << 23)
-
-#define R300_VPI_IN_REG_CLASS_TEMPORARY         (0 << 0)
-#define R300_VPI_IN_REG_CLASS_ATTRIBUTE         (1 << 0)
-#define R300_VPI_IN_REG_CLASS_PARAMETER         (2 << 0)
-#define R300_VPI_IN_REG_CLASS_NONE              (9 << 0)
-#define R300_VPI_IN_REG_CLASS_MASK              (31 << 0)
-
-#define R300_VPI_IN_REG_INDEX_SHIFT             5
-       /* GUESS based on fglrx native limits */
-#define R300_VPI_IN_REG_INDEX_MASK              (255 << 5)
-
-/* The R300 can select components from the input register arbitrarily.
- * Use the following constants, shifted by the component shift you
- * want to select
- */
-#define R300_VPI_IN_SELECT_X    0
-#define R300_VPI_IN_SELECT_Y    1
-#define R300_VPI_IN_SELECT_Z    2
-#define R300_VPI_IN_SELECT_W    3
-#define R300_VPI_IN_SELECT_ZERO 4
-#define R300_VPI_IN_SELECT_ONE  5
-#define R300_VPI_IN_SELECT_MASK 7
-
-#define R300_VPI_IN_X_SHIFT                     13
-#define R300_VPI_IN_Y_SHIFT                     16
-#define R300_VPI_IN_Z_SHIFT                     19
-#define R300_VPI_IN_W_SHIFT                     22
-
-#define R300_VPI_IN_NEG_X                       (1 << 25)
-#define R300_VPI_IN_NEG_Y                       (1 << 26)
-#define R300_VPI_IN_NEG_Z                       (1 << 27)
-#define R300_VPI_IN_NEG_W                       (1 << 28)
-/* END: Vertex program instruction set */
-
-/* BEGIN: Packet 3 commands */
-
-/* A primitive emission dword. */
-#define R300_PRIM_TYPE_NONE                     (0 << 0)
-#define R300_PRIM_TYPE_POINT                    (1 << 0)
-#define R300_PRIM_TYPE_LINE                     (2 << 0)
-#define R300_PRIM_TYPE_LINE_STRIP               (3 << 0)
-#define R300_PRIM_TYPE_TRI_LIST                 (4 << 0)
-#define R300_PRIM_TYPE_TRI_FAN                  (5 << 0)
-#define R300_PRIM_TYPE_TRI_STRIP                (6 << 0)
-#define R300_PRIM_TYPE_TRI_TYPE2                (7 << 0)
-#define R300_PRIM_TYPE_RECT_LIST                (8 << 0)
-#define R300_PRIM_TYPE_3VRT_POINT_LIST          (9 << 0)
-#define R300_PRIM_TYPE_3VRT_LINE_LIST           (10 << 0)
-       /* GUESS (based on r200) */
-#define R300_PRIM_TYPE_POINT_SPRITES            (11 << 0)
-#define R300_PRIM_TYPE_LINE_LOOP                (12 << 0)
-#define R300_PRIM_TYPE_QUADS                    (13 << 0)
-#define R300_PRIM_TYPE_QUAD_STRIP               (14 << 0)
-#define R300_PRIM_TYPE_POLYGON                  (15 << 0)
-#define R300_PRIM_TYPE_MASK                     0xF
-#define R300_PRIM_WALK_IND                      (1 << 4)
-#define R300_PRIM_WALK_LIST                     (2 << 4)
-#define R300_PRIM_WALK_RING                     (3 << 4)
-#define R300_PRIM_WALK_MASK                     (3 << 4)
-       /* GUESS (based on r200) */
-#define R300_PRIM_COLOR_ORDER_BGRA              (0 << 6)
-#define R300_PRIM_COLOR_ORDER_RGBA              (1 << 6)
-#define R300_PRIM_NUM_VERTICES_SHIFT            16
-#define R300_PRIM_NUM_VERTICES_MASK             0xffff
-
-/* Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
- * Two parameter dwords:
- * 0. The first parameter appears to be always 0
- * 1. The second parameter is a standard primitive emission dword.
- */
-#define R300_PACKET3_3D_DRAW_VBUF           0x00002800
-
-/* Specify the full set of vertex arrays as (address, stride).
- * The first parameter is the number of vertex arrays specified.
- * The rest of the command is a variable length list of blocks, where
- * each block is three dwords long and specifies two arrays.
- * The first dword of a block is split into two words, the lower significant
- * word refers to the first array, the more significant word to the second
- * array in the block.
- * The low byte of each word contains the size of an array entry in dwords,
- * the high byte contains the stride of the array.
- * The second dword of a block contains the pointer to the first array,
- * the third dword of a block contains the pointer to the second array.
- * Note that if the total number of arrays is odd, the third dword of
- * the last block is omitted.
- */
-#define R300_PACKET3_3D_LOAD_VBPNTR         0x00002F00
-
-#define R300_PACKET3_INDX_BUFFER            0x00003300
-#    define R300_EB_UNK1_SHIFT                      24
-#    define R300_EB_UNK1                    (0x80<<24)
-#    define R300_EB_UNK2                        0x0810
-#define R300_PACKET3_3D_DRAW_VBUF_2         0x00003400
-#define R300_PACKET3_3D_DRAW_INDX_2         0x00003600
-
-/* END: Packet 3 commands */
-
-
-/* Color formats for 2d packets
- */
-#define R300_CP_COLOR_FORMAT_CI8       2
-#define R300_CP_COLOR_FORMAT_ARGB1555  3
-#define R300_CP_COLOR_FORMAT_RGB565    4
-#define R300_CP_COLOR_FORMAT_ARGB8888  6
-#define R300_CP_COLOR_FORMAT_RGB332    7
-#define R300_CP_COLOR_FORMAT_RGB8      9
-#define R300_CP_COLOR_FORMAT_ARGB4444  15
-
-/*
- * CP type-3 packets
- */
-#define R300_CP_CMD_BITBLT_MULTI       0xC0009B00
-
-#define R500_VAP_INDEX_OFFSET          0x208c
-
-#define R500_GA_US_VECTOR_INDEX         0x4250
-#define R500_GA_US_VECTOR_DATA          0x4254
-
-#define R500_RS_IP_0                    0x4074
-#define R500_RS_INST_0                  0x4320
-
-#define R500_US_CONFIG                  0x4600
-
-#define R500_US_FC_CTRL                        0x4624
-#define R500_US_CODE_ADDR              0x4630
-
-#define R500_RB3D_COLOR_CLEAR_VALUE_AR  0x46c0
-#define R500_RB3D_CONSTANT_COLOR_AR     0x4ef8
-
-#endif /* _R300_REG_H */
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
deleted file mode 100644 (file)
index e53158f..0000000
+++ /dev/null
@@ -1,1773 +0,0 @@
-/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */
-/*
- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
- * Copyright 2007 Advanced Micro Devices, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Kevin E. Martin <martin@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "radeon_drm.h"
-#include "radeon_drv.h"
-#include "r300_reg.h"
-
-#include "radeon_microcode.h"
-
-#define RADEON_FIFO_DEBUG      0
-
-static int radeon_do_cleanup_cp(struct drm_device * dev);
-
-static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
-{
-       u32 ret;
-       RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff));
-       ret = RADEON_READ(R520_MC_IND_DATA);
-       RADEON_WRITE(R520_MC_IND_INDEX, 0);
-       return ret;
-}
-
-static u32 RS480_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
-{
-       u32 ret;
-       RADEON_WRITE(RS480_NB_MC_INDEX, addr & 0xff);
-       ret = RADEON_READ(RS480_NB_MC_DATA);
-       RADEON_WRITE(RS480_NB_MC_INDEX, 0xff);
-       return ret;
-}
-
-static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
-{
-       u32 ret;
-       RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK));
-       ret = RADEON_READ(RS690_MC_DATA);
-       RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_MASK);
-       return ret;
-}
-
-static u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
-{
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
-               return RS690_READ_MCIND(dev_priv, addr);
-       else
-               return RS480_READ_MCIND(dev_priv, addr);
-}
-
-u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv)
-{
-
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
-               return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION);
-       else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
-               return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION);
-       else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
-               return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION);
-       else
-               return RADEON_READ(RADEON_MC_FB_LOCATION);
-}
-
-static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc)
-{
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
-               R500_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc);
-       else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
-               RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc);
-       else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
-               R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc);
-       else
-               RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc);
-}
-
-static void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc)
-{
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
-               R500_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc);
-       else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
-               RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc);
-       else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
-               R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc);
-       else
-               RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc);
-}
-
-static void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base)
-{
-       u32 agp_base_hi = upper_32_bits(agp_base);
-       u32 agp_base_lo = agp_base & 0xffffffff;
-
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) {
-               R500_WRITE_MCIND(RV515_MC_AGP_BASE, agp_base_lo);
-               R500_WRITE_MCIND(RV515_MC_AGP_BASE_2, agp_base_hi);
-       } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
-               RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo);
-               RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi);
-       } else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) {
-               R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo);
-               R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi);
-       } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480) {
-               RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
-               RADEON_WRITE(RS480_AGP_BASE_2, 0);
-       } else {
-               RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
-               if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200)
-                       RADEON_WRITE(RADEON_AGP_BASE_2, agp_base_hi);
-       }
-}
-
-static int RADEON_READ_PLL(struct drm_device * dev, int addr)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-
-       RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
-       return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
-}
-
-static u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
-{
-       RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
-       return RADEON_READ(RADEON_PCIE_DATA);
-}
-
-#if RADEON_FIFO_DEBUG
-static void radeon_status(drm_radeon_private_t * dev_priv)
-{
-       printk("%s:\n", __func__);
-       printk("RBBM_STATUS = 0x%08x\n",
-              (unsigned int)RADEON_READ(RADEON_RBBM_STATUS));
-       printk("CP_RB_RTPR = 0x%08x\n",
-              (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR));
-       printk("CP_RB_WTPR = 0x%08x\n",
-              (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR));
-       printk("AIC_CNTL = 0x%08x\n",
-              (unsigned int)RADEON_READ(RADEON_AIC_CNTL));
-       printk("AIC_STAT = 0x%08x\n",
-              (unsigned int)RADEON_READ(RADEON_AIC_STAT));
-       printk("AIC_PT_BASE = 0x%08x\n",
-              (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE));
-       printk("TLB_ADDR = 0x%08x\n",
-              (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR));
-       printk("TLB_DATA = 0x%08x\n",
-              (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA));
-}
-#endif
-
-/* ================================================================
- * Engine, FIFO control
- */
-
-static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
-{
-       u32 tmp;
-       int i;
-
-       dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {
-               tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
-               tmp |= RADEON_RB3D_DC_FLUSH_ALL;
-               RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
-
-               for (i = 0; i < dev_priv->usec_timeout; i++) {
-                       if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT)
-                             & RADEON_RB3D_DC_BUSY)) {
-                               return 0;
-                       }
-                       DRM_UDELAY(1);
-               }
-       } else {
-               /* 3D */
-               tmp = RADEON_READ(R300_RB3D_DSTCACHE_CTLSTAT);
-               tmp |= RADEON_RB3D_DC_FLUSH_ALL;
-               RADEON_WRITE(R300_RB3D_DSTCACHE_CTLSTAT, tmp);
-
-               /* 2D */
-               tmp = RADEON_READ(R300_DSTCACHE_CTLSTAT);
-               tmp |= RADEON_RB3D_DC_FLUSH_ALL;
-               RADEON_WRITE(R300_DSTCACHE_CTLSTAT, tmp);
-
-               for (i = 0; i < dev_priv->usec_timeout; i++) {
-                       if (!(RADEON_READ(R300_DSTCACHE_CTLSTAT)
-                         & RADEON_RB3D_DC_BUSY)) {
-                               return 0;
-                       }
-                       DRM_UDELAY(1);
-               }
-       }
-
-#if RADEON_FIFO_DEBUG
-       DRM_ERROR("failed!\n");
-       radeon_status(dev_priv);
-#endif
-       return -EBUSY;
-}
-
-static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
-{
-       int i;
-
-       dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-       for (i = 0; i < dev_priv->usec_timeout; i++) {
-               int slots = (RADEON_READ(RADEON_RBBM_STATUS)
-                            & RADEON_RBBM_FIFOCNT_MASK);
-               if (slots >= entries)
-                       return 0;
-               DRM_UDELAY(1);
-       }
-
-#if RADEON_FIFO_DEBUG
-       DRM_ERROR("failed!\n");
-       radeon_status(dev_priv);
-#endif
-       return -EBUSY;
-}
-
-static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
-{
-       int i, ret;
-
-       dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-       ret = radeon_do_wait_for_fifo(dev_priv, 64);
-       if (ret)
-               return ret;
-
-       for (i = 0; i < dev_priv->usec_timeout; i++) {
-               if (!(RADEON_READ(RADEON_RBBM_STATUS)
-                     & RADEON_RBBM_ACTIVE)) {
-                       radeon_do_pixcache_flush(dev_priv);
-                       return 0;
-               }
-               DRM_UDELAY(1);
-       }
-
-#if RADEON_FIFO_DEBUG
-       DRM_ERROR("failed!\n");
-       radeon_status(dev_priv);
-#endif
-       return -EBUSY;
-}
-
-static void radeon_init_pipes(drm_radeon_private_t *dev_priv)
-{
-       uint32_t gb_tile_config, gb_pipe_sel = 0;
-
-       /* RS4xx/RS6xx/R4xx/R5xx */
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) {
-               gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT);
-               dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
-       } else {
-               /* R3xx */
-               if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
-                   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350)) {
-                       dev_priv->num_gb_pipes = 2;
-               } else {
-                       /* R3Vxx */
-                       dev_priv->num_gb_pipes = 1;
-               }
-       }
-       DRM_INFO("Num pipes: %d\n", dev_priv->num_gb_pipes);
-
-       gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 /*| R300_SUBPIXEL_1_16*/);
-
-       switch (dev_priv->num_gb_pipes) {
-       case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break;
-       case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break;
-       case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break;
-       default:
-       case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
-       }
-
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
-               RADEON_WRITE_PLL(R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
-               RADEON_WRITE(R500_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1));
-       }
-       RADEON_WRITE(R300_GB_TILE_CONFIG, gb_tile_config);
-       radeon_do_wait_for_idle(dev_priv);
-       RADEON_WRITE(R300_DST_PIPE_CONFIG, RADEON_READ(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG);
-       RADEON_WRITE(R300_RB2D_DSTCACHE_MODE, (RADEON_READ(R300_RB2D_DSTCACHE_MODE) |
-                                              R300_DC_AUTOFLUSH_ENABLE |
-                                              R300_DC_DC_DISABLE_IGNORE_PE));
-
-
-}
-
-/* ================================================================
- * CP control, initialization
- */
-
-/* Load the microcode for the CP */
-static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
-{
-       int i;
-       DRM_DEBUG("\n");
-
-       radeon_do_wait_for_idle(dev_priv);
-
-       RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
-       if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) ||
-           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) ||
-           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) ||
-           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) ||
-           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) {
-               DRM_INFO("Loading R100 Microcode\n");
-               for (i = 0; i < 256; i++) {
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
-                                    R100_cp_microcode[i][1]);
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-                                    R100_cp_microcode[i][0]);
-               }
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) {
-               DRM_INFO("Loading R200 Microcode\n");
-               for (i = 0; i < 256; i++) {
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
-                                    R200_cp_microcode[i][1]);
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-                                    R200_cp_microcode[i][0]);
-               }
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
-               DRM_INFO("Loading R300 Microcode\n");
-               for (i = 0; i < 256; i++) {
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
-                                    R300_cp_microcode[i][1]);
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-                                    R300_cp_microcode[i][0]);
-               }
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) {
-               DRM_INFO("Loading R400 Microcode\n");
-               for (i = 0; i < 256; i++) {
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
-                                    R420_cp_microcode[i][1]);
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-                                    R420_cp_microcode[i][0]);
-               }
-       } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
-               DRM_INFO("Loading RS690 Microcode\n");
-               for (i = 0; i < 256; i++) {
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
-                                    RS690_cp_microcode[i][1]);
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-                                    RS690_cp_microcode[i][0]);
-               }
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R580) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) {
-               DRM_INFO("Loading R500 Microcode\n");
-               for (i = 0; i < 256; i++) {
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
-                                    R520_cp_microcode[i][1]);
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-                                    R520_cp_microcode[i][0]);
-               }
-       }
-}
-
-/* Flush any pending commands to the CP.  This should only be used just
- * prior to a wait for idle, as it informs the engine that the command
- * stream is ending.
- */
-static void radeon_do_cp_flush(drm_radeon_private_t * dev_priv)
-{
-       DRM_DEBUG("\n");
-#if 0
-       u32 tmp;
-
-       tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31);
-       RADEON_WRITE(RADEON_CP_RB_WPTR, tmp);
-#endif
-}
-
-/* Wait for the CP to go idle.
- */
-int radeon_do_cp_idle(drm_radeon_private_t * dev_priv)
-{
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_RING(6);
-
-       RADEON_PURGE_CACHE();
-       RADEON_PURGE_ZCACHE();
-       RADEON_WAIT_UNTIL_IDLE();
-
-       ADVANCE_RING();
-       COMMIT_RING();
-
-       return radeon_do_wait_for_idle(dev_priv);
-}
-
-/* Start the Command Processor.
- */
-static void radeon_do_cp_start(drm_radeon_private_t * dev_priv)
-{
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       radeon_do_wait_for_idle(dev_priv);
-
-       RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode);
-
-       dev_priv->cp_running = 1;
-
-       BEGIN_RING(6);
-
-       RADEON_PURGE_CACHE();
-       RADEON_PURGE_ZCACHE();
-       RADEON_WAIT_UNTIL_IDLE();
-
-       ADVANCE_RING();
-       COMMIT_RING();
-}
-
-/* Reset the Command Processor.  This will not flush any pending
- * commands, so you must wait for the CP command stream to complete
- * before calling this routine.
- */
-static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv)
-{
-       u32 cur_read_ptr;
-       DRM_DEBUG("\n");
-
-       cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
-       RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
-       SET_RING_HEAD(dev_priv, cur_read_ptr);
-       dev_priv->ring.tail = cur_read_ptr;
-}
-
-/* Stop the Command Processor.  This will not flush any pending
- * commands, so you must flush the command stream and wait for the CP
- * to go idle before calling this routine.
- */
-static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
-{
-       DRM_DEBUG("\n");
-
-       RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
-
-       dev_priv->cp_running = 0;
-}
-
-/* Reset the engine.  This will stop the CP if it is running.
- */
-static int radeon_do_engine_reset(struct drm_device * dev)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       u32 clock_cntl_index = 0, mclk_cntl = 0, rbbm_soft_reset;
-       DRM_DEBUG("\n");
-
-       radeon_do_pixcache_flush(dev_priv);
-
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
-               /* may need something similar for newer chips */
-               clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
-               mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
-
-               RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
-                                                   RADEON_FORCEON_MCLKA |
-                                                   RADEON_FORCEON_MCLKB |
-                                                   RADEON_FORCEON_YCLKA |
-                                                   RADEON_FORCEON_YCLKB |
-                                                   RADEON_FORCEON_MC |
-                                                   RADEON_FORCEON_AIC));
-       }
-
-       rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
-
-       RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
-                                             RADEON_SOFT_RESET_CP |
-                                             RADEON_SOFT_RESET_HI |
-                                             RADEON_SOFT_RESET_SE |
-                                             RADEON_SOFT_RESET_RE |
-                                             RADEON_SOFT_RESET_PP |
-                                             RADEON_SOFT_RESET_E2 |
-                                             RADEON_SOFT_RESET_RB));
-       RADEON_READ(RADEON_RBBM_SOFT_RESET);
-       RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
-                                             ~(RADEON_SOFT_RESET_CP |
-                                               RADEON_SOFT_RESET_HI |
-                                               RADEON_SOFT_RESET_SE |
-                                               RADEON_SOFT_RESET_RE |
-                                               RADEON_SOFT_RESET_PP |
-                                               RADEON_SOFT_RESET_E2 |
-                                               RADEON_SOFT_RESET_RB)));
-       RADEON_READ(RADEON_RBBM_SOFT_RESET);
-
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
-               RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
-               RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
-               RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
-       }
-
-       /* setup the raster pipes */
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300)
-           radeon_init_pipes(dev_priv);
-
-       /* Reset the CP ring */
-       radeon_do_cp_reset(dev_priv);
-
-       /* The CP is no longer running after an engine reset */
-       dev_priv->cp_running = 0;
-
-       /* Reset any pending vertex, indirect buffers */
-       radeon_freelist_reset(dev);
-
-       return 0;
-}
-
-static void radeon_cp_init_ring_buffer(struct drm_device * dev,
-                                      drm_radeon_private_t * dev_priv)
-{
-       u32 ring_start, cur_read_ptr;
-       u32 tmp;
-
-       /* Initialize the memory controller. With new memory map, the fb location
-        * is not changed, it should have been properly initialized already. Part
-        * of the problem is that the code below is bogus, assuming the GART is
-        * always appended to the fb which is not necessarily the case
-        */
-       if (!dev_priv->new_memmap)
-               radeon_write_fb_location(dev_priv,
-                            ((dev_priv->gart_vm_start - 1) & 0xffff0000)
-                            | (dev_priv->fb_location >> 16));
-
-#if __OS_HAS_AGP
-       if (dev_priv->flags & RADEON_IS_AGP) {
-               radeon_write_agp_base(dev_priv, dev->agp->base);
-
-               radeon_write_agp_location(dev_priv,
-                            (((dev_priv->gart_vm_start - 1 +
-                               dev_priv->gart_size) & 0xffff0000) |
-                             (dev_priv->gart_vm_start >> 16)));
-
-               ring_start = (dev_priv->cp_ring->offset
-                             - dev->agp->base
-                             + dev_priv->gart_vm_start);
-       } else
-#endif
-               ring_start = (dev_priv->cp_ring->offset
-                             - (unsigned long)dev->sg->virtual
-                             + dev_priv->gart_vm_start);
-
-       RADEON_WRITE(RADEON_CP_RB_BASE, ring_start);
-
-       /* Set the write pointer delay */
-       RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0);
-
-       /* Initialize the ring buffer's read and write pointers */
-       cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
-       RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
-       SET_RING_HEAD(dev_priv, cur_read_ptr);
-       dev_priv->ring.tail = cur_read_ptr;
-
-#if __OS_HAS_AGP
-       if (dev_priv->flags & RADEON_IS_AGP) {
-               RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
-                            dev_priv->ring_rptr->offset
-                            - dev->agp->base + dev_priv->gart_vm_start);
-       } else
-#endif
-       {
-               struct drm_sg_mem *entry = dev->sg;
-               unsigned long tmp_ofs, page_ofs;
-
-               tmp_ofs = dev_priv->ring_rptr->offset -
-                               (unsigned long)dev->sg->virtual;
-               page_ofs = tmp_ofs >> PAGE_SHIFT;
-
-               RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]);
-               DRM_DEBUG("ring rptr: offset=0x%08lx handle=0x%08lx\n",
-                         (unsigned long)entry->busaddr[page_ofs],
-                         entry->handle + tmp_ofs);
-       }
-
-       /* Set ring buffer size */
-#ifdef __BIG_ENDIAN
-       RADEON_WRITE(RADEON_CP_RB_CNTL,
-                    RADEON_BUF_SWAP_32BIT |
-                    (dev_priv->ring.fetch_size_l2ow << 18) |
-                    (dev_priv->ring.rptr_update_l2qw << 8) |
-                    dev_priv->ring.size_l2qw);
-#else
-       RADEON_WRITE(RADEON_CP_RB_CNTL,
-                    (dev_priv->ring.fetch_size_l2ow << 18) |
-                    (dev_priv->ring.rptr_update_l2qw << 8) |
-                    dev_priv->ring.size_l2qw);
-#endif
-
-       /* Start with assuming that writeback doesn't work */
-       dev_priv->writeback_works = 0;
-
-       /* Initialize the scratch register pointer.  This will cause
-        * the scratch register values to be written out to memory
-        * whenever they are updated.
-        *
-        * We simply put this behind the ring read pointer, this works
-        * with PCI GART as well as (whatever kind of) AGP GART
-        */
-       RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)
-                    + RADEON_SCRATCH_REG_OFFSET);
-
-       dev_priv->scratch = ((__volatile__ u32 *)
-                            dev_priv->ring_rptr->handle +
-                            (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
-
-       RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
-
-       /* Turn on bus mastering */
-       tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
-       RADEON_WRITE(RADEON_BUS_CNTL, tmp);
-
-       dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
-       RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
-
-       dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
-       RADEON_WRITE(RADEON_LAST_DISPATCH_REG,
-                    dev_priv->sarea_priv->last_dispatch);
-
-       dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
-       RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
-
-       radeon_do_wait_for_idle(dev_priv);
-
-       /* Sync everything up */
-       RADEON_WRITE(RADEON_ISYNC_CNTL,
-                    (RADEON_ISYNC_ANY2D_IDLE3D |
-                     RADEON_ISYNC_ANY3D_IDLE2D |
-                     RADEON_ISYNC_WAIT_IDLEGUI |
-                     RADEON_ISYNC_CPSCRATCH_IDLEGUI));
-
-}
-
-static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
-{
-       u32 tmp;
-
-       /* Writeback doesn't seem to work everywhere, test it here and possibly
-        * enable it if it appears to work
-        */
-       DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);
-       RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
-
-       for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
-               if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==
-                   0xdeadbeef)
-                       break;
-               DRM_UDELAY(1);
-       }
-
-       if (tmp < dev_priv->usec_timeout) {
-               dev_priv->writeback_works = 1;
-               DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
-       } else {
-               dev_priv->writeback_works = 0;
-               DRM_INFO("writeback test failed\n");
-       }
-       if (radeon_no_wb == 1) {
-               dev_priv->writeback_works = 0;
-               DRM_INFO("writeback forced off\n");
-       }
-
-       if (!dev_priv->writeback_works) {
-               /* Disable writeback to avoid unnecessary bus master transfer */
-               RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) |
-                            RADEON_RB_NO_UPDATE);
-               RADEON_WRITE(RADEON_SCRATCH_UMSK, 0);
-       }
-}
-
-/* Enable or disable IGP GART on the chip */
-static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
-{
-       u32 temp;
-
-       if (on) {
-               DRM_DEBUG("programming igp gart %08X %08lX %08X\n",
-                         dev_priv->gart_vm_start,
-                         (long)dev_priv->gart_info.bus_addr,
-                         dev_priv->gart_size);
-
-               temp = IGP_READ_MCIND(dev_priv, RS480_MC_MISC_CNTL);
-               if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
-                       IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, (RS480_GART_INDEX_REG_EN |
-                                                            RS690_BLOCK_GFX_D3_EN));
-               else
-                       IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN);
-
-               IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN |
-                                                              RS480_VA_SIZE_32MB));
-
-               temp = IGP_READ_MCIND(dev_priv, RS480_GART_FEATURE_ID);
-               IGP_WRITE_MCIND(RS480_GART_FEATURE_ID, (RS480_HANG_EN |
-                                                       RS480_TLB_ENABLE |
-                                                       RS480_GTW_LAC_EN |
-                                                       RS480_1LEVEL_GART));
-
-               temp = dev_priv->gart_info.bus_addr & 0xfffff000;
-               temp |= (upper_32_bits(dev_priv->gart_info.bus_addr) & 0xff) << 4;
-               IGP_WRITE_MCIND(RS480_GART_BASE, temp);
-
-               temp = IGP_READ_MCIND(dev_priv, RS480_AGP_MODE_CNTL);
-               IGP_WRITE_MCIND(RS480_AGP_MODE_CNTL, ((1 << RS480_REQ_TYPE_SNOOP_SHIFT) |
-                                                     RS480_REQ_TYPE_SNOOP_DIS));
-
-               radeon_write_agp_base(dev_priv, dev_priv->gart_vm_start);
-
-               dev_priv->gart_size = 32*1024*1024;
-               temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) &
-                        0xffff0000) | (dev_priv->gart_vm_start >> 16));
-
-               radeon_write_agp_location(dev_priv, temp);
-
-               temp = IGP_READ_MCIND(dev_priv, RS480_AGP_ADDRESS_SPACE_SIZE);
-               IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN |
-                                                              RS480_VA_SIZE_32MB));
-
-               do {
-                       temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
-                       if ((temp & RS480_GART_CACHE_INVALIDATE) == 0)
-                               break;
-                       DRM_UDELAY(1);
-               } while (1);
-
-               IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL,
-                               RS480_GART_CACHE_INVALIDATE);
-
-               do {
-                       temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
-                       if ((temp & RS480_GART_CACHE_INVALIDATE) == 0)
-                               break;
-                       DRM_UDELAY(1);
-               } while (1);
-
-               IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, 0);
-       } else {
-               IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, 0);
-       }
-}
-
-static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
-{
-       u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);
-       if (on) {
-
-               DRM_DEBUG("programming pcie %08X %08lX %08X\n",
-                         dev_priv->gart_vm_start,
-                         (long)dev_priv->gart_info.bus_addr,
-                         dev_priv->gart_size);
-               RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO,
-                                 dev_priv->gart_vm_start);
-               RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE,
-                                 dev_priv->gart_info.bus_addr);
-               RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO,
-                                 dev_priv->gart_vm_start);
-               RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO,
-                                 dev_priv->gart_vm_start +
-                                 dev_priv->gart_size - 1);
-
-               radeon_write_agp_location(dev_priv, 0xffffffc0); /* ?? */
-
-               RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
-                                 RADEON_PCIE_TX_GART_EN);
-       } else {
-               RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
-                                 tmp & ~RADEON_PCIE_TX_GART_EN);
-       }
-}
-
-/* Enable or disable PCI GART on the chip */
-static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
-{
-       u32 tmp;
-
-       if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
-           (dev_priv->flags & RADEON_IS_IGPGART)) {
-               radeon_set_igpgart(dev_priv, on);
-               return;
-       }
-
-       if (dev_priv->flags & RADEON_IS_PCIE) {
-               radeon_set_pciegart(dev_priv, on);
-               return;
-       }
-
-       tmp = RADEON_READ(RADEON_AIC_CNTL);
-
-       if (on) {
-               RADEON_WRITE(RADEON_AIC_CNTL,
-                            tmp | RADEON_PCIGART_TRANSLATE_EN);
-
-               /* set PCI GART page-table base address
-                */
-               RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr);
-
-               /* set address range for PCI address translate
-                */
-               RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start);
-               RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start
-                            + dev_priv->gart_size - 1);
-
-               /* Turn off AGP aperture -- is this required for PCI GART?
-                */
-               radeon_write_agp_location(dev_priv, 0xffffffc0);
-               RADEON_WRITE(RADEON_AGP_COMMAND, 0);    /* clear AGP_COMMAND */
-       } else {
-               RADEON_WRITE(RADEON_AIC_CNTL,
-                            tmp & ~RADEON_PCIGART_TRANSLATE_EN);
-       }
-}
-
-static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-
-       DRM_DEBUG("\n");
-
-       /* if we require new memory map but we don't have it fail */
-       if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
-               DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
-               radeon_do_cleanup_cp(dev);
-               return -EINVAL;
-       }
-
-       if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
-               DRM_DEBUG("Forcing AGP card to PCI mode\n");
-               dev_priv->flags &= ~RADEON_IS_AGP;
-       } else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE))
-                  && !init->is_pci) {
-               DRM_DEBUG("Restoring AGP flag\n");
-               dev_priv->flags |= RADEON_IS_AGP;
-       }
-
-       if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) {
-               DRM_ERROR("PCI GART memory not allocated!\n");
-               radeon_do_cleanup_cp(dev);
-               return -EINVAL;
-       }
-
-       dev_priv->usec_timeout = init->usec_timeout;
-       if (dev_priv->usec_timeout < 1 ||
-           dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
-               DRM_DEBUG("TIMEOUT problem!\n");
-               radeon_do_cleanup_cp(dev);
-               return -EINVAL;
-       }
-
-       /* Enable vblank on CRTC1 for older X servers
-        */
-       dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
-
-       switch(init->func) {
-       case RADEON_INIT_R200_CP:
-               dev_priv->microcode_version = UCODE_R200;
-               break;
-       case RADEON_INIT_R300_CP:
-               dev_priv->microcode_version = UCODE_R300;
-               break;
-       default:
-               dev_priv->microcode_version = UCODE_R100;
-       }
-
-       dev_priv->do_boxes = 0;
-       dev_priv->cp_mode = init->cp_mode;
-
-       /* We don't support anything other than bus-mastering ring mode,
-        * but the ring can be in either AGP or PCI space for the ring
-        * read pointer.
-        */
-       if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
-           (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
-               DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
-               radeon_do_cleanup_cp(dev);
-               return -EINVAL;
-       }
-
-       switch (init->fb_bpp) {
-       case 16:
-               dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
-               break;
-       case 32:
-       default:
-               dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
-               break;
-       }
-       dev_priv->front_offset = init->front_offset;
-       dev_priv->front_pitch = init->front_pitch;
-       dev_priv->back_offset = init->back_offset;
-       dev_priv->back_pitch = init->back_pitch;
-
-       switch (init->depth_bpp) {
-       case 16:
-               dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
-               break;
-       case 32:
-       default:
-               dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
-               break;
-       }
-       dev_priv->depth_offset = init->depth_offset;
-       dev_priv->depth_pitch = init->depth_pitch;
-
-       /* Hardware state for depth clears.  Remove this if/when we no
-        * longer clear the depth buffer with a 3D rectangle.  Hard-code
-        * all values to prevent unwanted 3D state from slipping through
-        * and screwing with the clear operation.
-        */
-       dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
-                                          (dev_priv->color_fmt << 10) |
-                                          (dev_priv->microcode_version ==
-                                           UCODE_R100 ? RADEON_ZBLOCK16 : 0));
-
-       dev_priv->depth_clear.rb3d_zstencilcntl =
-           (dev_priv->depth_fmt |
-            RADEON_Z_TEST_ALWAYS |
-            RADEON_STENCIL_TEST_ALWAYS |
-            RADEON_STENCIL_S_FAIL_REPLACE |
-            RADEON_STENCIL_ZPASS_REPLACE |
-            RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE);
-
-       dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
-                                        RADEON_BFACE_SOLID |
-                                        RADEON_FFACE_SOLID |
-                                        RADEON_FLAT_SHADE_VTX_LAST |
-                                        RADEON_DIFFUSE_SHADE_FLAT |
-                                        RADEON_ALPHA_SHADE_FLAT |
-                                        RADEON_SPECULAR_SHADE_FLAT |
-                                        RADEON_FOG_SHADE_FLAT |
-                                        RADEON_VTX_PIX_CENTER_OGL |
-                                        RADEON_ROUND_MODE_TRUNC |
-                                        RADEON_ROUND_PREC_8TH_PIX);
-
-
-       dev_priv->ring_offset = init->ring_offset;
-       dev_priv->ring_rptr_offset = init->ring_rptr_offset;
-       dev_priv->buffers_offset = init->buffers_offset;
-       dev_priv->gart_textures_offset = init->gart_textures_offset;
-
-       dev_priv->sarea = drm_getsarea(dev);
-       if (!dev_priv->sarea) {
-               DRM_ERROR("could not find sarea!\n");
-               radeon_do_cleanup_cp(dev);
-               return -EINVAL;
-       }
-
-       dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
-       if (!dev_priv->cp_ring) {
-               DRM_ERROR("could not find cp ring region!\n");
-               radeon_do_cleanup_cp(dev);
-               return -EINVAL;
-       }
-       dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
-       if (!dev_priv->ring_rptr) {
-               DRM_ERROR("could not find ring read pointer!\n");
-               radeon_do_cleanup_cp(dev);
-               return -EINVAL;
-       }
-       dev->agp_buffer_token = init->buffers_offset;
-       dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
-       if (!dev->agp_buffer_map) {
-               DRM_ERROR("could not find dma buffer region!\n");
-               radeon_do_cleanup_cp(dev);
-               return -EINVAL;
-       }
-
-       if (init->gart_textures_offset) {
-               dev_priv->gart_textures =
-                   drm_core_findmap(dev, init->gart_textures_offset);
-               if (!dev_priv->gart_textures) {
-                       DRM_ERROR("could not find GART texture region!\n");
-                       radeon_do_cleanup_cp(dev);
-                       return -EINVAL;
-               }
-       }
-
-       dev_priv->sarea_priv =
-           (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle +
-                                   init->sarea_priv_offset);
-
-#if __OS_HAS_AGP
-       if (dev_priv->flags & RADEON_IS_AGP) {
-               drm_core_ioremap(dev_priv->cp_ring, dev);
-               drm_core_ioremap(dev_priv->ring_rptr, dev);
-               drm_core_ioremap(dev->agp_buffer_map, dev);
-               if (!dev_priv->cp_ring->handle ||
-                   !dev_priv->ring_rptr->handle ||
-                   !dev->agp_buffer_map->handle) {
-                       DRM_ERROR("could not find ioremap agp regions!\n");
-                       radeon_do_cleanup_cp(dev);
-                       return -EINVAL;
-               }
-       } else
-#endif
-       {
-               dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset;
-               dev_priv->ring_rptr->handle =
-                   (void *)dev_priv->ring_rptr->offset;
-               dev->agp_buffer_map->handle =
-                   (void *)dev->agp_buffer_map->offset;
-
-               DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
-                         dev_priv->cp_ring->handle);
-               DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
-                         dev_priv->ring_rptr->handle);
-               DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
-                         dev->agp_buffer_map->handle);
-       }
-
-       dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16;
-       dev_priv->fb_size =
-               ((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000)
-               - dev_priv->fb_location;
-
-       dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
-                                       ((dev_priv->front_offset
-                                         + dev_priv->fb_location) >> 10));
-
-       dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |
-                                      ((dev_priv->back_offset
-                                        + dev_priv->fb_location) >> 10));
-
-       dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |
-                                       ((dev_priv->depth_offset
-                                         + dev_priv->fb_location) >> 10));
-
-       dev_priv->gart_size = init->gart_size;
-
-       /* New let's set the memory map ... */
-       if (dev_priv->new_memmap) {
-               u32 base = 0;
-
-               DRM_INFO("Setting GART location based on new memory map\n");
-
-               /* If using AGP, try to locate the AGP aperture at the same
-                * location in the card and on the bus, though we have to
-                * align it down.
-                */
-#if __OS_HAS_AGP
-               if (dev_priv->flags & RADEON_IS_AGP) {
-                       base = dev->agp->base;
-                       /* Check if valid */
-                       if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location &&
-                           base < (dev_priv->fb_location + dev_priv->fb_size - 1)) {
-                               DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
-                                        dev->agp->base);
-                               base = 0;
-                       }
-               }
-#endif
-               /* If not or if AGP is at 0 (Macs), try to put it elsewhere */
-               if (base == 0) {
-                       base = dev_priv->fb_location + dev_priv->fb_size;
-                       if (base < dev_priv->fb_location ||
-                           ((base + dev_priv->gart_size) & 0xfffffffful) < base)
-                               base = dev_priv->fb_location
-                                       - dev_priv->gart_size;
-               }
-               dev_priv->gart_vm_start = base & 0xffc00000u;
-               if (dev_priv->gart_vm_start != base)
-                       DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
-                                base, dev_priv->gart_vm_start);
-       } else {
-               DRM_INFO("Setting GART location based on old memory map\n");
-               dev_priv->gart_vm_start = dev_priv->fb_location +
-                       RADEON_READ(RADEON_CONFIG_APER_SIZE);
-       }
-
-#if __OS_HAS_AGP
-       if (dev_priv->flags & RADEON_IS_AGP)
-               dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
-                                                - dev->agp->base
-                                                + dev_priv->gart_vm_start);
-       else
-#endif
-               dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
-                                       - (unsigned long)dev->sg->virtual
-                                       + dev_priv->gart_vm_start);
-
-       DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);
-       DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start);
-       DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n",
-                 dev_priv->gart_buffers_offset);
-
-       dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
-       dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
-                             + init->ring_size / sizeof(u32));
-       dev_priv->ring.size = init->ring_size;
-       dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
-
-       dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
-       dev_priv->ring.rptr_update_l2qw = drm_order( /* init->rptr_update */ 4096 / 8);
-
-       dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
-       dev_priv->ring.fetch_size_l2ow = drm_order( /* init->fetch_size */ 32 / 16);
-       dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
-
-       dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
-
-#if __OS_HAS_AGP
-       if (dev_priv->flags & RADEON_IS_AGP) {
-               /* Turn off PCI GART */
-               radeon_set_pcigart(dev_priv, 0);
-       } else
-#endif
-       {
-               dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
-               /* if we have an offset set from userspace */
-               if (dev_priv->pcigart_offset_set) {
-                       dev_priv->gart_info.bus_addr =
-                           dev_priv->pcigart_offset + dev_priv->fb_location;
-                       dev_priv->gart_info.mapping.offset =
-                           dev_priv->pcigart_offset + dev_priv->fb_aper_offset;
-                       dev_priv->gart_info.mapping.size =
-                           dev_priv->gart_info.table_size;
-
-                       drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
-                       dev_priv->gart_info.addr =
-                           dev_priv->gart_info.mapping.handle;
-
-                       if (dev_priv->flags & RADEON_IS_PCIE)
-                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;
-                       else
-                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
-                       dev_priv->gart_info.gart_table_location =
-                           DRM_ATI_GART_FB;
-
-                       DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
-                                 dev_priv->gart_info.addr,
-                                 dev_priv->pcigart_offset);
-               } else {
-                       if (dev_priv->flags & RADEON_IS_IGPGART)
-                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP;
-                       else
-                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
-                       dev_priv->gart_info.gart_table_location =
-                           DRM_ATI_GART_MAIN;
-                       dev_priv->gart_info.addr = NULL;
-                       dev_priv->gart_info.bus_addr = 0;
-                       if (dev_priv->flags & RADEON_IS_PCIE) {
-                               DRM_ERROR
-                                   ("Cannot use PCI Express without GART in FB memory\n");
-                               radeon_do_cleanup_cp(dev);
-                               return -EINVAL;
-                       }
-               }
-
-               if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
-                       DRM_ERROR("failed to init PCI GART!\n");
-                       radeon_do_cleanup_cp(dev);
-                       return -ENOMEM;
-               }
-
-               /* Turn on PCI GART */
-               radeon_set_pcigart(dev_priv, 1);
-       }
-
-       radeon_cp_load_microcode(dev_priv);
-       radeon_cp_init_ring_buffer(dev, dev_priv);
-
-       dev_priv->last_buf = 0;
-
-       radeon_do_engine_reset(dev);
-       radeon_test_writeback(dev_priv);
-
-       return 0;
-}
-
-static int radeon_do_cleanup_cp(struct drm_device * dev)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       /* Make sure interrupts are disabled here because the uninstall ioctl
-        * may not have been called from userspace and after dev_private
-        * is freed, it's too late.
-        */
-       if (dev->irq_enabled)
-               drm_irq_uninstall(dev);
-
-#if __OS_HAS_AGP
-       if (dev_priv->flags & RADEON_IS_AGP) {
-               if (dev_priv->cp_ring != NULL) {
-                       drm_core_ioremapfree(dev_priv->cp_ring, dev);
-                       dev_priv->cp_ring = NULL;
-               }
-               if (dev_priv->ring_rptr != NULL) {
-                       drm_core_ioremapfree(dev_priv->ring_rptr, dev);
-                       dev_priv->ring_rptr = NULL;
-               }
-               if (dev->agp_buffer_map != NULL) {
-                       drm_core_ioremapfree(dev->agp_buffer_map, dev);
-                       dev->agp_buffer_map = NULL;
-               }
-       } else
-#endif
-       {
-
-               if (dev_priv->gart_info.bus_addr) {
-                       /* Turn off PCI GART */
-                       radeon_set_pcigart(dev_priv, 0);
-                       if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
-                               DRM_ERROR("failed to cleanup PCI GART!\n");
-               }
-
-               if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
-               {
-                       drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
-                       dev_priv->gart_info.addr = 0;
-               }
-       }
-       /* only clear to the start of flags */
-       memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
-
-       return 0;
-}
-
-/* This code will reinit the Radeon CP hardware after a resume from disc.
- * AFAIK, it would be very difficult to pickle the state at suspend time, so
- * here we make sure that all Radeon hardware initialisation is re-done without
- * affecting running applications.
- *
- * Charl P. Botha <http://cpbotha.net>
- */
-static int radeon_do_resume_cp(struct drm_device * dev)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-
-       if (!dev_priv) {
-               DRM_ERROR("Called with no initialization\n");
-               return -EINVAL;
-       }
-
-       DRM_DEBUG("Starting radeon_do_resume_cp()\n");
-
-#if __OS_HAS_AGP
-       if (dev_priv->flags & RADEON_IS_AGP) {
-               /* Turn off PCI GART */
-               radeon_set_pcigart(dev_priv, 0);
-       } else
-#endif
-       {
-               /* Turn on PCI GART */
-               radeon_set_pcigart(dev_priv, 1);
-       }
-
-       radeon_cp_load_microcode(dev_priv);
-       radeon_cp_init_ring_buffer(dev, dev_priv);
-
-       radeon_do_engine_reset(dev);
-       radeon_enable_interrupt(dev);
-
-       DRM_DEBUG("radeon_do_resume_cp() complete\n");
-
-       return 0;
-}
-
-int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_init_t *init = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (init->func == RADEON_INIT_R300_CP)
-               r300_init_reg_flags(dev);
-
-       switch (init->func) {
-       case RADEON_INIT_CP:
-       case RADEON_INIT_R200_CP:
-       case RADEON_INIT_R300_CP:
-               return radeon_do_init_cp(dev, init);
-       case RADEON_CLEANUP_CP:
-               return radeon_do_cleanup_cp(dev);
-       }
-
-       return -EINVAL;
-}
-
-int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (dev_priv->cp_running) {
-               DRM_DEBUG("while CP running\n");
-               return 0;
-       }
-       if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) {
-               DRM_DEBUG("called with bogus CP mode (%d)\n",
-                         dev_priv->cp_mode);
-               return 0;
-       }
-
-       radeon_do_cp_start(dev_priv);
-
-       return 0;
-}
-
-/* Stop the CP.  The engine must have been idled before calling this
- * routine.
- */
-int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_cp_stop_t *stop = data;
-       int ret;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (!dev_priv->cp_running)
-               return 0;
-
-       /* Flush any pending CP commands.  This ensures any outstanding
-        * commands are exectuted by the engine before we turn it off.
-        */
-       if (stop->flush) {
-               radeon_do_cp_flush(dev_priv);
-       }
-
-       /* If we fail to make the engine go idle, we return an error
-        * code so that the DRM ioctl wrapper can try again.
-        */
-       if (stop->idle) {
-               ret = radeon_do_cp_idle(dev_priv);
-               if (ret)
-                       return ret;
-       }
-
-       /* Finally, we can turn off the CP.  If the engine isn't idle,
-        * we will get some dropped triangles as they won't be fully
-        * rendered before the CP is shut down.
-        */
-       radeon_do_cp_stop(dev_priv);
-
-       /* Reset the engine */
-       radeon_do_engine_reset(dev);
-
-       return 0;
-}
-
-void radeon_do_release(struct drm_device * dev)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       int i, ret;
-
-       if (dev_priv) {
-               if (dev_priv->cp_running) {
-                       /* Stop the cp */
-                       while ((ret = radeon_do_cp_idle(dev_priv)) != 0) {
-                               DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
-#ifdef __linux__
-                               schedule();
-#else
-                               tsleep(&ret, PZERO, "rdnrel", 1);
-#endif
-                       }
-                       radeon_do_cp_stop(dev_priv);
-                       radeon_do_engine_reset(dev);
-               }
-
-               /* Disable *all* interrupts */
-               if (dev_priv->mmio)     /* remove this after permanent addmaps */
-                       RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
-
-               if (dev_priv->mmio) {   /* remove all surfaces */
-                       for (i = 0; i < RADEON_MAX_SURFACES; i++) {
-                               RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0);
-                               RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND +
-                                            16 * i, 0);
-                               RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND +
-                                            16 * i, 0);
-                       }
-               }
-
-               /* Free memory heap structures */
-               radeon_mem_takedown(&(dev_priv->gart_heap));
-               radeon_mem_takedown(&(dev_priv->fb_heap));
-
-               /* deallocate kernel resources */
-               radeon_do_cleanup_cp(dev);
-       }
-}
-
-/* Just reset the CP ring.  Called as part of an X Server engine reset.
- */
-int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (!dev_priv) {
-               DRM_DEBUG("called before init done\n");
-               return -EINVAL;
-       }
-
-       radeon_do_cp_reset(dev_priv);
-
-       /* The CP is no longer running after an engine reset */
-       dev_priv->cp_running = 0;
-
-       return 0;
-}
-
-int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       return radeon_do_cp_idle(dev_priv);
-}
-
-/* Added by Charl P. Botha to call radeon_do_resume_cp().
- */
-int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-
-       return radeon_do_resume_cp(dev);
-}
-
-int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       return radeon_do_engine_reset(dev);
-}
-
-/* ================================================================
- * Fullscreen mode
- */
-
-/* KW: Deprecated to say the least:
- */
-int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       return 0;
-}
-
-/* ================================================================
- * Freelist management
- */
-
-/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
- *   bufs until freelist code is used.  Note this hides a problem with
- *   the scratch register * (used to keep track of last buffer
- *   completed) being written to before * the last buffer has actually
- *   completed rendering.
- *
- * KW:  It's also a good way to find free buffers quickly.
- *
- * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
- * sleep.  However, bugs in older versions of radeon_accel.c mean that
- * we essentially have to do this, else old clients will break.
- *
- * However, it does leave open a potential deadlock where all the
- * buffers are held by other clients, which can't release them because
- * they can't get the lock.
- */
-
-struct drm_buf *radeon_freelist_get(struct drm_device * dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_buf_priv_t *buf_priv;
-       struct drm_buf *buf;
-       int i, t;
-       int start;
-
-       if (++dev_priv->last_buf >= dma->buf_count)
-               dev_priv->last_buf = 0;
-
-       start = dev_priv->last_buf;
-
-       for (t = 0; t < dev_priv->usec_timeout; t++) {
-               u32 done_age = GET_SCRATCH(1);
-               DRM_DEBUG("done_age = %d\n", done_age);
-               for (i = start; i < dma->buf_count; i++) {
-                       buf = dma->buflist[i];
-                       buf_priv = buf->dev_private;
-                       if (buf->file_priv == NULL || (buf->pending &&
-                                                      buf_priv->age <=
-                                                      done_age)) {
-                               dev_priv->stats.requested_bufs++;
-                               buf->pending = 0;
-                               return buf;
-                       }
-                       start = 0;
-               }
-
-               if (t) {
-                       DRM_UDELAY(1);
-                       dev_priv->stats.freelist_loops++;
-               }
-       }
-
-       DRM_DEBUG("returning NULL!\n");
-       return NULL;
-}
-
-#if 0
-struct drm_buf *radeon_freelist_get(struct drm_device * dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_buf_priv_t *buf_priv;
-       struct drm_buf *buf;
-       int i, t;
-       int start;
-       u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
-
-       if (++dev_priv->last_buf >= dma->buf_count)
-               dev_priv->last_buf = 0;
-
-       start = dev_priv->last_buf;
-       dev_priv->stats.freelist_loops++;
-
-       for (t = 0; t < 2; t++) {
-               for (i = start; i < dma->buf_count; i++) {
-                       buf = dma->buflist[i];
-                       buf_priv = buf->dev_private;
-                       if (buf->file_priv == 0 || (buf->pending &&
-                                                   buf_priv->age <=
-                                                   done_age)) {
-                               dev_priv->stats.requested_bufs++;
-                               buf->pending = 0;
-                               return buf;
-                       }
-               }
-               start = 0;
-       }
-
-       return NULL;
-}
-#endif
-
-void radeon_freelist_reset(struct drm_device * dev)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       int i;
-
-       dev_priv->last_buf = 0;
-       for (i = 0; i < dma->buf_count; i++) {
-               struct drm_buf *buf = dma->buflist[i];
-               drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
-               buf_priv->age = 0;
-       }
-}
-
-/* ================================================================
- * CP command submission
- */
-
-int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n)
-{
-       drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
-       int i;
-       u32 last_head = GET_RING_HEAD(dev_priv);
-
-       for (i = 0; i < dev_priv->usec_timeout; i++) {
-               u32 head = GET_RING_HEAD(dev_priv);
-
-               ring->space = (head - ring->tail) * sizeof(u32);
-               if (ring->space <= 0)
-                       ring->space += ring->size;
-               if (ring->space > n)
-                       return 0;
-
-               dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-               if (head != last_head)
-                       i = 0;
-               last_head = head;
-
-               DRM_UDELAY(1);
-       }
-
-       /* FIXME: This return value is ignored in the BEGIN_RING macro! */
-#if RADEON_FIFO_DEBUG
-       radeon_status(dev_priv);
-       DRM_ERROR("failed!\n");
-#endif
-       return -EBUSY;
-}
-
-static int radeon_cp_get_buffers(struct drm_device *dev,
-                                struct drm_file *file_priv,
-                                struct drm_dma * d)
-{
-       int i;
-       struct drm_buf *buf;
-
-       for (i = d->granted_count; i < d->request_count; i++) {
-               buf = radeon_freelist_get(dev);
-               if (!buf)
-                       return -EBUSY;  /* NOTE: broken client */
-
-               buf->file_priv = file_priv;
-
-               if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
-                                    sizeof(buf->idx)))
-                       return -EFAULT;
-               if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
-                                    sizeof(buf->total)))
-                       return -EFAULT;
-
-               d->granted_count++;
-       }
-       return 0;
-}
-
-int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       int ret = 0;
-       struct drm_dma *d = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       /* Please don't send us buffers.
-        */
-       if (d->send_count != 0) {
-               DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-                         DRM_CURRENTPID, d->send_count);
-               return -EINVAL;
-       }
-
-       /* We'll send you buffers.
-        */
-       if (d->request_count < 0 || d->request_count > dma->buf_count) {
-               DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         DRM_CURRENTPID, d->request_count, dma->buf_count);
-               return -EINVAL;
-       }
-
-       d->granted_count = 0;
-
-       if (d->request_count) {
-               ret = radeon_cp_get_buffers(dev, file_priv, d);
-       }
-
-       return ret;
-}
-
-int radeon_driver_load(struct drm_device *dev, unsigned long flags)
-{
-       drm_radeon_private_t *dev_priv;
-       int ret = 0;
-
-       dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER);
-       if (dev_priv == NULL)
-               return -ENOMEM;
-
-       memset(dev_priv, 0, sizeof(drm_radeon_private_t));
-       dev->dev_private = (void *)dev_priv;
-       dev_priv->flags = flags;
-
-       switch (flags & RADEON_FAMILY_MASK) {
-       case CHIP_R100:
-       case CHIP_RV200:
-       case CHIP_R200:
-       case CHIP_R300:
-       case CHIP_R350:
-       case CHIP_R420:
-       case CHIP_RV410:
-       case CHIP_RV515:
-       case CHIP_R520:
-       case CHIP_RV570:
-       case CHIP_R580:
-               dev_priv->flags |= RADEON_HAS_HIERZ;
-               break;
-       default:
-               /* all other chips have no hierarchical z buffer */
-               break;
-       }
-
-       if (drm_device_is_agp(dev))
-               dev_priv->flags |= RADEON_IS_AGP;
-       else if (drm_device_is_pcie(dev))
-               dev_priv->flags |= RADEON_IS_PCIE;
-       else
-               dev_priv->flags |= RADEON_IS_PCI;
-
-       DRM_DEBUG("%s card detected\n",
-                 ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
-       return ret;
-}
-
-/* Create mappings for registers and framebuffer so userland doesn't necessarily
- * have to find them.
- */
-int radeon_driver_firstopen(struct drm_device *dev)
-{
-       int ret;
-       drm_local_map_t *map;
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-
-       dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
-
-       ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
-                        drm_get_resource_len(dev, 2), _DRM_REGISTERS,
-                        _DRM_READ_ONLY, &dev_priv->mmio);
-       if (ret != 0)
-               return ret;
-
-       dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0);
-       ret = drm_addmap(dev, dev_priv->fb_aper_offset,
-                        drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER,
-                        _DRM_WRITE_COMBINING, &map);
-       if (ret != 0)
-               return ret;
-
-       return 0;
-}
-
-int radeon_driver_unload(struct drm_device *dev)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-
-       DRM_DEBUG("\n");
-       drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
-
-       dev->dev_private = NULL;
-       return 0;
-}
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
deleted file mode 100644 (file)
index 73ff51f..0000000
+++ /dev/null
@@ -1,749 +0,0 @@
-/* radeon_drm.h -- Public header for the radeon driver -*- linux-c -*-
- *
- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
- * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Kevin E. Martin <martin@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- *    Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#ifndef __RADEON_DRM_H__
-#define __RADEON_DRM_H__
-
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the X server file (radeon_sarea.h)
- */
-#ifndef __RADEON_SAREA_DEFINES__
-#define __RADEON_SAREA_DEFINES__
-
-/* Old style state flags, required for sarea interface (1.1 and 1.2
- * clears) and 1.2 drm_vertex2 ioctl.
- */
-#define RADEON_UPLOAD_CONTEXT          0x00000001
-#define RADEON_UPLOAD_VERTFMT          0x00000002
-#define RADEON_UPLOAD_LINE             0x00000004
-#define RADEON_UPLOAD_BUMPMAP          0x00000008
-#define RADEON_UPLOAD_MASKS            0x00000010
-#define RADEON_UPLOAD_VIEWPORT         0x00000020
-#define RADEON_UPLOAD_SETUP            0x00000040
-#define RADEON_UPLOAD_TCL              0x00000080
-#define RADEON_UPLOAD_MISC             0x00000100
-#define RADEON_UPLOAD_TEX0             0x00000200
-#define RADEON_UPLOAD_TEX1             0x00000400
-#define RADEON_UPLOAD_TEX2             0x00000800
-#define RADEON_UPLOAD_TEX0IMAGES       0x00001000
-#define RADEON_UPLOAD_TEX1IMAGES       0x00002000
-#define RADEON_UPLOAD_TEX2IMAGES       0x00004000
-#define RADEON_UPLOAD_CLIPRECTS                0x00008000      /* handled client-side */
-#define RADEON_REQUIRE_QUIESCENCE      0x00010000
-#define RADEON_UPLOAD_ZBIAS            0x00020000      /* version 1.2 and newer */
-#define RADEON_UPLOAD_ALL              0x003effff
-#define RADEON_UPLOAD_CONTEXT_ALL       0x003e01ff
-
-/* New style per-packet identifiers for use in cmd_buffer ioctl with
- * the RADEON_EMIT_PACKET command.  Comments relate new packets to old
- * state bits and the packet size:
- */
-#define RADEON_EMIT_PP_MISC                         0  /* context/7 */
-#define RADEON_EMIT_PP_CNTL                         1  /* context/3 */
-#define RADEON_EMIT_RB3D_COLORPITCH                 2  /* context/1 */
-#define RADEON_EMIT_RE_LINE_PATTERN                 3  /* line/2 */
-#define RADEON_EMIT_SE_LINE_WIDTH                   4  /* line/1 */
-#define RADEON_EMIT_PP_LUM_MATRIX                   5  /* bumpmap/1 */
-#define RADEON_EMIT_PP_ROT_MATRIX_0                 6  /* bumpmap/2 */
-#define RADEON_EMIT_RB3D_STENCILREFMASK             7  /* masks/3 */
-#define RADEON_EMIT_SE_VPORT_XSCALE                 8  /* viewport/6 */
-#define RADEON_EMIT_SE_CNTL                         9  /* setup/2 */
-#define RADEON_EMIT_SE_CNTL_STATUS                  10 /* setup/1 */
-#define RADEON_EMIT_RE_MISC                         11 /* misc/1 */
-#define RADEON_EMIT_PP_TXFILTER_0                   12 /* tex0/6 */
-#define RADEON_EMIT_PP_BORDER_COLOR_0               13 /* tex0/1 */
-#define RADEON_EMIT_PP_TXFILTER_1                   14 /* tex1/6 */
-#define RADEON_EMIT_PP_BORDER_COLOR_1               15 /* tex1/1 */
-#define RADEON_EMIT_PP_TXFILTER_2                   16 /* tex2/6 */
-#define RADEON_EMIT_PP_BORDER_COLOR_2               17 /* tex2/1 */
-#define RADEON_EMIT_SE_ZBIAS_FACTOR                 18 /* zbias/2 */
-#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT           19 /* tcl/11 */
-#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED   20 /* material/17 */
-#define R200_EMIT_PP_TXCBLEND_0                     21 /* tex0/4 */
-#define R200_EMIT_PP_TXCBLEND_1                     22 /* tex1/4 */
-#define R200_EMIT_PP_TXCBLEND_2                     23 /* tex2/4 */
-#define R200_EMIT_PP_TXCBLEND_3                     24 /* tex3/4 */
-#define R200_EMIT_PP_TXCBLEND_4                     25 /* tex4/4 */
-#define R200_EMIT_PP_TXCBLEND_5                     26 /* tex5/4 */
-#define R200_EMIT_PP_TXCBLEND_6                     27 /* /4 */
-#define R200_EMIT_PP_TXCBLEND_7                     28 /* /4 */
-#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0             29 /* tcl/7 */
-#define R200_EMIT_TFACTOR_0                         30 /* tf/7 */
-#define R200_EMIT_VTX_FMT_0                         31 /* vtx/5 */
-#define R200_EMIT_VAP_CTL                           32 /* vap/1 */
-#define R200_EMIT_MATRIX_SELECT_0                   33 /* msl/5 */
-#define R200_EMIT_TEX_PROC_CTL_2                    34 /* tcg/5 */
-#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL            35 /* tcl/1 */
-#define R200_EMIT_PP_TXFILTER_0                     36 /* tex0/6 */
-#define R200_EMIT_PP_TXFILTER_1                     37 /* tex1/6 */
-#define R200_EMIT_PP_TXFILTER_2                     38 /* tex2/6 */
-#define R200_EMIT_PP_TXFILTER_3                     39 /* tex3/6 */
-#define R200_EMIT_PP_TXFILTER_4                     40 /* tex4/6 */
-#define R200_EMIT_PP_TXFILTER_5                     41 /* tex5/6 */
-#define R200_EMIT_PP_TXOFFSET_0                     42 /* tex0/1 */
-#define R200_EMIT_PP_TXOFFSET_1                     43 /* tex1/1 */
-#define R200_EMIT_PP_TXOFFSET_2                     44 /* tex2/1 */
-#define R200_EMIT_PP_TXOFFSET_3                     45 /* tex3/1 */
-#define R200_EMIT_PP_TXOFFSET_4                     46 /* tex4/1 */
-#define R200_EMIT_PP_TXOFFSET_5                     47 /* tex5/1 */
-#define R200_EMIT_VTE_CNTL                          48 /* vte/1 */
-#define R200_EMIT_OUTPUT_VTX_COMP_SEL               49 /* vtx/1 */
-#define R200_EMIT_PP_TAM_DEBUG3                     50 /* tam/1 */
-#define R200_EMIT_PP_CNTL_X                         51 /* cst/1 */
-#define R200_EMIT_RB3D_DEPTHXY_OFFSET               52 /* cst/1 */
-#define R200_EMIT_RE_AUX_SCISSOR_CNTL               53 /* cst/1 */
-#define R200_EMIT_RE_SCISSOR_TL_0                   54 /* cst/2 */
-#define R200_EMIT_RE_SCISSOR_TL_1                   55 /* cst/2 */
-#define R200_EMIT_RE_SCISSOR_TL_2                   56 /* cst/2 */
-#define R200_EMIT_SE_VAP_CNTL_STATUS                57 /* cst/1 */
-#define R200_EMIT_SE_VTX_STATE_CNTL                 58 /* cst/1 */
-#define R200_EMIT_RE_POINTSIZE                      59 /* cst/1 */
-#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0       60 /* cst/4 */
-#define R200_EMIT_PP_CUBIC_FACES_0                  61
-#define R200_EMIT_PP_CUBIC_OFFSETS_0                62
-#define R200_EMIT_PP_CUBIC_FACES_1                  63
-#define R200_EMIT_PP_CUBIC_OFFSETS_1                64
-#define R200_EMIT_PP_CUBIC_FACES_2                  65
-#define R200_EMIT_PP_CUBIC_OFFSETS_2                66
-#define R200_EMIT_PP_CUBIC_FACES_3                  67
-#define R200_EMIT_PP_CUBIC_OFFSETS_3                68
-#define R200_EMIT_PP_CUBIC_FACES_4                  69
-#define R200_EMIT_PP_CUBIC_OFFSETS_4                70
-#define R200_EMIT_PP_CUBIC_FACES_5                  71
-#define R200_EMIT_PP_CUBIC_OFFSETS_5                72
-#define RADEON_EMIT_PP_TEX_SIZE_0                   73
-#define RADEON_EMIT_PP_TEX_SIZE_1                   74
-#define RADEON_EMIT_PP_TEX_SIZE_2                   75
-#define R200_EMIT_RB3D_BLENDCOLOR                   76
-#define R200_EMIT_TCL_POINT_SPRITE_CNTL             77
-#define RADEON_EMIT_PP_CUBIC_FACES_0                78
-#define RADEON_EMIT_PP_CUBIC_OFFSETS_T0             79
-#define RADEON_EMIT_PP_CUBIC_FACES_1                80
-#define RADEON_EMIT_PP_CUBIC_OFFSETS_T1             81
-#define RADEON_EMIT_PP_CUBIC_FACES_2                82
-#define RADEON_EMIT_PP_CUBIC_OFFSETS_T2             83
-#define R200_EMIT_PP_TRI_PERF_CNTL                  84
-#define R200_EMIT_PP_AFS_0                          85
-#define R200_EMIT_PP_AFS_1                          86
-#define R200_EMIT_ATF_TFACTOR                       87
-#define R200_EMIT_PP_TXCTLALL_0                     88
-#define R200_EMIT_PP_TXCTLALL_1                     89
-#define R200_EMIT_PP_TXCTLALL_2                     90
-#define R200_EMIT_PP_TXCTLALL_3                     91
-#define R200_EMIT_PP_TXCTLALL_4                     92
-#define R200_EMIT_PP_TXCTLALL_5                     93
-#define R200_EMIT_VAP_PVS_CNTL                      94
-#define RADEON_MAX_STATE_PACKETS                    95
-
-/* Commands understood by cmd_buffer ioctl.  More can be added but
- * obviously these can't be removed or changed:
- */
-#define RADEON_CMD_PACKET      1       /* emit one of the register packets above */
-#define RADEON_CMD_SCALARS     2       /* emit scalar data */
-#define RADEON_CMD_VECTORS     3       /* emit vector data */
-#define RADEON_CMD_DMA_DISCARD 4       /* discard current dma buf */
-#define RADEON_CMD_PACKET3     5       /* emit hw packet */
-#define RADEON_CMD_PACKET3_CLIP 6      /* emit hw packet wrapped in cliprects */
-#define RADEON_CMD_SCALARS2     7      /* r200 stopgap */
-#define RADEON_CMD_WAIT         8      /* emit hw wait commands -- note:
-                                        *  doesn't make the cpu wait, just
-                                        *  the graphics hardware */
-#define RADEON_CMD_VECLINEAR   9       /* another r200 stopgap */
-
-typedef union {
-       int i;
-       struct {
-               unsigned char cmd_type, pad0, pad1, pad2;
-       } header;
-       struct {
-               unsigned char cmd_type, packet_id, pad0, pad1;
-       } packet;
-       struct {
-               unsigned char cmd_type, offset, stride, count;
-       } scalars;
-       struct {
-               unsigned char cmd_type, offset, stride, count;
-       } vectors;
-       struct {
-               unsigned char cmd_type, addr_lo, addr_hi, count;
-       } veclinear;
-       struct {
-               unsigned char cmd_type, buf_idx, pad0, pad1;
-       } dma;
-       struct {
-               unsigned char cmd_type, flags, pad0, pad1;
-       } wait;
-} drm_radeon_cmd_header_t;
-
-#define RADEON_WAIT_2D  0x1
-#define RADEON_WAIT_3D  0x2
-
-/* Allowed parameters for R300_CMD_PACKET3
- */
-#define R300_CMD_PACKET3_CLEAR         0
-#define R300_CMD_PACKET3_RAW           1
-
-/* Commands understood by cmd_buffer ioctl for R300.
- * The interface has not been stabilized, so some of these may be removed
- * and eventually reordered before stabilization.
- */
-#define R300_CMD_PACKET0               1
-#define R300_CMD_VPU                   2       /* emit vertex program upload */
-#define R300_CMD_PACKET3               3       /* emit a packet3 */
-#define R300_CMD_END3D                 4       /* emit sequence ending 3d rendering */
-#define R300_CMD_CP_DELAY              5
-#define R300_CMD_DMA_DISCARD           6
-#define R300_CMD_WAIT                  7
-#      define R300_WAIT_2D             0x1
-#      define R300_WAIT_3D             0x2
-/* these two defines are DOING IT WRONG - however
- * we have userspace which relies on using these.
- * The wait interface is backwards compat new 
- * code should use the NEW_WAIT defines below
- * THESE ARE NOT BIT FIELDS
- */
-#      define R300_WAIT_2D_CLEAN       0x3
-#      define R300_WAIT_3D_CLEAN       0x4
-
-#      define R300_NEW_WAIT_2D_3D      0x3
-#      define R300_NEW_WAIT_2D_2D_CLEAN        0x4
-#      define R300_NEW_WAIT_3D_3D_CLEAN        0x6
-#      define R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN    0x8
-
-#define R300_CMD_SCRATCH               8
-#define R300_CMD_R500FP                 9
-
-typedef union {
-       unsigned int u;
-       struct {
-               unsigned char cmd_type, pad0, pad1, pad2;
-       } header;
-       struct {
-               unsigned char cmd_type, count, reglo, reghi;
-       } packet0;
-       struct {
-               unsigned char cmd_type, count, adrlo, adrhi;
-       } vpu;
-       struct {
-               unsigned char cmd_type, packet, pad0, pad1;
-       } packet3;
-       struct {
-               unsigned char cmd_type, packet;
-               unsigned short count;   /* amount of packet2 to emit */
-       } delay;
-       struct {
-               unsigned char cmd_type, buf_idx, pad0, pad1;
-       } dma;
-       struct {
-               unsigned char cmd_type, flags, pad0, pad1;
-       } wait;
-       struct {
-               unsigned char cmd_type, reg, n_bufs, flags;
-       } scratch;
-       struct {
-               unsigned char cmd_type, count, adrlo, adrhi_flags;
-       } r500fp;
-} drm_r300_cmd_header_t;
-
-#define RADEON_FRONT                   0x1
-#define RADEON_BACK                    0x2
-#define RADEON_DEPTH                   0x4
-#define RADEON_STENCIL                 0x8
-#define RADEON_CLEAR_FASTZ             0x80000000
-#define RADEON_USE_HIERZ               0x40000000
-#define RADEON_USE_COMP_ZBUF           0x20000000
-
-#define R500FP_CONSTANT_TYPE  (1 << 1)
-#define R500FP_CONSTANT_CLAMP (1 << 2)
-
-/* Primitive types
- */
-#define RADEON_POINTS                  0x1
-#define RADEON_LINES                   0x2
-#define RADEON_LINE_STRIP              0x3
-#define RADEON_TRIANGLES               0x4
-#define RADEON_TRIANGLE_FAN            0x5
-#define RADEON_TRIANGLE_STRIP          0x6
-
-/* Vertex/indirect buffer size
- */
-#define RADEON_BUFFER_SIZE             65536
-
-/* Byte offsets for indirect buffer data
- */
-#define RADEON_INDEX_PRIM_OFFSET       20
-
-#define RADEON_SCRATCH_REG_OFFSET      32
-
-#define RADEON_NR_SAREA_CLIPRECTS      12
-
-/* There are 2 heaps (local/GART).  Each region within a heap is a
- * minimum of 64k, and there are at most 64 of them per heap.
- */
-#define RADEON_LOCAL_TEX_HEAP          0
-#define RADEON_GART_TEX_HEAP           1
-#define RADEON_NR_TEX_HEAPS            2
-#define RADEON_NR_TEX_REGIONS          64
-#define RADEON_LOG_TEX_GRANULARITY     16
-
-#define RADEON_MAX_TEXTURE_LEVELS      12
-#define RADEON_MAX_TEXTURE_UNITS       3
-
-#define RADEON_MAX_SURFACES            8
-
-/* Blits have strict offset rules.  All blit offset must be aligned on
- * a 1K-byte boundary.
- */
-#define RADEON_OFFSET_SHIFT             10
-#define RADEON_OFFSET_ALIGN             (1 << RADEON_OFFSET_SHIFT)
-#define RADEON_OFFSET_MASK              (RADEON_OFFSET_ALIGN - 1)
-
-#endif                         /* __RADEON_SAREA_DEFINES__ */
-
-typedef struct {
-       unsigned int red;
-       unsigned int green;
-       unsigned int blue;
-       unsigned int alpha;
-} radeon_color_regs_t;
-
-typedef struct {
-       /* Context state */
-       unsigned int pp_misc;   /* 0x1c14 */
-       unsigned int pp_fog_color;
-       unsigned int re_solid_color;
-       unsigned int rb3d_blendcntl;
-       unsigned int rb3d_depthoffset;
-       unsigned int rb3d_depthpitch;
-       unsigned int rb3d_zstencilcntl;
-
-       unsigned int pp_cntl;   /* 0x1c38 */
-       unsigned int rb3d_cntl;
-       unsigned int rb3d_coloroffset;
-       unsigned int re_width_height;
-       unsigned int rb3d_colorpitch;
-       unsigned int se_cntl;
-
-       /* Vertex format state */
-       unsigned int se_coord_fmt;      /* 0x1c50 */
-
-       /* Line state */
-       unsigned int re_line_pattern;   /* 0x1cd0 */
-       unsigned int re_line_state;
-
-       unsigned int se_line_width;     /* 0x1db8 */
-
-       /* Bumpmap state */
-       unsigned int pp_lum_matrix;     /* 0x1d00 */
-
-       unsigned int pp_rot_matrix_0;   /* 0x1d58 */
-       unsigned int pp_rot_matrix_1;
-
-       /* Mask state */
-       unsigned int rb3d_stencilrefmask;       /* 0x1d7c */
-       unsigned int rb3d_ropcntl;
-       unsigned int rb3d_planemask;
-
-       /* Viewport state */
-       unsigned int se_vport_xscale;   /* 0x1d98 */
-       unsigned int se_vport_xoffset;
-       unsigned int se_vport_yscale;
-       unsigned int se_vport_yoffset;
-       unsigned int se_vport_zscale;
-       unsigned int se_vport_zoffset;
-
-       /* Setup state */
-       unsigned int se_cntl_status;    /* 0x2140 */
-
-       /* Misc state */
-       unsigned int re_top_left;       /* 0x26c0 */
-       unsigned int re_misc;
-} drm_radeon_context_regs_t;
-
-typedef struct {
-       /* Zbias state */
-       unsigned int se_zbias_factor;   /* 0x1dac */
-       unsigned int se_zbias_constant;
-} drm_radeon_context2_regs_t;
-
-/* Setup registers for each texture unit
- */
-typedef struct {
-       unsigned int pp_txfilter;
-       unsigned int pp_txformat;
-       unsigned int pp_txoffset;
-       unsigned int pp_txcblend;
-       unsigned int pp_txablend;
-       unsigned int pp_tfactor;
-       unsigned int pp_border_color;
-} drm_radeon_texture_regs_t;
-
-typedef struct {
-       unsigned int start;
-       unsigned int finish;
-       unsigned int prim:8;
-       unsigned int stateidx:8;
-       unsigned int numverts:16;       /* overloaded as offset/64 for elt prims */
-       unsigned int vc_format; /* vertex format */
-} drm_radeon_prim_t;
-
-typedef struct {
-       drm_radeon_context_regs_t context;
-       drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS];
-       drm_radeon_context2_regs_t context2;
-       unsigned int dirty;
-} drm_radeon_state_t;
-
-typedef struct {
-       /* The channel for communication of state information to the
-        * kernel on firing a vertex buffer with either of the
-        * obsoleted vertex/index ioctls.
-        */
-       drm_radeon_context_regs_t context_state;
-       drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS];
-       unsigned int dirty;
-       unsigned int vertsize;
-       unsigned int vc_format;
-
-       /* The current cliprects, or a subset thereof.
-        */
-       struct drm_clip_rect boxes[RADEON_NR_SAREA_CLIPRECTS];
-       unsigned int nbox;
-
-       /* Counters for client-side throttling of rendering clients.
-        */
-       unsigned int last_frame;
-       unsigned int last_dispatch;
-       unsigned int last_clear;
-
-       struct drm_tex_region tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
-                                                      1];
-       unsigned int tex_age[RADEON_NR_TEX_HEAPS];
-       int ctx_owner;
-       int pfState;            /* number of 3d windows (0,1,2ormore) */
-       int pfCurrentPage;      /* which buffer is being displayed? */
-       int crtc2_base;         /* CRTC2 frame offset */
-       int tiling_enabled;     /* set by drm, read by 2d + 3d clients */
-} drm_radeon_sarea_t;
-
-/* WARNING: If you change any of these defines, make sure to change the
- * defines in the Xserver file (xf86drmRadeon.h)
- *
- * KW: actually it's illegal to change any of this (backwards compatibility).
- */
-
-/* Radeon specific ioctls
- * The device specific ioctl range is 0x40 to 0x79.
- */
-#define DRM_RADEON_CP_INIT    0x00
-#define DRM_RADEON_CP_START   0x01
-#define DRM_RADEON_CP_STOP    0x02
-#define DRM_RADEON_CP_RESET   0x03
-#define DRM_RADEON_CP_IDLE    0x04
-#define DRM_RADEON_RESET      0x05
-#define DRM_RADEON_FULLSCREEN 0x06
-#define DRM_RADEON_SWAP       0x07
-#define DRM_RADEON_CLEAR      0x08
-#define DRM_RADEON_VERTEX     0x09
-#define DRM_RADEON_INDICES    0x0A
-#define DRM_RADEON_NOT_USED
-#define DRM_RADEON_STIPPLE    0x0C
-#define DRM_RADEON_INDIRECT   0x0D
-#define DRM_RADEON_TEXTURE    0x0E
-#define DRM_RADEON_VERTEX2    0x0F
-#define DRM_RADEON_CMDBUF     0x10
-#define DRM_RADEON_GETPARAM   0x11
-#define DRM_RADEON_FLIP       0x12
-#define DRM_RADEON_ALLOC      0x13
-#define DRM_RADEON_FREE       0x14
-#define DRM_RADEON_INIT_HEAP  0x15
-#define DRM_RADEON_IRQ_EMIT   0x16
-#define DRM_RADEON_IRQ_WAIT   0x17
-#define DRM_RADEON_CP_RESUME  0x18
-#define DRM_RADEON_SETPARAM   0x19
-#define DRM_RADEON_SURF_ALLOC 0x1a
-#define DRM_RADEON_SURF_FREE  0x1b
-
-#define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
-#define DRM_IOCTL_RADEON_CP_START   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_START)
-#define DRM_IOCTL_RADEON_CP_STOP    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t)
-#define DRM_IOCTL_RADEON_CP_RESET   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_RESET)
-#define DRM_IOCTL_RADEON_CP_IDLE    DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_IDLE)
-#define DRM_IOCTL_RADEON_RESET      DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_RESET)
-#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FULLSCREEN, drm_radeon_fullscreen_t)
-#define DRM_IOCTL_RADEON_SWAP       DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_SWAP)
-#define DRM_IOCTL_RADEON_CLEAR      DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CLEAR, drm_radeon_clear_t)
-#define DRM_IOCTL_RADEON_VERTEX     DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX, drm_radeon_vertex_t)
-#define DRM_IOCTL_RADEON_INDICES    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INDICES, drm_radeon_indices_t)
-#define DRM_IOCTL_RADEON_STIPPLE    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_STIPPLE, drm_radeon_stipple_t)
-#define DRM_IOCTL_RADEON_INDIRECT   DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INDIRECT, drm_radeon_indirect_t)
-#define DRM_IOCTL_RADEON_TEXTURE    DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_TEXTURE, drm_radeon_texture_t)
-#define DRM_IOCTL_RADEON_VERTEX2    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX2, drm_radeon_vertex2_t)
-#define DRM_IOCTL_RADEON_CMDBUF     DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CMDBUF, drm_radeon_cmd_buffer_t)
-#define DRM_IOCTL_RADEON_GETPARAM   DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GETPARAM, drm_radeon_getparam_t)
-#define DRM_IOCTL_RADEON_FLIP       DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_FLIP)
-#define DRM_IOCTL_RADEON_ALLOC      DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_ALLOC, drm_radeon_mem_alloc_t)
-#define DRM_IOCTL_RADEON_FREE       DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FREE, drm_radeon_mem_free_t)
-#define DRM_IOCTL_RADEON_INIT_HEAP  DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INIT_HEAP, drm_radeon_mem_init_heap_t)
-#define DRM_IOCTL_RADEON_IRQ_EMIT   DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_IRQ_EMIT, drm_radeon_irq_emit_t)
-#define DRM_IOCTL_RADEON_IRQ_WAIT   DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_IRQ_WAIT, drm_radeon_irq_wait_t)
-#define DRM_IOCTL_RADEON_CP_RESUME  DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_RESUME)
-#define DRM_IOCTL_RADEON_SETPARAM   DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t)
-#define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t)
-#define DRM_IOCTL_RADEON_SURF_FREE  DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t)
-
-typedef struct drm_radeon_init {
-       enum {
-               RADEON_INIT_CP = 0x01,
-               RADEON_CLEANUP_CP = 0x02,
-               RADEON_INIT_R200_CP = 0x03,
-               RADEON_INIT_R300_CP = 0x04
-       } func;
-       unsigned long sarea_priv_offset;
-       int is_pci;
-       int cp_mode;
-       int gart_size;
-       int ring_size;
-       int usec_timeout;
-
-       unsigned int fb_bpp;
-       unsigned int front_offset, front_pitch;
-       unsigned int back_offset, back_pitch;
-       unsigned int depth_bpp;
-       unsigned int depth_offset, depth_pitch;
-
-       unsigned long fb_offset;
-       unsigned long mmio_offset;
-       unsigned long ring_offset;
-       unsigned long ring_rptr_offset;
-       unsigned long buffers_offset;
-       unsigned long gart_textures_offset;
-} drm_radeon_init_t;
-
-typedef struct drm_radeon_cp_stop {
-       int flush;
-       int idle;
-} drm_radeon_cp_stop_t;
-
-typedef struct drm_radeon_fullscreen {
-       enum {
-               RADEON_INIT_FULLSCREEN = 0x01,
-               RADEON_CLEANUP_FULLSCREEN = 0x02
-       } func;
-} drm_radeon_fullscreen_t;
-
-#define CLEAR_X1       0
-#define CLEAR_Y1       1
-#define CLEAR_X2       2
-#define CLEAR_Y2       3
-#define CLEAR_DEPTH    4
-
-typedef union drm_radeon_clear_rect {
-       float f[5];
-       unsigned int ui[5];
-} drm_radeon_clear_rect_t;
-
-typedef struct drm_radeon_clear {
-       unsigned int flags;
-       unsigned int clear_color;
-       unsigned int clear_depth;
-       unsigned int color_mask;
-       unsigned int depth_mask;        /* misnamed field:  should be stencil */
-       drm_radeon_clear_rect_t __user *depth_boxes;
-} drm_radeon_clear_t;
-
-typedef struct drm_radeon_vertex {
-       int prim;
-       int idx;                /* Index of vertex buffer */
-       int count;              /* Number of vertices in buffer */
-       int discard;            /* Client finished with buffer? */
-} drm_radeon_vertex_t;
-
-typedef struct drm_radeon_indices {
-       int prim;
-       int idx;
-       int start;
-       int end;
-       int discard;            /* Client finished with buffer? */
-} drm_radeon_indices_t;
-
-/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices
- *      - allows multiple primitives and state changes in a single ioctl
- *      - supports driver change to emit native primitives
- */
-typedef struct drm_radeon_vertex2 {
-       int idx;                /* Index of vertex buffer */
-       int discard;            /* Client finished with buffer? */
-       int nr_states;
-       drm_radeon_state_t __user *state;
-       int nr_prims;
-       drm_radeon_prim_t __user *prim;
-} drm_radeon_vertex2_t;
-
-/* v1.3 - obsoletes drm_radeon_vertex2
- *      - allows arbitarily large cliprect list
- *      - allows updating of tcl packet, vector and scalar state
- *      - allows memory-efficient description of state updates
- *      - allows state to be emitted without a primitive
- *           (for clears, ctx switches)
- *      - allows more than one dma buffer to be referenced per ioctl
- *      - supports tcl driver
- *      - may be extended in future versions with new cmd types, packets
- */
-typedef struct drm_radeon_cmd_buffer {
-       int bufsz;
-       char __user *buf;
-       int nbox;
-       struct drm_clip_rect __user *boxes;
-} drm_radeon_cmd_buffer_t;
-
-typedef struct drm_radeon_tex_image {
-       unsigned int x, y;      /* Blit coordinates */
-       unsigned int width, height;
-       const void __user *data;
-} drm_radeon_tex_image_t;
-
-typedef struct drm_radeon_texture {
-       unsigned int offset;
-       int pitch;
-       int format;
-       int width;              /* Texture image coordinates */
-       int height;
-       drm_radeon_tex_image_t __user *image;
-} drm_radeon_texture_t;
-
-typedef struct drm_radeon_stipple {
-       unsigned int __user *mask;
-} drm_radeon_stipple_t;
-
-typedef struct drm_radeon_indirect {
-       int idx;
-       int start;
-       int end;
-       int discard;
-} drm_radeon_indirect_t;
-
-/* enum for card type parameters */
-#define RADEON_CARD_PCI 0
-#define RADEON_CARD_AGP 1
-#define RADEON_CARD_PCIE 2
-
-/* 1.3: An ioctl to get parameters that aren't available to the 3d
- * client any other way.
- */
-#define RADEON_PARAM_GART_BUFFER_OFFSET    1   /* card offset of 1st GART buffer */
-#define RADEON_PARAM_LAST_FRAME            2
-#define RADEON_PARAM_LAST_DISPATCH         3
-#define RADEON_PARAM_LAST_CLEAR            4
-/* Added with DRM version 1.6. */
-#define RADEON_PARAM_IRQ_NR                5
-#define RADEON_PARAM_GART_BASE             6   /* card offset of GART base */
-/* Added with DRM version 1.8. */
-#define RADEON_PARAM_REGISTER_HANDLE       7   /* for drmMap() */
-#define RADEON_PARAM_STATUS_HANDLE         8
-#define RADEON_PARAM_SAREA_HANDLE          9
-#define RADEON_PARAM_GART_TEX_HANDLE       10
-#define RADEON_PARAM_SCRATCH_OFFSET        11
-#define RADEON_PARAM_CARD_TYPE             12
-#define RADEON_PARAM_VBLANK_CRTC           13   /* VBLANK CRTC */
-#define RADEON_PARAM_FB_LOCATION           14   /* FB location */
-#define RADEON_PARAM_NUM_GB_PIPES          15   /* num GB pipes */
-
-typedef struct drm_radeon_getparam {
-       int param;
-       void __user *value;
-} drm_radeon_getparam_t;
-
-/* 1.6: Set up a memory manager for regions of shared memory:
- */
-#define RADEON_MEM_REGION_GART 1
-#define RADEON_MEM_REGION_FB   2
-
-typedef struct drm_radeon_mem_alloc {
-       int region;
-       int alignment;
-       int size;
-       int __user *region_offset;      /* offset from start of fb or GART */
-} drm_radeon_mem_alloc_t;
-
-typedef struct drm_radeon_mem_free {
-       int region;
-       int region_offset;
-} drm_radeon_mem_free_t;
-
-typedef struct drm_radeon_mem_init_heap {
-       int region;
-       int size;
-       int start;
-} drm_radeon_mem_init_heap_t;
-
-/* 1.6: Userspace can request & wait on irq's:
- */
-typedef struct drm_radeon_irq_emit {
-       int __user *irq_seq;
-} drm_radeon_irq_emit_t;
-
-typedef struct drm_radeon_irq_wait {
-       int irq_seq;
-} drm_radeon_irq_wait_t;
-
-/* 1.10: Clients tell the DRM where they think the framebuffer is located in
- * the card's address space, via a new generic ioctl to set parameters
- */
-
-typedef struct drm_radeon_setparam {
-       unsigned int param;
-       int64_t value;
-} drm_radeon_setparam_t;
-
-#define RADEON_SETPARAM_FB_LOCATION    1       /* determined framebuffer location */
-#define RADEON_SETPARAM_SWITCH_TILING  2       /* enable/disable color tiling */
-#define RADEON_SETPARAM_PCIGART_LOCATION 3     /* PCI Gart Location */
-#define RADEON_SETPARAM_NEW_MEMMAP 4           /* Use new memory map */
-#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5    /* PCI GART Table Size */
-#define RADEON_SETPARAM_VBLANK_CRTC 6           /* VBLANK CRTC */
-/* 1.14: Clients can allocate/free a surface
- */
-typedef struct drm_radeon_surface_alloc {
-       unsigned int address;
-       unsigned int size;
-       unsigned int flags;
-} drm_radeon_surface_alloc_t;
-
-typedef struct drm_radeon_surface_free {
-       unsigned int address;
-} drm_radeon_surface_free_t;
-
-#define        DRM_RADEON_VBLANK_CRTC1         1
-#define        DRM_RADEON_VBLANK_CRTC2         2
-
-#endif
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
deleted file mode 100644 (file)
index 349ac3d..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/**
- * \file radeon_drv.c
- * ATI Radeon driver
- *
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "radeon_drm.h"
-#include "radeon_drv.h"
-
-#include "drm_pciids.h"
-
-int radeon_no_wb;
-
-MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers\n");
-module_param_named(no_wb, radeon_no_wb, int, 0444);
-
-static int dri_library_name(struct drm_device *dev, char *buf)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       int family = dev_priv->flags & RADEON_FAMILY_MASK;
-
-       return snprintf(buf, PAGE_SIZE, "%s\n",
-                       (family < CHIP_R200) ? "radeon" :
-                       ((family < CHIP_R300) ? "r200" :
-                       "r300"));
-}
-
-static struct pci_device_id pciidlist[] = {
-       radeon_PCI_IDS
-};
-
-static struct drm_driver driver = {
-       .driver_features =
-           DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
-           DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
-           DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
-       .dev_priv_size = sizeof(drm_radeon_buf_priv_t),
-       .load = radeon_driver_load,
-       .firstopen = radeon_driver_firstopen,
-       .open = radeon_driver_open,
-       .preclose = radeon_driver_preclose,
-       .postclose = radeon_driver_postclose,
-       .lastclose = radeon_driver_lastclose,
-       .unload = radeon_driver_unload,
-       .vblank_wait = radeon_driver_vblank_wait,
-       .vblank_wait2 = radeon_driver_vblank_wait2,
-       .dri_library_name = dri_library_name,
-       .irq_preinstall = radeon_driver_irq_preinstall,
-       .irq_postinstall = radeon_driver_irq_postinstall,
-       .irq_uninstall = radeon_driver_irq_uninstall,
-       .irq_handler = radeon_driver_irq_handler,
-       .reclaim_buffers = drm_core_reclaim_buffers,
-       .get_map_ofs = drm_core_get_map_ofs,
-       .get_reg_ofs = drm_core_get_reg_ofs,
-       .ioctls = radeon_ioctls,
-       .dma_ioctl = radeon_cp_buffers,
-       .fops = {
-                .owner = THIS_MODULE,
-                .open = drm_open,
-                .release = drm_release,
-                .ioctl = drm_ioctl,
-                .mmap = drm_mmap,
-                .poll = drm_poll,
-                .fasync = drm_fasync,
-#ifdef CONFIG_COMPAT
-                .compat_ioctl = radeon_compat_ioctl,
-#endif
-       },
-
-       .pci_driver = {
-                .name = DRIVER_NAME,
-                .id_table = pciidlist,
-       },
-
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int __init radeon_init(void)
-{
-       driver.num_ioctls = radeon_max_ioctl;
-       return drm_init(&driver);
-}
-
-static void __exit radeon_exit(void)
-{
-       drm_exit(&driver);
-}
-
-module_init(radeon_init);
-module_exit(radeon_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
deleted file mode 100644 (file)
index 3f0eca9..0000000
+++ /dev/null
@@ -1,1406 +0,0 @@
-/* radeon_drv.h -- Private header for radeon driver -*- linux-c -*-
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Kevin E. Martin <martin@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#ifndef __RADEON_DRV_H__
-#define __RADEON_DRV_H__
-
-/* General customization:
- */
-
-#define DRIVER_AUTHOR          "Gareth Hughes, Keith Whitwell, others."
-
-#define DRIVER_NAME            "radeon"
-#define DRIVER_DESC            "ATI Radeon"
-#define DRIVER_DATE            "20080528"
-
-/* Interface history:
- *
- * 1.1 - ??
- * 1.2 - Add vertex2 ioctl (keith)
- *     - Add stencil capability to clear ioctl (gareth, keith)
- *     - Increase MAX_TEXTURE_LEVELS (brian)
- * 1.3 - Add cmdbuf ioctl (keith)
- *     - Add support for new radeon packets (keith)
- *     - Add getparam ioctl (keith)
- *     - Add flip-buffers ioctl, deprecate fullscreen foo (keith).
- * 1.4 - Add scratch registers to get_param ioctl.
- * 1.5 - Add r200 packets to cmdbuf ioctl
- *     - Add r200 function to init ioctl
- *     - Add 'scalar2' instruction to cmdbuf
- * 1.6 - Add static GART memory manager
- *       Add irq handler (won't be turned on unless X server knows to)
- *       Add irq ioctls and irq_active getparam.
- *       Add wait command for cmdbuf ioctl
- *       Add GART offset query for getparam
- * 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5]
- *       and R200_PP_CUBIC_OFFSET_F1_[0..5].
- *       Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and
- *       R200_EMIT_PP_CUBIC_OFFSETS_[0..5].  (brian)
- * 1.8 - Remove need to call cleanup ioctls on last client exit (keith)
- *       Add 'GET' queries for starting additional clients on different VT's.
- * 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl.
- *       Add texture rectangle support for r100.
- * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which
- *       clients use to tell the DRM where they think the framebuffer is
- *       located in the card's address space
- * 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color
- *       and GL_EXT_blend_[func|equation]_separate on r200
- * 1.12- Add R300 CP microcode support - this just loads the CP on r300
- *       (No 3D support yet - just microcode loading).
- * 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters
- *     - Add hyperz support, add hyperz flags to clear ioctl.
- * 1.14- Add support for color tiling
- *     - Add R100/R200 surface allocation/free support
- * 1.15- Add support for texture micro tiling
- *     - Add support for r100 cube maps
- * 1.16- Add R200_EMIT_PP_TRI_PERF_CNTL packet to support brilinear
- *       texture filtering on r200
- * 1.17- Add initial support for R300 (3D).
- * 1.18- Add support for GL_ATI_fragment_shader, new packets
- *       R200_EMIT_PP_AFS_0/1, R200_EMIT_PP_TXCTLALL_0-5 (replaces
- *       R200_EMIT_PP_TXFILTER_0-5, 2 more regs) and R200_EMIT_ATF_TFACTOR
- *       (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6)
- * 1.19- Add support for gart table in FB memory and PCIE r300
- * 1.20- Add support for r300 texrect
- * 1.21- Add support for card type getparam
- * 1.22- Add support for texture cache flushes (R300_TX_CNTL)
- * 1.23- Add new radeon memory map work from benh
- * 1.24- Add general-purpose packet for manipulating scratch registers (r300)
- * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL,
- *       new packet type)
- * 1.26- Add support for variable size PCI(E) gart aperture
- * 1.27- Add support for IGP GART
- * 1.28- Add support for VBL on CRTC2
- * 1.29- R500 3D cmd buffer support
- */
-#define DRIVER_MAJOR           1
-#define DRIVER_MINOR           29
-#define DRIVER_PATCHLEVEL      0
-
-/*
- * Radeon chip families
- */
-enum radeon_family {
-       CHIP_R100,
-       CHIP_RV100,
-       CHIP_RS100,
-       CHIP_RV200,
-       CHIP_RS200,
-       CHIP_R200,
-       CHIP_RV250,
-       CHIP_RS300,
-       CHIP_RV280,
-       CHIP_R300,
-       CHIP_R350,
-       CHIP_RV350,
-       CHIP_RV380,
-       CHIP_R420,
-       CHIP_RV410,
-       CHIP_RS480,
-       CHIP_RS690,
-       CHIP_RV515,
-       CHIP_R520,
-       CHIP_RV530,
-       CHIP_RV560,
-       CHIP_RV570,
-       CHIP_R580,
-       CHIP_LAST,
-};
-
-enum radeon_cp_microcode_version {
-       UCODE_R100,
-       UCODE_R200,
-       UCODE_R300,
-};
-
-/*
- * Chip flags
- */
-enum radeon_chip_flags {
-       RADEON_FAMILY_MASK = 0x0000ffffUL,
-       RADEON_FLAGS_MASK = 0xffff0000UL,
-       RADEON_IS_MOBILITY = 0x00010000UL,
-       RADEON_IS_IGP = 0x00020000UL,
-       RADEON_SINGLE_CRTC = 0x00040000UL,
-       RADEON_IS_AGP = 0x00080000UL,
-       RADEON_HAS_HIERZ = 0x00100000UL,
-       RADEON_IS_PCIE = 0x00200000UL,
-       RADEON_NEW_MEMMAP = 0x00400000UL,
-       RADEON_IS_PCI = 0x00800000UL,
-       RADEON_IS_IGPGART = 0x01000000UL,
-};
-
-#define GET_RING_HEAD(dev_priv)        (dev_priv->writeback_works ? \
-        DRM_READ32(  (dev_priv)->ring_rptr, 0 ) : RADEON_READ(RADEON_CP_RB_RPTR))
-#define SET_RING_HEAD(dev_priv,val)    DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
-
-typedef struct drm_radeon_freelist {
-       unsigned int age;
-       struct drm_buf *buf;
-       struct drm_radeon_freelist *next;
-       struct drm_radeon_freelist *prev;
-} drm_radeon_freelist_t;
-
-typedef struct drm_radeon_ring_buffer {
-       u32 *start;
-       u32 *end;
-       int size;
-       int size_l2qw;
-
-       int rptr_update; /* Double Words */
-       int rptr_update_l2qw; /* log2 Quad Words */
-
-       int fetch_size; /* Double Words */
-       int fetch_size_l2ow; /* log2 Oct Words */
-
-       u32 tail;
-       u32 tail_mask;
-       int space;
-
-       int high_mark;
-} drm_radeon_ring_buffer_t;
-
-typedef struct drm_radeon_depth_clear_t {
-       u32 rb3d_cntl;
-       u32 rb3d_zstencilcntl;
-       u32 se_cntl;
-} drm_radeon_depth_clear_t;
-
-struct drm_radeon_driver_file_fields {
-       int64_t radeon_fb_delta;
-};
-
-struct mem_block {
-       struct mem_block *next;
-       struct mem_block *prev;
-       int start;
-       int size;
-       struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */
-};
-
-struct radeon_surface {
-       int refcount;
-       u32 lower;
-       u32 upper;
-       u32 flags;
-};
-
-struct radeon_virt_surface {
-       int surface_index;
-       u32 lower;
-       u32 upper;
-       u32 flags;
-       struct drm_file *file_priv;
-};
-
-typedef struct drm_radeon_private {
-       drm_radeon_ring_buffer_t ring;
-       drm_radeon_sarea_t *sarea_priv;
-
-       u32 fb_location;
-       u32 fb_size;
-       int new_memmap;
-
-       int gart_size;
-       u32 gart_vm_start;
-       unsigned long gart_buffers_offset;
-
-       int cp_mode;
-       int cp_running;
-
-       drm_radeon_freelist_t *head;
-       drm_radeon_freelist_t *tail;
-       int last_buf;
-       volatile u32 *scratch;
-       int writeback_works;
-
-       int usec_timeout;
-
-       int microcode_version;
-
-       struct {
-               u32 boxes;
-               int freelist_timeouts;
-               int freelist_loops;
-               int requested_bufs;
-               int last_frame_reads;
-               int last_clear_reads;
-               int clears;
-               int texture_uploads;
-       } stats;
-
-       int do_boxes;
-       int page_flipping;
-
-       u32 color_fmt;
-       unsigned int front_offset;
-       unsigned int front_pitch;
-       unsigned int back_offset;
-       unsigned int back_pitch;
-
-       u32 depth_fmt;
-       unsigned int depth_offset;
-       unsigned int depth_pitch;
-
-       u32 front_pitch_offset;
-       u32 back_pitch_offset;
-       u32 depth_pitch_offset;
-
-       drm_radeon_depth_clear_t depth_clear;
-
-       unsigned long ring_offset;
-       unsigned long ring_rptr_offset;
-       unsigned long buffers_offset;
-       unsigned long gart_textures_offset;
-
-       drm_local_map_t *sarea;
-       drm_local_map_t *mmio;
-       drm_local_map_t *cp_ring;
-       drm_local_map_t *ring_rptr;
-       drm_local_map_t *gart_textures;
-
-       struct mem_block *gart_heap;
-       struct mem_block *fb_heap;
-
-       /* SW interrupt */
-       wait_queue_head_t swi_queue;
-       atomic_t swi_emitted;
-       int vblank_crtc;
-       uint32_t irq_enable_reg;
-       int irq_enabled;
-       uint32_t r500_disp_irq_reg;
-
-       struct radeon_surface surfaces[RADEON_MAX_SURFACES];
-       struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
-
-       unsigned long pcigart_offset;
-       unsigned int pcigart_offset_set;
-       struct drm_ati_pcigart_info gart_info;
-
-       u32 scratch_ages[5];
-
-       /* starting from here on, data is preserved accross an open */
-       uint32_t flags;         /* see radeon_chip_flags */
-       unsigned long fb_aper_offset;
-
-       int num_gb_pipes;
-} drm_radeon_private_t;
-
-typedef struct drm_radeon_buf_priv {
-       u32 age;
-} drm_radeon_buf_priv_t;
-
-typedef struct drm_radeon_kcmd_buffer {
-       int bufsz;
-       char *buf;
-       int nbox;
-       struct drm_clip_rect __user *boxes;
-} drm_radeon_kcmd_buffer_t;
-
-extern int radeon_no_wb;
-extern struct drm_ioctl_desc radeon_ioctls[];
-extern int radeon_max_ioctl;
-
-/* Check whether the given hardware address is inside the framebuffer or the
- * GART area.
- */
-static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv,
-                                         u64 off)
-{
-       u32 fb_start = dev_priv->fb_location;
-       u32 fb_end = fb_start + dev_priv->fb_size - 1;
-       u32 gart_start = dev_priv->gart_vm_start;
-       u32 gart_end = gart_start + dev_priv->gart_size - 1;
-
-       return ((off >= fb_start && off <= fb_end) ||
-               (off >= gart_start && off <= gart_end));
-}
-
-                               /* radeon_cp.c */
-extern int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv);
-
-extern void radeon_freelist_reset(struct drm_device * dev);
-extern struct drm_buf *radeon_freelist_get(struct drm_device * dev);
-
-extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n);
-
-extern int radeon_do_cp_idle(drm_radeon_private_t * dev_priv);
-
-extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags);
-extern int radeon_presetup(struct drm_device *dev);
-extern int radeon_driver_postcleanup(struct drm_device *dev);
-
-extern int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern void radeon_mem_takedown(struct mem_block **heap);
-extern void radeon_mem_release(struct drm_file *file_priv,
-                              struct mem_block *heap);
-
-                               /* radeon_irq.c */
-extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
-
-extern void radeon_do_release(struct drm_device * dev);
-extern int radeon_driver_vblank_wait(struct drm_device * dev,
-                                    unsigned int *sequence);
-extern int radeon_driver_vblank_wait2(struct drm_device * dev,
-                                     unsigned int *sequence);
-extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
-extern void radeon_driver_irq_preinstall(struct drm_device * dev);
-extern void radeon_driver_irq_postinstall(struct drm_device * dev);
-extern void radeon_driver_irq_uninstall(struct drm_device * dev);
-extern void radeon_enable_interrupt(struct drm_device *dev);
-extern int radeon_vblank_crtc_get(struct drm_device *dev);
-extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
-
-extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
-extern int radeon_driver_unload(struct drm_device *dev);
-extern int radeon_driver_firstopen(struct drm_device *dev);
-extern void radeon_driver_preclose(struct drm_device * dev, struct drm_file *file_priv);
-extern void radeon_driver_postclose(struct drm_device * dev, struct drm_file * filp);
-extern void radeon_driver_lastclose(struct drm_device * dev);
-extern int radeon_driver_open(struct drm_device * dev, struct drm_file * filp_priv);
-extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
-                               unsigned long arg);
-
-/* r300_cmdbuf.c */
-extern void r300_init_reg_flags(struct drm_device *dev);
-
-extern int r300_do_cp_cmdbuf(struct drm_device * dev,
-                            struct drm_file *file_priv,
-                            drm_radeon_kcmd_buffer_t * cmdbuf);
-
-/* Flags for stats.boxes
- */
-#define RADEON_BOX_DMA_IDLE      0x1
-#define RADEON_BOX_RING_FULL     0x2
-#define RADEON_BOX_FLIP          0x4
-#define RADEON_BOX_WAIT_IDLE     0x8
-#define RADEON_BOX_TEXTURE_LOAD  0x10
-
-/* Register definitions, register access macros and drmAddMap constants
- * for Radeon kernel driver.
- */
-
-#define RADEON_AGP_COMMAND             0x0f60
-#define RADEON_AGP_COMMAND_PCI_CONFIG   0x0060 /* offset in PCI config */
-#      define RADEON_AGP_ENABLE        (1<<8)
-#define RADEON_AUX_SCISSOR_CNTL                0x26f0
-#      define RADEON_EXCLUSIVE_SCISSOR_0       (1 << 24)
-#      define RADEON_EXCLUSIVE_SCISSOR_1       (1 << 25)
-#      define RADEON_EXCLUSIVE_SCISSOR_2       (1 << 26)
-#      define RADEON_SCISSOR_0_ENABLE          (1 << 28)
-#      define RADEON_SCISSOR_1_ENABLE          (1 << 29)
-#      define RADEON_SCISSOR_2_ENABLE          (1 << 30)
-
-#define RADEON_BUS_CNTL                        0x0030
-#      define RADEON_BUS_MASTER_DIS            (1 << 6)
-
-#define RADEON_CLOCK_CNTL_DATA         0x000c
-#      define RADEON_PLL_WR_EN                 (1 << 7)
-#define RADEON_CLOCK_CNTL_INDEX                0x0008
-#define RADEON_CONFIG_APER_SIZE                0x0108
-#define RADEON_CONFIG_MEMSIZE          0x00f8
-#define RADEON_CRTC_OFFSET             0x0224
-#define RADEON_CRTC_OFFSET_CNTL                0x0228
-#      define RADEON_CRTC_TILE_EN              (1 << 15)
-#      define RADEON_CRTC_OFFSET_FLIP_CNTL     (1 << 16)
-#define RADEON_CRTC2_OFFSET            0x0324
-#define RADEON_CRTC2_OFFSET_CNTL       0x0328
-
-#define RADEON_PCIE_INDEX               0x0030
-#define RADEON_PCIE_DATA                0x0034
-#define RADEON_PCIE_TX_GART_CNTL       0x10
-#      define RADEON_PCIE_TX_GART_EN           (1 << 0)
-#      define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0 << 1)
-#      define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO  (1 << 1)
-#      define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD   (3 << 1)
-#      define RADEON_PCIE_TX_GART_MODE_32_128_CACHE    (0 << 3)
-#      define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE   (1 << 3)
-#      define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN      (1 << 5)
-#      define RADEON_PCIE_TX_GART_INVALIDATE_TLB       (1 << 8)
-#define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11
-#define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12
-#define RADEON_PCIE_TX_GART_BASE       0x13
-#define RADEON_PCIE_TX_GART_START_LO   0x14
-#define RADEON_PCIE_TX_GART_START_HI   0x15
-#define RADEON_PCIE_TX_GART_END_LO     0x16
-#define RADEON_PCIE_TX_GART_END_HI     0x17
-
-#define RS480_NB_MC_INDEX               0x168
-#      define RS480_NB_MC_IND_WR_EN    (1 << 8)
-#define RS480_NB_MC_DATA                0x16c
-
-#define RS690_MC_INDEX                  0x78
-#   define RS690_MC_INDEX_MASK          0x1ff
-#   define RS690_MC_INDEX_WR_EN         (1 << 9)
-#   define RS690_MC_INDEX_WR_ACK        0x7f
-#define RS690_MC_DATA                   0x7c
-
-/* MC indirect registers */
-#define RS480_MC_MISC_CNTL              0x18
-#      define RS480_DISABLE_GTW        (1 << 1)
-/* switch between MCIND GART and MM GART registers. 0 = mmgart, 1 = mcind gart */
-#      define RS480_GART_INDEX_REG_EN  (1 << 12)
-#      define RS690_BLOCK_GFX_D3_EN    (1 << 14)
-#define RS480_K8_FB_LOCATION            0x1e
-#define RS480_GART_FEATURE_ID           0x2b
-#      define RS480_HANG_EN            (1 << 11)
-#      define RS480_TLB_ENABLE         (1 << 18)
-#      define RS480_P2P_ENABLE         (1 << 19)
-#      define RS480_GTW_LAC_EN         (1 << 25)
-#      define RS480_2LEVEL_GART        (0 << 30)
-#      define RS480_1LEVEL_GART        (1 << 30)
-#      define RS480_PDC_EN             (1 << 31)
-#define RS480_GART_BASE                 0x2c
-#define RS480_GART_CACHE_CNTRL          0x2e
-#      define RS480_GART_CACHE_INVALIDATE (1 << 0) /* wait for it to clear */
-#define RS480_AGP_ADDRESS_SPACE_SIZE    0x38
-#      define RS480_GART_EN            (1 << 0)
-#      define RS480_VA_SIZE_32MB       (0 << 1)
-#      define RS480_VA_SIZE_64MB       (1 << 1)
-#      define RS480_VA_SIZE_128MB      (2 << 1)
-#      define RS480_VA_SIZE_256MB      (3 << 1)
-#      define RS480_VA_SIZE_512MB      (4 << 1)
-#      define RS480_VA_SIZE_1GB        (5 << 1)
-#      define RS480_VA_SIZE_2GB        (6 << 1)
-#define RS480_AGP_MODE_CNTL             0x39
-#      define RS480_POST_GART_Q_SIZE   (1 << 18)
-#      define RS480_NONGART_SNOOP      (1 << 19)
-#      define RS480_AGP_RD_BUF_SIZE    (1 << 20)
-#      define RS480_REQ_TYPE_SNOOP_SHIFT 22
-#      define RS480_REQ_TYPE_SNOOP_MASK  0x3
-#      define RS480_REQ_TYPE_SNOOP_DIS (1 << 24)
-#define RS480_MC_MISC_UMA_CNTL          0x5f
-#define RS480_MC_MCLK_CNTL              0x7a
-#define RS480_MC_UMA_DUALCH_CNTL        0x86
-
-#define RS690_MC_FB_LOCATION            0x100
-#define RS690_MC_AGP_LOCATION           0x101
-#define RS690_MC_AGP_BASE               0x102
-#define RS690_MC_AGP_BASE_2             0x103
-
-#define R520_MC_IND_INDEX 0x70
-#define R520_MC_IND_WR_EN (1 << 24)
-#define R520_MC_IND_DATA  0x74
-
-#define RV515_MC_FB_LOCATION 0x01
-#define RV515_MC_AGP_LOCATION 0x02
-#define RV515_MC_AGP_BASE     0x03
-#define RV515_MC_AGP_BASE_2   0x04
-
-#define R520_MC_FB_LOCATION 0x04
-#define R520_MC_AGP_LOCATION 0x05
-#define R520_MC_AGP_BASE     0x06
-#define R520_MC_AGP_BASE_2   0x07
-
-#define RADEON_MPP_TB_CONFIG           0x01c0
-#define RADEON_MEM_CNTL                        0x0140
-#define RADEON_MEM_SDRAM_MODE_REG      0x0158
-#define RADEON_AGP_BASE_2              0x015c /* r200+ only */
-#define RS480_AGP_BASE_2               0x0164
-#define RADEON_AGP_BASE                        0x0170
-
-/* pipe config regs */
-#define R400_GB_PIPE_SELECT             0x402c
-#define R500_DYN_SCLK_PWMEM_PIPE        0x000d /* PLL */
-#define R500_SU_REG_DEST                0x42c8
-#define R300_GB_TILE_CONFIG             0x4018
-#       define R300_ENABLE_TILING       (1 << 0)
-#       define R300_PIPE_COUNT_RV350    (0 << 1)
-#       define R300_PIPE_COUNT_R300     (3 << 1)
-#       define R300_PIPE_COUNT_R420_3P  (6 << 1)
-#       define R300_PIPE_COUNT_R420     (7 << 1)
-#       define R300_TILE_SIZE_8         (0 << 4)
-#       define R300_TILE_SIZE_16        (1 << 4)
-#       define R300_TILE_SIZE_32        (2 << 4)
-#       define R300_SUBPIXEL_1_12       (0 << 16)
-#       define R300_SUBPIXEL_1_16       (1 << 16)
-#define R300_DST_PIPE_CONFIG            0x170c
-#       define R300_PIPE_AUTO_CONFIG    (1 << 31)
-#define R300_RB2D_DSTCACHE_MODE         0x3428
-#       define R300_DC_AUTOFLUSH_ENABLE (1 << 8)
-#       define R300_DC_DC_DISABLE_IGNORE_PE (1 << 17)
-
-#define RADEON_RB3D_COLOROFFSET                0x1c40
-#define RADEON_RB3D_COLORPITCH         0x1c48
-
-#define        RADEON_SRC_X_Y                  0x1590
-
-#define RADEON_DP_GUI_MASTER_CNTL      0x146c
-#      define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
-#      define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
-#      define RADEON_GMC_BRUSH_SOLID_COLOR     (13 << 4)
-#      define RADEON_GMC_BRUSH_NONE            (15 << 4)
-#      define RADEON_GMC_DST_16BPP             (4 << 8)
-#      define RADEON_GMC_DST_24BPP             (5 << 8)
-#      define RADEON_GMC_DST_32BPP             (6 << 8)
-#      define RADEON_GMC_DST_DATATYPE_SHIFT    8
-#      define RADEON_GMC_SRC_DATATYPE_COLOR    (3 << 12)
-#      define RADEON_DP_SRC_SOURCE_MEMORY      (2 << 24)
-#      define RADEON_DP_SRC_SOURCE_HOST_DATA   (3 << 24)
-#      define RADEON_GMC_CLR_CMP_CNTL_DIS      (1 << 28)
-#      define RADEON_GMC_WR_MSK_DIS            (1 << 30)
-#      define RADEON_ROP3_S                    0x00cc0000
-#      define RADEON_ROP3_P                    0x00f00000
-#define RADEON_DP_WRITE_MASK           0x16cc
-#define RADEON_SRC_PITCH_OFFSET                0x1428
-#define RADEON_DST_PITCH_OFFSET                0x142c
-#define RADEON_DST_PITCH_OFFSET_C      0x1c80
-#      define RADEON_DST_TILE_LINEAR           (0 << 30)
-#      define RADEON_DST_TILE_MACRO            (1 << 30)
-#      define RADEON_DST_TILE_MICRO            (2 << 30)
-#      define RADEON_DST_TILE_BOTH             (3 << 30)
-
-#define RADEON_SCRATCH_REG0            0x15e0
-#define RADEON_SCRATCH_REG1            0x15e4
-#define RADEON_SCRATCH_REG2            0x15e8
-#define RADEON_SCRATCH_REG3            0x15ec
-#define RADEON_SCRATCH_REG4            0x15f0
-#define RADEON_SCRATCH_REG5            0x15f4
-#define RADEON_SCRATCH_UMSK            0x0770
-#define RADEON_SCRATCH_ADDR            0x0774
-
-#define RADEON_SCRATCHOFF( x )         (RADEON_SCRATCH_REG_OFFSET + 4*(x))
-
-#define GET_SCRATCH( x )       (dev_priv->writeback_works                      \
-                               ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
-                               : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
-
-#define RADEON_GEN_INT_CNTL            0x0040
-#      define RADEON_CRTC_VBLANK_MASK          (1 << 0)
-#      define RADEON_CRTC2_VBLANK_MASK         (1 << 9)
-#      define RADEON_GUI_IDLE_INT_ENABLE       (1 << 19)
-#      define RADEON_SW_INT_ENABLE             (1 << 25)
-
-#define RADEON_GEN_INT_STATUS          0x0044
-#      define RADEON_CRTC_VBLANK_STAT          (1 << 0)
-#      define RADEON_CRTC_VBLANK_STAT_ACK      (1 << 0)
-#      define RADEON_CRTC2_VBLANK_STAT         (1 << 9)
-#      define RADEON_CRTC2_VBLANK_STAT_ACK     (1 << 9)
-#      define RADEON_GUI_IDLE_INT_TEST_ACK     (1 << 19)
-#      define RADEON_SW_INT_TEST               (1 << 25)
-#      define RADEON_SW_INT_TEST_ACK           (1 << 25)
-#      define RADEON_SW_INT_FIRE               (1 << 26)
-
-#define RADEON_HOST_PATH_CNTL          0x0130
-#      define RADEON_HDP_SOFT_RESET            (1 << 26)
-#      define RADEON_HDP_WC_TIMEOUT_MASK       (7 << 28)
-#      define RADEON_HDP_WC_TIMEOUT_28BCLK     (7 << 28)
-
-#define RADEON_ISYNC_CNTL              0x1724
-#      define RADEON_ISYNC_ANY2D_IDLE3D        (1 << 0)
-#      define RADEON_ISYNC_ANY3D_IDLE2D        (1 << 1)
-#      define RADEON_ISYNC_TRIG2D_IDLE3D       (1 << 2)
-#      define RADEON_ISYNC_TRIG3D_IDLE2D       (1 << 3)
-#      define RADEON_ISYNC_WAIT_IDLEGUI        (1 << 4)
-#      define RADEON_ISYNC_CPSCRATCH_IDLEGUI   (1 << 5)
-
-#define RADEON_RBBM_GUICNTL            0x172c
-#      define RADEON_HOST_DATA_SWAP_NONE       (0 << 0)
-#      define RADEON_HOST_DATA_SWAP_16BIT      (1 << 0)
-#      define RADEON_HOST_DATA_SWAP_32BIT      (2 << 0)
-#      define RADEON_HOST_DATA_SWAP_HDW        (3 << 0)
-
-#define RADEON_MC_AGP_LOCATION         0x014c
-#define RADEON_MC_FB_LOCATION          0x0148
-#define RADEON_MCLK_CNTL               0x0012
-#      define RADEON_FORCEON_MCLKA             (1 << 16)
-#      define RADEON_FORCEON_MCLKB             (1 << 17)
-#      define RADEON_FORCEON_YCLKA             (1 << 18)
-#      define RADEON_FORCEON_YCLKB             (1 << 19)
-#      define RADEON_FORCEON_MC                (1 << 20)
-#      define RADEON_FORCEON_AIC               (1 << 21)
-
-#define RADEON_PP_BORDER_COLOR_0       0x1d40
-#define RADEON_PP_BORDER_COLOR_1       0x1d44
-#define RADEON_PP_BORDER_COLOR_2       0x1d48
-#define RADEON_PP_CNTL                 0x1c38
-#      define RADEON_SCISSOR_ENABLE            (1 <<  1)
-#define RADEON_PP_LUM_MATRIX           0x1d00
-#define RADEON_PP_MISC                 0x1c14
-#define RADEON_PP_ROT_MATRIX_0         0x1d58
-#define RADEON_PP_TXFILTER_0           0x1c54
-#define RADEON_PP_TXOFFSET_0           0x1c5c
-#define RADEON_PP_TXFILTER_1           0x1c6c
-#define RADEON_PP_TXFILTER_2           0x1c84
-
-#define R300_RB2D_DSTCACHE_CTLSTAT     0x342c /* use R300_DSTCACHE_CTLSTAT */
-#define R300_DSTCACHE_CTLSTAT          0x1714
-#      define R300_RB2D_DC_FLUSH               (3 << 0)
-#      define R300_RB2D_DC_FREE                (3 << 2)
-#      define R300_RB2D_DC_FLUSH_ALL           0xf
-#      define R300_RB2D_DC_BUSY                (1 << 31)
-#define RADEON_RB3D_CNTL               0x1c3c
-#      define RADEON_ALPHA_BLEND_ENABLE        (1 << 0)
-#      define RADEON_PLANE_MASK_ENABLE         (1 << 1)
-#      define RADEON_DITHER_ENABLE             (1 << 2)
-#      define RADEON_ROUND_ENABLE              (1 << 3)
-#      define RADEON_SCALE_DITHER_ENABLE       (1 << 4)
-#      define RADEON_DITHER_INIT               (1 << 5)
-#      define RADEON_ROP_ENABLE                (1 << 6)
-#      define RADEON_STENCIL_ENABLE            (1 << 7)
-#      define RADEON_Z_ENABLE                  (1 << 8)
-#      define RADEON_ZBLOCK16                  (1 << 15)
-#define RADEON_RB3D_DEPTHOFFSET                0x1c24
-#define RADEON_RB3D_DEPTHCLEARVALUE    0x3230
-#define RADEON_RB3D_DEPTHPITCH         0x1c28
-#define RADEON_RB3D_PLANEMASK          0x1d84
-#define RADEON_RB3D_STENCILREFMASK     0x1d7c
-#define RADEON_RB3D_ZCACHE_MODE                0x3250
-#define RADEON_RB3D_ZCACHE_CTLSTAT     0x3254
-#      define RADEON_RB3D_ZC_FLUSH             (1 << 0)
-#      define RADEON_RB3D_ZC_FREE              (1 << 2)
-#      define RADEON_RB3D_ZC_FLUSH_ALL         0x5
-#      define RADEON_RB3D_ZC_BUSY              (1 << 31)
-#define R300_ZB_ZCACHE_CTLSTAT                  0x4f18
-#      define R300_ZC_FLUSH                    (1 << 0)
-#      define R300_ZC_FREE                     (1 << 1)
-#      define R300_ZC_FLUSH_ALL                0x3
-#      define R300_ZC_BUSY                     (1 << 31)
-#define RADEON_RB3D_DSTCACHE_CTLSTAT   0x325c
-#      define RADEON_RB3D_DC_FLUSH             (3 << 0)
-#      define RADEON_RB3D_DC_FREE              (3 << 2)
-#      define RADEON_RB3D_DC_FLUSH_ALL         0xf
-#      define RADEON_RB3D_DC_BUSY              (1 << 31)
-#define R300_RB3D_DSTCACHE_CTLSTAT              0x4e4c
-#      define R300_RB3D_DC_FINISH              (1 << 4)
-#define RADEON_RB3D_ZSTENCILCNTL       0x1c2c
-#      define RADEON_Z_TEST_MASK               (7 << 4)
-#      define RADEON_Z_TEST_ALWAYS             (7 << 4)
-#      define RADEON_Z_HIERARCHY_ENABLE        (1 << 8)
-#      define RADEON_STENCIL_TEST_ALWAYS       (7 << 12)
-#      define RADEON_STENCIL_S_FAIL_REPLACE    (2 << 16)
-#      define RADEON_STENCIL_ZPASS_REPLACE     (2 << 20)
-#      define RADEON_STENCIL_ZFAIL_REPLACE     (2 << 24)
-#      define RADEON_Z_COMPRESSION_ENABLE      (1 << 28)
-#      define RADEON_FORCE_Z_DIRTY             (1 << 29)
-#      define RADEON_Z_WRITE_ENABLE            (1 << 30)
-#      define RADEON_Z_DECOMPRESSION_ENABLE    (1 << 31)
-#define RADEON_RBBM_SOFT_RESET         0x00f0
-#      define RADEON_SOFT_RESET_CP             (1 <<  0)
-#      define RADEON_SOFT_RESET_HI             (1 <<  1)
-#      define RADEON_SOFT_RESET_SE             (1 <<  2)
-#      define RADEON_SOFT_RESET_RE             (1 <<  3)
-#      define RADEON_SOFT_RESET_PP             (1 <<  4)
-#      define RADEON_SOFT_RESET_E2             (1 <<  5)
-#      define RADEON_SOFT_RESET_RB             (1 <<  6)
-#      define RADEON_SOFT_RESET_HDP            (1 <<  7)
-/*
- *   6:0  Available slots in the FIFO
- *   8    Host Interface active
- *   9    CP request active
- *   10   FIFO request active
- *   11   Host Interface retry active
- *   12   CP retry active
- *   13   FIFO retry active
- *   14   FIFO pipeline busy
- *   15   Event engine busy
- *   16   CP command stream busy
- *   17   2D engine busy
- *   18   2D portion of render backend busy
- *   20   3D setup engine busy
- *   26   GA engine busy
- *   27   CBA 2D engine busy
- *   31   2D engine busy or 3D engine busy or FIFO not empty or CP busy or
- *           command stream queue not empty or Ring Buffer not empty
- */
-#define RADEON_RBBM_STATUS             0x0e40
-/* Same as the previous RADEON_RBBM_STATUS; this is a mirror of that register.  */
-/* #define RADEON_RBBM_STATUS          0x1740 */
-/* bits 6:0 are dword slots available in the cmd fifo */
-#      define RADEON_RBBM_FIFOCNT_MASK         0x007f
-#      define RADEON_HIRQ_ON_RBB       (1 <<  8)
-#      define RADEON_CPRQ_ON_RBB       (1 <<  9)
-#      define RADEON_CFRQ_ON_RBB       (1 << 10)
-#      define RADEON_HIRQ_IN_RTBUF     (1 << 11)
-#      define RADEON_CPRQ_IN_RTBUF     (1 << 12)
-#      define RADEON_CFRQ_IN_RTBUF     (1 << 13)
-#      define RADEON_PIPE_BUSY         (1 << 14)
-#      define RADEON_ENG_EV_BUSY       (1 << 15)
-#      define RADEON_CP_CMDSTRM_BUSY   (1 << 16)
-#      define RADEON_E2_BUSY           (1 << 17)
-#      define RADEON_RB2D_BUSY         (1 << 18)
-#      define RADEON_RB3D_BUSY         (1 << 19) /* not used on r300 */
-#      define RADEON_VAP_BUSY          (1 << 20)
-#      define RADEON_RE_BUSY           (1 << 21) /* not used on r300 */
-#      define RADEON_TAM_BUSY          (1 << 22) /* not used on r300 */
-#      define RADEON_TDM_BUSY          (1 << 23) /* not used on r300 */
-#      define RADEON_PB_BUSY           (1 << 24) /* not used on r300 */
-#      define RADEON_TIM_BUSY          (1 << 25) /* not used on r300 */
-#      define RADEON_GA_BUSY           (1 << 26)
-#      define RADEON_CBA2D_BUSY        (1 << 27)
-#      define RADEON_RBBM_ACTIVE       (1 << 31)
-#define RADEON_RE_LINE_PATTERN         0x1cd0
-#define RADEON_RE_MISC                 0x26c4
-#define RADEON_RE_TOP_LEFT             0x26c0
-#define RADEON_RE_WIDTH_HEIGHT         0x1c44
-#define RADEON_RE_STIPPLE_ADDR         0x1cc8
-#define RADEON_RE_STIPPLE_DATA         0x1ccc
-
-#define RADEON_SCISSOR_TL_0            0x1cd8
-#define RADEON_SCISSOR_BR_0            0x1cdc
-#define RADEON_SCISSOR_TL_1            0x1ce0
-#define RADEON_SCISSOR_BR_1            0x1ce4
-#define RADEON_SCISSOR_TL_2            0x1ce8
-#define RADEON_SCISSOR_BR_2            0x1cec
-#define RADEON_SE_COORD_FMT            0x1c50
-#define RADEON_SE_CNTL                 0x1c4c
-#      define RADEON_FFACE_CULL_CW             (0 << 0)
-#      define RADEON_BFACE_SOLID               (3 << 1)
-#      define RADEON_FFACE_SOLID               (3 << 3)
-#      define RADEON_FLAT_SHADE_VTX_LAST       (3 << 6)
-#      define RADEON_DIFFUSE_SHADE_FLAT        (1 << 8)
-#      define RADEON_DIFFUSE_SHADE_GOURAUD     (2 << 8)
-#      define RADEON_ALPHA_SHADE_FLAT          (1 << 10)
-#      define RADEON_ALPHA_SHADE_GOURAUD       (2 << 10)
-#      define RADEON_SPECULAR_SHADE_FLAT       (1 << 12)
-#      define RADEON_SPECULAR_SHADE_GOURAUD    (2 << 12)
-#      define RADEON_FOG_SHADE_FLAT            (1 << 14)
-#      define RADEON_FOG_SHADE_GOURAUD         (2 << 14)
-#      define RADEON_VPORT_XY_XFORM_ENABLE     (1 << 24)
-#      define RADEON_VPORT_Z_XFORM_ENABLE      (1 << 25)
-#      define RADEON_VTX_PIX_CENTER_OGL        (1 << 27)
-#      define RADEON_ROUND_MODE_TRUNC          (0 << 28)
-#      define RADEON_ROUND_PREC_8TH_PIX        (1 << 30)
-#define RADEON_SE_CNTL_STATUS          0x2140
-#define RADEON_SE_LINE_WIDTH           0x1db8
-#define RADEON_SE_VPORT_XSCALE         0x1d98
-#define RADEON_SE_ZBIAS_FACTOR         0x1db0
-#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210
-#define RADEON_SE_TCL_OUTPUT_VTX_FMT         0x2254
-#define RADEON_SE_TCL_VECTOR_INDX_REG        0x2200
-#       define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT  16
-#       define RADEON_VEC_INDX_DWORD_COUNT_SHIFT     28
-#define RADEON_SE_TCL_VECTOR_DATA_REG       0x2204
-#define RADEON_SE_TCL_SCALAR_INDX_REG       0x2208
-#       define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT  16
-#define RADEON_SE_TCL_SCALAR_DATA_REG       0x220C
-#define RADEON_SURFACE_ACCESS_FLAGS    0x0bf8
-#define RADEON_SURFACE_ACCESS_CLR      0x0bfc
-#define RADEON_SURFACE_CNTL            0x0b00
-#      define RADEON_SURF_TRANSLATION_DIS      (1 << 8)
-#      define RADEON_NONSURF_AP0_SWP_MASK      (3 << 20)
-#      define RADEON_NONSURF_AP0_SWP_LITTLE    (0 << 20)
-#      define RADEON_NONSURF_AP0_SWP_BIG16     (1 << 20)
-#      define RADEON_NONSURF_AP0_SWP_BIG32     (2 << 20)
-#      define RADEON_NONSURF_AP1_SWP_MASK      (3 << 22)
-#      define RADEON_NONSURF_AP1_SWP_LITTLE    (0 << 22)
-#      define RADEON_NONSURF_AP1_SWP_BIG16     (1 << 22)
-#      define RADEON_NONSURF_AP1_SWP_BIG32     (2 << 22)
-#define RADEON_SURFACE0_INFO           0x0b0c
-#      define RADEON_SURF_PITCHSEL_MASK        (0x1ff << 0)
-#      define RADEON_SURF_TILE_MODE_MASK       (3 << 16)
-#      define RADEON_SURF_TILE_MODE_MACRO      (0 << 16)
-#      define RADEON_SURF_TILE_MODE_MICRO      (1 << 16)
-#      define RADEON_SURF_TILE_MODE_32BIT_Z    (2 << 16)
-#      define RADEON_SURF_TILE_MODE_16BIT_Z    (3 << 16)
-#define RADEON_SURFACE0_LOWER_BOUND    0x0b04
-#define RADEON_SURFACE0_UPPER_BOUND    0x0b08
-#      define RADEON_SURF_ADDRESS_FIXED_MASK   (0x3ff << 0)
-#define RADEON_SURFACE1_INFO           0x0b1c
-#define RADEON_SURFACE1_LOWER_BOUND    0x0b14
-#define RADEON_SURFACE1_UPPER_BOUND    0x0b18
-#define RADEON_SURFACE2_INFO           0x0b2c
-#define RADEON_SURFACE2_LOWER_BOUND    0x0b24
-#define RADEON_SURFACE2_UPPER_BOUND    0x0b28
-#define RADEON_SURFACE3_INFO           0x0b3c
-#define RADEON_SURFACE3_LOWER_BOUND    0x0b34
-#define RADEON_SURFACE3_UPPER_BOUND    0x0b38
-#define RADEON_SURFACE4_INFO           0x0b4c
-#define RADEON_SURFACE4_LOWER_BOUND    0x0b44
-#define RADEON_SURFACE4_UPPER_BOUND    0x0b48
-#define RADEON_SURFACE5_INFO           0x0b5c
-#define RADEON_SURFACE5_LOWER_BOUND    0x0b54
-#define RADEON_SURFACE5_UPPER_BOUND    0x0b58
-#define RADEON_SURFACE6_INFO           0x0b6c
-#define RADEON_SURFACE6_LOWER_BOUND    0x0b64
-#define RADEON_SURFACE6_UPPER_BOUND    0x0b68
-#define RADEON_SURFACE7_INFO           0x0b7c
-#define RADEON_SURFACE7_LOWER_BOUND    0x0b74
-#define RADEON_SURFACE7_UPPER_BOUND    0x0b78
-#define RADEON_SW_SEMAPHORE            0x013c
-
-#define RADEON_WAIT_UNTIL              0x1720
-#      define RADEON_WAIT_CRTC_PFLIP           (1 << 0)
-#      define RADEON_WAIT_2D_IDLE              (1 << 14)
-#      define RADEON_WAIT_3D_IDLE              (1 << 15)
-#      define RADEON_WAIT_2D_IDLECLEAN         (1 << 16)
-#      define RADEON_WAIT_3D_IDLECLEAN         (1 << 17)
-#      define RADEON_WAIT_HOST_IDLECLEAN       (1 << 18)
-
-#define RADEON_RB3D_ZMASKOFFSET                0x3234
-#define RADEON_RB3D_ZSTENCILCNTL       0x1c2c
-#      define RADEON_DEPTH_FORMAT_16BIT_INT_Z  (0 << 0)
-#      define RADEON_DEPTH_FORMAT_24BIT_INT_Z  (2 << 0)
-
-/* CP registers */
-#define RADEON_CP_ME_RAM_ADDR          0x07d4
-#define RADEON_CP_ME_RAM_RADDR         0x07d8
-#define RADEON_CP_ME_RAM_DATAH         0x07dc
-#define RADEON_CP_ME_RAM_DATAL         0x07e0
-
-#define RADEON_CP_RB_BASE              0x0700
-#define RADEON_CP_RB_CNTL              0x0704
-#      define RADEON_BUF_SWAP_32BIT            (2 << 16)
-#      define RADEON_RB_NO_UPDATE              (1 << 27)
-#define RADEON_CP_RB_RPTR_ADDR         0x070c
-#define RADEON_CP_RB_RPTR              0x0710
-#define RADEON_CP_RB_WPTR              0x0714
-
-#define RADEON_CP_RB_WPTR_DELAY                0x0718
-#      define RADEON_PRE_WRITE_TIMER_SHIFT     0
-#      define RADEON_PRE_WRITE_LIMIT_SHIFT     23
-
-#define RADEON_CP_IB_BASE              0x0738
-
-#define RADEON_CP_CSQ_CNTL             0x0740
-#      define RADEON_CSQ_CNT_PRIMARY_MASK      (0xff << 0)
-#      define RADEON_CSQ_PRIDIS_INDDIS         (0 << 28)
-#      define RADEON_CSQ_PRIPIO_INDDIS         (1 << 28)
-#      define RADEON_CSQ_PRIBM_INDDIS          (2 << 28)
-#      define RADEON_CSQ_PRIPIO_INDBM          (3 << 28)
-#      define RADEON_CSQ_PRIBM_INDBM           (4 << 28)
-#      define RADEON_CSQ_PRIPIO_INDPIO         (15 << 28)
-
-#define RADEON_AIC_CNTL                        0x01d0
-#      define RADEON_PCIGART_TRANSLATE_EN      (1 << 0)
-#define RADEON_AIC_STAT                        0x01d4
-#define RADEON_AIC_PT_BASE             0x01d8
-#define RADEON_AIC_LO_ADDR             0x01dc
-#define RADEON_AIC_HI_ADDR             0x01e0
-#define RADEON_AIC_TLB_ADDR            0x01e4
-#define RADEON_AIC_TLB_DATA            0x01e8
-
-/* CP command packets */
-#define RADEON_CP_PACKET0              0x00000000
-#      define RADEON_ONE_REG_WR                (1 << 15)
-#define RADEON_CP_PACKET1              0x40000000
-#define RADEON_CP_PACKET2              0x80000000
-#define RADEON_CP_PACKET3              0xC0000000
-#       define RADEON_CP_NOP                    0x00001000
-#       define RADEON_CP_NEXT_CHAR              0x00001900
-#       define RADEON_CP_PLY_NEXTSCAN           0x00001D00
-#       define RADEON_CP_SET_SCISSORS           0x00001E00
-            /* GEN_INDX_PRIM is unsupported starting with R300 */
-#      define RADEON_3D_RNDR_GEN_INDX_PRIM     0x00002300
-#      define RADEON_WAIT_FOR_IDLE             0x00002600
-#      define RADEON_3D_DRAW_VBUF              0x00002800
-#      define RADEON_3D_DRAW_IMMD              0x00002900
-#      define RADEON_3D_DRAW_INDX              0x00002A00
-#       define RADEON_CP_LOAD_PALETTE           0x00002C00
-#      define RADEON_3D_LOAD_VBPNTR            0x00002F00
-#      define RADEON_MPEG_IDCT_MACROBLOCK      0x00003000
-#      define RADEON_MPEG_IDCT_MACROBLOCK_REV  0x00003100
-#      define RADEON_3D_CLEAR_ZMASK            0x00003200
-#      define RADEON_CP_INDX_BUFFER            0x00003300
-#       define RADEON_CP_3D_DRAW_VBUF_2         0x00003400
-#       define RADEON_CP_3D_DRAW_IMMD_2         0x00003500
-#       define RADEON_CP_3D_DRAW_INDX_2         0x00003600
-#      define RADEON_3D_CLEAR_HIZ              0x00003700
-#       define RADEON_CP_3D_CLEAR_CMASK         0x00003802
-#      define RADEON_CNTL_HOSTDATA_BLT         0x00009400
-#      define RADEON_CNTL_PAINT_MULTI          0x00009A00
-#      define RADEON_CNTL_BITBLT_MULTI         0x00009B00
-#      define RADEON_CNTL_SET_SCISSORS         0xC0001E00
-
-#define RADEON_CP_PACKET_MASK          0xC0000000
-#define RADEON_CP_PACKET_COUNT_MASK    0x3fff0000
-#define RADEON_CP_PACKET0_REG_MASK     0x000007ff
-#define RADEON_CP_PACKET1_REG0_MASK    0x000007ff
-#define RADEON_CP_PACKET1_REG1_MASK    0x003ff800
-
-#define RADEON_VTX_Z_PRESENT                   (1 << 31)
-#define RADEON_VTX_PKCOLOR_PRESENT             (1 << 3)
-
-#define RADEON_PRIM_TYPE_NONE                  (0 << 0)
-#define RADEON_PRIM_TYPE_POINT                 (1 << 0)
-#define RADEON_PRIM_TYPE_LINE                  (2 << 0)
-#define RADEON_PRIM_TYPE_LINE_STRIP            (3 << 0)
-#define RADEON_PRIM_TYPE_TRI_LIST              (4 << 0)
-#define RADEON_PRIM_TYPE_TRI_FAN               (5 << 0)
-#define RADEON_PRIM_TYPE_TRI_STRIP             (6 << 0)
-#define RADEON_PRIM_TYPE_TRI_TYPE2             (7 << 0)
-#define RADEON_PRIM_TYPE_RECT_LIST             (8 << 0)
-#define RADEON_PRIM_TYPE_3VRT_POINT_LIST       (9 << 0)
-#define RADEON_PRIM_TYPE_3VRT_LINE_LIST                (10 << 0)
-#define RADEON_PRIM_TYPE_MASK                   0xf
-#define RADEON_PRIM_WALK_IND                   (1 << 4)
-#define RADEON_PRIM_WALK_LIST                  (2 << 4)
-#define RADEON_PRIM_WALK_RING                  (3 << 4)
-#define RADEON_COLOR_ORDER_BGRA                        (0 << 6)
-#define RADEON_COLOR_ORDER_RGBA                        (1 << 6)
-#define RADEON_MAOS_ENABLE                     (1 << 7)
-#define RADEON_VTX_FMT_R128_MODE               (0 << 8)
-#define RADEON_VTX_FMT_RADEON_MODE             (1 << 8)
-#define RADEON_NUM_VERTICES_SHIFT              16
-
-#define RADEON_COLOR_FORMAT_CI8                2
-#define RADEON_COLOR_FORMAT_ARGB1555   3
-#define RADEON_COLOR_FORMAT_RGB565     4
-#define RADEON_COLOR_FORMAT_ARGB8888   6
-#define RADEON_COLOR_FORMAT_RGB332     7
-#define RADEON_COLOR_FORMAT_RGB8       9
-#define RADEON_COLOR_FORMAT_ARGB4444   15
-
-#define RADEON_TXFORMAT_I8             0
-#define RADEON_TXFORMAT_AI88           1
-#define RADEON_TXFORMAT_RGB332         2
-#define RADEON_TXFORMAT_ARGB1555       3
-#define RADEON_TXFORMAT_RGB565         4
-#define RADEON_TXFORMAT_ARGB4444       5
-#define RADEON_TXFORMAT_ARGB8888       6
-#define RADEON_TXFORMAT_RGBA8888       7
-#define RADEON_TXFORMAT_Y8             8
-#define RADEON_TXFORMAT_VYUY422         10
-#define RADEON_TXFORMAT_YVYU422         11
-#define RADEON_TXFORMAT_DXT1            12
-#define RADEON_TXFORMAT_DXT23           14
-#define RADEON_TXFORMAT_DXT45           15
-
-#define R200_PP_TXCBLEND_0                0x2f00
-#define R200_PP_TXCBLEND_1                0x2f10
-#define R200_PP_TXCBLEND_2                0x2f20
-#define R200_PP_TXCBLEND_3                0x2f30
-#define R200_PP_TXCBLEND_4                0x2f40
-#define R200_PP_TXCBLEND_5                0x2f50
-#define R200_PP_TXCBLEND_6                0x2f60
-#define R200_PP_TXCBLEND_7                0x2f70
-#define R200_SE_TCL_LIGHT_MODEL_CTL_0     0x2268
-#define R200_PP_TFACTOR_0                 0x2ee0
-#define R200_SE_VTX_FMT_0                 0x2088
-#define R200_SE_VAP_CNTL                  0x2080
-#define R200_SE_TCL_MATRIX_SEL_0          0x2230
-#define R200_SE_TCL_TEX_PROC_CTL_2        0x22a8
-#define R200_SE_TCL_UCP_VERT_BLEND_CTL    0x22c0
-#define R200_PP_TXFILTER_5                0x2ca0
-#define R200_PP_TXFILTER_4                0x2c80
-#define R200_PP_TXFILTER_3                0x2c60
-#define R200_PP_TXFILTER_2                0x2c40
-#define R200_PP_TXFILTER_1                0x2c20
-#define R200_PP_TXFILTER_0                0x2c00
-#define R200_PP_TXOFFSET_5                0x2d78
-#define R200_PP_TXOFFSET_4                0x2d60
-#define R200_PP_TXOFFSET_3                0x2d48
-#define R200_PP_TXOFFSET_2                0x2d30
-#define R200_PP_TXOFFSET_1                0x2d18
-#define R200_PP_TXOFFSET_0                0x2d00
-
-#define R200_PP_CUBIC_FACES_0             0x2c18
-#define R200_PP_CUBIC_FACES_1             0x2c38
-#define R200_PP_CUBIC_FACES_2             0x2c58
-#define R200_PP_CUBIC_FACES_3             0x2c78
-#define R200_PP_CUBIC_FACES_4             0x2c98
-#define R200_PP_CUBIC_FACES_5             0x2cb8
-#define R200_PP_CUBIC_OFFSET_F1_0         0x2d04
-#define R200_PP_CUBIC_OFFSET_F2_0         0x2d08
-#define R200_PP_CUBIC_OFFSET_F3_0         0x2d0c
-#define R200_PP_CUBIC_OFFSET_F4_0         0x2d10
-#define R200_PP_CUBIC_OFFSET_F5_0         0x2d14
-#define R200_PP_CUBIC_OFFSET_F1_1         0x2d1c
-#define R200_PP_CUBIC_OFFSET_F2_1         0x2d20
-#define R200_PP_CUBIC_OFFSET_F3_1         0x2d24
-#define R200_PP_CUBIC_OFFSET_F4_1         0x2d28
-#define R200_PP_CUBIC_OFFSET_F5_1         0x2d2c
-#define R200_PP_CUBIC_OFFSET_F1_2         0x2d34
-#define R200_PP_CUBIC_OFFSET_F2_2         0x2d38
-#define R200_PP_CUBIC_OFFSET_F3_2         0x2d3c
-#define R200_PP_CUBIC_OFFSET_F4_2         0x2d40
-#define R200_PP_CUBIC_OFFSET_F5_2         0x2d44
-#define R200_PP_CUBIC_OFFSET_F1_3         0x2d4c
-#define R200_PP_CUBIC_OFFSET_F2_3         0x2d50
-#define R200_PP_CUBIC_OFFSET_F3_3         0x2d54
-#define R200_PP_CUBIC_OFFSET_F4_3         0x2d58
-#define R200_PP_CUBIC_OFFSET_F5_3         0x2d5c
-#define R200_PP_CUBIC_OFFSET_F1_4         0x2d64
-#define R200_PP_CUBIC_OFFSET_F2_4         0x2d68
-#define R200_PP_CUBIC_OFFSET_F3_4         0x2d6c
-#define R200_PP_CUBIC_OFFSET_F4_4         0x2d70
-#define R200_PP_CUBIC_OFFSET_F5_4         0x2d74
-#define R200_PP_CUBIC_OFFSET_F1_5         0x2d7c
-#define R200_PP_CUBIC_OFFSET_F2_5         0x2d80
-#define R200_PP_CUBIC_OFFSET_F3_5         0x2d84
-#define R200_PP_CUBIC_OFFSET_F4_5         0x2d88
-#define R200_PP_CUBIC_OFFSET_F5_5         0x2d8c
-
-#define R200_RE_AUX_SCISSOR_CNTL          0x26f0
-#define R200_SE_VTE_CNTL                  0x20b0
-#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL   0x2250
-#define R200_PP_TAM_DEBUG3                0x2d9c
-#define R200_PP_CNTL_X                    0x2cc4
-#define R200_SE_VAP_CNTL_STATUS           0x2140
-#define R200_RE_SCISSOR_TL_0              0x1cd8
-#define R200_RE_SCISSOR_TL_1              0x1ce0
-#define R200_RE_SCISSOR_TL_2              0x1ce8
-#define R200_RB3D_DEPTHXY_OFFSET          0x1d60
-#define R200_RE_AUX_SCISSOR_CNTL          0x26f0
-#define R200_SE_VTX_STATE_CNTL            0x2180
-#define R200_RE_POINTSIZE                 0x2648
-#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254
-
-#define RADEON_PP_TEX_SIZE_0                0x1d04     /* NPOT */
-#define RADEON_PP_TEX_SIZE_1                0x1d0c
-#define RADEON_PP_TEX_SIZE_2                0x1d14
-
-#define RADEON_PP_CUBIC_FACES_0             0x1d24
-#define RADEON_PP_CUBIC_FACES_1             0x1d28
-#define RADEON_PP_CUBIC_FACES_2             0x1d2c
-#define RADEON_PP_CUBIC_OFFSET_T0_0         0x1dd0     /* bits [31:5] */
-#define RADEON_PP_CUBIC_OFFSET_T1_0         0x1e00
-#define RADEON_PP_CUBIC_OFFSET_T2_0         0x1e14
-
-#define RADEON_SE_TCL_STATE_FLUSH           0x2284
-
-#define SE_VAP_CNTL__TCL_ENA_MASK                          0x00000001
-#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK                   0x00010000
-#define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT                 0x00000012
-#define SE_VTE_CNTL__VTX_XY_FMT_MASK                       0x00000100
-#define SE_VTE_CNTL__VTX_Z_FMT_MASK                        0x00000200
-#define SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK                  0x00000001
-#define SE_VTX_FMT_0__VTX_W0_PRESENT_MASK                  0x00000002
-#define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT               0x0000000b
-#define R200_3D_DRAW_IMMD_2      0xC0003500
-#define R200_SE_VTX_FMT_1                 0x208c
-#define R200_RE_CNTL                      0x1c50
-
-#define R200_RB3D_BLENDCOLOR              0x3218
-
-#define R200_SE_TCL_POINT_SPRITE_CNTL     0x22c4
-
-#define R200_PP_TRI_PERF 0x2cf8
-
-#define R200_PP_AFS_0                     0x2f80
-#define R200_PP_AFS_1                     0x2f00       /* same as txcblend_0 */
-
-#define R200_VAP_PVS_CNTL_1               0x22D0
-
-#define R500_D1CRTC_STATUS 0x609c
-#define R500_D2CRTC_STATUS 0x689c
-#define R500_CRTC_V_BLANK (1<<0)
-
-#define R500_D1CRTC_FRAME_COUNT 0x60a4
-#define R500_D2CRTC_FRAME_COUNT 0x68a4
-
-#define R500_D1MODE_V_COUNTER 0x6530
-#define R500_D2MODE_V_COUNTER 0x6d30
-
-#define R500_D1MODE_VBLANK_STATUS 0x6534
-#define R500_D2MODE_VBLANK_STATUS 0x6d34
-#define R500_VBLANK_OCCURED (1<<0)
-#define R500_VBLANK_ACK     (1<<4)
-#define R500_VBLANK_STAT    (1<<12)
-#define R500_VBLANK_INT     (1<<16)
-
-#define R500_DxMODE_INT_MASK 0x6540
-#define R500_D1MODE_INT_MASK (1<<0)
-#define R500_D2MODE_INT_MASK (1<<8)
-
-#define R500_DISP_INTERRUPT_STATUS 0x7edc
-#define R500_D1_VBLANK_INTERRUPT (1 << 4)
-#define R500_D2_VBLANK_INTERRUPT (1 << 5)
-
-/* Constants */
-#define RADEON_MAX_USEC_TIMEOUT                100000  /* 100 ms */
-
-#define RADEON_LAST_FRAME_REG          RADEON_SCRATCH_REG0
-#define RADEON_LAST_DISPATCH_REG       RADEON_SCRATCH_REG1
-#define RADEON_LAST_CLEAR_REG          RADEON_SCRATCH_REG2
-#define RADEON_LAST_SWI_REG            RADEON_SCRATCH_REG3
-#define RADEON_LAST_DISPATCH           1
-
-#define RADEON_MAX_VB_AGE              0x7fffffff
-#define RADEON_MAX_VB_VERTS            (0xffff)
-
-#define RADEON_RING_HIGH_MARK          128
-
-#define RADEON_PCIGART_TABLE_SIZE      (32*1024)
-
-#define RADEON_READ(reg)       DRM_READ32(  dev_priv->mmio, (reg) )
-#define RADEON_WRITE(reg,val)  DRM_WRITE32( dev_priv->mmio, (reg), (val) )
-#define RADEON_READ8(reg)      DRM_READ8(  dev_priv->mmio, (reg) )
-#define RADEON_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) )
-
-#define RADEON_WRITE_PLL(addr, val)                                    \
-do {                                                                   \
-       RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX,                          \
-                      ((addr) & 0x1f) | RADEON_PLL_WR_EN );            \
-       RADEON_WRITE(RADEON_CLOCK_CNTL_DATA, (val));                    \
-} while (0)
-
-#define RADEON_WRITE_PCIE(addr, val)                                   \
-do {                                                                   \
-       RADEON_WRITE8(RADEON_PCIE_INDEX,                                \
-                       ((addr) & 0xff));                               \
-       RADEON_WRITE(RADEON_PCIE_DATA, (val));                  \
-} while (0)
-
-#define R500_WRITE_MCIND(addr, val)                                    \
-do {                                                           \
-       RADEON_WRITE(R520_MC_IND_INDEX, 0xff0000 | ((addr) & 0xff));    \
-       RADEON_WRITE(R520_MC_IND_DATA, (val));                  \
-       RADEON_WRITE(R520_MC_IND_INDEX, 0);     \
-} while (0)
-
-#define RS480_WRITE_MCIND(addr, val)                           \
-do {                                                                   \
-       RADEON_WRITE(RS480_NB_MC_INDEX,                         \
-                       ((addr) & 0xff) | RS480_NB_MC_IND_WR_EN);       \
-       RADEON_WRITE(RS480_NB_MC_DATA, (val));                  \
-       RADEON_WRITE(RS480_NB_MC_INDEX, 0xff);                  \
-} while (0)
-
-#define RS690_WRITE_MCIND(addr, val)                                   \
-do {                                                           \
-       RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_EN | ((addr) & RS690_MC_INDEX_MASK));    \
-       RADEON_WRITE(RS690_MC_DATA, val);                       \
-       RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK);    \
-} while (0)
-
-#define IGP_WRITE_MCIND(addr, val)                             \
-do {                                                                   \
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)       \
-               RS690_WRITE_MCIND(addr, val);                           \
-       else                                                            \
-               RS480_WRITE_MCIND(addr, val);                           \
-} while (0)
-
-#define CP_PACKET0( reg, n )                                           \
-       (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
-#define CP_PACKET0_TABLE( reg, n )                                     \
-       (RADEON_CP_PACKET0 | RADEON_ONE_REG_WR | ((n) << 16) | ((reg) >> 2))
-#define CP_PACKET1( reg0, reg1 )                                       \
-       (RADEON_CP_PACKET1 | (((reg1) >> 2) << 15) | ((reg0) >> 2))
-#define CP_PACKET2()                                                   \
-       (RADEON_CP_PACKET2)
-#define CP_PACKET3( pkt, n )                                           \
-       (RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
-
-/* ================================================================
- * Engine control helper macros
- */
-
-#define RADEON_WAIT_UNTIL_2D_IDLE() do {                               \
-       OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );                 \
-       OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |                           \
-                  RADEON_WAIT_HOST_IDLECLEAN) );                       \
-} while (0)
-
-#define RADEON_WAIT_UNTIL_3D_IDLE() do {                               \
-       OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );                 \
-       OUT_RING( (RADEON_WAIT_3D_IDLECLEAN |                           \
-                  RADEON_WAIT_HOST_IDLECLEAN) );                       \
-} while (0)
-
-#define RADEON_WAIT_UNTIL_IDLE() do {                                  \
-       OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );                 \
-       OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |                           \
-                  RADEON_WAIT_3D_IDLECLEAN |                           \
-                  RADEON_WAIT_HOST_IDLECLEAN) );                       \
-} while (0)
-
-#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do {                          \
-       OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );                 \
-       OUT_RING( RADEON_WAIT_CRTC_PFLIP );                             \
-} while (0)
-
-#define RADEON_FLUSH_CACHE() do {                                      \
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {     \
-               OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0));  \
-               OUT_RING(RADEON_RB3D_DC_FLUSH);                         \
-       } else {                                                        \
-               OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));    \
-               OUT_RING(RADEON_RB3D_DC_FLUSH);                         \
-       }                                                               \
-} while (0)
-
-#define RADEON_PURGE_CACHE() do {                                      \
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {     \
-               OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0));  \
-               OUT_RING(RADEON_RB3D_DC_FLUSH_ALL);                     \
-       } else {                                                        \
-               OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));    \
-               OUT_RING(RADEON_RB3D_DC_FLUSH_ALL);                     \
-       }                                                               \
-} while (0)
-
-#define RADEON_FLUSH_ZCACHE() do {                                     \
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {     \
-               OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));    \
-               OUT_RING(RADEON_RB3D_ZC_FLUSH);                         \
-       } else {                                                        \
-               OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));        \
-               OUT_RING(R300_ZC_FLUSH);                                \
-       }                                                               \
-} while (0)
-
-#define RADEON_PURGE_ZCACHE() do {                                     \
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {     \
-               OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));    \
-               OUT_RING(RADEON_RB3D_ZC_FLUSH_ALL);                     \
-       } else {                                                        \
-               OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));    \
-               OUT_RING(R300_ZC_FLUSH_ALL);                            \
-       }                                                               \
-} while (0)
-
-/* ================================================================
- * Misc helper macros
- */
-
-/* Perfbox functionality only.
- */
-#define RING_SPACE_TEST_WITH_RETURN( dev_priv )                                \
-do {                                                                   \
-       if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) {           \
-               u32 head = GET_RING_HEAD( dev_priv );                   \
-               if (head == dev_priv->ring.tail)                        \
-                       dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE;   \
-       }                                                               \
-} while (0)
-
-#define VB_AGE_TEST_WITH_RETURN( dev_priv )                            \
-do {                                                                   \
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;          \
-       if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) {         \
-               int __ret = radeon_do_cp_idle( dev_priv );              \
-               if ( __ret ) return __ret;                              \
-               sarea_priv->last_dispatch = 0;                          \
-               radeon_freelist_reset( dev );                           \
-       }                                                               \
-} while (0)
-
-#define RADEON_DISPATCH_AGE( age ) do {                                        \
-       OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) );          \
-       OUT_RING( age );                                                \
-} while (0)
-
-#define RADEON_FRAME_AGE( age ) do {                                   \
-       OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) );             \
-       OUT_RING( age );                                                \
-} while (0)
-
-#define RADEON_CLEAR_AGE( age ) do {                                   \
-       OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) );             \
-       OUT_RING( age );                                                \
-} while (0)
-
-/* ================================================================
- * Ring control
- */
-
-#define RADEON_VERBOSE 0
-
-#define RING_LOCALS    int write, _nr; unsigned int mask; u32 *ring;
-
-#define BEGIN_RING( n ) do {                                           \
-       if ( RADEON_VERBOSE ) {                                         \
-               DRM_INFO( "BEGIN_RING( %d )\n", (n));                   \
-       }                                                               \
-       if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {              \
-                COMMIT_RING();                                         \
-               radeon_wait_ring( dev_priv, (n) * sizeof(u32) );        \
-       }                                                               \
-       _nr = n; dev_priv->ring.space -= (n) * sizeof(u32);             \
-       ring = dev_priv->ring.start;                                    \
-       write = dev_priv->ring.tail;                                    \
-       mask = dev_priv->ring.tail_mask;                                \
-} while (0)
-
-#define ADVANCE_RING() do {                                            \
-       if ( RADEON_VERBOSE ) {                                         \
-               DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",     \
-                         write, dev_priv->ring.tail );                 \
-       }                                                               \
-       if (((dev_priv->ring.tail + _nr) & mask) != write) {            \
-               DRM_ERROR(                                              \
-                       "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n",        \
-                       ((dev_priv->ring.tail + _nr) & mask),           \
-                       write, __LINE__);                                               \
-       } else                                                          \
-               dev_priv->ring.tail = write;                            \
-} while (0)
-
-#define COMMIT_RING() do {                                             \
-       /* Flush writes to ring */                                      \
-       DRM_MEMORYBARRIER();                                            \
-       GET_RING_HEAD( dev_priv );                                      \
-       RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail );         \
-       /* read from PCI bus to ensure correct posting */               \
-       RADEON_READ( RADEON_CP_RB_RPTR );                               \
-} while (0)
-
-#define OUT_RING( x ) do {                                             \
-       if ( RADEON_VERBOSE ) {                                         \
-               DRM_INFO( "   OUT_RING( 0x%08x ) at 0x%x\n",            \
-                          (unsigned int)(x), write );                  \
-       }                                                               \
-       ring[write++] = (x);                                            \
-       write &= mask;                                                  \
-} while (0)
-
-#define OUT_RING_REG( reg, val ) do {                                  \
-       OUT_RING( CP_PACKET0( reg, 0 ) );                               \
-       OUT_RING( val );                                                \
-} while (0)
-
-#define OUT_RING_TABLE( tab, sz ) do {                                 \
-       int _size = (sz);                                       \
-       int *_tab = (int *)(tab);                               \
-                                                               \
-       if (write + _size > mask) {                             \
-               int _i = (mask+1) - write;                      \
-               _size -= _i;                                    \
-               while (_i > 0 ) {                               \
-                       *(int *)(ring + write) = *_tab++;       \
-                       write++;                                \
-                       _i--;                                   \
-               }                                               \
-               write = 0;                                      \
-               _tab += _i;                                     \
-       }                                                       \
-       while (_size > 0) {                                     \
-               *(ring + write) = *_tab++;                      \
-               write++;                                        \
-               _size--;                                        \
-       }                                                       \
-       write &= mask;                                          \
-} while (0)
-
-#endif                         /* __RADEON_DRV_H__ */
diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
deleted file mode 100644 (file)
index 56decda..0000000
+++ /dev/null
@@ -1,424 +0,0 @@
-/**
- * \file radeon_ioc32.c
- *
- * 32-bit ioctl compatibility routines for the Radeon DRM.
- *
- * \author Paul Mackerras <paulus@samba.org>
- *
- * Copyright (C) Paul Mackerras 2005
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <linux/compat.h>
-
-#include "drmP.h"
-#include "drm.h"
-#include "radeon_drm.h"
-#include "radeon_drv.h"
-
-typedef struct drm_radeon_init32 {
-       int func;
-       u32 sarea_priv_offset;
-       int is_pci;
-       int cp_mode;
-       int gart_size;
-       int ring_size;
-       int usec_timeout;
-
-       unsigned int fb_bpp;
-       unsigned int front_offset, front_pitch;
-       unsigned int back_offset, back_pitch;
-       unsigned int depth_bpp;
-       unsigned int depth_offset, depth_pitch;
-
-       u32 fb_offset;
-       u32 mmio_offset;
-       u32 ring_offset;
-       u32 ring_rptr_offset;
-       u32 buffers_offset;
-       u32 gart_textures_offset;
-} drm_radeon_init32_t;
-
-static int compat_radeon_cp_init(struct file *file, unsigned int cmd,
-                                unsigned long arg)
-{
-       drm_radeon_init32_t init32;
-       drm_radeon_init_t __user *init;
-
-       if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
-               return -EFAULT;
-
-       init = compat_alloc_user_space(sizeof(*init));
-       if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
-           || __put_user(init32.func, &init->func)
-           || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
-           || __put_user(init32.is_pci, &init->is_pci)
-           || __put_user(init32.cp_mode, &init->cp_mode)
-           || __put_user(init32.gart_size, &init->gart_size)
-           || __put_user(init32.ring_size, &init->ring_size)
-           || __put_user(init32.usec_timeout, &init->usec_timeout)
-           || __put_user(init32.fb_bpp, &init->fb_bpp)
-           || __put_user(init32.front_offset, &init->front_offset)
-           || __put_user(init32.front_pitch, &init->front_pitch)
-           || __put_user(init32.back_offset, &init->back_offset)
-           || __put_user(init32.back_pitch, &init->back_pitch)
-           || __put_user(init32.depth_bpp, &init->depth_bpp)
-           || __put_user(init32.depth_offset, &init->depth_offset)
-           || __put_user(init32.depth_pitch, &init->depth_pitch)
-           || __put_user(init32.fb_offset, &init->fb_offset)
-           || __put_user(init32.mmio_offset, &init->mmio_offset)
-           || __put_user(init32.ring_offset, &init->ring_offset)
-           || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
-           || __put_user(init32.buffers_offset, &init->buffers_offset)
-           || __put_user(init32.gart_textures_offset,
-                         &init->gart_textures_offset))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init);
-}
-
-typedef struct drm_radeon_clear32 {
-       unsigned int flags;
-       unsigned int clear_color;
-       unsigned int clear_depth;
-       unsigned int color_mask;
-       unsigned int depth_mask;        /* misnamed field:  should be stencil */
-       u32 depth_boxes;
-} drm_radeon_clear32_t;
-
-static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
-                                 unsigned long arg)
-{
-       drm_radeon_clear32_t clr32;
-       drm_radeon_clear_t __user *clr;
-
-       if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32)))
-               return -EFAULT;
-
-       clr = compat_alloc_user_space(sizeof(*clr));
-       if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr))
-           || __put_user(clr32.flags, &clr->flags)
-           || __put_user(clr32.clear_color, &clr->clear_color)
-           || __put_user(clr32.clear_depth, &clr->clear_depth)
-           || __put_user(clr32.color_mask, &clr->color_mask)
-           || __put_user(clr32.depth_mask, &clr->depth_mask)
-           || __put_user((void __user *)(unsigned long)clr32.depth_boxes,
-                         &clr->depth_boxes))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr);
-}
-
-typedef struct drm_radeon_stipple32 {
-       u32 mask;
-} drm_radeon_stipple32_t;
-
-static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
-                                   unsigned long arg)
-{
-       drm_radeon_stipple32_t __user *argp = (void __user *)arg;
-       drm_radeon_stipple_t __user *request;
-       u32 mask;
-
-       if (get_user(mask, &argp->mask))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user((unsigned int __user *)(unsigned long)mask,
-                         &request->mask))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request);
-}
-
-typedef struct drm_radeon_tex_image32 {
-       unsigned int x, y;      /* Blit coordinates */
-       unsigned int width, height;
-       u32 data;
-} drm_radeon_tex_image32_t;
-
-typedef struct drm_radeon_texture32 {
-       unsigned int offset;
-       int pitch;
-       int format;
-       int width;              /* Texture image coordinates */
-       int height;
-       u32 image;
-} drm_radeon_texture32_t;
-
-static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
-                                   unsigned long arg)
-{
-       drm_radeon_texture32_t req32;
-       drm_radeon_texture_t __user *request;
-       drm_radeon_tex_image32_t img32;
-       drm_radeon_tex_image_t __user *image;
-
-       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
-               return -EFAULT;
-       if (req32.image == 0)
-               return -EINVAL;
-       if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image,
-                          sizeof(img32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request) + sizeof(*image));
-       if (!access_ok(VERIFY_WRITE, request,
-                      sizeof(*request) + sizeof(*image)))
-               return -EFAULT;
-       image = (drm_radeon_tex_image_t __user *) (request + 1);
-
-       if (__put_user(req32.offset, &request->offset)
-           || __put_user(req32.pitch, &request->pitch)
-           || __put_user(req32.format, &request->format)
-           || __put_user(req32.width, &request->width)
-           || __put_user(req32.height, &request->height)
-           || __put_user(image, &request->image)
-           || __put_user(img32.x, &image->x)
-           || __put_user(img32.y, &image->y)
-           || __put_user(img32.width, &image->width)
-           || __put_user(img32.height, &image->height)
-           || __put_user((const void __user *)(unsigned long)img32.data,
-                         &image->data))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request);
-}
-
-typedef struct drm_radeon_vertex2_32 {
-       int idx;                /* Index of vertex buffer */
-       int discard;            /* Client finished with buffer? */
-       int nr_states;
-       u32 state;
-       int nr_prims;
-       u32 prim;
-} drm_radeon_vertex2_32_t;
-
-static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
-                                   unsigned long arg)
-{
-       drm_radeon_vertex2_32_t req32;
-       drm_radeon_vertex2_t __user *request;
-
-       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user(req32.idx, &request->idx)
-           || __put_user(req32.discard, &request->discard)
-           || __put_user(req32.nr_states, &request->nr_states)
-           || __put_user((void __user *)(unsigned long)req32.state,
-                         &request->state)
-           || __put_user(req32.nr_prims, &request->nr_prims)
-           || __put_user((void __user *)(unsigned long)req32.prim,
-                         &request->prim))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request);
-}
-
-typedef struct drm_radeon_cmd_buffer32 {
-       int bufsz;
-       u32 buf;
-       int nbox;
-       u32 boxes;
-} drm_radeon_cmd_buffer32_t;
-
-static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
-                                  unsigned long arg)
-{
-       drm_radeon_cmd_buffer32_t req32;
-       drm_radeon_cmd_buffer_t __user *request;
-
-       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user(req32.bufsz, &request->bufsz)
-           || __put_user((void __user *)(unsigned long)req32.buf,
-                         &request->buf)
-           || __put_user(req32.nbox, &request->nbox)
-           || __put_user((void __user *)(unsigned long)req32.boxes,
-                         &request->boxes))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request);
-}
-
-typedef struct drm_radeon_getparam32 {
-       int param;
-       u32 value;
-} drm_radeon_getparam32_t;
-
-static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
-                                    unsigned long arg)
-{
-       drm_radeon_getparam32_t req32;
-       drm_radeon_getparam_t __user *request;
-
-       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user(req32.param, &request->param)
-           || __put_user((void __user *)(unsigned long)req32.value,
-                         &request->value))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request);
-}
-
-typedef struct drm_radeon_mem_alloc32 {
-       int region;
-       int alignment;
-       int size;
-       u32 region_offset;      /* offset from start of fb or GART */
-} drm_radeon_mem_alloc32_t;
-
-static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
-                                  unsigned long arg)
-{
-       drm_radeon_mem_alloc32_t req32;
-       drm_radeon_mem_alloc_t __user *request;
-
-       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user(req32.region, &request->region)
-           || __put_user(req32.alignment, &request->alignment)
-           || __put_user(req32.size, &request->size)
-           || __put_user((int __user *)(unsigned long)req32.region_offset,
-                         &request->region_offset))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_ALLOC, (unsigned long)request);
-}
-
-typedef struct drm_radeon_irq_emit32 {
-       u32 irq_seq;
-} drm_radeon_irq_emit32_t;
-
-static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
-                                 unsigned long arg)
-{
-       drm_radeon_irq_emit32_t req32;
-       drm_radeon_irq_emit_t __user *request;
-
-       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user((int __user *)(unsigned long)req32.irq_seq,
-                         &request->irq_seq))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_path.dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
-}
-
-/* The two 64-bit arches where alignof(u64)==4 in 32-bit code */
-#if defined (CONFIG_X86_64) || defined(CONFIG_IA64)
-typedef struct drm_radeon_setparam32 {
-       int param;
-       u64 value;
-} __attribute__((packed)) drm_radeon_setparam32_t;
-
-static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd,
-                                    unsigned long arg)
-{
-       drm_radeon_setparam32_t req32;
-       drm_radeon_setparam_t __user *request;
-
-       if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
-               return -EFAULT;
-
-       request = compat_alloc_user_space(sizeof(*request));
-       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
-           || __put_user(req32.param, &request->param)
-           || __put_user((void __user *)(unsigned long)req32.value,
-                         &request->value))
-               return -EFAULT;
-
-       return drm_ioctl(file->f_dentry->d_inode, file,
-                        DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request);
-}
-#else
-#define compat_radeon_cp_setparam NULL
-#endif /* X86_64 || IA64 */
-
-drm_ioctl_compat_t *radeon_compat_ioctls[] = {
-       [DRM_RADEON_CP_INIT] = compat_radeon_cp_init,
-       [DRM_RADEON_CLEAR] = compat_radeon_cp_clear,
-       [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple,
-       [DRM_RADEON_TEXTURE] = compat_radeon_cp_texture,
-       [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2,
-       [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf,
-       [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam,
-       [DRM_RADEON_SETPARAM] = compat_radeon_cp_setparam,
-       [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc,
-       [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit,
-};
-
-/**
- * Called whenever a 32-bit process running under a 64-bit kernel
- * performs an ioctl on /dev/dri/card<n>.
- *
- * \param filp file pointer.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
- */
-long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       unsigned int nr = DRM_IOCTL_NR(cmd);
-       drm_ioctl_compat_t *fn = NULL;
-       int ret;
-
-       if (nr < DRM_COMMAND_BASE)
-               return drm_compat_ioctl(filp, cmd, arg);
-
-       if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls))
-               fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE];
-
-       lock_kernel();          /* XXX for now */
-       if (fn != NULL)
-               ret = (*fn) (filp, cmd, arg);
-       else
-               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
-       unlock_kernel();
-
-       return ret;
-}
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
deleted file mode 100644 (file)
index ee40d19..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */
-/*
- * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
- *
- * The Weather Channel (TM) funded Tungsten Graphics to develop the
- * initial release of the Radeon 8500 driver under the XFree86 license.
- * This notice must be preserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- *    Michel Dänzer <michel@daenzer.net>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "radeon_drm.h"
-#include "radeon_drv.h"
-
-static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
-                                             u32 mask)
-{
-       u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
-       if (irqs)
-               RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
-       return irqs;
-}
-
-/* Interrupts - Used for device synchronization and flushing in the
- * following circumstances:
- *
- * - Exclusive FB access with hw idle:
- *    - Wait for GUI Idle (?) interrupt, then do normal flush.
- *
- * - Frame throttling, NV_fence:
- *    - Drop marker irq's into command stream ahead of time.
- *    - Wait on irq's with lock *not held*
- *    - Check each for termination condition
- *
- * - Internally in cp_getbuffer, etc:
- *    - as above, but wait with lock held???
- *
- * NOTE: These functions are misleadingly named -- the irq's aren't
- * tied to dma at all, this is just a hangover from dri prehistory.
- */
-
-irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
-{
-       struct drm_device *dev = (struct drm_device *) arg;
-       drm_radeon_private_t *dev_priv =
-           (drm_radeon_private_t *) dev->dev_private;
-       u32 stat;
-
-       /* Only consider the bits we're interested in - others could be used
-        * outside the DRM
-        */
-       stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-                                                 RADEON_CRTC_VBLANK_STAT |
-                                                 RADEON_CRTC2_VBLANK_STAT));
-       if (!stat)
-               return IRQ_NONE;
-
-       stat &= dev_priv->irq_enable_reg;
-
-       /* SW interrupt */
-       if (stat & RADEON_SW_INT_TEST) {
-               DRM_WAKEUP(&dev_priv->swi_queue);
-       }
-
-       /* VBLANK interrupt */
-       if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
-               int vblank_crtc = dev_priv->vblank_crtc;
-
-               if ((vblank_crtc &
-                    (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
-                   (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
-                       if (stat & RADEON_CRTC_VBLANK_STAT)
-                               atomic_inc(&dev->vbl_received);
-                       if (stat & RADEON_CRTC2_VBLANK_STAT)
-                               atomic_inc(&dev->vbl_received2);
-               } else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
-                          (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
-                          ((stat & RADEON_CRTC2_VBLANK_STAT) &&
-                           (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
-                       atomic_inc(&dev->vbl_received);
-
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
-       }
-
-       return IRQ_HANDLED;
-}
-
-static int radeon_emit_irq(struct drm_device * dev)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       unsigned int ret;
-       RING_LOCALS;
-
-       atomic_inc(&dev_priv->swi_emitted);
-       ret = atomic_read(&dev_priv->swi_emitted);
-
-       BEGIN_RING(4);
-       OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
-       OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
-       ADVANCE_RING();
-       COMMIT_RING();
-
-       return ret;
-}
-
-static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
-{
-       drm_radeon_private_t *dev_priv =
-           (drm_radeon_private_t *) dev->dev_private;
-       int ret = 0;
-
-       if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr)
-               return 0;
-
-       dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-       DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
-                   RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
-
-       return ret;
-}
-
-static int radeon_driver_vblank_do_wait(struct drm_device * dev,
-                                       unsigned int *sequence, int crtc)
-{
-       drm_radeon_private_t *dev_priv =
-           (drm_radeon_private_t *) dev->dev_private;
-       unsigned int cur_vblank;
-       int ret = 0;
-       int ack = 0;
-       atomic_t *counter;
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       if (crtc == DRM_RADEON_VBLANK_CRTC1) {
-               counter = &dev->vbl_received;
-               ack |= RADEON_CRTC_VBLANK_STAT;
-       } else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
-               counter = &dev->vbl_received2;
-               ack |= RADEON_CRTC2_VBLANK_STAT;
-       } else
-               return -EINVAL;
-
-       radeon_acknowledge_irqs(dev_priv, ack);
-
-       dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using vertical blanks...
-        */
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(counter))
-                     - *sequence) <= (1 << 23)));
-
-       *sequence = cur_vblank;
-
-       return ret;
-}
-
-int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
-{
-       return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
-}
-
-int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
-{
-       return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
-}
-
-/* Needs the lock as it touches the ring.
- */
-int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_irq_emit_t *emit = data;
-       int result;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       result = radeon_emit_irq(dev);
-
-       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
-               DRM_ERROR("copy_to_user\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-/* Doesn't need the hardware lock.
- */
-int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_irq_wait_t *irqwait = data;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       return radeon_wait_irq(dev, irqwait->irq_seq);
-}
-
-void radeon_enable_interrupt(struct drm_device *dev)
-{
-       drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-
-       dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
-       if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
-               dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
-
-       if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
-               dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
-
-       RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
-       dev_priv->irq_enabled = 1;
-}
-
-/* drm_dma.h hooks
-*/
-void radeon_driver_irq_preinstall(struct drm_device * dev)
-{
-       drm_radeon_private_t *dev_priv =
-           (drm_radeon_private_t *) dev->dev_private;
-
-       /* Disable *all* interrupts */
-       RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
-
-       /* Clear bits if they're already high */
-       radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
-                                          RADEON_CRTC_VBLANK_STAT |
-                                          RADEON_CRTC2_VBLANK_STAT));
-}
-
-void radeon_driver_irq_postinstall(struct drm_device * dev)
-{
-       drm_radeon_private_t *dev_priv =
-           (drm_radeon_private_t *) dev->dev_private;
-
-       atomic_set(&dev_priv->swi_emitted, 0);
-       DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
-
-       radeon_enable_interrupt(dev);
-}
-
-void radeon_driver_irq_uninstall(struct drm_device * dev)
-{
-       drm_radeon_private_t *dev_priv =
-           (drm_radeon_private_t *) dev->dev_private;
-       if (!dev_priv)
-               return;
-
-       dev_priv->irq_enabled = 0;
-
-       /* Disable *all* interrupts */
-       RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
-}
-
-
-int radeon_vblank_crtc_get(struct drm_device *dev)
-{
-       drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-       u32 flag;
-       u32 value;
-
-       flag = RADEON_READ(RADEON_GEN_INT_CNTL);
-       value = 0;
-
-       if (flag & RADEON_CRTC_VBLANK_MASK)
-               value |= DRM_RADEON_VBLANK_CRTC1;
-
-       if (flag & RADEON_CRTC2_VBLANK_MASK)
-               value |= DRM_RADEON_VBLANK_CRTC2;
-       return value;
-}
-
-int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
-{
-       drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-       if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
-               DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
-               return -EINVAL;
-       }
-       dev_priv->vblank_crtc = (unsigned int)value;
-       radeon_enable_interrupt(dev);
-       return 0;
-}
diff --git a/drivers/char/drm/radeon_mem.c b/drivers/char/drm/radeon_mem.c
deleted file mode 100644 (file)
index 4af5286..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- */
-/*
- * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
- *
- * The Weather Channel (TM) funded Tungsten Graphics to develop the
- * initial release of the Radeon 8500 driver under the XFree86 license.
- * This notice must be preserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "radeon_drm.h"
-#include "radeon_drv.h"
-
-/* Very simple allocator for GART memory, working on a static range
- * already mapped into each client's address space.
- */
-
-static struct mem_block *split_block(struct mem_block *p, int start, int size,
-                                    struct drm_file *file_priv)
-{
-       /* Maybe cut off the start of an existing block */
-       if (start > p->start) {
-               struct mem_block *newblock =
-                   drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
-               if (!newblock)
-                       goto out;
-               newblock->start = start;
-               newblock->size = p->size - (start - p->start);
-               newblock->file_priv = NULL;
-               newblock->next = p->next;
-               newblock->prev = p;
-               p->next->prev = newblock;
-               p->next = newblock;
-               p->size -= newblock->size;
-               p = newblock;
-       }
-
-       /* Maybe cut off the end of an existing block */
-       if (size < p->size) {
-               struct mem_block *newblock =
-                   drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
-               if (!newblock)
-                       goto out;
-               newblock->start = start + size;
-               newblock->size = p->size - size;
-               newblock->file_priv = NULL;
-               newblock->next = p->next;
-               newblock->prev = p;
-               p->next->prev = newblock;
-               p->next = newblock;
-               p->size = size;
-       }
-
-      out:
-       /* Our block is in the middle */
-       p->file_priv = file_priv;
-       return p;
-}
-
-static struct mem_block *alloc_block(struct mem_block *heap, int size,
-                                    int align2, struct drm_file *file_priv)
-{
-       struct mem_block *p;
-       int mask = (1 << align2) - 1;
-
-       list_for_each(p, heap) {
-               int start = (p->start + mask) & ~mask;
-               if (p->file_priv == NULL && start + size <= p->start + p->size)
-                       return split_block(p, start, size, file_priv);
-       }
-
-       return NULL;
-}
-
-static struct mem_block *find_block(struct mem_block *heap, int start)
-{
-       struct mem_block *p;
-
-       list_for_each(p, heap)
-           if (p->start == start)
-               return p;
-
-       return NULL;
-}
-
-static void free_block(struct mem_block *p)
-{
-       p->file_priv = NULL;
-
-       /* Assumes a single contiguous range.  Needs a special file_priv in
-        * 'heap' to stop it being subsumed.
-        */
-       if (p->next->file_priv == NULL) {
-               struct mem_block *q = p->next;
-               p->size += q->size;
-               p->next = q->next;
-               p->next->prev = p;
-               drm_free(q, sizeof(*q), DRM_MEM_BUFS);
-       }
-
-       if (p->prev->file_priv == NULL) {
-               struct mem_block *q = p->prev;
-               q->size += p->size;
-               q->next = p->next;
-               q->next->prev = q;
-               drm_free(p, sizeof(*q), DRM_MEM_BUFS);
-       }
-}
-
-/* Initialize.  How to check for an uninitialized heap?
- */
-static int init_heap(struct mem_block **heap, int start, int size)
-{
-       struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS);
-
-       if (!blocks)
-               return -ENOMEM;
-
-       *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS);
-       if (!*heap) {
-               drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS);
-               return -ENOMEM;
-       }
-
-       blocks->start = start;
-       blocks->size = size;
-       blocks->file_priv = NULL;
-       blocks->next = blocks->prev = *heap;
-
-       memset(*heap, 0, sizeof(**heap));
-       (*heap)->file_priv = (struct drm_file *) - 1;
-       (*heap)->next = (*heap)->prev = blocks;
-       return 0;
-}
-
-/* Free all blocks associated with the releasing file.
- */
-void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap)
-{
-       struct mem_block *p;
-
-       if (!heap || !heap->next)
-               return;
-
-       list_for_each(p, heap) {
-               if (p->file_priv == file_priv)
-                       p->file_priv = NULL;
-       }
-
-       /* Assumes a single contiguous range.  Needs a special file_priv in
-        * 'heap' to stop it being subsumed.
-        */
-       list_for_each(p, heap) {
-               while (p->file_priv == NULL && p->next->file_priv == NULL) {
-                       struct mem_block *q = p->next;
-                       p->size += q->size;
-                       p->next = q->next;
-                       p->next->prev = p;
-                       drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
-               }
-       }
-}
-
-/* Shutdown.
- */
-void radeon_mem_takedown(struct mem_block **heap)
-{
-       struct mem_block *p;
-
-       if (!*heap)
-               return;
-
-       for (p = (*heap)->next; p != *heap;) {
-               struct mem_block *q = p;
-               p = p->next;
-               drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
-       }
-
-       drm_free(*heap, sizeof(**heap), DRM_MEM_DRIVER);
-       *heap = NULL;
-}
-
-/* IOCTL HANDLERS */
-
-static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region)
-{
-       switch (region) {
-       case RADEON_MEM_REGION_GART:
-               return &dev_priv->gart_heap;
-       case RADEON_MEM_REGION_FB:
-               return &dev_priv->fb_heap;
-       default:
-               return NULL;
-       }
-}
-
-int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_mem_alloc_t *alloc = data;
-       struct mem_block *block, **heap;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       heap = get_heap(dev_priv, alloc->region);
-       if (!heap || !*heap)
-               return -EFAULT;
-
-       /* Make things easier on ourselves: all allocations at least
-        * 4k aligned.
-        */
-       if (alloc->alignment < 12)
-               alloc->alignment = 12;
-
-       block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv);
-
-       if (!block)
-               return -ENOMEM;
-
-       if (DRM_COPY_TO_USER(alloc->region_offset, &block->start,
-                            sizeof(int))) {
-               DRM_ERROR("copy_to_user\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_mem_free_t *memfree = data;
-       struct mem_block *block, **heap;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       heap = get_heap(dev_priv, memfree->region);
-       if (!heap || !*heap)
-               return -EFAULT;
-
-       block = find_block(*heap, memfree->region_offset);
-       if (!block)
-               return -EFAULT;
-
-       if (block->file_priv != file_priv)
-               return -EPERM;
-
-       free_block(block);
-       return 0;
-}
-
-int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_mem_init_heap_t *initheap = data;
-       struct mem_block **heap;
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       heap = get_heap(dev_priv, initheap->region);
-       if (!heap)
-               return -EFAULT;
-
-       if (*heap) {
-               DRM_ERROR("heap already initialized?");
-               return -EFAULT;
-       }
-
-       return init_heap(heap, initheap->start, initheap->size);
-}
diff --git a/drivers/char/drm/radeon_microcode.h b/drivers/char/drm/radeon_microcode.h
deleted file mode 100644 (file)
index a348c9e..0000000
+++ /dev/null
@@ -1,1844 +0,0 @@
-/*
- * Copyright 2007 Advanced Micro Devices, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#ifndef RADEON_MICROCODE_H
-#define RADEON_MICROCODE_H
-
-/* production radeon ucode r1xx-r6xx */
-static const u32 R100_cp_microcode[][2] = {
-    { 0x21007000, 0000000000 },
-    { 0x20007000, 0000000000 },
-    { 0x000000b4, 0x00000004 },
-    { 0x000000b8, 0x00000004 },
-    { 0x6f5b4d4c, 0000000000 },
-    { 0x4c4c427f, 0000000000 },
-    { 0x5b568a92, 0000000000 },
-    { 0x4ca09c6d, 0000000000 },
-    { 0xad4c4c4c, 0000000000 },
-    { 0x4ce1af3d, 0000000000 },
-    { 0xd8afafaf, 0000000000 },
-    { 0xd64c4cdc, 0000000000 },
-    { 0x4cd10d10, 0000000000 },
-    { 0x000f0000, 0x00000016 },
-    { 0x362f242d, 0000000000 },
-    { 0x00000012, 0x00000004 },
-    { 0x000f0000, 0x00000016 },
-    { 0x362f282d, 0000000000 },
-    { 0x000380e7, 0x00000002 },
-    { 0x04002c97, 0x00000002 },
-    { 0x000f0001, 0x00000016 },
-    { 0x333a3730, 0000000000 },
-    { 0x000077ef, 0x00000002 },
-    { 0x00061000, 0x00000002 },
-    { 0x00000021, 0x0000001a },
-    { 0x00004000, 0x0000001e },
-    { 0x00061000, 0x00000002 },
-    { 0x00000021, 0x0000001a },
-    { 0x00004000, 0x0000001e },
-    { 0x00061000, 0x00000002 },
-    { 0x00000021, 0x0000001a },
-    { 0x00004000, 0x0000001e },
-    { 0x00000017, 0x00000004 },
-    { 0x0003802b, 0x00000002 },
-    { 0x040067e0, 0x00000002 },
-    { 0x00000017, 0x00000004 },
-    { 0x000077e0, 0x00000002 },
-    { 0x00065000, 0x00000002 },
-    { 0x000037e1, 0x00000002 },
-    { 0x040067e1, 0x00000006 },
-    { 0x000077e0, 0x00000002 },
-    { 0x000077e1, 0x00000002 },
-    { 0x000077e1, 0x00000006 },
-    { 0xffffffff, 0000000000 },
-    { 0x10000000, 0000000000 },
-    { 0x0003802b, 0x00000002 },
-    { 0x040067e0, 0x00000006 },
-    { 0x00007675, 0x00000002 },
-    { 0x00007676, 0x00000002 },
-    { 0x00007677, 0x00000002 },
-    { 0x00007678, 0x00000006 },
-    { 0x0003802c, 0x00000002 },
-    { 0x04002676, 0x00000002 },
-    { 0x00007677, 0x00000002 },
-    { 0x00007678, 0x00000006 },
-    { 0x0000002f, 0x00000018 },
-    { 0x0000002f, 0x00000018 },
-    { 0000000000, 0x00000006 },
-    { 0x00000030, 0x00000018 },
-    { 0x00000030, 0x00000018 },
-    { 0000000000, 0x00000006 },
-    { 0x01605000, 0x00000002 },
-    { 0x00065000, 0x00000002 },
-    { 0x00098000, 0x00000002 },
-    { 0x00061000, 0x00000002 },
-    { 0x64c0603e, 0x00000004 },
-    { 0x000380e6, 0x00000002 },
-    { 0x040025c5, 0x00000002 },
-    { 0x00080000, 0x00000016 },
-    { 0000000000, 0000000000 },
-    { 0x0400251d, 0x00000002 },
-    { 0x00007580, 0x00000002 },
-    { 0x00067581, 0x00000002 },
-    { 0x04002580, 0x00000002 },
-    { 0x00067581, 0x00000002 },
-    { 0x00000049, 0x00000004 },
-    { 0x00005000, 0000000000 },
-    { 0x000380e6, 0x00000002 },
-    { 0x040025c5, 0x00000002 },
-    { 0x00061000, 0x00000002 },
-    { 0x0000750e, 0x00000002 },
-    { 0x00019000, 0x00000002 },
-    { 0x00011055, 0x00000014 },
-    { 0x00000055, 0x00000012 },
-    { 0x0400250f, 0x00000002 },
-    { 0x0000504f, 0x00000004 },
-    { 0x000380e6, 0x00000002 },
-    { 0x040025c5, 0x00000002 },
-    { 0x00007565, 0x00000002 },
-    { 0x00007566, 0x00000002 },
-    { 0x00000058, 0x00000004 },
-    { 0x000380e6, 0x00000002 },
-    { 0x040025c5, 0x00000002 },
-    { 0x01e655b4, 0x00000002 },
-    { 0x4401b0e4, 0x00000002 },
-    { 0x01c110e4, 0x00000002 },
-    { 0x26667066, 0x00000018 },
-    { 0x040c2565, 0x00000002 },
-    { 0x00000066, 0x00000018 },
-    { 0x04002564, 0x00000002 },
-    { 0x00007566, 0x00000002 },
-    { 0x0000005d, 0x00000004 },
-    { 0x00401069, 0x00000008 },
-    { 0x00101000, 0x00000002 },
-    { 0x000d80ff, 0x00000002 },
-    { 0x0080006c, 0x00000008 },
-    { 0x000f9000, 0x00000002 },
-    { 0x000e00ff, 0x00000002 },
-    { 0000000000, 0x00000006 },
-    { 0x0000008f, 0x00000018 },
-    { 0x0000005b, 0x00000004 },
-    { 0x000380e6, 0x00000002 },
-    { 0x040025c5, 0x00000002 },
-    { 0x00007576, 0x00000002 },
-    { 0x00065000, 0x00000002 },
-    { 0x00009000, 0x00000002 },
-    { 0x00041000, 0x00000002 },
-    { 0x0c00350e, 0x00000002 },
-    { 0x00049000, 0x00000002 },
-    { 0x00051000, 0x00000002 },
-    { 0x01e785f8, 0x00000002 },
-    { 0x00200000, 0x00000002 },
-    { 0x0060007e, 0x0000000c },
-    { 0x00007563, 0x00000002 },
-    { 0x006075f0, 0x00000021 },
-    { 0x20007073, 0x00000004 },
-    { 0x00005073, 0x00000004 },
-    { 0x000380e6, 0x00000002 },
-    { 0x040025c5, 0x00000002 },
-    { 0x00007576, 0x00000002 },
-    { 0x00007577, 0x00000002 },
-    { 0x0000750e, 0x00000002 },
-    { 0x0000750f, 0x00000002 },
-    { 0x00a05000, 0x00000002 },
-    { 0x00600083, 0x0000000c },
-    { 0x006075f0, 0x00000021 },
-    { 0x000075f8, 0x00000002 },
-    { 0x00000083, 0x00000004 },
-    { 0x000a750e, 0x00000002 },
-    { 0x000380e6, 0x00000002 },
-    { 0x040025c5, 0x00000002 },
-    { 0x0020750f, 0x00000002 },
-    { 0x00600086, 0x00000004 },
-    { 0x00007570, 0x00000002 },
-    { 0x00007571, 0x00000002 },
-    { 0x00007572, 0x00000006 },
-    { 0x000380e6, 0x00000002 },
-    { 0x040025c5, 0x00000002 },
-    { 0x00005000, 0x00000002 },
-    { 0x00a05000, 0x00000002 },
-    { 0x00007568, 0x00000002 },
-    { 0x00061000, 0x00000002 },
-    { 0x00000095, 0x0000000c },
-    { 0x00058000, 0x00000002 },
-    { 0x0c607562, 0x00000002 },
-    { 0x00000097, 0x00000004 },
-    { 0x000380e6, 0x00000002 },
-    { 0x040025c5, 0x00000002 },
-    { 0x00600096, 0x00000004 },
-    { 0x400070e5, 0000000000 },
-    { 0x000380e6, 0x00000002 },
-    { 0x040025c5, 0x00000002 },
-    { 0x000380e5, 0x00000002 },
-    { 0x000000a8, 0x0000001c },
-    { 0x000650aa, 0x00000018 },
-    { 0x040025bb, 0x00000002 },
-    { 0x000610ab, 0x00000018 },
-    { 0x040075bc, 0000000000 },
-    { 0x000075bb, 0x00000002 },
-    { 0x000075bc, 0000000000 },
-    { 0x00090000, 0x00000006 },
-    { 0x00090000, 0x00000002 },
-    { 0x000d8002, 0x00000006 },
-    { 0x00007832, 0x00000002 },
-    { 0x00005000, 0x00000002 },
-    { 0x000380e7, 0x00000002 },
-    { 0x04002c97, 0x00000002 },
-    { 0x00007820, 0x00000002 },
-    { 0x00007821, 0x00000002 },
-    { 0x00007800, 0000000000 },
-    { 0x01200000, 0x00000002 },
-    { 0x20077000, 0x00000002 },
-    { 0x01200000, 0x00000002 },
-    { 0x20007000, 0x00000002 },
-    { 0x00061000, 0x00000002 },
-    { 0x0120751b, 0x00000002 },
-    { 0x8040750a, 0x00000002 },
-    { 0x8040750b, 0x00000002 },
-    { 0x00110000, 0x00000002 },
-    { 0x000380e5, 0x00000002 },
-    { 0x000000c6, 0x0000001c },
-    { 0x000610ab, 0x00000018 },
-    { 0x844075bd, 0x00000002 },
-    { 0x000610aa, 0x00000018 },
-    { 0x840075bb, 0x00000002 },
-    { 0x000610ab, 0x00000018 },
-    { 0x844075bc, 0x00000002 },
-    { 0x000000c9, 0x00000004 },
-    { 0x804075bd, 0x00000002 },
-    { 0x800075bb, 0x00000002 },
-    { 0x804075bc, 0x00000002 },
-    { 0x00108000, 0x00000002 },
-    { 0x01400000, 0x00000002 },
-    { 0x006000cd, 0x0000000c },
-    { 0x20c07000, 0x00000020 },
-    { 0x000000cf, 0x00000012 },
-    { 0x00800000, 0x00000006 },
-    { 0x0080751d, 0x00000006 },
-    { 0000000000, 0000000000 },
-    { 0x0000775c, 0x00000002 },
-    { 0x00a05000, 0x00000002 },
-    { 0x00661000, 0x00000002 },
-    { 0x0460275d, 0x00000020 },
-    { 0x00004000, 0000000000 },
-    { 0x01e00830, 0x00000002 },
-    { 0x21007000, 0000000000 },
-    { 0x6464614d, 0000000000 },
-    { 0x69687420, 0000000000 },
-    { 0x00000073, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x00005000, 0x00000002 },
-    { 0x000380d0, 0x00000002 },
-    { 0x040025e0, 0x00000002 },
-    { 0x000075e1, 0000000000 },
-    { 0x00000001, 0000000000 },
-    { 0x000380e0, 0x00000002 },
-    { 0x04002394, 0x00000002 },
-    { 0x00005000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x00000008, 0000000000 },
-    { 0x00000004, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-};
-
-static const u32 R200_cp_microcode[][2] = {
-    { 0x21007000, 0000000000 },
-    { 0x20007000, 0000000000 },
-    { 0x000000bf, 0x00000004 },
-    { 0x000000c3, 0x00000004 },
-    { 0x7a685e5d, 0000000000 },
-    { 0x5d5d5588, 0000000000 },
-    { 0x68659197, 0000000000 },
-    { 0x5da19f78, 0000000000 },
-    { 0x5d5d5d5d, 0000000000 },
-    { 0x5dee5d50, 0000000000 },
-    { 0xf2acacac, 0000000000 },
-    { 0xe75df9e9, 0000000000 },
-    { 0xb1dd0e11, 0000000000 },
-    { 0xe2afafaf, 0000000000 },
-    { 0x000f0000, 0x00000016 },
-    { 0x452f232d, 0000000000 },
-    { 0x00000013, 0x00000004 },
-    { 0x000f0000, 0x00000016 },
-    { 0x452f272d, 0000000000 },
-    { 0x000f0001, 0x00000016 },
-    { 0x3e4d4a37, 0000000000 },
-    { 0x000077ef, 0x00000002 },
-    { 0x00061000, 0x00000002 },
-    { 0x00000020, 0x0000001a },
-    { 0x00004000, 0x0000001e },
-    { 0x00061000, 0x00000002 },
-    { 0x00000020, 0x0000001a },
-    { 0x00004000, 0x0000001e },
-    { 0x00061000, 0x00000002 },
-    { 0x00000020, 0x0000001a },
-    { 0x00004000, 0x0000001e },
-    { 0x00000016, 0x00000004 },
-    { 0x0003802a, 0x00000002 },
-    { 0x040067e0, 0x00000002 },
-    { 0x00000016, 0x00000004 },
-    { 0x000077e0, 0x00000002 },
-    { 0x00065000, 0x00000002 },
-    { 0x000037e1, 0x00000002 },
-    { 0x040067e1, 0x00000006 },
-    { 0x000077e0, 0x00000002 },
-    { 0x000077e1, 0x00000002 },
-    { 0x000077e1, 0x00000006 },
-    { 0xffffffff, 0000000000 },
-    { 0x10000000, 0000000000 },
-    { 0x07f007f0, 0000000000 },
-    { 0x0003802a, 0x00000002 },
-    { 0x040067e0, 0x00000006 },
-    { 0x0003802c, 0x00000002 },
-    { 0x04002741, 0x00000002 },
-    { 0x04002741, 0x00000002 },
-    { 0x04002743, 0x00000002 },
-    { 0x00007675, 0x00000002 },
-    { 0x00007676, 0x00000002 },
-    { 0x00007677, 0x00000002 },
-    { 0x00007678, 0x00000006 },
-    { 0x0003802c, 0x00000002 },
-    { 0x04002741, 0x00000002 },
-    { 0x04002741, 0x00000002 },
-    { 0x04002743, 0x00000002 },
-    { 0x00007676, 0x00000002 },
-    { 0x00007677, 0x00000002 },
-    { 0x00007678, 0x00000006 },
-    { 0x0003802b, 0x00000002 },
-    { 0x04002676, 0x00000002 },
-    { 0x00007677, 0x00000002 },
-    { 0x0003802c, 0x00000002 },
-    { 0x04002741, 0x00000002 },
-    { 0x04002743, 0x00000002 },
-    { 0x00007678, 0x00000006 },
-    { 0x0003802c, 0x00000002 },
-    { 0x04002741, 0x00000002 },
-    { 0x04002741, 0x00000002 },
-    { 0x04002743, 0x00000002 },
-    { 0x00007678, 0x00000006 },
-    { 0x0000002f, 0x00000018 },
-    { 0x0000002f, 0x00000018 },
-    { 0000000000, 0x00000006 },
-    { 0x00000037, 0x00000018 },
-    { 0x00000037, 0x00000018 },
-    { 0000000000, 0x00000006 },
-    { 0x01605000, 0x00000002 },
-    { 0x00065000, 0x00000002 },
-    { 0x00098000, 0x00000002 },
-    { 0x00061000, 0x00000002 },
-    { 0x64c06051, 0x00000004 },
-    { 0x00080000, 0x00000016 },
-    { 0000000000, 0000000000 },
-    { 0x0400251d, 0x00000002 },
-    { 0x00007580, 0x00000002 },
-    { 0x00067581, 0x00000002 },
-    { 0x04002580, 0x00000002 },
-    { 0x00067581, 0x00000002 },
-    { 0x0000005a, 0x00000004 },
-    { 0x00005000, 0000000000 },
-    { 0x00061000, 0x00000002 },
-    { 0x0000750e, 0x00000002 },
-    { 0x00019000, 0x00000002 },
-    { 0x00011064, 0x00000014 },
-    { 0x00000064, 0x00000012 },
-    { 0x0400250f, 0x00000002 },
-    { 0x0000505e, 0x00000004 },
-    { 0x00007565, 0x00000002 },
-    { 0x00007566, 0x00000002 },
-    { 0x00000065, 0x00000004 },
-    { 0x01e655b4, 0x00000002 },
-    { 0x4401b0f0, 0x00000002 },
-    { 0x01c110f0, 0x00000002 },
-    { 0x26667071, 0x00000018 },
-    { 0x040c2565, 0x00000002 },
-    { 0x00000071, 0x00000018 },
-    { 0x04002564, 0x00000002 },
-    { 0x00007566, 0x00000002 },
-    { 0x00000068, 0x00000004 },
-    { 0x00401074, 0x00000008 },
-    { 0x00101000, 0x00000002 },
-    { 0x000d80ff, 0x00000002 },
-    { 0x00800077, 0x00000008 },
-    { 0x000f9000, 0x00000002 },
-    { 0x000e00ff, 0x00000002 },
-    { 0000000000, 0x00000006 },
-    { 0x00000094, 0x00000018 },
-    { 0x00000068, 0x00000004 },
-    { 0x00007576, 0x00000002 },
-    { 0x00065000, 0x00000002 },
-    { 0x00009000, 0x00000002 },
-    { 0x00041000, 0x00000002 },
-    { 0x0c00350e, 0x00000002 },
-    { 0x00049000, 0x00000002 },
-    { 0x00051000, 0x00000002 },
-    { 0x01e785f8, 0x00000002 },
-    { 0x00200000, 0x00000002 },
-    { 0x00600087, 0x0000000c },
-    { 0x00007563, 0x00000002 },
-    { 0x006075f0, 0x00000021 },
-    { 0x2000707c, 0x00000004 },
-    { 0x0000507c, 0x00000004 },
-    { 0x00007576, 0x00000002 },
-    { 0x00007577, 0x00000002 },
-    { 0x0000750e, 0x00000002 },
-    { 0x0000750f, 0x00000002 },
-    { 0x00a05000, 0x00000002 },
-    { 0x0060008a, 0x0000000c },
-    { 0x006075f0, 0x00000021 },
-    { 0x000075f8, 0x00000002 },
-    { 0x0000008a, 0x00000004 },
-    { 0x000a750e, 0x00000002 },
-    { 0x0020750f, 0x00000002 },
-    { 0x0060008d, 0x00000004 },
-    { 0x00007570, 0x00000002 },
-    { 0x00007571, 0x00000002 },
-    { 0x00007572, 0x00000006 },
-    { 0x00005000, 0x00000002 },
-    { 0x00a05000, 0x00000002 },
-    { 0x00007568, 0x00000002 },
-    { 0x00061000, 0x00000002 },
-    { 0x00000098, 0x0000000c },
-    { 0x00058000, 0x00000002 },
-    { 0x0c607562, 0x00000002 },
-    { 0x0000009a, 0x00000004 },
-    { 0x00600099, 0x00000004 },
-    { 0x400070f1, 0000000000 },
-    { 0x000380f1, 0x00000002 },
-    { 0x000000a7, 0x0000001c },
-    { 0x000650a9, 0x00000018 },
-    { 0x040025bb, 0x00000002 },
-    { 0x000610aa, 0x00000018 },
-    { 0x040075bc, 0000000000 },
-    { 0x000075bb, 0x00000002 },
-    { 0x000075bc, 0000000000 },
-    { 0x00090000, 0x00000006 },
-    { 0x00090000, 0x00000002 },
-    { 0x000d8002, 0x00000006 },
-    { 0x00005000, 0x00000002 },
-    { 0x00007821, 0x00000002 },
-    { 0x00007800, 0000000000 },
-    { 0x00007821, 0x00000002 },
-    { 0x00007800, 0000000000 },
-    { 0x01665000, 0x00000002 },
-    { 0x000a0000, 0x00000002 },
-    { 0x000671cc, 0x00000002 },
-    { 0x0286f1cd, 0x00000002 },
-    { 0x000000b7, 0x00000010 },
-    { 0x21007000, 0000000000 },
-    { 0x000000be, 0x0000001c },
-    { 0x00065000, 0x00000002 },
-    { 0x000a0000, 0x00000002 },
-    { 0x00061000, 0x00000002 },
-    { 0x000b0000, 0x00000002 },
-    { 0x38067000, 0x00000002 },
-    { 0x000a00ba, 0x00000004 },
-    { 0x20007000, 0000000000 },
-    { 0x01200000, 0x00000002 },
-    { 0x20077000, 0x00000002 },
-    { 0x01200000, 0x00000002 },
-    { 0x20007000, 0000000000 },
-    { 0x00061000, 0x00000002 },
-    { 0x0120751b, 0x00000002 },
-    { 0x8040750a, 0x00000002 },
-    { 0x8040750b, 0x00000002 },
-    { 0x00110000, 0x00000002 },
-    { 0x000380f1, 0x00000002 },
-    { 0x000000d1, 0x0000001c },
-    { 0x000610aa, 0x00000018 },
-    { 0x844075bd, 0x00000002 },
-    { 0x000610a9, 0x00000018 },
-    { 0x840075bb, 0x00000002 },
-    { 0x000610aa, 0x00000018 },
-    { 0x844075bc, 0x00000002 },
-    { 0x000000d4, 0x00000004 },
-    { 0x804075bd, 0x00000002 },
-    { 0x800075bb, 0x00000002 },
-    { 0x804075bc, 0x00000002 },
-    { 0x00108000, 0x00000002 },
-    { 0x01400000, 0x00000002 },
-    { 0x006000d8, 0x0000000c },
-    { 0x20c07000, 0x00000020 },
-    { 0x000000da, 0x00000012 },
-    { 0x00800000, 0x00000006 },
-    { 0x0080751d, 0x00000006 },
-    { 0x000025bb, 0x00000002 },
-    { 0x000040d4, 0x00000004 },
-    { 0x0000775c, 0x00000002 },
-    { 0x00a05000, 0x00000002 },
-    { 0x00661000, 0x00000002 },
-    { 0x0460275d, 0x00000020 },
-    { 0x00004000, 0000000000 },
-    { 0x00007999, 0x00000002 },
-    { 0x00a05000, 0x00000002 },
-    { 0x00661000, 0x00000002 },
-    { 0x0460299b, 0x00000020 },
-    { 0x00004000, 0000000000 },
-    { 0x01e00830, 0x00000002 },
-    { 0x21007000, 0000000000 },
-    { 0x00005000, 0x00000002 },
-    { 0x00038056, 0x00000002 },
-    { 0x040025e0, 0x00000002 },
-    { 0x000075e1, 0000000000 },
-    { 0x00000001, 0000000000 },
-    { 0x000380ed, 0x00000002 },
-    { 0x04007394, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x000078c4, 0x00000002 },
-    { 0x000078c5, 0x00000002 },
-    { 0x000078c6, 0x00000002 },
-    { 0x00007924, 0x00000002 },
-    { 0x00007925, 0x00000002 },
-    { 0x00007926, 0x00000002 },
-    { 0x000000f2, 0x00000004 },
-    { 0x00007924, 0x00000002 },
-    { 0x00007925, 0x00000002 },
-    { 0x00007926, 0x00000002 },
-    { 0x000000f9, 0x00000004 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-};
-
-static const u32 R300_cp_microcode[][2] = {
-    { 0x4200e000, 0000000000 },
-    { 0x4000e000, 0000000000 },
-    { 0x000000ae, 0x00000008 },
-    { 0x000000b2, 0x00000008 },
-    { 0x67554b4a, 0000000000 },
-    { 0x4a4a4475, 0000000000 },
-    { 0x55527d83, 0000000000 },
-    { 0x4a8c8b65, 0000000000 },
-    { 0x4aef4af6, 0000000000 },
-    { 0x4ae14a4a, 0000000000 },
-    { 0xe4979797, 0000000000 },
-    { 0xdb4aebdd, 0000000000 },
-    { 0x9ccc4a4a, 0000000000 },
-    { 0xd1989898, 0000000000 },
-    { 0x4a0f9ad6, 0000000000 },
-    { 0x000ca000, 0x00000004 },
-    { 0x000d0012, 0x00000038 },
-    { 0x0000e8b4, 0x00000004 },
-    { 0x000d0014, 0x00000038 },
-    { 0x0000e8b6, 0x00000004 },
-    { 0x000d0016, 0x00000038 },
-    { 0x0000e854, 0x00000004 },
-    { 0x000d0018, 0x00000038 },
-    { 0x0000e855, 0x00000004 },
-    { 0x000d001a, 0x00000038 },
-    { 0x0000e856, 0x00000004 },
-    { 0x000d001c, 0x00000038 },
-    { 0x0000e857, 0x00000004 },
-    { 0x000d001e, 0x00000038 },
-    { 0x0000e824, 0x00000004 },
-    { 0x000d0020, 0x00000038 },
-    { 0x0000e825, 0x00000004 },
-    { 0x000d0022, 0x00000038 },
-    { 0x0000e830, 0x00000004 },
-    { 0x000d0024, 0x00000038 },
-    { 0x0000f0c0, 0x00000004 },
-    { 0x000d0026, 0x00000038 },
-    { 0x0000f0c1, 0x00000004 },
-    { 0x000d0028, 0x00000038 },
-    { 0x0000f041, 0x00000004 },
-    { 0x000d002a, 0x00000038 },
-    { 0x0000f184, 0x00000004 },
-    { 0x000d002c, 0x00000038 },
-    { 0x0000f185, 0x00000004 },
-    { 0x000d002e, 0x00000038 },
-    { 0x0000f186, 0x00000004 },
-    { 0x000d0030, 0x00000038 },
-    { 0x0000f187, 0x00000004 },
-    { 0x000d0032, 0x00000038 },
-    { 0x0000f180, 0x00000004 },
-    { 0x000d0034, 0x00000038 },
-    { 0x0000f393, 0x00000004 },
-    { 0x000d0036, 0x00000038 },
-    { 0x0000f38a, 0x00000004 },
-    { 0x000d0038, 0x00000038 },
-    { 0x0000f38e, 0x00000004 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00000043, 0x00000018 },
-    { 0x00cce800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x0000003a, 0x00000008 },
-    { 0x0000a000, 0000000000 },
-    { 0x2000451d, 0x00000004 },
-    { 0x0000e580, 0x00000004 },
-    { 0x000ce581, 0x00000004 },
-    { 0x08004580, 0x00000004 },
-    { 0x000ce581, 0x00000004 },
-    { 0x00000047, 0x00000008 },
-    { 0x0000a000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x0000e50e, 0x00000004 },
-    { 0x00032000, 0x00000004 },
-    { 0x00022051, 0x00000028 },
-    { 0x00000051, 0x00000024 },
-    { 0x0800450f, 0x00000004 },
-    { 0x0000a04b, 0x00000008 },
-    { 0x0000e565, 0x00000004 },
-    { 0x0000e566, 0x00000004 },
-    { 0x00000052, 0x00000008 },
-    { 0x03cca5b4, 0x00000004 },
-    { 0x05432000, 0x00000004 },
-    { 0x00022000, 0x00000004 },
-    { 0x4ccce05e, 0x00000030 },
-    { 0x08274565, 0x00000004 },
-    { 0x0000005e, 0x00000030 },
-    { 0x08004564, 0x00000004 },
-    { 0x0000e566, 0x00000004 },
-    { 0x00000055, 0x00000008 },
-    { 0x00802061, 0x00000010 },
-    { 0x00202000, 0x00000004 },
-    { 0x001b00ff, 0x00000004 },
-    { 0x01000064, 0x00000010 },
-    { 0x001f2000, 0x00000004 },
-    { 0x001c00ff, 0x00000004 },
-    { 0000000000, 0x0000000c },
-    { 0x00000080, 0x00000030 },
-    { 0x00000055, 0x00000008 },
-    { 0x0000e576, 0x00000004 },
-    { 0x000ca000, 0x00000004 },
-    { 0x00012000, 0x00000004 },
-    { 0x00082000, 0x00000004 },
-    { 0x1800650e, 0x00000004 },
-    { 0x00092000, 0x00000004 },
-    { 0x000a2000, 0x00000004 },
-    { 0x000f0000, 0x00000004 },
-    { 0x00400000, 0x00000004 },
-    { 0x00000074, 0x00000018 },
-    { 0x0000e563, 0x00000004 },
-    { 0x00c0e5f9, 0x000000c2 },
-    { 0x00000069, 0x00000008 },
-    { 0x0000a069, 0x00000008 },
-    { 0x0000e576, 0x00000004 },
-    { 0x0000e577, 0x00000004 },
-    { 0x0000e50e, 0x00000004 },
-    { 0x0000e50f, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00000077, 0x00000018 },
-    { 0x00c0e5f9, 0x000000c2 },
-    { 0x00000077, 0x00000008 },
-    { 0x0014e50e, 0x00000004 },
-    { 0x0040e50f, 0x00000004 },
-    { 0x00c0007a, 0x00000008 },
-    { 0x0000e570, 0x00000004 },
-    { 0x0000e571, 0x00000004 },
-    { 0x0000e572, 0x0000000c },
-    { 0x0000a000, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x0000e568, 0x00000004 },
-    { 0x000c2000, 0x00000004 },
-    { 0x00000084, 0x00000018 },
-    { 0x000b0000, 0x00000004 },
-    { 0x18c0e562, 0x00000004 },
-    { 0x00000086, 0x00000008 },
-    { 0x00c00085, 0x00000008 },
-    { 0x000700e3, 0x00000004 },
-    { 0x00000092, 0x00000038 },
-    { 0x000ca094, 0x00000030 },
-    { 0x080045bb, 0x00000004 },
-    { 0x000c2095, 0x00000030 },
-    { 0x0800e5bc, 0000000000 },
-    { 0x0000e5bb, 0x00000004 },
-    { 0x0000e5bc, 0000000000 },
-    { 0x00120000, 0x0000000c },
-    { 0x00120000, 0x00000004 },
-    { 0x001b0002, 0x0000000c },
-    { 0x0000a000, 0x00000004 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0000e800, 0000000000 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0000e82e, 0000000000 },
-    { 0x02cca000, 0x00000004 },
-    { 0x00140000, 0x00000004 },
-    { 0x000ce1cc, 0x00000004 },
-    { 0x050de1cd, 0x00000004 },
-    { 0x00400000, 0x00000004 },
-    { 0x000000a4, 0x00000018 },
-    { 0x00c0a000, 0x00000004 },
-    { 0x000000a1, 0x00000008 },
-    { 0x000000a6, 0x00000020 },
-    { 0x4200e000, 0000000000 },
-    { 0x000000ad, 0x00000038 },
-    { 0x000ca000, 0x00000004 },
-    { 0x00140000, 0x00000004 },
-    { 0x000c2000, 0x00000004 },
-    { 0x00160000, 0x00000004 },
-    { 0x700ce000, 0x00000004 },
-    { 0x001400a9, 0x00000008 },
-    { 0x4000e000, 0000000000 },
-    { 0x02400000, 0x00000004 },
-    { 0x400ee000, 0x00000004 },
-    { 0x02400000, 0x00000004 },
-    { 0x4000e000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x0240e51b, 0x00000004 },
-    { 0x0080e50a, 0x00000005 },
-    { 0x0080e50b, 0x00000005 },
-    { 0x00220000, 0x00000004 },
-    { 0x000700e3, 0x00000004 },
-    { 0x000000c0, 0x00000038 },
-    { 0x000c2095, 0x00000030 },
-    { 0x0880e5bd, 0x00000005 },
-    { 0x000c2094, 0x00000030 },
-    { 0x0800e5bb, 0x00000005 },
-    { 0x000c2095, 0x00000030 },
-    { 0x0880e5bc, 0x00000005 },
-    { 0x000000c3, 0x00000008 },
-    { 0x0080e5bd, 0x00000005 },
-    { 0x0000e5bb, 0x00000005 },
-    { 0x0080e5bc, 0x00000005 },
-    { 0x00210000, 0x00000004 },
-    { 0x02800000, 0x00000004 },
-    { 0x00c000c7, 0x00000018 },
-    { 0x4180e000, 0x00000040 },
-    { 0x000000c9, 0x00000024 },
-    { 0x01000000, 0x0000000c },
-    { 0x0100e51d, 0x0000000c },
-    { 0x000045bb, 0x00000004 },
-    { 0x000080c3, 0x00000008 },
-    { 0x0000f3ce, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00cc2000, 0x00000004 },
-    { 0x08c053cf, 0x00000040 },
-    { 0x00008000, 0000000000 },
-    { 0x0000f3d2, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00cc2000, 0x00000004 },
-    { 0x08c053d3, 0x00000040 },
-    { 0x00008000, 0000000000 },
-    { 0x0000f39d, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00cc2000, 0x00000004 },
-    { 0x08c0539e, 0x00000040 },
-    { 0x00008000, 0000000000 },
-    { 0x03c00830, 0x00000004 },
-    { 0x4200e000, 0000000000 },
-    { 0x0000a000, 0x00000004 },
-    { 0x200045e0, 0x00000004 },
-    { 0x0000e5e1, 0000000000 },
-    { 0x00000001, 0000000000 },
-    { 0x000700e0, 0x00000004 },
-    { 0x0800e394, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x0000e8c4, 0x00000004 },
-    { 0x0000e8c5, 0x00000004 },
-    { 0x0000e8c6, 0x00000004 },
-    { 0x0000e928, 0x00000004 },
-    { 0x0000e929, 0x00000004 },
-    { 0x0000e92a, 0x00000004 },
-    { 0x000000e4, 0x00000008 },
-    { 0x0000e928, 0x00000004 },
-    { 0x0000e929, 0x00000004 },
-    { 0x0000e92a, 0x00000004 },
-    { 0x000000eb, 0x00000008 },
-    { 0x02c02000, 0x00000004 },
-    { 0x00060000, 0x00000004 },
-    { 0x000000f3, 0x00000034 },
-    { 0x000000f0, 0x00000008 },
-    { 0x00008000, 0x00000004 },
-    { 0xc000e000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x001d0018, 0x00000004 },
-    { 0x001a0001, 0x00000004 },
-    { 0x000000fb, 0x00000034 },
-    { 0x0000004a, 0x00000008 },
-    { 0x0500a04a, 0x00000008 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-};
-
-static const u32 R420_cp_microcode[][2] = {
-    { 0x4200e000, 0000000000 },
-    { 0x4000e000, 0000000000 },
-    { 0x00000099, 0x00000008 },
-    { 0x0000009d, 0x00000008 },
-    { 0x4a554b4a, 0000000000 },
-    { 0x4a4a4467, 0000000000 },
-    { 0x55526f75, 0000000000 },
-    { 0x4a7e7d65, 0000000000 },
-    { 0xd9d3dff6, 0000000000 },
-    { 0x4ac54a4a, 0000000000 },
-    { 0xc8828282, 0000000000 },
-    { 0xbf4acfc1, 0000000000 },
-    { 0x87b04a4a, 0000000000 },
-    { 0xb5838383, 0000000000 },
-    { 0x4a0f85ba, 0000000000 },
-    { 0x000ca000, 0x00000004 },
-    { 0x000d0012, 0x00000038 },
-    { 0x0000e8b4, 0x00000004 },
-    { 0x000d0014, 0x00000038 },
-    { 0x0000e8b6, 0x00000004 },
-    { 0x000d0016, 0x00000038 },
-    { 0x0000e854, 0x00000004 },
-    { 0x000d0018, 0x00000038 },
-    { 0x0000e855, 0x00000004 },
-    { 0x000d001a, 0x00000038 },
-    { 0x0000e856, 0x00000004 },
-    { 0x000d001c, 0x00000038 },
-    { 0x0000e857, 0x00000004 },
-    { 0x000d001e, 0x00000038 },
-    { 0x0000e824, 0x00000004 },
-    { 0x000d0020, 0x00000038 },
-    { 0x0000e825, 0x00000004 },
-    { 0x000d0022, 0x00000038 },
-    { 0x0000e830, 0x00000004 },
-    { 0x000d0024, 0x00000038 },
-    { 0x0000f0c0, 0x00000004 },
-    { 0x000d0026, 0x00000038 },
-    { 0x0000f0c1, 0x00000004 },
-    { 0x000d0028, 0x00000038 },
-    { 0x0000f041, 0x00000004 },
-    { 0x000d002a, 0x00000038 },
-    { 0x0000f184, 0x00000004 },
-    { 0x000d002c, 0x00000038 },
-    { 0x0000f185, 0x00000004 },
-    { 0x000d002e, 0x00000038 },
-    { 0x0000f186, 0x00000004 },
-    { 0x000d0030, 0x00000038 },
-    { 0x0000f187, 0x00000004 },
-    { 0x000d0032, 0x00000038 },
-    { 0x0000f180, 0x00000004 },
-    { 0x000d0034, 0x00000038 },
-    { 0x0000f393, 0x00000004 },
-    { 0x000d0036, 0x00000038 },
-    { 0x0000f38a, 0x00000004 },
-    { 0x000d0038, 0x00000038 },
-    { 0x0000f38e, 0x00000004 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00000043, 0x00000018 },
-    { 0x00cce800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x0000003a, 0x00000008 },
-    { 0x0000a000, 0000000000 },
-    { 0x2000451d, 0x00000004 },
-    { 0x0000e580, 0x00000004 },
-    { 0x000ce581, 0x00000004 },
-    { 0x08004580, 0x00000004 },
-    { 0x000ce581, 0x00000004 },
-    { 0x00000047, 0x00000008 },
-    { 0x0000a000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x0000e50e, 0x00000004 },
-    { 0x00032000, 0x00000004 },
-    { 0x00022051, 0x00000028 },
-    { 0x00000051, 0x00000024 },
-    { 0x0800450f, 0x00000004 },
-    { 0x0000a04b, 0x00000008 },
-    { 0x0000e565, 0x00000004 },
-    { 0x0000e566, 0x00000004 },
-    { 0x00000052, 0x00000008 },
-    { 0x03cca5b4, 0x00000004 },
-    { 0x05432000, 0x00000004 },
-    { 0x00022000, 0x00000004 },
-    { 0x4ccce05e, 0x00000030 },
-    { 0x08274565, 0x00000004 },
-    { 0x0000005e, 0x00000030 },
-    { 0x08004564, 0x00000004 },
-    { 0x0000e566, 0x00000004 },
-    { 0x00000055, 0x00000008 },
-    { 0x00802061, 0x00000010 },
-    { 0x00202000, 0x00000004 },
-    { 0x001b00ff, 0x00000004 },
-    { 0x01000064, 0x00000010 },
-    { 0x001f2000, 0x00000004 },
-    { 0x001c00ff, 0x00000004 },
-    { 0000000000, 0x0000000c },
-    { 0x00000072, 0x00000030 },
-    { 0x00000055, 0x00000008 },
-    { 0x0000e576, 0x00000004 },
-    { 0x0000e577, 0x00000004 },
-    { 0x0000e50e, 0x00000004 },
-    { 0x0000e50f, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00000069, 0x00000018 },
-    { 0x00c0e5f9, 0x000000c2 },
-    { 0x00000069, 0x00000008 },
-    { 0x0014e50e, 0x00000004 },
-    { 0x0040e50f, 0x00000004 },
-    { 0x00c0006c, 0x00000008 },
-    { 0x0000e570, 0x00000004 },
-    { 0x0000e571, 0x00000004 },
-    { 0x0000e572, 0x0000000c },
-    { 0x0000a000, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x0000e568, 0x00000004 },
-    { 0x000c2000, 0x00000004 },
-    { 0x00000076, 0x00000018 },
-    { 0x000b0000, 0x00000004 },
-    { 0x18c0e562, 0x00000004 },
-    { 0x00000078, 0x00000008 },
-    { 0x00c00077, 0x00000008 },
-    { 0x000700c7, 0x00000004 },
-    { 0x00000080, 0x00000038 },
-    { 0x0000e5bb, 0x00000004 },
-    { 0x0000e5bc, 0000000000 },
-    { 0x0000a000, 0x00000004 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0000e800, 0000000000 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0000e82e, 0000000000 },
-    { 0x02cca000, 0x00000004 },
-    { 0x00140000, 0x00000004 },
-    { 0x000ce1cc, 0x00000004 },
-    { 0x050de1cd, 0x00000004 },
-    { 0x00400000, 0x00000004 },
-    { 0x0000008f, 0x00000018 },
-    { 0x00c0a000, 0x00000004 },
-    { 0x0000008c, 0x00000008 },
-    { 0x00000091, 0x00000020 },
-    { 0x4200e000, 0000000000 },
-    { 0x00000098, 0x00000038 },
-    { 0x000ca000, 0x00000004 },
-    { 0x00140000, 0x00000004 },
-    { 0x000c2000, 0x00000004 },
-    { 0x00160000, 0x00000004 },
-    { 0x700ce000, 0x00000004 },
-    { 0x00140094, 0x00000008 },
-    { 0x4000e000, 0000000000 },
-    { 0x02400000, 0x00000004 },
-    { 0x400ee000, 0x00000004 },
-    { 0x02400000, 0x00000004 },
-    { 0x4000e000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x0240e51b, 0x00000004 },
-    { 0x0080e50a, 0x00000005 },
-    { 0x0080e50b, 0x00000005 },
-    { 0x00220000, 0x00000004 },
-    { 0x000700c7, 0x00000004 },
-    { 0x000000a4, 0x00000038 },
-    { 0x0080e5bd, 0x00000005 },
-    { 0x0000e5bb, 0x00000005 },
-    { 0x0080e5bc, 0x00000005 },
-    { 0x00210000, 0x00000004 },
-    { 0x02800000, 0x00000004 },
-    { 0x00c000ab, 0x00000018 },
-    { 0x4180e000, 0x00000040 },
-    { 0x000000ad, 0x00000024 },
-    { 0x01000000, 0x0000000c },
-    { 0x0100e51d, 0x0000000c },
-    { 0x000045bb, 0x00000004 },
-    { 0x000080a7, 0x00000008 },
-    { 0x0000f3ce, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00cc2000, 0x00000004 },
-    { 0x08c053cf, 0x00000040 },
-    { 0x00008000, 0000000000 },
-    { 0x0000f3d2, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00cc2000, 0x00000004 },
-    { 0x08c053d3, 0x00000040 },
-    { 0x00008000, 0000000000 },
-    { 0x0000f39d, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00cc2000, 0x00000004 },
-    { 0x08c0539e, 0x00000040 },
-    { 0x00008000, 0000000000 },
-    { 0x03c00830, 0x00000004 },
-    { 0x4200e000, 0000000000 },
-    { 0x0000a000, 0x00000004 },
-    { 0x200045e0, 0x00000004 },
-    { 0x0000e5e1, 0000000000 },
-    { 0x00000001, 0000000000 },
-    { 0x000700c4, 0x00000004 },
-    { 0x0800e394, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x0000e8c4, 0x00000004 },
-    { 0x0000e8c5, 0x00000004 },
-    { 0x0000e8c6, 0x00000004 },
-    { 0x0000e928, 0x00000004 },
-    { 0x0000e929, 0x00000004 },
-    { 0x0000e92a, 0x00000004 },
-    { 0x000000c8, 0x00000008 },
-    { 0x0000e928, 0x00000004 },
-    { 0x0000e929, 0x00000004 },
-    { 0x0000e92a, 0x00000004 },
-    { 0x000000cf, 0x00000008 },
-    { 0x02c02000, 0x00000004 },
-    { 0x00060000, 0x00000004 },
-    { 0x000000d7, 0x00000034 },
-    { 0x000000d4, 0x00000008 },
-    { 0x00008000, 0x00000004 },
-    { 0xc000e000, 0000000000 },
-    { 0x0000e1cc, 0x00000004 },
-    { 0x0500e1cd, 0x00000004 },
-    { 0x000ca000, 0x00000004 },
-    { 0x000000de, 0x00000034 },
-    { 0x000000da, 0x00000008 },
-    { 0x0000a000, 0000000000 },
-    { 0x0019e1cc, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x0500a000, 0x00000004 },
-    { 0x080041cd, 0x00000004 },
-    { 0x000ca000, 0x00000004 },
-    { 0x000000fb, 0x00000034 },
-    { 0x0000004a, 0x00000008 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x001d0018, 0x00000004 },
-    { 0x001a0001, 0x00000004 },
-    { 0x000000fb, 0x00000034 },
-    { 0x0000004a, 0x00000008 },
-    { 0x0500a04a, 0x00000008 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-};
-
-static const u32 RS600_cp_microcode[][2] = {
-    { 0x4200e000, 0000000000 },
-    { 0x4000e000, 0000000000 },
-    { 0x000000a0, 0x00000008 },
-    { 0x000000a4, 0x00000008 },
-    { 0x4a554b4a, 0000000000 },
-    { 0x4a4a4467, 0000000000 },
-    { 0x55526f75, 0000000000 },
-    { 0x4a7e7d65, 0000000000 },
-    { 0x4ae74af6, 0000000000 },
-    { 0x4ad34a4a, 0000000000 },
-    { 0xd6898989, 0000000000 },
-    { 0xcd4addcf, 0000000000 },
-    { 0x8ebe4ae2, 0000000000 },
-    { 0xc38a8a8a, 0000000000 },
-    { 0x4a0f8cc8, 0000000000 },
-    { 0x000ca000, 0x00000004 },
-    { 0x000d0012, 0x00000038 },
-    { 0x0000e8b4, 0x00000004 },
-    { 0x000d0014, 0x00000038 },
-    { 0x0000e8b6, 0x00000004 },
-    { 0x000d0016, 0x00000038 },
-    { 0x0000e854, 0x00000004 },
-    { 0x000d0018, 0x00000038 },
-    { 0x0000e855, 0x00000004 },
-    { 0x000d001a, 0x00000038 },
-    { 0x0000e856, 0x00000004 },
-    { 0x000d001c, 0x00000038 },
-    { 0x0000e857, 0x00000004 },
-    { 0x000d001e, 0x00000038 },
-    { 0x0000e824, 0x00000004 },
-    { 0x000d0020, 0x00000038 },
-    { 0x0000e825, 0x00000004 },
-    { 0x000d0022, 0x00000038 },
-    { 0x0000e830, 0x00000004 },
-    { 0x000d0024, 0x00000038 },
-    { 0x0000f0c0, 0x00000004 },
-    { 0x000d0026, 0x00000038 },
-    { 0x0000f0c1, 0x00000004 },
-    { 0x000d0028, 0x00000038 },
-    { 0x0000f041, 0x00000004 },
-    { 0x000d002a, 0x00000038 },
-    { 0x0000f184, 0x00000004 },
-    { 0x000d002c, 0x00000038 },
-    { 0x0000f185, 0x00000004 },
-    { 0x000d002e, 0x00000038 },
-    { 0x0000f186, 0x00000004 },
-    { 0x000d0030, 0x00000038 },
-    { 0x0000f187, 0x00000004 },
-    { 0x000d0032, 0x00000038 },
-    { 0x0000f180, 0x00000004 },
-    { 0x000d0034, 0x00000038 },
-    { 0x0000f393, 0x00000004 },
-    { 0x000d0036, 0x00000038 },
-    { 0x0000f38a, 0x00000004 },
-    { 0x000d0038, 0x00000038 },
-    { 0x0000f38e, 0x00000004 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00000043, 0x00000018 },
-    { 0x00cce800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x0000003a, 0x00000008 },
-    { 0x0000a000, 0000000000 },
-    { 0x2000451d, 0x00000004 },
-    { 0x0000e580, 0x00000004 },
-    { 0x000ce581, 0x00000004 },
-    { 0x08004580, 0x00000004 },
-    { 0x000ce581, 0x00000004 },
-    { 0x00000047, 0x00000008 },
-    { 0x0000a000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x0000e50e, 0x00000004 },
-    { 0x00032000, 0x00000004 },
-    { 0x00022051, 0x00000028 },
-    { 0x00000051, 0x00000024 },
-    { 0x0800450f, 0x00000004 },
-    { 0x0000a04b, 0x00000008 },
-    { 0x0000e565, 0x00000004 },
-    { 0x0000e566, 0x00000004 },
-    { 0x00000052, 0x00000008 },
-    { 0x03cca5b4, 0x00000004 },
-    { 0x05432000, 0x00000004 },
-    { 0x00022000, 0x00000004 },
-    { 0x4ccce05e, 0x00000030 },
-    { 0x08274565, 0x00000004 },
-    { 0x0000005e, 0x00000030 },
-    { 0x08004564, 0x00000004 },
-    { 0x0000e566, 0x00000004 },
-    { 0x00000055, 0x00000008 },
-    { 0x00802061, 0x00000010 },
-    { 0x00202000, 0x00000004 },
-    { 0x001b00ff, 0x00000004 },
-    { 0x01000064, 0x00000010 },
-    { 0x001f2000, 0x00000004 },
-    { 0x001c00ff, 0x00000004 },
-    { 0000000000, 0x0000000c },
-    { 0x00000072, 0x00000030 },
-    { 0x00000055, 0x00000008 },
-    { 0x0000e576, 0x00000004 },
-    { 0x0000e577, 0x00000004 },
-    { 0x0000e50e, 0x00000004 },
-    { 0x0000e50f, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00000069, 0x00000018 },
-    { 0x00c0e5f9, 0x000000c2 },
-    { 0x00000069, 0x00000008 },
-    { 0x0014e50e, 0x00000004 },
-    { 0x0040e50f, 0x00000004 },
-    { 0x00c0006c, 0x00000008 },
-    { 0x0000e570, 0x00000004 },
-    { 0x0000e571, 0x00000004 },
-    { 0x0000e572, 0x0000000c },
-    { 0x0000a000, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x0000e568, 0x00000004 },
-    { 0x000c2000, 0x00000004 },
-    { 0x00000076, 0x00000018 },
-    { 0x000b0000, 0x00000004 },
-    { 0x18c0e562, 0x00000004 },
-    { 0x00000078, 0x00000008 },
-    { 0x00c00077, 0x00000008 },
-    { 0x000700d5, 0x00000004 },
-    { 0x00000084, 0x00000038 },
-    { 0x000ca086, 0x00000030 },
-    { 0x080045bb, 0x00000004 },
-    { 0x000c2087, 0x00000030 },
-    { 0x0800e5bc, 0000000000 },
-    { 0x0000e5bb, 0x00000004 },
-    { 0x0000e5bc, 0000000000 },
-    { 0x00120000, 0x0000000c },
-    { 0x00120000, 0x00000004 },
-    { 0x001b0002, 0x0000000c },
-    { 0x0000a000, 0x00000004 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0000e800, 0000000000 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0000e82e, 0000000000 },
-    { 0x02cca000, 0x00000004 },
-    { 0x00140000, 0x00000004 },
-    { 0x000ce1cc, 0x00000004 },
-    { 0x050de1cd, 0x00000004 },
-    { 0x00400000, 0x00000004 },
-    { 0x00000096, 0x00000018 },
-    { 0x00c0a000, 0x00000004 },
-    { 0x00000093, 0x00000008 },
-    { 0x00000098, 0x00000020 },
-    { 0x4200e000, 0000000000 },
-    { 0x0000009f, 0x00000038 },
-    { 0x000ca000, 0x00000004 },
-    { 0x00140000, 0x00000004 },
-    { 0x000c2000, 0x00000004 },
-    { 0x00160000, 0x00000004 },
-    { 0x700ce000, 0x00000004 },
-    { 0x0014009b, 0x00000008 },
-    { 0x4000e000, 0000000000 },
-    { 0x02400000, 0x00000004 },
-    { 0x400ee000, 0x00000004 },
-    { 0x02400000, 0x00000004 },
-    { 0x4000e000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x0240e51b, 0x00000004 },
-    { 0x0080e50a, 0x00000005 },
-    { 0x0080e50b, 0x00000005 },
-    { 0x00220000, 0x00000004 },
-    { 0x000700d5, 0x00000004 },
-    { 0x000000b2, 0x00000038 },
-    { 0x000c2087, 0x00000030 },
-    { 0x0880e5bd, 0x00000005 },
-    { 0x000c2086, 0x00000030 },
-    { 0x0800e5bb, 0x00000005 },
-    { 0x000c2087, 0x00000030 },
-    { 0x0880e5bc, 0x00000005 },
-    { 0x000000b5, 0x00000008 },
-    { 0x0080e5bd, 0x00000005 },
-    { 0x0000e5bb, 0x00000005 },
-    { 0x0080e5bc, 0x00000005 },
-    { 0x00210000, 0x00000004 },
-    { 0x02800000, 0x00000004 },
-    { 0x00c000b9, 0x00000018 },
-    { 0x4180e000, 0x00000040 },
-    { 0x000000bb, 0x00000024 },
-    { 0x01000000, 0x0000000c },
-    { 0x0100e51d, 0x0000000c },
-    { 0x000045bb, 0x00000004 },
-    { 0x000080b5, 0x00000008 },
-    { 0x0000f3ce, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00cc2000, 0x00000004 },
-    { 0x08c053cf, 0x00000040 },
-    { 0x00008000, 0000000000 },
-    { 0x0000f3d2, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00cc2000, 0x00000004 },
-    { 0x08c053d3, 0x00000040 },
-    { 0x00008000, 0000000000 },
-    { 0x0000f39d, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00cc2000, 0x00000004 },
-    { 0x08c0539e, 0x00000040 },
-    { 0x00008000, 0000000000 },
-    { 0x03c00830, 0x00000004 },
-    { 0x4200e000, 0000000000 },
-    { 0x0000a000, 0x00000004 },
-    { 0x200045e0, 0x00000004 },
-    { 0x0000e5e1, 0000000000 },
-    { 0x00000001, 0000000000 },
-    { 0x000700d2, 0x00000004 },
-    { 0x0800e394, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x0000e8c4, 0x00000004 },
-    { 0x0000e8c5, 0x00000004 },
-    { 0x0000e8c6, 0x00000004 },
-    { 0x0000e928, 0x00000004 },
-    { 0x0000e929, 0x00000004 },
-    { 0x0000e92a, 0x00000004 },
-    { 0x000000d6, 0x00000008 },
-    { 0x0000e928, 0x00000004 },
-    { 0x0000e929, 0x00000004 },
-    { 0x0000e92a, 0x00000004 },
-    { 0x000000dd, 0x00000008 },
-    { 0x00e00116, 0000000000 },
-    { 0x000700e1, 0x00000004 },
-    { 0x0800401c, 0x00000004 },
-    { 0x200050e7, 0x00000004 },
-    { 0x0000e01d, 0x00000004 },
-    { 0x000000e4, 0x00000008 },
-    { 0x02c02000, 0x00000004 },
-    { 0x00060000, 0x00000004 },
-    { 0x000000eb, 0x00000034 },
-    { 0x000000e8, 0x00000008 },
-    { 0x00008000, 0x00000004 },
-    { 0xc000e000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x001d0018, 0x00000004 },
-    { 0x001a0001, 0x00000004 },
-    { 0x000000fb, 0x00000034 },
-    { 0x0000004a, 0x00000008 },
-    { 0x0500a04a, 0x00000008 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-};
-
-static const u32 RS690_cp_microcode[][2] = {
-    { 0x000000dd, 0x00000008 },
-    { 0x000000df, 0x00000008 },
-    { 0x000000a0, 0x00000008 },
-    { 0x000000a4, 0x00000008 },
-    { 0x4a554b4a, 0000000000 },
-    { 0x4a4a4467, 0000000000 },
-    { 0x55526f75, 0000000000 },
-    { 0x4a7e7d65, 0000000000 },
-    { 0x4ad74af6, 0000000000 },
-    { 0x4ac94a4a, 0000000000 },
-    { 0xcc898989, 0000000000 },
-    { 0xc34ad3c5, 0000000000 },
-    { 0x8e4a4a4a, 0000000000 },
-    { 0x4a8a8a8a, 0000000000 },
-    { 0x4a0f8c4a, 0000000000 },
-    { 0x000ca000, 0x00000004 },
-    { 0x000d0012, 0x00000038 },
-    { 0x0000e8b4, 0x00000004 },
-    { 0x000d0014, 0x00000038 },
-    { 0x0000e8b6, 0x00000004 },
-    { 0x000d0016, 0x00000038 },
-    { 0x0000e854, 0x00000004 },
-    { 0x000d0018, 0x00000038 },
-    { 0x0000e855, 0x00000004 },
-    { 0x000d001a, 0x00000038 },
-    { 0x0000e856, 0x00000004 },
-    { 0x000d001c, 0x00000038 },
-    { 0x0000e857, 0x00000004 },
-    { 0x000d001e, 0x00000038 },
-    { 0x0000e824, 0x00000004 },
-    { 0x000d0020, 0x00000038 },
-    { 0x0000e825, 0x00000004 },
-    { 0x000d0022, 0x00000038 },
-    { 0x0000e830, 0x00000004 },
-    { 0x000d0024, 0x00000038 },
-    { 0x0000f0c0, 0x00000004 },
-    { 0x000d0026, 0x00000038 },
-    { 0x0000f0c1, 0x00000004 },
-    { 0x000d0028, 0x00000038 },
-    { 0x0000f041, 0x00000004 },
-    { 0x000d002a, 0x00000038 },
-    { 0x0000f184, 0x00000004 },
-    { 0x000d002c, 0x00000038 },
-    { 0x0000f185, 0x00000004 },
-    { 0x000d002e, 0x00000038 },
-    { 0x0000f186, 0x00000004 },
-    { 0x000d0030, 0x00000038 },
-    { 0x0000f187, 0x00000004 },
-    { 0x000d0032, 0x00000038 },
-    { 0x0000f180, 0x00000004 },
-    { 0x000d0034, 0x00000038 },
-    { 0x0000f393, 0x00000004 },
-    { 0x000d0036, 0x00000038 },
-    { 0x0000f38a, 0x00000004 },
-    { 0x000d0038, 0x00000038 },
-    { 0x0000f38e, 0x00000004 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00000043, 0x00000018 },
-    { 0x00cce800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x0000003a, 0x00000008 },
-    { 0x0000a000, 0000000000 },
-    { 0x2000451d, 0x00000004 },
-    { 0x0000e580, 0x00000004 },
-    { 0x000ce581, 0x00000004 },
-    { 0x08004580, 0x00000004 },
-    { 0x000ce581, 0x00000004 },
-    { 0x00000047, 0x00000008 },
-    { 0x0000a000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x0000e50e, 0x00000004 },
-    { 0x00032000, 0x00000004 },
-    { 0x00022051, 0x00000028 },
-    { 0x00000051, 0x00000024 },
-    { 0x0800450f, 0x00000004 },
-    { 0x0000a04b, 0x00000008 },
-    { 0x0000e565, 0x00000004 },
-    { 0x0000e566, 0x00000004 },
-    { 0x00000052, 0x00000008 },
-    { 0x03cca5b4, 0x00000004 },
-    { 0x05432000, 0x00000004 },
-    { 0x00022000, 0x00000004 },
-    { 0x4ccce05e, 0x00000030 },
-    { 0x08274565, 0x00000004 },
-    { 0x0000005e, 0x00000030 },
-    { 0x08004564, 0x00000004 },
-    { 0x0000e566, 0x00000004 },
-    { 0x00000055, 0x00000008 },
-    { 0x00802061, 0x00000010 },
-    { 0x00202000, 0x00000004 },
-    { 0x001b00ff, 0x00000004 },
-    { 0x01000064, 0x00000010 },
-    { 0x001f2000, 0x00000004 },
-    { 0x001c00ff, 0x00000004 },
-    { 0000000000, 0x0000000c },
-    { 0x00000072, 0x00000030 },
-    { 0x00000055, 0x00000008 },
-    { 0x0000e576, 0x00000004 },
-    { 0x0000e577, 0x00000004 },
-    { 0x0000e50e, 0x00000004 },
-    { 0x0000e50f, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00000069, 0x00000018 },
-    { 0x00c0e5f9, 0x000000c2 },
-    { 0x00000069, 0x00000008 },
-    { 0x0014e50e, 0x00000004 },
-    { 0x0040e50f, 0x00000004 },
-    { 0x00c0006c, 0x00000008 },
-    { 0x0000e570, 0x00000004 },
-    { 0x0000e571, 0x00000004 },
-    { 0x0000e572, 0x0000000c },
-    { 0x0000a000, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x0000e568, 0x00000004 },
-    { 0x000c2000, 0x00000004 },
-    { 0x00000076, 0x00000018 },
-    { 0x000b0000, 0x00000004 },
-    { 0x18c0e562, 0x00000004 },
-    { 0x00000078, 0x00000008 },
-    { 0x00c00077, 0x00000008 },
-    { 0x000700cb, 0x00000004 },
-    { 0x00000084, 0x00000038 },
-    { 0x000ca086, 0x00000030 },
-    { 0x080045bb, 0x00000004 },
-    { 0x000c2087, 0x00000030 },
-    { 0x0800e5bc, 0000000000 },
-    { 0x0000e5bb, 0x00000004 },
-    { 0x0000e5bc, 0000000000 },
-    { 0x00120000, 0x0000000c },
-    { 0x00120000, 0x00000004 },
-    { 0x001b0002, 0x0000000c },
-    { 0x0000a000, 0x00000004 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0000e800, 0000000000 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0000e82e, 0000000000 },
-    { 0x02cca000, 0x00000004 },
-    { 0x00140000, 0x00000004 },
-    { 0x000ce1cc, 0x00000004 },
-    { 0x050de1cd, 0x00000004 },
-    { 0x00400000, 0x00000004 },
-    { 0x00000096, 0x00000018 },
-    { 0x00c0a000, 0x00000004 },
-    { 0x00000093, 0x00000008 },
-    { 0x00000098, 0x00000020 },
-    { 0x4200e000, 0000000000 },
-    { 0x0000009f, 0x00000038 },
-    { 0x000ca000, 0x00000004 },
-    { 0x00140000, 0x00000004 },
-    { 0x000c2000, 0x00000004 },
-    { 0x00160000, 0x00000004 },
-    { 0x700ce000, 0x00000004 },
-    { 0x0014009b, 0x00000008 },
-    { 0x4000e000, 0000000000 },
-    { 0x02400000, 0x00000004 },
-    { 0x400ee000, 0x00000004 },
-    { 0x02400000, 0x00000004 },
-    { 0x4000e000, 0000000000 },
-    { 0x00100000, 0x0000002c },
-    { 0x00004000, 0000000000 },
-    { 0x080045c8, 0x00000004 },
-    { 0x00240005, 0x00000004 },
-    { 0x08004d0b, 0x00000004 },
-    { 0x000c2000, 0x00000004 },
-    { 0x0240e51b, 0x00000004 },
-    { 0x0080e50a, 0x00000005 },
-    { 0x0080e50b, 0x00000005 },
-    { 0x00220000, 0x00000004 },
-    { 0x000700cb, 0x00000004 },
-    { 0x000000b7, 0x00000038 },
-    { 0x000c2087, 0x00000030 },
-    { 0x0880e5bd, 0x00000005 },
-    { 0x000c2086, 0x00000030 },
-    { 0x0800e5bb, 0x00000005 },
-    { 0x000c2087, 0x00000030 },
-    { 0x0880e5bc, 0x00000005 },
-    { 0x000000ba, 0x00000008 },
-    { 0x0080e5bd, 0x00000005 },
-    { 0x0000e5bb, 0x00000005 },
-    { 0x0080e5bc, 0x00000005 },
-    { 0x00210000, 0x00000004 },
-    { 0x02800000, 0x00000004 },
-    { 0x00c000be, 0x00000018 },
-    { 0x4180e000, 0x00000040 },
-    { 0x000000c0, 0x00000024 },
-    { 0x01000000, 0x0000000c },
-    { 0x0100e51d, 0x0000000c },
-    { 0x000045bb, 0x00000004 },
-    { 0x000080ba, 0x00000008 },
-    { 0x03c00830, 0x00000004 },
-    { 0x4200e000, 0000000000 },
-    { 0x0000a000, 0x00000004 },
-    { 0x200045e0, 0x00000004 },
-    { 0x0000e5e1, 0000000000 },
-    { 0x00000001, 0000000000 },
-    { 0x000700c8, 0x00000004 },
-    { 0x0800e394, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x0000e8c4, 0x00000004 },
-    { 0x0000e8c5, 0x00000004 },
-    { 0x0000e8c6, 0x00000004 },
-    { 0x0000e928, 0x00000004 },
-    { 0x0000e929, 0x00000004 },
-    { 0x0000e92a, 0x00000004 },
-    { 0x000000cc, 0x00000008 },
-    { 0x0000e928, 0x00000004 },
-    { 0x0000e929, 0x00000004 },
-    { 0x0000e92a, 0x00000004 },
-    { 0x000000d3, 0x00000008 },
-    { 0x02c02000, 0x00000004 },
-    { 0x00060000, 0x00000004 },
-    { 0x000000db, 0x00000034 },
-    { 0x000000d8, 0x00000008 },
-    { 0x00008000, 0x00000004 },
-    { 0xc000e000, 0000000000 },
-    { 0x000000e1, 0x00000030 },
-    { 0x4200e000, 0000000000 },
-    { 0x000000e1, 0x00000030 },
-    { 0x4000e000, 0000000000 },
-    { 0x0025001b, 0x00000004 },
-    { 0x00230000, 0x00000004 },
-    { 0x00250005, 0x00000004 },
-    { 0x000000e6, 0x00000034 },
-    { 0000000000, 0x0000000c },
-    { 0x00244000, 0x00000004 },
-    { 0x080045c8, 0x00000004 },
-    { 0x00240005, 0x00000004 },
-    { 0x08004d0b, 0x0000000c },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x001d0018, 0x00000004 },
-    { 0x001a0001, 0x00000004 },
-    { 0x000000fb, 0x00000034 },
-    { 0x0000004a, 0x00000008 },
-    { 0x0500a04a, 0x00000008 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-};
-
-static const u32 R520_cp_microcode[][2] = {
-    { 0x4200e000, 0000000000 },
-    { 0x4000e000, 0000000000 },
-    { 0x00000099, 0x00000008 },
-    { 0x0000009d, 0x00000008 },
-    { 0x4a554b4a, 0000000000 },
-    { 0x4a4a4467, 0000000000 },
-    { 0x55526f75, 0000000000 },
-    { 0x4a7e7d65, 0000000000 },
-    { 0xe0dae6f6, 0000000000 },
-    { 0x4ac54a4a, 0000000000 },
-    { 0xc8828282, 0000000000 },
-    { 0xbf4acfc1, 0000000000 },
-    { 0x87b04ad5, 0000000000 },
-    { 0xb5838383, 0000000000 },
-    { 0x4a0f85ba, 0000000000 },
-    { 0x000ca000, 0x00000004 },
-    { 0x000d0012, 0x00000038 },
-    { 0x0000e8b4, 0x00000004 },
-    { 0x000d0014, 0x00000038 },
-    { 0x0000e8b6, 0x00000004 },
-    { 0x000d0016, 0x00000038 },
-    { 0x0000e854, 0x00000004 },
-    { 0x000d0018, 0x00000038 },
-    { 0x0000e855, 0x00000004 },
-    { 0x000d001a, 0x00000038 },
-    { 0x0000e856, 0x00000004 },
-    { 0x000d001c, 0x00000038 },
-    { 0x0000e857, 0x00000004 },
-    { 0x000d001e, 0x00000038 },
-    { 0x0000e824, 0x00000004 },
-    { 0x000d0020, 0x00000038 },
-    { 0x0000e825, 0x00000004 },
-    { 0x000d0022, 0x00000038 },
-    { 0x0000e830, 0x00000004 },
-    { 0x000d0024, 0x00000038 },
-    { 0x0000f0c0, 0x00000004 },
-    { 0x000d0026, 0x00000038 },
-    { 0x0000f0c1, 0x00000004 },
-    { 0x000d0028, 0x00000038 },
-    { 0x0000e000, 0x00000004 },
-    { 0x000d002a, 0x00000038 },
-    { 0x0000e000, 0x00000004 },
-    { 0x000d002c, 0x00000038 },
-    { 0x0000e000, 0x00000004 },
-    { 0x000d002e, 0x00000038 },
-    { 0x0000e000, 0x00000004 },
-    { 0x000d0030, 0x00000038 },
-    { 0x0000e000, 0x00000004 },
-    { 0x000d0032, 0x00000038 },
-    { 0x0000f180, 0x00000004 },
-    { 0x000d0034, 0x00000038 },
-    { 0x0000f393, 0x00000004 },
-    { 0x000d0036, 0x00000038 },
-    { 0x0000f38a, 0x00000004 },
-    { 0x000d0038, 0x00000038 },
-    { 0x0000f38e, 0x00000004 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00000043, 0x00000018 },
-    { 0x00cce800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x08004800, 0x00000004 },
-    { 0x0000003a, 0x00000008 },
-    { 0x0000a000, 0000000000 },
-    { 0x2000451d, 0x00000004 },
-    { 0x0000e580, 0x00000004 },
-    { 0x000ce581, 0x00000004 },
-    { 0x08004580, 0x00000004 },
-    { 0x000ce581, 0x00000004 },
-    { 0x00000047, 0x00000008 },
-    { 0x0000a000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x0000e50e, 0x00000004 },
-    { 0x00032000, 0x00000004 },
-    { 0x00022051, 0x00000028 },
-    { 0x00000051, 0x00000024 },
-    { 0x0800450f, 0x00000004 },
-    { 0x0000a04b, 0x00000008 },
-    { 0x0000e565, 0x00000004 },
-    { 0x0000e566, 0x00000004 },
-    { 0x00000052, 0x00000008 },
-    { 0x03cca5b4, 0x00000004 },
-    { 0x05432000, 0x00000004 },
-    { 0x00022000, 0x00000004 },
-    { 0x4ccce05e, 0x00000030 },
-    { 0x08274565, 0x00000004 },
-    { 0x0000005e, 0x00000030 },
-    { 0x08004564, 0x00000004 },
-    { 0x0000e566, 0x00000004 },
-    { 0x00000055, 0x00000008 },
-    { 0x00802061, 0x00000010 },
-    { 0x00202000, 0x00000004 },
-    { 0x001b00ff, 0x00000004 },
-    { 0x01000064, 0x00000010 },
-    { 0x001f2000, 0x00000004 },
-    { 0x001c00ff, 0x00000004 },
-    { 0000000000, 0x0000000c },
-    { 0x00000072, 0x00000030 },
-    { 0x00000055, 0x00000008 },
-    { 0x0000e576, 0x00000004 },
-    { 0x0000e577, 0x00000004 },
-    { 0x0000e50e, 0x00000004 },
-    { 0x0000e50f, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00000069, 0x00000018 },
-    { 0x00c0e5f9, 0x000000c2 },
-    { 0x00000069, 0x00000008 },
-    { 0x0014e50e, 0x00000004 },
-    { 0x0040e50f, 0x00000004 },
-    { 0x00c0006c, 0x00000008 },
-    { 0x0000e570, 0x00000004 },
-    { 0x0000e571, 0x00000004 },
-    { 0x0000e572, 0x0000000c },
-    { 0x0000a000, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x0000e568, 0x00000004 },
-    { 0x000c2000, 0x00000004 },
-    { 0x00000076, 0x00000018 },
-    { 0x000b0000, 0x00000004 },
-    { 0x18c0e562, 0x00000004 },
-    { 0x00000078, 0x00000008 },
-    { 0x00c00077, 0x00000008 },
-    { 0x000700c7, 0x00000004 },
-    { 0x00000080, 0x00000038 },
-    { 0x0000e5bb, 0x00000004 },
-    { 0x0000e5bc, 0000000000 },
-    { 0x0000a000, 0x00000004 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0000e800, 0000000000 },
-    { 0x0000e821, 0x00000004 },
-    { 0x0000e82e, 0000000000 },
-    { 0x02cca000, 0x00000004 },
-    { 0x00140000, 0x00000004 },
-    { 0x000ce1cc, 0x00000004 },
-    { 0x050de1cd, 0x00000004 },
-    { 0x00400000, 0x00000004 },
-    { 0x0000008f, 0x00000018 },
-    { 0x00c0a000, 0x00000004 },
-    { 0x0000008c, 0x00000008 },
-    { 0x00000091, 0x00000020 },
-    { 0x4200e000, 0000000000 },
-    { 0x00000098, 0x00000038 },
-    { 0x000ca000, 0x00000004 },
-    { 0x00140000, 0x00000004 },
-    { 0x000c2000, 0x00000004 },
-    { 0x00160000, 0x00000004 },
-    { 0x700ce000, 0x00000004 },
-    { 0x00140094, 0x00000008 },
-    { 0x4000e000, 0000000000 },
-    { 0x02400000, 0x00000004 },
-    { 0x400ee000, 0x00000004 },
-    { 0x02400000, 0x00000004 },
-    { 0x4000e000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x0240e51b, 0x00000004 },
-    { 0x0080e50a, 0x00000005 },
-    { 0x0080e50b, 0x00000005 },
-    { 0x00220000, 0x00000004 },
-    { 0x000700c7, 0x00000004 },
-    { 0x000000a4, 0x00000038 },
-    { 0x0080e5bd, 0x00000005 },
-    { 0x0000e5bb, 0x00000005 },
-    { 0x0080e5bc, 0x00000005 },
-    { 0x00210000, 0x00000004 },
-    { 0x02800000, 0x00000004 },
-    { 0x00c000ab, 0x00000018 },
-    { 0x4180e000, 0x00000040 },
-    { 0x000000ad, 0x00000024 },
-    { 0x01000000, 0x0000000c },
-    { 0x0100e51d, 0x0000000c },
-    { 0x000045bb, 0x00000004 },
-    { 0x000080a7, 0x00000008 },
-    { 0x0000f3ce, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00cc2000, 0x00000004 },
-    { 0x08c053cf, 0x00000040 },
-    { 0x00008000, 0000000000 },
-    { 0x0000f3d2, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00cc2000, 0x00000004 },
-    { 0x08c053d3, 0x00000040 },
-    { 0x00008000, 0000000000 },
-    { 0x0000f39d, 0x00000004 },
-    { 0x0140a000, 0x00000004 },
-    { 0x00cc2000, 0x00000004 },
-    { 0x08c0539e, 0x00000040 },
-    { 0x00008000, 0000000000 },
-    { 0x03c00830, 0x00000004 },
-    { 0x4200e000, 0000000000 },
-    { 0x0000a000, 0x00000004 },
-    { 0x200045e0, 0x00000004 },
-    { 0x0000e5e1, 0000000000 },
-    { 0x00000001, 0000000000 },
-    { 0x000700c4, 0x00000004 },
-    { 0x0800e394, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x0000e8c4, 0x00000004 },
-    { 0x0000e8c5, 0x00000004 },
-    { 0x0000e8c6, 0x00000004 },
-    { 0x0000e928, 0x00000004 },
-    { 0x0000e929, 0x00000004 },
-    { 0x0000e92a, 0x00000004 },
-    { 0x000000c8, 0x00000008 },
-    { 0x0000e928, 0x00000004 },
-    { 0x0000e929, 0x00000004 },
-    { 0x0000e92a, 0x00000004 },
-    { 0x000000cf, 0x00000008 },
-    { 0xdeadbeef, 0000000000 },
-    { 0x00000116, 0000000000 },
-    { 0x000700d3, 0x00000004 },
-    { 0x080050e7, 0x00000004 },
-    { 0x000700d4, 0x00000004 },
-    { 0x0800401c, 0x00000004 },
-    { 0x0000e01d, 0000000000 },
-    { 0x02c02000, 0x00000004 },
-    { 0x00060000, 0x00000004 },
-    { 0x000000de, 0x00000034 },
-    { 0x000000db, 0x00000008 },
-    { 0x00008000, 0x00000004 },
-    { 0xc000e000, 0000000000 },
-    { 0x0000e1cc, 0x00000004 },
-    { 0x0500e1cd, 0x00000004 },
-    { 0x000ca000, 0x00000004 },
-    { 0x000000e5, 0x00000034 },
-    { 0x000000e1, 0x00000008 },
-    { 0x0000a000, 0000000000 },
-    { 0x0019e1cc, 0x00000004 },
-    { 0x001b0001, 0x00000004 },
-    { 0x0500a000, 0x00000004 },
-    { 0x080041cd, 0x00000004 },
-    { 0x000ca000, 0x00000004 },
-    { 0x000000fb, 0x00000034 },
-    { 0x0000004a, 0x00000008 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0x000c2000, 0x00000004 },
-    { 0x001d0018, 0x00000004 },
-    { 0x001a0001, 0x00000004 },
-    { 0x000000fb, 0x00000034 },
-    { 0x0000004a, 0x00000008 },
-    { 0x0500a04a, 0x00000008 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-    { 0000000000, 0000000000 },
-};
-
-
-#endif
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
deleted file mode 100644 (file)
index 11c146b..0000000
+++ /dev/null
@@ -1,3203 +0,0 @@
-/* radeon_state.c -- State support for Radeon -*- linux-c -*- */
-/*
- * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Gareth Hughes <gareth@valinux.com>
- *    Kevin E. Martin <martin@valinux.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "drm_sarea.h"
-#include "radeon_drm.h"
-#include "radeon_drv.h"
-
-/* ================================================================
- * Helper functions for client state checking and fixup
- */
-
-static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
-                                                   dev_priv,
-                                                   struct drm_file * file_priv,
-                                                   u32 *offset)
-{
-       u64 off = *offset;
-       u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1;
-       struct drm_radeon_driver_file_fields *radeon_priv;
-
-       /* Hrm ... the story of the offset ... So this function converts
-        * the various ideas of what userland clients might have for an
-        * offset in the card address space into an offset into the card
-        * address space :) So with a sane client, it should just keep
-        * the value intact and just do some boundary checking. However,
-        * not all clients are sane. Some older clients pass us 0 based
-        * offsets relative to the start of the framebuffer and some may
-        * assume the AGP aperture it appended to the framebuffer, so we
-        * try to detect those cases and fix them up.
-        *
-        * Note: It might be a good idea here to make sure the offset lands
-        * in some "allowed" area to protect things like the PCIE GART...
-        */
-
-       /* First, the best case, the offset already lands in either the
-        * framebuffer or the GART mapped space
-        */
-       if (radeon_check_offset(dev_priv, off))
-               return 0;
-
-       /* Ok, that didn't happen... now check if we have a zero based
-        * offset that fits in the framebuffer + gart space, apply the
-        * magic offset we get from SETPARAM or calculated from fb_location
-        */
-       if (off < (dev_priv->fb_size + dev_priv->gart_size)) {
-               radeon_priv = file_priv->driver_priv;
-               off += radeon_priv->radeon_fb_delta;
-       }
-
-       /* Finally, assume we aimed at a GART offset if beyond the fb */
-       if (off > fb_end)
-               off = off - fb_end - 1 + dev_priv->gart_vm_start;
-
-       /* Now recheck and fail if out of bounds */
-       if (radeon_check_offset(dev_priv, off)) {
-               DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
-               *offset = off;
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
-                                                    dev_priv,
-                                                    struct drm_file *file_priv,
-                                                    int id, u32 *data)
-{
-       switch (id) {
-
-       case RADEON_EMIT_PP_MISC:
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                   &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) {
-                       DRM_ERROR("Invalid depth buffer offset\n");
-                       return -EINVAL;
-               }
-               break;
-
-       case RADEON_EMIT_PP_CNTL:
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                   &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) {
-                       DRM_ERROR("Invalid colour buffer offset\n");
-                       return -EINVAL;
-               }
-               break;
-
-       case R200_EMIT_PP_TXOFFSET_0:
-       case R200_EMIT_PP_TXOFFSET_1:
-       case R200_EMIT_PP_TXOFFSET_2:
-       case R200_EMIT_PP_TXOFFSET_3:
-       case R200_EMIT_PP_TXOFFSET_4:
-       case R200_EMIT_PP_TXOFFSET_5:
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                                                 &data[0])) {
-                       DRM_ERROR("Invalid R200 texture offset\n");
-                       return -EINVAL;
-               }
-               break;
-
-       case RADEON_EMIT_PP_TXFILTER_0:
-       case RADEON_EMIT_PP_TXFILTER_1:
-       case RADEON_EMIT_PP_TXFILTER_2:
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                   &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) {
-                       DRM_ERROR("Invalid R100 texture offset\n");
-                       return -EINVAL;
-               }
-               break;
-
-       case R200_EMIT_PP_CUBIC_OFFSETS_0:
-       case R200_EMIT_PP_CUBIC_OFFSETS_1:
-       case R200_EMIT_PP_CUBIC_OFFSETS_2:
-       case R200_EMIT_PP_CUBIC_OFFSETS_3:
-       case R200_EMIT_PP_CUBIC_OFFSETS_4:
-       case R200_EMIT_PP_CUBIC_OFFSETS_5:{
-                       int i;
-                       for (i = 0; i < 5; i++) {
-                               if (radeon_check_and_fixup_offset(dev_priv,
-                                                                 file_priv,
-                                                                 &data[i])) {
-                                       DRM_ERROR
-                                           ("Invalid R200 cubic texture offset\n");
-                                       return -EINVAL;
-                               }
-                       }
-                       break;
-               }
-
-       case RADEON_EMIT_PP_CUBIC_OFFSETS_T0:
-       case RADEON_EMIT_PP_CUBIC_OFFSETS_T1:
-       case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
-                       int i;
-                       for (i = 0; i < 5; i++) {
-                               if (radeon_check_and_fixup_offset(dev_priv,
-                                                                 file_priv,
-                                                                 &data[i])) {
-                                       DRM_ERROR
-                                           ("Invalid R100 cubic texture offset\n");
-                                       return -EINVAL;
-                               }
-                       }
-               }
-               break;
-
-       case R200_EMIT_VAP_CTL:{
-                       RING_LOCALS;
-                       BEGIN_RING(2);
-                       OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
-                       ADVANCE_RING();
-               }
-               break;
-
-       case RADEON_EMIT_RB3D_COLORPITCH:
-       case RADEON_EMIT_RE_LINE_PATTERN:
-       case RADEON_EMIT_SE_LINE_WIDTH:
-       case RADEON_EMIT_PP_LUM_MATRIX:
-       case RADEON_EMIT_PP_ROT_MATRIX_0:
-       case RADEON_EMIT_RB3D_STENCILREFMASK:
-       case RADEON_EMIT_SE_VPORT_XSCALE:
-       case RADEON_EMIT_SE_CNTL:
-       case RADEON_EMIT_SE_CNTL_STATUS:
-       case RADEON_EMIT_RE_MISC:
-       case RADEON_EMIT_PP_BORDER_COLOR_0:
-       case RADEON_EMIT_PP_BORDER_COLOR_1:
-       case RADEON_EMIT_PP_BORDER_COLOR_2:
-       case RADEON_EMIT_SE_ZBIAS_FACTOR:
-       case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
-       case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
-       case R200_EMIT_PP_TXCBLEND_0:
-       case R200_EMIT_PP_TXCBLEND_1:
-       case R200_EMIT_PP_TXCBLEND_2:
-       case R200_EMIT_PP_TXCBLEND_3:
-       case R200_EMIT_PP_TXCBLEND_4:
-       case R200_EMIT_PP_TXCBLEND_5:
-       case R200_EMIT_PP_TXCBLEND_6:
-       case R200_EMIT_PP_TXCBLEND_7:
-       case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
-       case R200_EMIT_TFACTOR_0:
-       case R200_EMIT_VTX_FMT_0:
-       case R200_EMIT_MATRIX_SELECT_0:
-       case R200_EMIT_TEX_PROC_CTL_2:
-       case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
-       case R200_EMIT_PP_TXFILTER_0:
-       case R200_EMIT_PP_TXFILTER_1:
-       case R200_EMIT_PP_TXFILTER_2:
-       case R200_EMIT_PP_TXFILTER_3:
-       case R200_EMIT_PP_TXFILTER_4:
-       case R200_EMIT_PP_TXFILTER_5:
-       case R200_EMIT_VTE_CNTL:
-       case R200_EMIT_OUTPUT_VTX_COMP_SEL:
-       case R200_EMIT_PP_TAM_DEBUG3:
-       case R200_EMIT_PP_CNTL_X:
-       case R200_EMIT_RB3D_DEPTHXY_OFFSET:
-       case R200_EMIT_RE_AUX_SCISSOR_CNTL:
-       case R200_EMIT_RE_SCISSOR_TL_0:
-       case R200_EMIT_RE_SCISSOR_TL_1:
-       case R200_EMIT_RE_SCISSOR_TL_2:
-       case R200_EMIT_SE_VAP_CNTL_STATUS:
-       case R200_EMIT_SE_VTX_STATE_CNTL:
-       case R200_EMIT_RE_POINTSIZE:
-       case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0:
-       case R200_EMIT_PP_CUBIC_FACES_0:
-       case R200_EMIT_PP_CUBIC_FACES_1:
-       case R200_EMIT_PP_CUBIC_FACES_2:
-       case R200_EMIT_PP_CUBIC_FACES_3:
-       case R200_EMIT_PP_CUBIC_FACES_4:
-       case R200_EMIT_PP_CUBIC_FACES_5:
-       case RADEON_EMIT_PP_TEX_SIZE_0:
-       case RADEON_EMIT_PP_TEX_SIZE_1:
-       case RADEON_EMIT_PP_TEX_SIZE_2:
-       case R200_EMIT_RB3D_BLENDCOLOR:
-       case R200_EMIT_TCL_POINT_SPRITE_CNTL:
-       case RADEON_EMIT_PP_CUBIC_FACES_0:
-       case RADEON_EMIT_PP_CUBIC_FACES_1:
-       case RADEON_EMIT_PP_CUBIC_FACES_2:
-       case R200_EMIT_PP_TRI_PERF_CNTL:
-       case R200_EMIT_PP_AFS_0:
-       case R200_EMIT_PP_AFS_1:
-       case R200_EMIT_ATF_TFACTOR:
-       case R200_EMIT_PP_TXCTLALL_0:
-       case R200_EMIT_PP_TXCTLALL_1:
-       case R200_EMIT_PP_TXCTLALL_2:
-       case R200_EMIT_PP_TXCTLALL_3:
-       case R200_EMIT_PP_TXCTLALL_4:
-       case R200_EMIT_PP_TXCTLALL_5:
-       case R200_EMIT_VAP_PVS_CNTL:
-               /* These packets don't contain memory offsets */
-               break;
-
-       default:
-               DRM_ERROR("Unknown state packet ID %d\n", id);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
-                                                    dev_priv,
-                                                    struct drm_file *file_priv,
-                                                    drm_radeon_kcmd_buffer_t *
-                                                    cmdbuf,
-                                                    unsigned int *cmdsz)
-{
-       u32 *cmd = (u32 *) cmdbuf->buf;
-       u32 offset, narrays;
-       int count, i, k;
-
-       *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
-
-       if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
-               DRM_ERROR("Not a type 3 packet\n");
-               return -EINVAL;
-       }
-
-       if (4 * *cmdsz > cmdbuf->bufsz) {
-               DRM_ERROR("Packet size larger than size of data provided\n");
-               return -EINVAL;
-       }
-
-       switch(cmd[0] & 0xff00) {
-       /* XXX Are there old drivers needing other packets? */
-
-       case RADEON_3D_DRAW_IMMD:
-       case RADEON_3D_DRAW_VBUF:
-       case RADEON_3D_DRAW_INDX:
-       case RADEON_WAIT_FOR_IDLE:
-       case RADEON_CP_NOP:
-       case RADEON_3D_CLEAR_ZMASK:
-/*     case RADEON_CP_NEXT_CHAR:
-       case RADEON_CP_PLY_NEXTSCAN:
-       case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */
-               /* these packets are safe */
-               break;
-
-       case RADEON_CP_3D_DRAW_IMMD_2:
-       case RADEON_CP_3D_DRAW_VBUF_2:
-       case RADEON_CP_3D_DRAW_INDX_2:
-       case RADEON_3D_CLEAR_HIZ:
-               /* safe but r200 only */
-               if (dev_priv->microcode_version != UCODE_R200) {
-                       DRM_ERROR("Invalid 3d packet for r100-class chip\n");
-                       return -EINVAL;
-               }
-               break;
-
-       case RADEON_3D_LOAD_VBPNTR:
-               count = (cmd[0] >> 16) & 0x3fff;
-
-               if (count > 18) { /* 12 arrays max */
-                       DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
-                                 count);
-                       return -EINVAL;
-               }
-
-               /* carefully check packet contents */
-               narrays = cmd[1] & ~0xc000;
-               k = 0;
-               i = 2;
-               while ((k < narrays) && (i < (count + 2))) {
-                       i++;            /* skip attribute field */
-                       if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                                                         &cmd[i])) {
-                               DRM_ERROR
-                                   ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
-                                    k, i);
-                               return -EINVAL;
-                       }
-                       k++;
-                       i++;
-                       if (k == narrays)
-                               break;
-                       /* have one more to process, they come in pairs */
-                       if (radeon_check_and_fixup_offset(dev_priv,
-                                                         file_priv, &cmd[i]))
-                       {
-                               DRM_ERROR
-                                   ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
-                                    k, i);
-                               return -EINVAL;
-                       }
-                       k++;
-                       i++;
-               }
-               /* do the counts match what we expect ? */
-               if ((k != narrays) || (i != (count + 2))) {
-                       DRM_ERROR
-                           ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
-                             k, i, narrays, count + 1);
-                       return -EINVAL;
-               }
-               break;
-
-       case RADEON_3D_RNDR_GEN_INDX_PRIM:
-               if (dev_priv->microcode_version != UCODE_R100) {
-                       DRM_ERROR("Invalid 3d packet for r200-class chip\n");
-                       return -EINVAL;
-               }
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) {
-                               DRM_ERROR("Invalid rndr_gen_indx offset\n");
-                               return -EINVAL;
-               }
-               break;
-
-       case RADEON_CP_INDX_BUFFER:
-               if (dev_priv->microcode_version != UCODE_R200) {
-                       DRM_ERROR("Invalid 3d packet for r100-class chip\n");
-                       return -EINVAL;
-               }
-               if ((cmd[1] & 0x8000ffff) != 0x80000810) {
-                       DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
-                       return -EINVAL;
-               }
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[2])) {
-                       DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
-                       return -EINVAL;
-               }
-               break;
-
-       case RADEON_CNTL_HOSTDATA_BLT:
-       case RADEON_CNTL_PAINT_MULTI:
-       case RADEON_CNTL_BITBLT_MULTI:
-               /* MSB of opcode: next DWORD GUI_CNTL */
-               if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
-                             | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-                       offset = cmd[2] << 10;
-                       if (radeon_check_and_fixup_offset
-                           (dev_priv, file_priv, &offset)) {
-                               DRM_ERROR("Invalid first packet offset\n");
-                               return -EINVAL;
-                       }
-                       cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
-               }
-
-               if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
-                   (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
-                       offset = cmd[3] << 10;
-                       if (radeon_check_and_fixup_offset
-                           (dev_priv, file_priv, &offset)) {
-                               DRM_ERROR("Invalid second packet offset\n");
-                               return -EINVAL;
-                       }
-                       cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
-               }
-               break;
-
-       default:
-               DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/* ================================================================
- * CP hardware state programming functions
- */
-
-static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
-                                            struct drm_clip_rect * box)
-{
-       RING_LOCALS;
-
-       DRM_DEBUG("   box:  x1=%d y1=%d  x2=%d y2=%d\n",
-                 box->x1, box->y1, box->x2, box->y2);
-
-       BEGIN_RING(4);
-       OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
-       OUT_RING((box->y1 << 16) | box->x1);
-       OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
-       OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1));
-       ADVANCE_RING();
-}
-
-/* Emit 1.1 state
- */
-static int radeon_emit_state(drm_radeon_private_t * dev_priv,
-                            struct drm_file *file_priv,
-                            drm_radeon_context_regs_t * ctx,
-                            drm_radeon_texture_regs_t * tex,
-                            unsigned int dirty)
-{
-       RING_LOCALS;
-       DRM_DEBUG("dirty=0x%08x\n", dirty);
-
-       if (dirty & RADEON_UPLOAD_CONTEXT) {
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                                                 &ctx->rb3d_depthoffset)) {
-                       DRM_ERROR("Invalid depth buffer offset\n");
-                       return -EINVAL;
-               }
-
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                                                 &ctx->rb3d_coloroffset)) {
-                       DRM_ERROR("Invalid depth buffer offset\n");
-                       return -EINVAL;
-               }
-
-               BEGIN_RING(14);
-               OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6));
-               OUT_RING(ctx->pp_misc);
-               OUT_RING(ctx->pp_fog_color);
-               OUT_RING(ctx->re_solid_color);
-               OUT_RING(ctx->rb3d_blendcntl);
-               OUT_RING(ctx->rb3d_depthoffset);
-               OUT_RING(ctx->rb3d_depthpitch);
-               OUT_RING(ctx->rb3d_zstencilcntl);
-               OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2));
-               OUT_RING(ctx->pp_cntl);
-               OUT_RING(ctx->rb3d_cntl);
-               OUT_RING(ctx->rb3d_coloroffset);
-               OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
-               OUT_RING(ctx->rb3d_colorpitch);
-               ADVANCE_RING();
-       }
-
-       if (dirty & RADEON_UPLOAD_VERTFMT) {
-               BEGIN_RING(2);
-               OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0));
-               OUT_RING(ctx->se_coord_fmt);
-               ADVANCE_RING();
-       }
-
-       if (dirty & RADEON_UPLOAD_LINE) {
-               BEGIN_RING(5);
-               OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1));
-               OUT_RING(ctx->re_line_pattern);
-               OUT_RING(ctx->re_line_state);
-               OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0));
-               OUT_RING(ctx->se_line_width);
-               ADVANCE_RING();
-       }
-
-       if (dirty & RADEON_UPLOAD_BUMPMAP) {
-               BEGIN_RING(5);
-               OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0));
-               OUT_RING(ctx->pp_lum_matrix);
-               OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1));
-               OUT_RING(ctx->pp_rot_matrix_0);
-               OUT_RING(ctx->pp_rot_matrix_1);
-               ADVANCE_RING();
-       }
-
-       if (dirty & RADEON_UPLOAD_MASKS) {
-               BEGIN_RING(4);
-               OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2));
-               OUT_RING(ctx->rb3d_stencilrefmask);
-               OUT_RING(ctx->rb3d_ropcntl);
-               OUT_RING(ctx->rb3d_planemask);
-               ADVANCE_RING();
-       }
-
-       if (dirty & RADEON_UPLOAD_VIEWPORT) {
-               BEGIN_RING(7);
-               OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5));
-               OUT_RING(ctx->se_vport_xscale);
-               OUT_RING(ctx->se_vport_xoffset);
-               OUT_RING(ctx->se_vport_yscale);
-               OUT_RING(ctx->se_vport_yoffset);
-               OUT_RING(ctx->se_vport_zscale);
-               OUT_RING(ctx->se_vport_zoffset);
-               ADVANCE_RING();
-       }
-
-       if (dirty & RADEON_UPLOAD_SETUP) {
-               BEGIN_RING(4);
-               OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0));
-               OUT_RING(ctx->se_cntl);
-               OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0));
-               OUT_RING(ctx->se_cntl_status);
-               ADVANCE_RING();
-       }
-
-       if (dirty & RADEON_UPLOAD_MISC) {
-               BEGIN_RING(2);
-               OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0));
-               OUT_RING(ctx->re_misc);
-               ADVANCE_RING();
-       }
-
-       if (dirty & RADEON_UPLOAD_TEX0) {
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                                                 &tex[0].pp_txoffset)) {
-                       DRM_ERROR("Invalid texture offset for unit 0\n");
-                       return -EINVAL;
-               }
-
-               BEGIN_RING(9);
-               OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5));
-               OUT_RING(tex[0].pp_txfilter);
-               OUT_RING(tex[0].pp_txformat);
-               OUT_RING(tex[0].pp_txoffset);
-               OUT_RING(tex[0].pp_txcblend);
-               OUT_RING(tex[0].pp_txablend);
-               OUT_RING(tex[0].pp_tfactor);
-               OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0));
-               OUT_RING(tex[0].pp_border_color);
-               ADVANCE_RING();
-       }
-
-       if (dirty & RADEON_UPLOAD_TEX1) {
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                                                 &tex[1].pp_txoffset)) {
-                       DRM_ERROR("Invalid texture offset for unit 1\n");
-                       return -EINVAL;
-               }
-
-               BEGIN_RING(9);
-               OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5));
-               OUT_RING(tex[1].pp_txfilter);
-               OUT_RING(tex[1].pp_txformat);
-               OUT_RING(tex[1].pp_txoffset);
-               OUT_RING(tex[1].pp_txcblend);
-               OUT_RING(tex[1].pp_txablend);
-               OUT_RING(tex[1].pp_tfactor);
-               OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0));
-               OUT_RING(tex[1].pp_border_color);
-               ADVANCE_RING();
-       }
-
-       if (dirty & RADEON_UPLOAD_TEX2) {
-               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
-                                                 &tex[2].pp_txoffset)) {
-                       DRM_ERROR("Invalid texture offset for unit 2\n");
-                       return -EINVAL;
-               }
-
-               BEGIN_RING(9);
-               OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5));
-               OUT_RING(tex[2].pp_txfilter);
-               OUT_RING(tex[2].pp_txformat);
-               OUT_RING(tex[2].pp_txoffset);
-               OUT_RING(tex[2].pp_txcblend);
-               OUT_RING(tex[2].pp_txablend);
-               OUT_RING(tex[2].pp_tfactor);
-               OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0));
-               OUT_RING(tex[2].pp_border_color);
-               ADVANCE_RING();
-       }
-
-       return 0;
-}
-
-/* Emit 1.2 state
- */
-static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
-                             struct drm_file *file_priv,
-                             drm_radeon_state_t * state)
-{
-       RING_LOCALS;
-
-       if (state->dirty & RADEON_UPLOAD_ZBIAS) {
-               BEGIN_RING(3);
-               OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1));
-               OUT_RING(state->context2.se_zbias_factor);
-               OUT_RING(state->context2.se_zbias_constant);
-               ADVANCE_RING();
-       }
-
-       return radeon_emit_state(dev_priv, file_priv, &state->context,
-                                state->tex, state->dirty);
-}
-
-/* New (1.3) state mechanism.  3 commands (packet, scalar, vector) in
- * 1.3 cmdbuffers allow all previous state to be updated as well as
- * the tcl scalar and vector areas.
- */
-static struct {
-       int start;
-       int len;
-       const char *name;
-} packet[RADEON_MAX_STATE_PACKETS] = {
-       {RADEON_PP_MISC, 7, "RADEON_PP_MISC"},
-       {RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"},
-       {RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"},
-       {RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"},
-       {RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"},
-       {RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"},
-       {RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"},
-       {RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"},
-       {RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"},
-       {RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"},
-       {RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"},
-       {RADEON_RE_MISC, 1, "RADEON_RE_MISC"},
-       {RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"},
-       {RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"},
-       {RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"},
-       {RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"},
-       {RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"},
-       {RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"},
-       {RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"},
-       {RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"},
-       {RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17,
-                   "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"},
-       {R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"},
-       {R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"},
-       {R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"},
-       {R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"},
-       {R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"},
-       {R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"},
-       {R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"},
-       {R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"},
-       {R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"},
-       {R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"},
-       {R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"},
-       {R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"},
-       {R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"},
-       {R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"},
-       {R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"},
-       {R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"},
-       {R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"},
-       {R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"},
-       {R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"},
-       {R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"},
-       {R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"},
-       {R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"},
-       {R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"},
-       {R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"},
-       {R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"},
-       {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
-       {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
-       {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
-       {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1,
-        "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
-       {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
-       {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
-       {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
-       {R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"},
-       {R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"},
-       {R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"},
-       {R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"},
-       {R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"},
-       {R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"},
-       {R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"},
-       {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
-                   "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
-       {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"},    /* 61 */
-       {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
-       {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
-       {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
-       {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
-       {R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"},
-       {R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"},
-       {R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"},
-       {R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"},
-       {R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"},
-       {R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"},
-       {R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"},
-       {RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"},
-       {RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"},
-       {RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"},
-       {R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"},
-       {R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"},
-       {RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
-       {RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
-       {RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
-       {RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
-       {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
-       {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
-       {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
-       {R200_PP_AFS_0, 32, "R200_PP_AFS_0"},     /* 85 */
-       {R200_PP_AFS_1, 32, "R200_PP_AFS_1"},
-       {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
-       {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
-       {R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"},
-       {R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"},
-       {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
-       {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
-       {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
-       {R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"},
-};
-
-/* ================================================================
- * Performance monitoring functions
- */
-
-static void radeon_clear_box(drm_radeon_private_t * dev_priv,
-                            int x, int y, int w, int h, int r, int g, int b)
-{
-       u32 color;
-       RING_LOCALS;
-
-       x += dev_priv->sarea_priv->boxes[0].x1;
-       y += dev_priv->sarea_priv->boxes[0].y1;
-
-       switch (dev_priv->color_fmt) {
-       case RADEON_COLOR_FORMAT_RGB565:
-               color = (((r & 0xf8) << 8) |
-                        ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
-               break;
-       case RADEON_COLOR_FORMAT_ARGB8888:
-       default:
-               color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
-               break;
-       }
-
-       BEGIN_RING(4);
-       RADEON_WAIT_UNTIL_3D_IDLE();
-       OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
-       OUT_RING(0xffffffff);
-       ADVANCE_RING();
-
-       BEGIN_RING(6);
-
-       OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4));
-       OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-                RADEON_GMC_BRUSH_SOLID_COLOR |
-                (dev_priv->color_fmt << 8) |
-                RADEON_GMC_SRC_DATATYPE_COLOR |
-                RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
-
-       if (dev_priv->sarea_priv->pfCurrentPage == 1) {
-               OUT_RING(dev_priv->front_pitch_offset);
-       } else {
-               OUT_RING(dev_priv->back_pitch_offset);
-       }
-
-       OUT_RING(color);
-
-       OUT_RING((x << 16) | y);
-       OUT_RING((w << 16) | h);
-
-       ADVANCE_RING();
-}
-
-static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
-{
-       /* Collapse various things into a wait flag -- trying to
-        * guess if userspase slept -- better just to have them tell us.
-        */
-       if (dev_priv->stats.last_frame_reads > 1 ||
-           dev_priv->stats.last_clear_reads > dev_priv->stats.clears) {
-               dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-       }
-
-       if (dev_priv->stats.freelist_loops) {
-               dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
-       }
-
-       /* Purple box for page flipping
-        */
-       if (dev_priv->stats.boxes & RADEON_BOX_FLIP)
-               radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255);
-
-       /* Red box if we have to wait for idle at any point
-        */
-       if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE)
-               radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0);
-
-       /* Blue box: lost context?
-        */
-
-       /* Yellow box for texture swaps
-        */
-       if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD)
-               radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0);
-
-       /* Green box if hardware never idles (as far as we can tell)
-        */
-       if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE))
-               radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
-
-       /* Draw bars indicating number of buffers allocated
-        * (not a great measure, easily confused)
-        */
-       if (dev_priv->stats.requested_bufs) {
-               if (dev_priv->stats.requested_bufs > 100)
-                       dev_priv->stats.requested_bufs = 100;
-
-               radeon_clear_box(dev_priv, 4, 16,
-                                dev_priv->stats.requested_bufs, 4,
-                                196, 128, 128);
-       }
-
-       memset(&dev_priv->stats, 0, sizeof(dev_priv->stats));
-
-}
-
-/* ================================================================
- * CP command dispatch functions
- */
-
-static void radeon_cp_dispatch_clear(struct drm_device * dev,
-                                    drm_radeon_clear_t * clear,
-                                    drm_radeon_clear_rect_t * depth_boxes)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
-       int nbox = sarea_priv->nbox;
-       struct drm_clip_rect *pbox = sarea_priv->boxes;
-       unsigned int flags = clear->flags;
-       u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
-       int i;
-       RING_LOCALS;
-       DRM_DEBUG("flags = 0x%x\n", flags);
-
-       dev_priv->stats.clears++;
-
-       if (dev_priv->sarea_priv->pfCurrentPage == 1) {
-               unsigned int tmp = flags;
-
-               flags &= ~(RADEON_FRONT | RADEON_BACK);
-               if (tmp & RADEON_FRONT)
-                       flags |= RADEON_BACK;
-               if (tmp & RADEON_BACK)
-                       flags |= RADEON_FRONT;
-       }
-
-       if (flags & (RADEON_FRONT | RADEON_BACK)) {
-
-               BEGIN_RING(4);
-
-               /* Ensure the 3D stream is idle before doing a
-                * 2D fill to clear the front or back buffer.
-                */
-               RADEON_WAIT_UNTIL_3D_IDLE();
-
-               OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
-               OUT_RING(clear->color_mask);
-
-               ADVANCE_RING();
-
-               /* Make sure we restore the 3D state next time.
-                */
-               dev_priv->sarea_priv->ctx_owner = 0;
-
-               for (i = 0; i < nbox; i++) {
-                       int x = pbox[i].x1;
-                       int y = pbox[i].y1;
-                       int w = pbox[i].x2 - x;
-                       int h = pbox[i].y2 - y;
-
-                       DRM_DEBUG("%d,%d-%d,%d flags 0x%x\n",
-                                 x, y, w, h, flags);
-
-                       if (flags & RADEON_FRONT) {
-                               BEGIN_RING(6);
-
-                               OUT_RING(CP_PACKET3
-                                        (RADEON_CNTL_PAINT_MULTI, 4));
-                               OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-                                        RADEON_GMC_BRUSH_SOLID_COLOR |
-                                        (dev_priv->
-                                         color_fmt << 8) |
-                                        RADEON_GMC_SRC_DATATYPE_COLOR |
-                                        RADEON_ROP3_P |
-                                        RADEON_GMC_CLR_CMP_CNTL_DIS);
-
-                               OUT_RING(dev_priv->front_pitch_offset);
-                               OUT_RING(clear->clear_color);
-
-                               OUT_RING((x << 16) | y);
-                               OUT_RING((w << 16) | h);
-
-                               ADVANCE_RING();
-                       }
-
-                       if (flags & RADEON_BACK) {
-                               BEGIN_RING(6);
-
-                               OUT_RING(CP_PACKET3
-                                        (RADEON_CNTL_PAINT_MULTI, 4));
-                               OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-                                        RADEON_GMC_BRUSH_SOLID_COLOR |
-                                        (dev_priv->
-                                         color_fmt << 8) |
-                                        RADEON_GMC_SRC_DATATYPE_COLOR |
-                                        RADEON_ROP3_P |
-                                        RADEON_GMC_CLR_CMP_CNTL_DIS);
-
-                               OUT_RING(dev_priv->back_pitch_offset);
-                               OUT_RING(clear->clear_color);
-
-                               OUT_RING((x << 16) | y);
-                               OUT_RING((w << 16) | h);
-
-                               ADVANCE_RING();
-                       }
-               }
-       }
-
-       /* hyper z clear */
-       /* no docs available, based on reverse engeneering by Stephane Marchesin */
-       if ((flags & (RADEON_DEPTH | RADEON_STENCIL))
-           && (flags & RADEON_CLEAR_FASTZ)) {
-
-               int i;
-               int depthpixperline =
-                   dev_priv->depth_fmt ==
-                   RADEON_DEPTH_FORMAT_16BIT_INT_Z ? (dev_priv->depth_pitch /
-                                                      2) : (dev_priv->
-                                                            depth_pitch / 4);
-
-               u32 clearmask;
-
-               u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth |
-                   ((clear->depth_mask & 0xff) << 24);
-
-               /* Make sure we restore the 3D state next time.
-                * we haven't touched any "normal" state - still need this?
-                */
-               dev_priv->sarea_priv->ctx_owner = 0;
-
-               if ((dev_priv->flags & RADEON_HAS_HIERZ)
-                   && (flags & RADEON_USE_HIERZ)) {
-                       /* FIXME : reverse engineer that for Rx00 cards */
-                       /* FIXME : the mask supposedly contains low-res z values. So can't set
-                          just to the max (0xff? or actually 0x3fff?), need to take z clear
-                          value into account? */
-                       /* pattern seems to work for r100, though get slight
-                          rendering errors with glxgears. If hierz is not enabled for r100,
-                          only 4 bits which indicate clear (15,16,31,32, all zero) matter, the
-                          other ones are ignored, and the same clear mask can be used. That's
-                          very different behaviour than R200 which needs different clear mask
-                          and different number of tiles to clear if hierz is enabled or not !?!
-                        */
-                       clearmask = (0xff << 22) | (0xff << 6) | 0x003f003f;
-               } else {
-                       /* clear mask : chooses the clearing pattern.
-                          rv250: could be used to clear only parts of macrotiles
-                          (but that would get really complicated...)?
-                          bit 0 and 1 (either or both of them ?!?!) are used to
-                          not clear tile (or maybe one of the bits indicates if the tile is
-                          compressed or not), bit 2 and 3 to not clear tile 1,...,.
-                          Pattern is as follows:
-                          | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29|
-                          bits -------------------------------------------------
-                          | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31|
-                          rv100: clearmask covers 2x8 4x1 tiles, but one clear still
-                          covers 256 pixels ?!?
-                        */
-                       clearmask = 0x0;
-               }
-
-               BEGIN_RING(8);
-               RADEON_WAIT_UNTIL_2D_IDLE();
-               OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE,
-                            tempRB3D_DEPTHCLEARVALUE);
-               /* what offset is this exactly ? */
-               OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0);
-               /* need ctlstat, otherwise get some strange black flickering */
-               OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT,
-                            RADEON_RB3D_ZC_FLUSH_ALL);
-               ADVANCE_RING();
-
-               for (i = 0; i < nbox; i++) {
-                       int tileoffset, nrtilesx, nrtilesy, j;
-                       /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
-                       if ((dev_priv->flags & RADEON_HAS_HIERZ)
-                           && !(dev_priv->microcode_version == UCODE_R200)) {
-                               /* FIXME : figure this out for r200 (when hierz is enabled). Or
-                                  maybe r200 actually doesn't need to put the low-res z value into
-                                  the tile cache like r100, but just needs to clear the hi-level z-buffer?
-                                  Works for R100, both with hierz and without.
-                                  R100 seems to operate on 2x1 8x8 tiles, but...
-                                  odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially
-                                  problematic with resolutions which are not 64 pix aligned? */
-                               tileoffset =
-                                   ((pbox[i].y1 >> 3) * depthpixperline +
-                                    pbox[i].x1) >> 6;
-                               nrtilesx =
-                                   ((pbox[i].x2 & ~63) -
-                                    (pbox[i].x1 & ~63)) >> 4;
-                               nrtilesy =
-                                   (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
-                               for (j = 0; j <= nrtilesy; j++) {
-                                       BEGIN_RING(4);
-                                       OUT_RING(CP_PACKET3
-                                                (RADEON_3D_CLEAR_ZMASK, 2));
-                                       /* first tile */
-                                       OUT_RING(tileoffset * 8);
-                                       /* the number of tiles to clear */
-                                       OUT_RING(nrtilesx + 4);
-                                       /* clear mask : chooses the clearing pattern. */
-                                       OUT_RING(clearmask);
-                                       ADVANCE_RING();
-                                       tileoffset += depthpixperline >> 6;
-                               }
-                       } else if (dev_priv->microcode_version == UCODE_R200) {
-                               /* works for rv250. */
-                               /* find first macro tile (8x2 4x4 z-pixels on rv250) */
-                               tileoffset =
-                                   ((pbox[i].y1 >> 3) * depthpixperline +
-                                    pbox[i].x1) >> 5;
-                               nrtilesx =
-                                   (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);
-                               nrtilesy =
-                                   (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
-                               for (j = 0; j <= nrtilesy; j++) {
-                                       BEGIN_RING(4);
-                                       OUT_RING(CP_PACKET3
-                                                (RADEON_3D_CLEAR_ZMASK, 2));
-                                       /* first tile */
-                                       /* judging by the first tile offset needed, could possibly
-                                          directly address/clear 4x4 tiles instead of 8x2 * 4x4
-                                          macro tiles, though would still need clear mask for
-                                          right/bottom if truely 4x4 granularity is desired ? */
-                                       OUT_RING(tileoffset * 16);
-                                       /* the number of tiles to clear */
-                                       OUT_RING(nrtilesx + 1);
-                                       /* clear mask : chooses the clearing pattern. */
-                                       OUT_RING(clearmask);
-                                       ADVANCE_RING();
-                                       tileoffset += depthpixperline >> 5;
-                               }
-                       } else {        /* rv 100 */
-                               /* rv100 might not need 64 pix alignment, who knows */
-                               /* offsets are, hmm, weird */
-                               tileoffset =
-                                   ((pbox[i].y1 >> 4) * depthpixperline +
-                                    pbox[i].x1) >> 6;
-                               nrtilesx =
-                                   ((pbox[i].x2 & ~63) -
-                                    (pbox[i].x1 & ~63)) >> 4;
-                               nrtilesy =
-                                   (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);
-                               for (j = 0; j <= nrtilesy; j++) {
-                                       BEGIN_RING(4);
-                                       OUT_RING(CP_PACKET3
-                                                (RADEON_3D_CLEAR_ZMASK, 2));
-                                       OUT_RING(tileoffset * 128);
-                                       /* the number of tiles to clear */
-                                       OUT_RING(nrtilesx + 4);
-                                       /* clear mask : chooses the clearing pattern. */
-                                       OUT_RING(clearmask);
-                                       ADVANCE_RING();
-                                       tileoffset += depthpixperline >> 6;
-                               }
-                       }
-               }
-
-               /* TODO don't always clear all hi-level z tiles */
-               if ((dev_priv->flags & RADEON_HAS_HIERZ)
-                   && (dev_priv->microcode_version == UCODE_R200)
-                   && (flags & RADEON_USE_HIERZ))
-                       /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
-                       /* FIXME : the mask supposedly contains low-res z values. So can't set
-                          just to the max (0xff? or actually 0x3fff?), need to take z clear
-                          value into account? */
-               {
-                       BEGIN_RING(4);
-                       OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2));
-                       OUT_RING(0x0);  /* First tile */
-                       OUT_RING(0x3cc0);
-                       OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f);
-                       ADVANCE_RING();
-               }
-       }
-
-       /* We have to clear the depth and/or stencil buffers by
-        * rendering a quad into just those buffers.  Thus, we have to
-        * make sure the 3D engine is configured correctly.
-        */
-       else if ((dev_priv->microcode_version == UCODE_R200) &&
-               (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
-
-               int tempPP_CNTL;
-               int tempRE_CNTL;
-               int tempRB3D_CNTL;
-               int tempRB3D_ZSTENCILCNTL;
-               int tempRB3D_STENCILREFMASK;
-               int tempRB3D_PLANEMASK;
-               int tempSE_CNTL;
-               int tempSE_VTE_CNTL;
-               int tempSE_VTX_FMT_0;
-               int tempSE_VTX_FMT_1;
-               int tempSE_VAP_CNTL;
-               int tempRE_AUX_SCISSOR_CNTL;
-
-               tempPP_CNTL = 0;
-               tempRE_CNTL = 0;
-
-               tempRB3D_CNTL = depth_clear->rb3d_cntl;
-
-               tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
-               tempRB3D_STENCILREFMASK = 0x0;
-
-               tempSE_CNTL = depth_clear->se_cntl;
-
-               /* Disable TCL */
-
-               tempSE_VAP_CNTL = (     /* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK |  */
-                                         (0x9 <<
-                                          SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
-
-               tempRB3D_PLANEMASK = 0x0;
-
-               tempRE_AUX_SCISSOR_CNTL = 0x0;
-
-               tempSE_VTE_CNTL =
-                   SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK;
-
-               /* Vertex format (X, Y, Z, W) */
-               tempSE_VTX_FMT_0 =
-                   SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
-                   SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
-               tempSE_VTX_FMT_1 = 0x0;
-
-               /*
-                * Depth buffer specific enables
-                */
-               if (flags & RADEON_DEPTH) {
-                       /* Enable depth buffer */
-                       tempRB3D_CNTL |= RADEON_Z_ENABLE;
-               } else {
-                       /* Disable depth buffer */
-                       tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
-               }
-
-               /*
-                * Stencil buffer specific enables
-                */
-               if (flags & RADEON_STENCIL) {
-                       tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;
-                       tempRB3D_STENCILREFMASK = clear->depth_mask;
-               } else {
-                       tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
-                       tempRB3D_STENCILREFMASK = 0x00000000;
-               }
-
-               if (flags & RADEON_USE_COMP_ZBUF) {
-                       tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
-                           RADEON_Z_DECOMPRESSION_ENABLE;
-               }
-               if (flags & RADEON_USE_HIERZ) {
-                       tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
-               }
-
-               BEGIN_RING(26);
-               RADEON_WAIT_UNTIL_2D_IDLE();
-
-               OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL);
-               OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL);
-               OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL);
-               OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
-               OUT_RING_REG(RADEON_RB3D_STENCILREFMASK,
-                            tempRB3D_STENCILREFMASK);
-               OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK);
-               OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL);
-               OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL);
-               OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0);
-               OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1);
-               OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL);
-               OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL);
-               ADVANCE_RING();
-
-               /* Make sure we restore the 3D state next time.
-                */
-               dev_priv->sarea_priv->ctx_owner = 0;
-
-               for (i = 0; i < nbox; i++) {
-
-                       /* Funny that this should be required --
-                        *  sets top-left?
-                        */
-                       radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
-
-                       BEGIN_RING(14);
-                       OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12));
-                       OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
-                                 RADEON_PRIM_WALK_RING |
-                                 (3 << RADEON_NUM_VERTICES_SHIFT)));
-                       OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
-                       OUT_RING(0x3f800000);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
-                       OUT_RING(0x3f800000);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
-                       OUT_RING(0x3f800000);
-                       ADVANCE_RING();
-               }
-       } else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) {
-
-               int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
-
-               rb3d_cntl = depth_clear->rb3d_cntl;
-
-               if (flags & RADEON_DEPTH) {
-                       rb3d_cntl |= RADEON_Z_ENABLE;
-               } else {
-                       rb3d_cntl &= ~RADEON_Z_ENABLE;
-               }
-
-               if (flags & RADEON_STENCIL) {
-                       rb3d_cntl |= RADEON_STENCIL_ENABLE;
-                       rb3d_stencilrefmask = clear->depth_mask;        /* misnamed field */
-               } else {
-                       rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
-                       rb3d_stencilrefmask = 0x00000000;
-               }
-
-               if (flags & RADEON_USE_COMP_ZBUF) {
-                       tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
-                           RADEON_Z_DECOMPRESSION_ENABLE;
-               }
-               if (flags & RADEON_USE_HIERZ) {
-                       tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
-               }
-
-               BEGIN_RING(13);
-               RADEON_WAIT_UNTIL_2D_IDLE();
-
-               OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1));
-               OUT_RING(0x00000000);
-               OUT_RING(rb3d_cntl);
-
-               OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
-               OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask);
-               OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000);
-               OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl);
-               ADVANCE_RING();
-
-               /* Make sure we restore the 3D state next time.
-                */
-               dev_priv->sarea_priv->ctx_owner = 0;
-
-               for (i = 0; i < nbox; i++) {
-
-                       /* Funny that this should be required --
-                        *  sets top-left?
-                        */
-                       radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
-
-                       BEGIN_RING(15);
-
-                       OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13));
-                       OUT_RING(RADEON_VTX_Z_PRESENT |
-                                RADEON_VTX_PKCOLOR_PRESENT);
-                       OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
-                                 RADEON_PRIM_WALK_RING |
-                                 RADEON_MAOS_ENABLE |
-                                 RADEON_VTX_FMT_RADEON_MODE |
-                                 (3 << RADEON_NUM_VERTICES_SHIFT)));
-
-                       OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
-                       OUT_RING(0x0);
-
-                       OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
-                       OUT_RING(0x0);
-
-                       OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
-                       OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
-                       OUT_RING(0x0);
-
-                       ADVANCE_RING();
-               }
-       }
-
-       /* Increment the clear counter.  The client-side 3D driver must
-        * wait on this value before performing the clear ioctl.  We
-        * need this because the card's so damned fast...
-        */
-       dev_priv->sarea_priv->last_clear++;
-
-       BEGIN_RING(4);
-
-       RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear);
-       RADEON_WAIT_UNTIL_IDLE();
-
-       ADVANCE_RING();
-}
-
-static void radeon_cp_dispatch_swap(struct drm_device * dev)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int nbox = sarea_priv->nbox;
-       struct drm_clip_rect *pbox = sarea_priv->boxes;
-       int i;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       /* Do some trivial performance monitoring...
-        */
-       if (dev_priv->do_boxes)
-               radeon_cp_performance_boxes(dev_priv);
-
-       /* Wait for the 3D stream to idle before dispatching the bitblt.
-        * This will prevent data corruption between the two streams.
-        */
-       BEGIN_RING(2);
-
-       RADEON_WAIT_UNTIL_3D_IDLE();
-
-       ADVANCE_RING();
-
-       for (i = 0; i < nbox; i++) {
-               int x = pbox[i].x1;
-               int y = pbox[i].y1;
-               int w = pbox[i].x2 - x;
-               int h = pbox[i].y2 - y;
-
-               DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h);
-
-               BEGIN_RING(9);
-
-               OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0));
-               OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
-                        RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-                        RADEON_GMC_BRUSH_NONE |
-                        (dev_priv->color_fmt << 8) |
-                        RADEON_GMC_SRC_DATATYPE_COLOR |
-                        RADEON_ROP3_S |
-                        RADEON_DP_SRC_SOURCE_MEMORY |
-                        RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
-
-               /* Make this work even if front & back are flipped:
-                */
-               OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
-               if (dev_priv->sarea_priv->pfCurrentPage == 0) {
-                       OUT_RING(dev_priv->back_pitch_offset);
-                       OUT_RING(dev_priv->front_pitch_offset);
-               } else {
-                       OUT_RING(dev_priv->front_pitch_offset);
-                       OUT_RING(dev_priv->back_pitch_offset);
-               }
-
-               OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2));
-               OUT_RING((x << 16) | y);
-               OUT_RING((x << 16) | y);
-               OUT_RING((w << 16) | h);
-
-               ADVANCE_RING();
-       }
-
-       /* Increment the frame counter.  The client-side 3D driver must
-        * throttle the framerate by waiting for this value before
-        * performing the swapbuffer ioctl.
-        */
-       dev_priv->sarea_priv->last_frame++;
-
-       BEGIN_RING(4);
-
-       RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
-       RADEON_WAIT_UNTIL_2D_IDLE();
-
-       ADVANCE_RING();
-}
-
-static void radeon_cp_dispatch_flip(struct drm_device * dev)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle;
-       int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
-           ? dev_priv->front_offset : dev_priv->back_offset;
-       RING_LOCALS;
-       DRM_DEBUG("pfCurrentPage=%d\n",
-                 dev_priv->sarea_priv->pfCurrentPage);
-
-       /* Do some trivial performance monitoring...
-        */
-       if (dev_priv->do_boxes) {
-               dev_priv->stats.boxes |= RADEON_BOX_FLIP;
-               radeon_cp_performance_boxes(dev_priv);
-       }
-
-       /* Update the frame offsets for both CRTCs
-        */
-       BEGIN_RING(6);
-
-       RADEON_WAIT_UNTIL_3D_IDLE();
-       OUT_RING_REG(RADEON_CRTC_OFFSET,
-                    ((sarea->frame.y * dev_priv->front_pitch +
-                      sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7)
-                    + offset);
-       OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
-                    + offset);
-
-       ADVANCE_RING();
-
-       /* Increment the frame counter.  The client-side 3D driver must
-        * throttle the framerate by waiting for this value before
-        * performing the swapbuffer ioctl.
-        */
-       dev_priv->sarea_priv->last_frame++;
-       dev_priv->sarea_priv->pfCurrentPage =
-               1 - dev_priv->sarea_priv->pfCurrentPage;
-
-       BEGIN_RING(2);
-
-       RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
-
-       ADVANCE_RING();
-}
-
-static int bad_prim_vertex_nr(int primitive, int nr)
-{
-       switch (primitive & RADEON_PRIM_TYPE_MASK) {
-       case RADEON_PRIM_TYPE_NONE:
-       case RADEON_PRIM_TYPE_POINT:
-               return nr < 1;
-       case RADEON_PRIM_TYPE_LINE:
-               return (nr & 1) || nr == 0;
-       case RADEON_PRIM_TYPE_LINE_STRIP:
-               return nr < 2;
-       case RADEON_PRIM_TYPE_TRI_LIST:
-       case RADEON_PRIM_TYPE_3VRT_POINT_LIST:
-       case RADEON_PRIM_TYPE_3VRT_LINE_LIST:
-       case RADEON_PRIM_TYPE_RECT_LIST:
-               return nr % 3 || nr == 0;
-       case RADEON_PRIM_TYPE_TRI_FAN:
-       case RADEON_PRIM_TYPE_TRI_STRIP:
-               return nr < 3;
-       default:
-               return 1;
-       }
-}
-
-typedef struct {
-       unsigned int start;
-       unsigned int finish;
-       unsigned int prim;
-       unsigned int numverts;
-       unsigned int offset;
-       unsigned int vc_format;
-} drm_radeon_tcl_prim_t;
-
-static void radeon_cp_dispatch_vertex(struct drm_device * dev,
-                                     struct drm_buf * buf,
-                                     drm_radeon_tcl_prim_t * prim)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
-       int numverts = (int)prim->numverts;
-       int nbox = sarea_priv->nbox;
-       int i = 0;
-       RING_LOCALS;
-
-       DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
-                 prim->prim,
-                 prim->vc_format, prim->start, prim->finish, prim->numverts);
-
-       if (bad_prim_vertex_nr(prim->prim, prim->numverts)) {
-               DRM_ERROR("bad prim %x numverts %d\n",
-                         prim->prim, prim->numverts);
-               return;
-       }
-
-       do {
-               /* Emit the next cliprect */
-               if (i < nbox) {
-                       radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
-               }
-
-               /* Emit the vertex buffer rendering commands */
-               BEGIN_RING(5);
-
-               OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3));
-               OUT_RING(offset);
-               OUT_RING(numverts);
-               OUT_RING(prim->vc_format);
-               OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST |
-                        RADEON_COLOR_ORDER_RGBA |
-                        RADEON_VTX_FMT_RADEON_MODE |
-                        (numverts << RADEON_NUM_VERTICES_SHIFT));
-
-               ADVANCE_RING();
-
-               i++;
-       } while (i < nbox);
-}
-
-static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
-       RING_LOCALS;
-
-       buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
-
-       /* Emit the vertex buffer age */
-       BEGIN_RING(2);
-       RADEON_DISPATCH_AGE(buf_priv->age);
-       ADVANCE_RING();
-
-       buf->pending = 1;
-       buf->used = 0;
-}
-
-static void radeon_cp_dispatch_indirect(struct drm_device * dev,
-                                       struct drm_buf * buf, int start, int end)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-       DRM_DEBUG("buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
-
-       if (start != end) {
-               int offset = (dev_priv->gart_buffers_offset
-                             + buf->offset + start);
-               int dwords = (end - start + 3) / sizeof(u32);
-
-               /* Indirect buffer data must be an even number of
-                * dwords, so if we've been given an odd number we must
-                * pad the data with a Type-2 CP packet.
-                */
-               if (dwords & 1) {
-                       u32 *data = (u32 *)
-                           ((char *)dev->agp_buffer_map->handle
-                            + buf->offset + start);
-                       data[dwords++] = RADEON_CP_PACKET2;
-               }
-
-               /* Fire off the indirect buffer */
-               BEGIN_RING(3);
-
-               OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
-               OUT_RING(offset);
-               OUT_RING(dwords);
-
-               ADVANCE_RING();
-       }
-}
-
-static void radeon_cp_dispatch_indices(struct drm_device * dev,
-                                      struct drm_buf * elt_buf,
-                                      drm_radeon_tcl_prim_t * prim)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       int offset = dev_priv->gart_buffers_offset + prim->offset;
-       u32 *data;
-       int dwords;
-       int i = 0;
-       int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
-       int count = (prim->finish - start) / sizeof(u16);
-       int nbox = sarea_priv->nbox;
-
-       DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
-                 prim->prim,
-                 prim->vc_format,
-                 prim->start, prim->finish, prim->offset, prim->numverts);
-
-       if (bad_prim_vertex_nr(prim->prim, count)) {
-               DRM_ERROR("bad prim %x count %d\n", prim->prim, count);
-               return;
-       }
-
-       if (start >= prim->finish || (prim->start & 0x7)) {
-               DRM_ERROR("buffer prim %d\n", prim->prim);
-               return;
-       }
-
-       dwords = (prim->finish - prim->start + 3) / sizeof(u32);
-
-       data = (u32 *) ((char *)dev->agp_buffer_map->handle +
-                       elt_buf->offset + prim->start);
-
-       data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2);
-       data[1] = offset;
-       data[2] = prim->numverts;
-       data[3] = prim->vc_format;
-       data[4] = (prim->prim |
-                  RADEON_PRIM_WALK_IND |
-                  RADEON_COLOR_ORDER_RGBA |
-                  RADEON_VTX_FMT_RADEON_MODE |
-                  (count << RADEON_NUM_VERTICES_SHIFT));
-
-       do {
-               if (i < nbox)
-                       radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
-
-               radeon_cp_dispatch_indirect(dev, elt_buf,
-                                           prim->start, prim->finish);
-
-               i++;
-       } while (i < nbox);
-
-}
-
-#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
-
-static int radeon_cp_dispatch_texture(struct drm_device * dev,
-                                     struct drm_file *file_priv,
-                                     drm_radeon_texture_t * tex,
-                                     drm_radeon_tex_image_t * image)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_buf *buf;
-       u32 format;
-       u32 *buffer;
-       const u8 __user *data;
-       int size, dwords, tex_width, blit_width, spitch;
-       u32 height;
-       int i;
-       u32 texpitch, microtile;
-       u32 offset, byte_offset;
-       RING_LOCALS;
-
-       if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) {
-               DRM_ERROR("Invalid destination offset\n");
-               return -EINVAL;
-       }
-
-       dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
-
-       /* Flush the pixel cache.  This ensures no pixel data gets mixed
-        * up with the texture data from the host data blit, otherwise
-        * part of the texture image may be corrupted.
-        */
-       BEGIN_RING(4);
-       RADEON_FLUSH_CACHE();
-       RADEON_WAIT_UNTIL_IDLE();
-       ADVANCE_RING();
-
-       /* The compiler won't optimize away a division by a variable,
-        * even if the only legal values are powers of two.  Thus, we'll
-        * use a shift instead.
-        */
-       switch (tex->format) {
-       case RADEON_TXFORMAT_ARGB8888:
-       case RADEON_TXFORMAT_RGBA8888:
-               format = RADEON_COLOR_FORMAT_ARGB8888;
-               tex_width = tex->width * 4;
-               blit_width = image->width * 4;
-               break;
-       case RADEON_TXFORMAT_AI88:
-       case RADEON_TXFORMAT_ARGB1555:
-       case RADEON_TXFORMAT_RGB565:
-       case RADEON_TXFORMAT_ARGB4444:
-       case RADEON_TXFORMAT_VYUY422:
-       case RADEON_TXFORMAT_YVYU422:
-               format = RADEON_COLOR_FORMAT_RGB565;
-               tex_width = tex->width * 2;
-               blit_width = image->width * 2;
-               break;
-       case RADEON_TXFORMAT_I8:
-       case RADEON_TXFORMAT_RGB332:
-               format = RADEON_COLOR_FORMAT_CI8;
-               tex_width = tex->width * 1;
-               blit_width = image->width * 1;
-               break;
-       default:
-               DRM_ERROR("invalid texture format %d\n", tex->format);
-               return -EINVAL;
-       }
-       spitch = blit_width >> 6;
-       if (spitch == 0 && image->height > 1)
-               return -EINVAL;
-
-       texpitch = tex->pitch;
-       if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
-               microtile = 1;
-               if (tex_width < 64) {
-                       texpitch &= ~(RADEON_DST_TILE_MICRO >> 22);
-                       /* we got tiled coordinates, untile them */
-                       image->x *= 2;
-               }
-       } else
-               microtile = 0;
-
-       /* this might fail for zero-sized uploads - are those illegal? */
-       if (!radeon_check_offset(dev_priv, tex->offset + image->height *
-                               blit_width - 1)) {
-               DRM_ERROR("Invalid final destination offset\n");
-               return -EINVAL;
-       }
-
-       DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width);
-
-       do {
-               DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
-                         tex->offset >> 10, tex->pitch, tex->format,
-                         image->x, image->y, image->width, image->height);
-
-               /* Make a copy of some parameters in case we have to
-                * update them for a multi-pass texture blit.
-                */
-               height = image->height;
-               data = (const u8 __user *)image->data;
-
-               size = height * blit_width;
-
-               if (size > RADEON_MAX_TEXTURE_SIZE) {
-                       height = RADEON_MAX_TEXTURE_SIZE / blit_width;
-                       size = height * blit_width;
-               } else if (size < 4 && size > 0) {
-                       size = 4;
-               } else if (size == 0) {
-                       return 0;
-               }
-
-               buf = radeon_freelist_get(dev);
-               if (0 && !buf) {
-                       radeon_do_cp_idle(dev_priv);
-                       buf = radeon_freelist_get(dev);
-               }
-               if (!buf) {
-                       DRM_DEBUG("EAGAIN\n");
-                       if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
-                               return -EFAULT;
-                       return -EAGAIN;
-               }
-
-               /* Dispatch the indirect buffer.
-                */
-               buffer =
-                   (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
-               dwords = size / 4;
-
-#define RADEON_COPY_MT(_buf, _data, _width) \
-       do { \
-               if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\
-                       DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \
-                       return -EFAULT; \
-               } \
-       } while(0)
-
-               if (microtile) {
-                       /* texture micro tiling in use, minimum texture width is thus 16 bytes.
-                          however, we cannot use blitter directly for texture width < 64 bytes,
-                          since minimum tex pitch is 64 bytes and we need this to match
-                          the texture width, otherwise the blitter will tile it wrong.
-                          Thus, tiling manually in this case. Additionally, need to special
-                          case tex height = 1, since our actual image will have height 2
-                          and we need to ensure we don't read beyond the texture size
-                          from user space. */
-                       if (tex->height == 1) {
-                               if (tex_width >= 64 || tex_width <= 16) {
-                                       RADEON_COPY_MT(buffer, data,
-                                               (int)(tex_width * sizeof(u32)));
-                               } else if (tex_width == 32) {
-                                       RADEON_COPY_MT(buffer, data, 16);
-                                       RADEON_COPY_MT(buffer + 8,
-                                                      data + 16, 16);
-                               }
-                       } else if (tex_width >= 64 || tex_width == 16) {
-                               RADEON_COPY_MT(buffer, data,
-                                              (int)(dwords * sizeof(u32)));
-                       } else if (tex_width < 16) {
-                               for (i = 0; i < tex->height; i++) {
-                                       RADEON_COPY_MT(buffer, data, tex_width);
-                                       buffer += 4;
-                                       data += tex_width;
-                               }
-                       } else if (tex_width == 32) {
-                               /* TODO: make sure this works when not fitting in one buffer
-                                  (i.e. 32bytes x 2048...) */
-                               for (i = 0; i < tex->height; i += 2) {
-                                       RADEON_COPY_MT(buffer, data, 16);
-                                       data += 16;
-                                       RADEON_COPY_MT(buffer + 8, data, 16);
-                                       data += 16;
-                                       RADEON_COPY_MT(buffer + 4, data, 16);
-                                       data += 16;
-                                       RADEON_COPY_MT(buffer + 12, data, 16);
-                                       data += 16;
-                                       buffer += 16;
-                               }
-                       }
-               } else {
-                       if (tex_width >= 32) {
-                               /* Texture image width is larger than the minimum, so we
-                                * can upload it directly.
-                                */
-                               RADEON_COPY_MT(buffer, data,
-                                              (int)(dwords * sizeof(u32)));
-                       } else {
-                               /* Texture image width is less than the minimum, so we
-                                * need to pad out each image scanline to the minimum
-                                * width.
-                                */
-                               for (i = 0; i < tex->height; i++) {
-                                       RADEON_COPY_MT(buffer, data, tex_width);
-                                       buffer += 8;
-                                       data += tex_width;
-                               }
-                       }
-               }
-
-#undef RADEON_COPY_MT
-               byte_offset = (image->y & ~2047) * blit_width;
-               buf->file_priv = file_priv;
-               buf->used = size;
-               offset = dev_priv->gart_buffers_offset + buf->offset;
-               BEGIN_RING(9);
-               OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
-               OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
-                        RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-                        RADEON_GMC_BRUSH_NONE |
-                        (format << 8) |
-                        RADEON_GMC_SRC_DATATYPE_COLOR |
-                        RADEON_ROP3_S |
-                        RADEON_DP_SRC_SOURCE_MEMORY |
-                        RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
-               OUT_RING((spitch << 22) | (offset >> 10));
-               OUT_RING((texpitch << 22) | ((tex->offset >> 10) + (byte_offset >> 10)));
-               OUT_RING(0);
-               OUT_RING((image->x << 16) | (image->y % 2048));
-               OUT_RING((image->width << 16) | height);
-               RADEON_WAIT_UNTIL_2D_IDLE();
-               ADVANCE_RING();
-               COMMIT_RING();
-
-               radeon_cp_discard_buffer(dev, buf);
-
-               /* Update the input parameters for next time */
-               image->y += height;
-               image->height -= height;
-               image->data = (const u8 __user *)image->data + size;
-       } while (image->height > 0);
-
-       /* Flush the pixel cache after the blit completes.  This ensures
-        * the texture data is written out to memory before rendering
-        * continues.
-        */
-       BEGIN_RING(4);
-       RADEON_FLUSH_CACHE();
-       RADEON_WAIT_UNTIL_2D_IDLE();
-       ADVANCE_RING();
-       COMMIT_RING();
-
-       return 0;
-}
-
-static void radeon_cp_dispatch_stipple(struct drm_device * dev, u32 * stipple)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       int i;
-       RING_LOCALS;
-       DRM_DEBUG("\n");
-
-       BEGIN_RING(35);
-
-       OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0));
-       OUT_RING(0x00000000);
-
-       OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31));
-       for (i = 0; i < 32; i++) {
-               OUT_RING(stipple[i]);
-       }
-
-       ADVANCE_RING();
-}
-
-static void radeon_apply_surface_regs(int surf_index,
-                                     drm_radeon_private_t *dev_priv)
-{
-       if (!dev_priv->mmio)
-               return;
-
-       radeon_do_cp_idle(dev_priv);
-
-       RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * surf_index,
-                    dev_priv->surfaces[surf_index].flags);
-       RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * surf_index,
-                    dev_priv->surfaces[surf_index].lower);
-       RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * surf_index,
-                    dev_priv->surfaces[surf_index].upper);
-}
-
-/* Allocates a virtual surface
- * doesn't always allocate a real surface, will stretch an existing
- * surface when possible.
- *
- * Note that refcount can be at most 2, since during a free refcount=3
- * might mean we have to allocate a new surface which might not always
- * be available.
- * For example : we allocate three contigous surfaces ABC. If B is
- * freed, we suddenly need two surfaces to store A and C, which might
- * not always be available.
- */
-static int alloc_surface(drm_radeon_surface_alloc_t *new,
-                        drm_radeon_private_t *dev_priv,
-                        struct drm_file *file_priv)
-{
-       struct radeon_virt_surface *s;
-       int i;
-       int virt_surface_index;
-       uint32_t new_upper, new_lower;
-
-       new_lower = new->address;
-       new_upper = new_lower + new->size - 1;
-
-       /* sanity check */
-       if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) ||
-           ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) !=
-            RADEON_SURF_ADDRESS_FIXED_MASK)
-           || ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0))
-               return -1;
-
-       /* make sure there is no overlap with existing surfaces */
-       for (i = 0; i < RADEON_MAX_SURFACES; i++) {
-               if ((dev_priv->surfaces[i].refcount != 0) &&
-                   (((new_lower >= dev_priv->surfaces[i].lower) &&
-                     (new_lower < dev_priv->surfaces[i].upper)) ||
-                    ((new_lower < dev_priv->surfaces[i].lower) &&
-                     (new_upper > dev_priv->surfaces[i].lower)))) {
-                       return -1;
-               }
-       }
-
-       /* find a virtual surface */
-       for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++)
-               if (dev_priv->virt_surfaces[i].file_priv == 0)
-                       break;
-       if (i == 2 * RADEON_MAX_SURFACES) {
-               return -1;
-       }
-       virt_surface_index = i;
-
-       /* try to reuse an existing surface */
-       for (i = 0; i < RADEON_MAX_SURFACES; i++) {
-               /* extend before */
-               if ((dev_priv->surfaces[i].refcount == 1) &&
-                   (new->flags == dev_priv->surfaces[i].flags) &&
-                   (new_upper + 1 == dev_priv->surfaces[i].lower)) {
-                       s = &(dev_priv->virt_surfaces[virt_surface_index]);
-                       s->surface_index = i;
-                       s->lower = new_lower;
-                       s->upper = new_upper;
-                       s->flags = new->flags;
-                       s->file_priv = file_priv;
-                       dev_priv->surfaces[i].refcount++;
-                       dev_priv->surfaces[i].lower = s->lower;
-                       radeon_apply_surface_regs(s->surface_index, dev_priv);
-                       return virt_surface_index;
-               }
-
-               /* extend after */
-               if ((dev_priv->surfaces[i].refcount == 1) &&
-                   (new->flags == dev_priv->surfaces[i].flags) &&
-                   (new_lower == dev_priv->surfaces[i].upper + 1)) {
-                       s = &(dev_priv->virt_surfaces[virt_surface_index]);
-                       s->surface_index = i;
-                       s->lower = new_lower;
-                       s->upper = new_upper;
-                       s->flags = new->flags;
-                       s->file_priv = file_priv;
-                       dev_priv->surfaces[i].refcount++;
-                       dev_priv->surfaces[i].upper = s->upper;
-                       radeon_apply_surface_regs(s->surface_index, dev_priv);
-                       return virt_surface_index;
-               }
-       }
-
-       /* okay, we need a new one */
-       for (i = 0; i < RADEON_MAX_SURFACES; i++) {
-               if (dev_priv->surfaces[i].refcount == 0) {
-                       s = &(dev_priv->virt_surfaces[virt_surface_index]);
-                       s->surface_index = i;
-                       s->lower = new_lower;
-                       s->upper = new_upper;
-                       s->flags = new->flags;
-                       s->file_priv = file_priv;
-                       dev_priv->surfaces[i].refcount = 1;
-                       dev_priv->surfaces[i].lower = s->lower;
-                       dev_priv->surfaces[i].upper = s->upper;
-                       dev_priv->surfaces[i].flags = s->flags;
-                       radeon_apply_surface_regs(s->surface_index, dev_priv);
-                       return virt_surface_index;
-               }
-       }
-
-       /* we didn't find anything */
-       return -1;
-}
-
-static int free_surface(struct drm_file *file_priv,
-                       drm_radeon_private_t * dev_priv,
-                       int lower)
-{
-       struct radeon_virt_surface *s;
-       int i;
-       /* find the virtual surface */
-       for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
-               s = &(dev_priv->virt_surfaces[i]);
-               if (s->file_priv) {
-                       if ((lower == s->lower) && (file_priv == s->file_priv))
-                       {
-                               if (dev_priv->surfaces[s->surface_index].
-                                   lower == s->lower)
-                                       dev_priv->surfaces[s->surface_index].
-                                           lower = s->upper;
-
-                               if (dev_priv->surfaces[s->surface_index].
-                                   upper == s->upper)
-                                       dev_priv->surfaces[s->surface_index].
-                                           upper = s->lower;
-
-                               dev_priv->surfaces[s->surface_index].refcount--;
-                               if (dev_priv->surfaces[s->surface_index].
-                                   refcount == 0)
-                                       dev_priv->surfaces[s->surface_index].
-                                           flags = 0;
-                               s->file_priv = NULL;
-                               radeon_apply_surface_regs(s->surface_index,
-                                                         dev_priv);
-                               return 0;
-                       }
-               }
-       }
-       return 1;
-}
-
-static void radeon_surfaces_release(struct drm_file *file_priv,
-                                   drm_radeon_private_t * dev_priv)
-{
-       int i;
-       for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
-               if (dev_priv->virt_surfaces[i].file_priv == file_priv)
-                       free_surface(file_priv, dev_priv,
-                                    dev_priv->virt_surfaces[i].lower);
-       }
-}
-
-/* ================================================================
- * IOCTL functions
- */
-static int radeon_surface_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_surface_alloc_t *alloc = data;
-
-       if (alloc_surface(alloc, dev_priv, file_priv) == -1)
-               return -EINVAL;
-       else
-               return 0;
-}
-
-static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_surface_free_t *memfree = data;
-
-       if (free_surface(file_priv, dev_priv, memfree->address))
-               return -EINVAL;
-       else
-               return 0;
-}
-
-static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       drm_radeon_clear_t *clear = data;
-       drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-       if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
-               sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
-
-       if (DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes,
-                              sarea_priv->nbox * sizeof(depth_boxes[0])))
-               return -EFAULT;
-
-       radeon_cp_dispatch_clear(dev, clear, depth_boxes);
-
-       COMMIT_RING();
-       return 0;
-}
-
-/* Not sure why this isn't set all the time:
- */
-static int radeon_do_init_pageflip(struct drm_device * dev)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-
-       DRM_DEBUG("\n");
-
-       BEGIN_RING(6);
-       RADEON_WAIT_UNTIL_3D_IDLE();
-       OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0));
-       OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) |
-                RADEON_CRTC_OFFSET_FLIP_CNTL);
-       OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0));
-       OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) |
-                RADEON_CRTC_OFFSET_FLIP_CNTL);
-       ADVANCE_RING();
-
-       dev_priv->page_flipping = 1;
-
-       if (dev_priv->sarea_priv->pfCurrentPage != 1)
-               dev_priv->sarea_priv->pfCurrentPage = 0;
-
-       return 0;
-}
-
-/* Swapping and flipping are different operations, need different ioctls.
- * They can & should be intermixed to support multiple 3d windows.
- */
-static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-       if (!dev_priv->page_flipping)
-               radeon_do_init_pageflip(dev);
-
-       radeon_cp_dispatch_flip(dev);
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-       if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
-               sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
-
-       radeon_cp_dispatch_swap(dev);
-       dev_priv->sarea_priv->ctx_owner = 0;
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_radeon_vertex_t *vertex = data;
-       drm_radeon_tcl_prim_t prim;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
-                 DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
-
-       if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
-               DRM_ERROR("buffer index %d (of %d max)\n",
-                         vertex->idx, dma->buf_count - 1);
-               return -EINVAL;
-       }
-       if (vertex->prim < 0 || vertex->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
-               DRM_ERROR("buffer prim %d\n", vertex->prim);
-               return -EINVAL;
-       }
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-       VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-       buf = dma->buflist[vertex->idx];
-
-       if (buf->file_priv != file_priv) {
-               DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->file_priv);
-               return -EINVAL;
-       }
-       if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", vertex->idx);
-               return -EINVAL;
-       }
-
-       /* Build up a prim_t record:
-        */
-       if (vertex->count) {
-               buf->used = vertex->count;      /* not used? */
-
-               if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
-                       if (radeon_emit_state(dev_priv, file_priv,
-                                             &sarea_priv->context_state,
-                                             sarea_priv->tex_state,
-                                             sarea_priv->dirty)) {
-                               DRM_ERROR("radeon_emit_state failed\n");
-                               return -EINVAL;
-                       }
-
-                       sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
-                                              RADEON_UPLOAD_TEX1IMAGES |
-                                              RADEON_UPLOAD_TEX2IMAGES |
-                                              RADEON_REQUIRE_QUIESCENCE);
-               }
-
-               prim.start = 0;
-               prim.finish = vertex->count;    /* unused */
-               prim.prim = vertex->prim;
-               prim.numverts = vertex->count;
-               prim.vc_format = dev_priv->sarea_priv->vc_format;
-
-               radeon_cp_dispatch_vertex(dev, buf, &prim);
-       }
-
-       if (vertex->discard) {
-               radeon_cp_discard_buffer(dev, buf);
-       }
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_radeon_indices_t *elts = data;
-       drm_radeon_tcl_prim_t prim;
-       int count;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
-                 DRM_CURRENTPID, elts->idx, elts->start, elts->end,
-                 elts->discard);
-
-       if (elts->idx < 0 || elts->idx >= dma->buf_count) {
-               DRM_ERROR("buffer index %d (of %d max)\n",
-                         elts->idx, dma->buf_count - 1);
-               return -EINVAL;
-       }
-       if (elts->prim < 0 || elts->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
-               DRM_ERROR("buffer prim %d\n", elts->prim);
-               return -EINVAL;
-       }
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-       VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-       buf = dma->buflist[elts->idx];
-
-       if (buf->file_priv != file_priv) {
-               DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->file_priv);
-               return -EINVAL;
-       }
-       if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", elts->idx);
-               return -EINVAL;
-       }
-
-       count = (elts->end - elts->start) / sizeof(u16);
-       elts->start -= RADEON_INDEX_PRIM_OFFSET;
-
-       if (elts->start & 0x7) {
-               DRM_ERROR("misaligned buffer 0x%x\n", elts->start);
-               return -EINVAL;
-       }
-       if (elts->start < buf->used) {
-               DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);
-               return -EINVAL;
-       }
-
-       buf->used = elts->end;
-
-       if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
-               if (radeon_emit_state(dev_priv, file_priv,
-                                     &sarea_priv->context_state,
-                                     sarea_priv->tex_state,
-                                     sarea_priv->dirty)) {
-                       DRM_ERROR("radeon_emit_state failed\n");
-                       return -EINVAL;
-               }
-
-               sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
-                                      RADEON_UPLOAD_TEX1IMAGES |
-                                      RADEON_UPLOAD_TEX2IMAGES |
-                                      RADEON_REQUIRE_QUIESCENCE);
-       }
-
-       /* Build up a prim_t record:
-        */
-       prim.start = elts->start;
-       prim.finish = elts->end;
-       prim.prim = elts->prim;
-       prim.offset = 0;        /* offset from start of dma buffers */
-       prim.numverts = RADEON_MAX_VB_VERTS;    /* duh */
-       prim.vc_format = dev_priv->sarea_priv->vc_format;
-
-       radeon_cp_dispatch_indices(dev, buf, &prim);
-       if (elts->discard) {
-               radeon_cp_discard_buffer(dev, buf);
-       }
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_texture_t *tex = data;
-       drm_radeon_tex_image_t image;
-       int ret;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (tex->image == NULL) {
-               DRM_ERROR("null texture image!\n");
-               return -EINVAL;
-       }
-
-       if (DRM_COPY_FROM_USER(&image,
-                              (drm_radeon_tex_image_t __user *) tex->image,
-                              sizeof(image)))
-               return -EFAULT;
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-       VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-       ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image);
-
-       return ret;
-}
-
-static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_stipple_t *stipple = data;
-       u32 mask[32];
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
-               return -EFAULT;
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-
-       radeon_cp_dispatch_stipple(dev, mask);
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_radeon_indirect_t *indirect = data;
-       RING_LOCALS;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
-                 indirect->idx, indirect->start, indirect->end,
-                 indirect->discard);
-
-       if (indirect->idx < 0 || indirect->idx >= dma->buf_count) {
-               DRM_ERROR("buffer index %d (of %d max)\n",
-                         indirect->idx, dma->buf_count - 1);
-               return -EINVAL;
-       }
-
-       buf = dma->buflist[indirect->idx];
-
-       if (buf->file_priv != file_priv) {
-               DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->file_priv);
-               return -EINVAL;
-       }
-       if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", indirect->idx);
-               return -EINVAL;
-       }
-
-       if (indirect->start < buf->used) {
-               DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
-                         indirect->start, buf->used);
-               return -EINVAL;
-       }
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-       VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-       buf->used = indirect->end;
-
-       /* Wait for the 3D stream to idle before the indirect buffer
-        * containing 2D acceleration commands is processed.
-        */
-       BEGIN_RING(2);
-
-       RADEON_WAIT_UNTIL_3D_IDLE();
-
-       ADVANCE_RING();
-
-       /* Dispatch the indirect buffer full of commands from the
-        * X server.  This is insecure and is thus only available to
-        * privileged clients.
-        */
-       radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);
-       if (indirect->discard) {
-               radeon_cp_discard_buffer(dev, buf);
-       }
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_radeon_vertex2_t *vertex = data;
-       int i;
-       unsigned char laststate;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       DRM_DEBUG("pid=%d index=%d discard=%d\n",
-                 DRM_CURRENTPID, vertex->idx, vertex->discard);
-
-       if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
-               DRM_ERROR("buffer index %d (of %d max)\n",
-                         vertex->idx, dma->buf_count - 1);
-               return -EINVAL;
-       }
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-       VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-       buf = dma->buflist[vertex->idx];
-
-       if (buf->file_priv != file_priv) {
-               DRM_ERROR("process %d using buffer owned by %p\n",
-                         DRM_CURRENTPID, buf->file_priv);
-               return -EINVAL;
-       }
-
-       if (buf->pending) {
-               DRM_ERROR("sending pending buffer %d\n", vertex->idx);
-               return -EINVAL;
-       }
-
-       if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
-               return -EINVAL;
-
-       for (laststate = 0xff, i = 0; i < vertex->nr_prims; i++) {
-               drm_radeon_prim_t prim;
-               drm_radeon_tcl_prim_t tclprim;
-
-               if (DRM_COPY_FROM_USER(&prim, &vertex->prim[i], sizeof(prim)))
-                       return -EFAULT;
-
-               if (prim.stateidx != laststate) {
-                       drm_radeon_state_t state;
-
-                       if (DRM_COPY_FROM_USER(&state,
-                                              &vertex->state[prim.stateidx],
-                                              sizeof(state)))
-                               return -EFAULT;
-
-                       if (radeon_emit_state2(dev_priv, file_priv, &state)) {
-                               DRM_ERROR("radeon_emit_state2 failed\n");
-                               return -EINVAL;
-                       }
-
-                       laststate = prim.stateidx;
-               }
-
-               tclprim.start = prim.start;
-               tclprim.finish = prim.finish;
-               tclprim.prim = prim.prim;
-               tclprim.vc_format = prim.vc_format;
-
-               if (prim.prim & RADEON_PRIM_WALK_IND) {
-                       tclprim.offset = prim.numverts * 64;
-                       tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
-
-                       radeon_cp_dispatch_indices(dev, buf, &tclprim);
-               } else {
-                       tclprim.numverts = prim.numverts;
-                       tclprim.offset = 0;     /* not used */
-
-                       radeon_cp_dispatch_vertex(dev, buf, &tclprim);
-               }
-
-               if (sarea_priv->nbox == 1)
-                       sarea_priv->nbox = 0;
-       }
-
-       if (vertex->discard) {
-               radeon_cp_discard_buffer(dev, buf);
-       }
-
-       COMMIT_RING();
-       return 0;
-}
-
-static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
-                              struct drm_file *file_priv,
-                              drm_radeon_cmd_header_t header,
-                              drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-       int id = (int)header.packet.packet_id;
-       int sz, reg;
-       int *data = (int *)cmdbuf->buf;
-       RING_LOCALS;
-
-       if (id >= RADEON_MAX_STATE_PACKETS)
-               return -EINVAL;
-
-       sz = packet[id].len;
-       reg = packet[id].start;
-
-       if (sz * sizeof(int) > cmdbuf->bufsz) {
-               DRM_ERROR("Packet size provided larger than data provided\n");
-               return -EINVAL;
-       }
-
-       if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, data)) {
-               DRM_ERROR("Packet verification failed\n");
-               return -EINVAL;
-       }
-
-       BEGIN_RING(sz + 1);
-       OUT_RING(CP_PACKET0(reg, (sz - 1)));
-       OUT_RING_TABLE(data, sz);
-       ADVANCE_RING();
-
-       cmdbuf->buf += sz * sizeof(int);
-       cmdbuf->bufsz -= sz * sizeof(int);
-       return 0;
-}
-
-static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv,
-                                         drm_radeon_cmd_header_t header,
-                                         drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-       int sz = header.scalars.count;
-       int start = header.scalars.offset;
-       int stride = header.scalars.stride;
-       RING_LOCALS;
-
-       BEGIN_RING(3 + sz);
-       OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
-       OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
-       OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
-       OUT_RING_TABLE(cmdbuf->buf, sz);
-       ADVANCE_RING();
-       cmdbuf->buf += sz * sizeof(int);
-       cmdbuf->bufsz -= sz * sizeof(int);
-       return 0;
-}
-
-/* God this is ugly
- */
-static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv,
-                                          drm_radeon_cmd_header_t header,
-                                          drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-       int sz = header.scalars.count;
-       int start = ((unsigned int)header.scalars.offset) + 0x100;
-       int stride = header.scalars.stride;
-       RING_LOCALS;
-
-       BEGIN_RING(3 + sz);
-       OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
-       OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
-       OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
-       OUT_RING_TABLE(cmdbuf->buf, sz);
-       ADVANCE_RING();
-       cmdbuf->buf += sz * sizeof(int);
-       cmdbuf->bufsz -= sz * sizeof(int);
-       return 0;
-}
-
-static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
-                                         drm_radeon_cmd_header_t header,
-                                         drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-       int sz = header.vectors.count;
-       int start = header.vectors.offset;
-       int stride = header.vectors.stride;
-       RING_LOCALS;
-
-       BEGIN_RING(5 + sz);
-       OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
-       OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
-       OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
-       OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
-       OUT_RING_TABLE(cmdbuf->buf, sz);
-       ADVANCE_RING();
-
-       cmdbuf->buf += sz * sizeof(int);
-       cmdbuf->bufsz -= sz * sizeof(int);
-       return 0;
-}
-
-static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
-                                         drm_radeon_cmd_header_t header,
-                                         drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-       int sz = header.veclinear.count * 4;
-       int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8);
-       RING_LOCALS;
-
-        if (!sz)
-                return 0;
-        if (sz * 4 > cmdbuf->bufsz)
-                return -EINVAL;
-
-       BEGIN_RING(5 + sz);
-       OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
-       OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
-       OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
-       OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
-       OUT_RING_TABLE(cmdbuf->buf, sz);
-       ADVANCE_RING();
-
-       cmdbuf->buf += sz * sizeof(int);
-       cmdbuf->bufsz -= sz * sizeof(int);
-       return 0;
-}
-
-static int radeon_emit_packet3(struct drm_device * dev,
-                              struct drm_file *file_priv,
-                              drm_radeon_kcmd_buffer_t *cmdbuf)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       unsigned int cmdsz;
-       int ret;
-       RING_LOCALS;
-
-       DRM_DEBUG("\n");
-
-       if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv,
-                                                 cmdbuf, &cmdsz))) {
-               DRM_ERROR("Packet verification failed\n");
-               return ret;
-       }
-
-       BEGIN_RING(cmdsz);
-       OUT_RING_TABLE(cmdbuf->buf, cmdsz);
-       ADVANCE_RING();
-
-       cmdbuf->buf += cmdsz * 4;
-       cmdbuf->bufsz -= cmdsz * 4;
-       return 0;
-}
-
-static int radeon_emit_packet3_cliprect(struct drm_device *dev,
-                                       struct drm_file *file_priv,
-                                       drm_radeon_kcmd_buffer_t *cmdbuf,
-                                       int orig_nbox)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_clip_rect box;
-       unsigned int cmdsz;
-       int ret;
-       struct drm_clip_rect __user *boxes = cmdbuf->boxes;
-       int i = 0;
-       RING_LOCALS;
-
-       DRM_DEBUG("\n");
-
-       if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv,
-                                                 cmdbuf, &cmdsz))) {
-               DRM_ERROR("Packet verification failed\n");
-               return ret;
-       }
-
-       if (!orig_nbox)
-               goto out;
-
-       do {
-               if (i < cmdbuf->nbox) {
-                       if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box)))
-                               return -EFAULT;
-                       /* FIXME The second and subsequent times round
-                        * this loop, send a WAIT_UNTIL_3D_IDLE before
-                        * calling emit_clip_rect(). This fixes a
-                        * lockup on fast machines when sending
-                        * several cliprects with a cmdbuf, as when
-                        * waving a 2D window over a 3D
-                        * window. Something in the commands from user
-                        * space seems to hang the card when they're
-                        * sent several times in a row. That would be
-                        * the correct place to fix it but this works
-                        * around it until I can figure that out - Tim
-                        * Smith */
-                       if (i) {
-                               BEGIN_RING(2);
-                               RADEON_WAIT_UNTIL_3D_IDLE();
-                               ADVANCE_RING();
-                       }
-                       radeon_emit_clip_rect(dev_priv, &box);
-               }
-
-               BEGIN_RING(cmdsz);
-               OUT_RING_TABLE(cmdbuf->buf, cmdsz);
-               ADVANCE_RING();
-
-       } while (++i < cmdbuf->nbox);
-       if (cmdbuf->nbox == 1)
-               cmdbuf->nbox = 0;
-
-      out:
-       cmdbuf->buf += cmdsz * 4;
-       cmdbuf->bufsz -= cmdsz * 4;
-       return 0;
-}
-
-static int radeon_emit_wait(struct drm_device * dev, int flags)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       RING_LOCALS;
-
-       DRM_DEBUG("%x\n", flags);
-       switch (flags) {
-       case RADEON_WAIT_2D:
-               BEGIN_RING(2);
-               RADEON_WAIT_UNTIL_2D_IDLE();
-               ADVANCE_RING();
-               break;
-       case RADEON_WAIT_3D:
-               BEGIN_RING(2);
-               RADEON_WAIT_UNTIL_3D_IDLE();
-               ADVANCE_RING();
-               break;
-       case RADEON_WAIT_2D | RADEON_WAIT_3D:
-               BEGIN_RING(2);
-               RADEON_WAIT_UNTIL_IDLE();
-               ADVANCE_RING();
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf = NULL;
-       int idx;
-       drm_radeon_kcmd_buffer_t *cmdbuf = data;
-       drm_radeon_cmd_header_t header;
-       int orig_nbox, orig_bufsz;
-       char *kbuf = NULL;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       RING_SPACE_TEST_WITH_RETURN(dev_priv);
-       VB_AGE_TEST_WITH_RETURN(dev_priv);
-
-       if (cmdbuf->bufsz > 64 * 1024 || cmdbuf->bufsz < 0) {
-               return -EINVAL;
-       }
-
-       /* Allocate an in-kernel area and copy in the cmdbuf.  Do this to avoid
-        * races between checking values and using those values in other code,
-        * and simply to avoid a lot of function calls to copy in data.
-        */
-       orig_bufsz = cmdbuf->bufsz;
-       if (orig_bufsz != 0) {
-               kbuf = drm_alloc(cmdbuf->bufsz, DRM_MEM_DRIVER);
-               if (kbuf == NULL)
-                       return -ENOMEM;
-               if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf,
-                                      cmdbuf->bufsz)) {
-                       drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
-                       return -EFAULT;
-               }
-               cmdbuf->buf = kbuf;
-       }
-
-       orig_nbox = cmdbuf->nbox;
-
-       if (dev_priv->microcode_version == UCODE_R300) {
-               int temp;
-               temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
-
-               if (orig_bufsz != 0)
-                       drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
-
-               return temp;
-       }
-
-       /* microcode_version != r300 */
-       while (cmdbuf->bufsz >= sizeof(header)) {
-
-               header.i = *(int *)cmdbuf->buf;
-               cmdbuf->buf += sizeof(header);
-               cmdbuf->bufsz -= sizeof(header);
-
-               switch (header.header.cmd_type) {
-               case RADEON_CMD_PACKET:
-                       DRM_DEBUG("RADEON_CMD_PACKET\n");
-                       if (radeon_emit_packets
-                           (dev_priv, file_priv, header, cmdbuf)) {
-                               DRM_ERROR("radeon_emit_packets failed\n");
-                               goto err;
-                       }
-                       break;
-
-               case RADEON_CMD_SCALARS:
-                       DRM_DEBUG("RADEON_CMD_SCALARS\n");
-                       if (radeon_emit_scalars(dev_priv, header, cmdbuf)) {
-                               DRM_ERROR("radeon_emit_scalars failed\n");
-                               goto err;
-                       }
-                       break;
-
-               case RADEON_CMD_VECTORS:
-                       DRM_DEBUG("RADEON_CMD_VECTORS\n");
-                       if (radeon_emit_vectors(dev_priv, header, cmdbuf)) {
-                               DRM_ERROR("radeon_emit_vectors failed\n");
-                               goto err;
-                       }
-                       break;
-
-               case RADEON_CMD_DMA_DISCARD:
-                       DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
-                       idx = header.dma.buf_idx;
-                       if (idx < 0 || idx >= dma->buf_count) {
-                               DRM_ERROR("buffer index %d (of %d max)\n",
-                                         idx, dma->buf_count - 1);
-                               goto err;
-                       }
-
-                       buf = dma->buflist[idx];
-                       if (buf->file_priv != file_priv || buf->pending) {
-                               DRM_ERROR("bad buffer %p %p %d\n",
-                                         buf->file_priv, file_priv,
-                                         buf->pending);
-                               goto err;
-                       }
-
-                       radeon_cp_discard_buffer(dev, buf);
-                       break;
-
-               case RADEON_CMD_PACKET3:
-                       DRM_DEBUG("RADEON_CMD_PACKET3\n");
-                       if (radeon_emit_packet3(dev, file_priv, cmdbuf)) {
-                               DRM_ERROR("radeon_emit_packet3 failed\n");
-                               goto err;
-                       }
-                       break;
-
-               case RADEON_CMD_PACKET3_CLIP:
-                       DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
-                       if (radeon_emit_packet3_cliprect
-                           (dev, file_priv, cmdbuf, orig_nbox)) {
-                               DRM_ERROR("radeon_emit_packet3_clip failed\n");
-                               goto err;
-                       }
-                       break;
-
-               case RADEON_CMD_SCALARS2:
-                       DRM_DEBUG("RADEON_CMD_SCALARS2\n");
-                       if (radeon_emit_scalars2(dev_priv, header, cmdbuf)) {
-                               DRM_ERROR("radeon_emit_scalars2 failed\n");
-                               goto err;
-                       }
-                       break;
-
-               case RADEON_CMD_WAIT:
-                       DRM_DEBUG("RADEON_CMD_WAIT\n");
-                       if (radeon_emit_wait(dev, header.wait.flags)) {
-                               DRM_ERROR("radeon_emit_wait failed\n");
-                               goto err;
-                       }
-                       break;
-               case RADEON_CMD_VECLINEAR:
-                       DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
-                       if (radeon_emit_veclinear(dev_priv, header, cmdbuf)) {
-                               DRM_ERROR("radeon_emit_veclinear failed\n");
-                               goto err;
-                       }
-                       break;
-
-               default:
-                       DRM_ERROR("bad cmd_type %d at %p\n",
-                                 header.header.cmd_type,
-                                 cmdbuf->buf - sizeof(header));
-                       goto err;
-               }
-       }
-
-       if (orig_bufsz != 0)
-               drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
-
-       DRM_DEBUG("DONE\n");
-       COMMIT_RING();
-       return 0;
-
-      err:
-       if (orig_bufsz != 0)
-               drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
-       return -EINVAL;
-}
-
-static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_getparam_t *param = data;
-       int value;
-
-       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
-
-       switch (param->param) {
-       case RADEON_PARAM_GART_BUFFER_OFFSET:
-               value = dev_priv->gart_buffers_offset;
-               break;
-       case RADEON_PARAM_LAST_FRAME:
-               dev_priv->stats.last_frame_reads++;
-               value = GET_SCRATCH(0);
-               break;
-       case RADEON_PARAM_LAST_DISPATCH:
-               value = GET_SCRATCH(1);
-               break;
-       case RADEON_PARAM_LAST_CLEAR:
-               dev_priv->stats.last_clear_reads++;
-               value = GET_SCRATCH(2);
-               break;
-       case RADEON_PARAM_IRQ_NR:
-               value = dev->irq;
-               break;
-       case RADEON_PARAM_GART_BASE:
-               value = dev_priv->gart_vm_start;
-               break;
-       case RADEON_PARAM_REGISTER_HANDLE:
-               value = dev_priv->mmio->offset;
-               break;
-       case RADEON_PARAM_STATUS_HANDLE:
-               value = dev_priv->ring_rptr_offset;
-               break;
-#if BITS_PER_LONG == 32
-               /*
-                * This ioctl() doesn't work on 64-bit platforms because hw_lock is a
-                * pointer which can't fit into an int-sized variable.  According to
-                * Michel Dänzer, the ioctl() is only used on embedded platforms, so
-                * not supporting it shouldn't be a problem.  If the same functionality
-                * is needed on 64-bit platforms, a new ioctl() would have to be added,
-                * so backwards-compatibility for the embedded platforms can be
-                * maintained.  --davidm 4-Feb-2004.
-                */
-       case RADEON_PARAM_SAREA_HANDLE:
-               /* The lock is the first dword in the sarea. */
-               value = (long)dev->lock.hw_lock;
-               break;
-#endif
-       case RADEON_PARAM_GART_TEX_HANDLE:
-               value = dev_priv->gart_textures_offset;
-               break;
-       case RADEON_PARAM_SCRATCH_OFFSET:
-               if (!dev_priv->writeback_works)
-                       return -EINVAL;
-               value = RADEON_SCRATCH_REG_OFFSET;
-               break;
-       case RADEON_PARAM_CARD_TYPE:
-               if (dev_priv->flags & RADEON_IS_PCIE)
-                       value = RADEON_CARD_PCIE;
-               else if (dev_priv->flags & RADEON_IS_AGP)
-                       value = RADEON_CARD_AGP;
-               else
-                       value = RADEON_CARD_PCI;
-               break;
-       case RADEON_PARAM_VBLANK_CRTC:
-               value = radeon_vblank_crtc_get(dev);
-               break;
-       case RADEON_PARAM_FB_LOCATION:
-               value = radeon_read_fb_location(dev_priv);
-               break;
-       case RADEON_PARAM_NUM_GB_PIPES:
-               value = dev_priv->num_gb_pipes;
-               break;
-       default:
-               DRM_DEBUG("Invalid parameter %d\n", param->param);
-               return -EINVAL;
-       }
-
-       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
-               DRM_ERROR("copy_to_user\n");
-               return -EFAULT;
-       }
-
-       return 0;
-}
-
-static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       drm_radeon_setparam_t *sp = data;
-       struct drm_radeon_driver_file_fields *radeon_priv;
-
-       switch (sp->param) {
-       case RADEON_SETPARAM_FB_LOCATION:
-               radeon_priv = file_priv->driver_priv;
-               radeon_priv->radeon_fb_delta = dev_priv->fb_location -
-                   sp->value;
-               break;
-       case RADEON_SETPARAM_SWITCH_TILING:
-               if (sp->value == 0) {
-                       DRM_DEBUG("color tiling disabled\n");
-                       dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
-                       dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
-                       dev_priv->sarea_priv->tiling_enabled = 0;
-               } else if (sp->value == 1) {
-                       DRM_DEBUG("color tiling enabled\n");
-                       dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
-                       dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
-                       dev_priv->sarea_priv->tiling_enabled = 1;
-               }
-               break;
-       case RADEON_SETPARAM_PCIGART_LOCATION:
-               dev_priv->pcigart_offset = sp->value;
-               dev_priv->pcigart_offset_set = 1;
-               break;
-       case RADEON_SETPARAM_NEW_MEMMAP:
-               dev_priv->new_memmap = sp->value;
-               break;
-       case RADEON_SETPARAM_PCIGART_TABLE_SIZE:
-               dev_priv->gart_info.table_size = sp->value;
-               if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
-                       dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
-               break;
-       case RADEON_SETPARAM_VBLANK_CRTC:
-               return radeon_vblank_crtc_set(dev, sp->value);
-               break;
-       default:
-               DRM_DEBUG("Invalid parameter %d\n", sp->param);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/* When a client dies:
- *    - Check for and clean up flipped page state
- *    - Free any alloced GART memory.
- *    - Free any alloced radeon surfaces.
- *
- * DRM infrastructure takes care of reclaiming dma buffers.
- */
-void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
-{
-       if (dev->dev_private) {
-               drm_radeon_private_t *dev_priv = dev->dev_private;
-               dev_priv->page_flipping = 0;
-               radeon_mem_release(file_priv, dev_priv->gart_heap);
-               radeon_mem_release(file_priv, dev_priv->fb_heap);
-               radeon_surfaces_release(file_priv, dev_priv);
-       }
-}
-
-void radeon_driver_lastclose(struct drm_device *dev)
-{
-       if (dev->dev_private) {
-               drm_radeon_private_t *dev_priv = dev->dev_private;
-
-               if (dev_priv->sarea_priv &&
-                   dev_priv->sarea_priv->pfCurrentPage != 0)
-                       radeon_cp_dispatch_flip(dev);
-       }
-
-       radeon_do_release(dev);
-}
-
-int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv)
-{
-       drm_radeon_private_t *dev_priv = dev->dev_private;
-       struct drm_radeon_driver_file_fields *radeon_priv;
-
-       DRM_DEBUG("\n");
-       radeon_priv =
-           (struct drm_radeon_driver_file_fields *)
-           drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
-
-       if (!radeon_priv)
-               return -ENOMEM;
-
-       file_priv->driver_priv = radeon_priv;
-
-       if (dev_priv)
-               radeon_priv->radeon_fb_delta = dev_priv->fb_location;
-       else
-               radeon_priv->radeon_fb_delta = 0;
-       return 0;
-}
-
-void radeon_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
-{
-       struct drm_radeon_driver_file_fields *radeon_priv =
-           file_priv->driver_priv;
-
-       drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
-}
-
-struct drm_ioctl_desc radeon_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH)
-};
-
-int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
deleted file mode 100644 (file)
index d465b2f..0000000
+++ /dev/null
@@ -1,1095 +0,0 @@
-/* savage_bci.c -- BCI support for Savage
- *
- * Copyright 2004  Felix Kuehling
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "drmP.h"
-#include "savage_drm.h"
-#include "savage_drv.h"
-
-/* Need a long timeout for shadow status updates can take a while
- * and so can waiting for events when the queue is full. */
-#define SAVAGE_DEFAULT_USEC_TIMEOUT    1000000 /* 1s */
-#define SAVAGE_EVENT_USEC_TIMEOUT      5000000 /* 5s */
-#define SAVAGE_FREELIST_DEBUG          0
-
-static int savage_do_cleanup_bci(struct drm_device *dev);
-
-static int
-savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n)
-{
-       uint32_t mask = dev_priv->status_used_mask;
-       uint32_t threshold = dev_priv->bci_threshold_hi;
-       uint32_t status;
-       int i;
-
-#if SAVAGE_BCI_DEBUG
-       if (n > dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - threshold)
-               DRM_ERROR("Trying to emit %d words "
-                         "(more than guaranteed space in COB)\n", n);
-#endif
-
-       for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
-               DRM_MEMORYBARRIER();
-               status = dev_priv->status_ptr[0];
-               if ((status & mask) < threshold)
-                       return 0;
-               DRM_UDELAY(1);
-       }
-
-#if SAVAGE_BCI_DEBUG
-       DRM_ERROR("failed!\n");
-       DRM_INFO("   status=0x%08x, threshold=0x%08x\n", status, threshold);
-#endif
-       return -EBUSY;
-}
-
-static int
-savage_bci_wait_fifo_s3d(drm_savage_private_t * dev_priv, unsigned int n)
-{
-       uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n;
-       uint32_t status;
-       int i;
-
-       for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
-               status = SAVAGE_READ(SAVAGE_STATUS_WORD0);
-               if ((status & SAVAGE_FIFO_USED_MASK_S3D) <= maxUsed)
-                       return 0;
-               DRM_UDELAY(1);
-       }
-
-#if SAVAGE_BCI_DEBUG
-       DRM_ERROR("failed!\n");
-       DRM_INFO("   status=0x%08x\n", status);
-#endif
-       return -EBUSY;
-}
-
-static int
-savage_bci_wait_fifo_s4(drm_savage_private_t * dev_priv, unsigned int n)
-{
-       uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n;
-       uint32_t status;
-       int i;
-
-       for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
-               status = SAVAGE_READ(SAVAGE_ALT_STATUS_WORD0);
-               if ((status & SAVAGE_FIFO_USED_MASK_S4) <= maxUsed)
-                       return 0;
-               DRM_UDELAY(1);
-       }
-
-#if SAVAGE_BCI_DEBUG
-       DRM_ERROR("failed!\n");
-       DRM_INFO("   status=0x%08x\n", status);
-#endif
-       return -EBUSY;
-}
-
-/*
- * Waiting for events.
- *
- * The BIOSresets the event tag to 0 on mode changes. Therefore we
- * never emit 0 to the event tag. If we find a 0 event tag we know the
- * BIOS stomped on it and return success assuming that the BIOS waited
- * for engine idle.
- *
- * Note: if the Xserver uses the event tag it has to follow the same
- * rule. Otherwise there may be glitches every 2^16 events.
- */
-static int
-savage_bci_wait_event_shadow(drm_savage_private_t * dev_priv, uint16_t e)
-{
-       uint32_t status;
-       int i;
-
-       for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) {
-               DRM_MEMORYBARRIER();
-               status = dev_priv->status_ptr[1];
-               if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff ||
-                   (status & 0xffff) == 0)
-                       return 0;
-               DRM_UDELAY(1);
-       }
-
-#if SAVAGE_BCI_DEBUG
-       DRM_ERROR("failed!\n");
-       DRM_INFO("   status=0x%08x, e=0x%04x\n", status, e);
-#endif
-
-       return -EBUSY;
-}
-
-static int
-savage_bci_wait_event_reg(drm_savage_private_t * dev_priv, uint16_t e)
-{
-       uint32_t status;
-       int i;
-
-       for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) {
-               status = SAVAGE_READ(SAVAGE_STATUS_WORD1);
-               if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff ||
-                   (status & 0xffff) == 0)
-                       return 0;
-               DRM_UDELAY(1);
-       }
-
-#if SAVAGE_BCI_DEBUG
-       DRM_ERROR("failed!\n");
-       DRM_INFO("   status=0x%08x, e=0x%04x\n", status, e);
-#endif
-
-       return -EBUSY;
-}
-
-uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv,
-                              unsigned int flags)
-{
-       uint16_t count;
-       BCI_LOCALS;
-
-       if (dev_priv->status_ptr) {
-               /* coordinate with Xserver */
-               count = dev_priv->status_ptr[1023];
-               if (count < dev_priv->event_counter)
-                       dev_priv->event_wrap++;
-       } else {
-               count = dev_priv->event_counter;
-       }
-       count = (count + 1) & 0xffff;
-       if (count == 0) {
-               count++;        /* See the comment above savage_wait_event_*. */
-               dev_priv->event_wrap++;
-       }
-       dev_priv->event_counter = count;
-       if (dev_priv->status_ptr)
-               dev_priv->status_ptr[1023] = (uint32_t) count;
-
-       if ((flags & (SAVAGE_WAIT_2D | SAVAGE_WAIT_3D))) {
-               unsigned int wait_cmd = BCI_CMD_WAIT;
-               if ((flags & SAVAGE_WAIT_2D))
-                       wait_cmd |= BCI_CMD_WAIT_2D;
-               if ((flags & SAVAGE_WAIT_3D))
-                       wait_cmd |= BCI_CMD_WAIT_3D;
-               BEGIN_BCI(2);
-               BCI_WRITE(wait_cmd);
-       } else {
-               BEGIN_BCI(1);
-       }
-       BCI_WRITE(BCI_CMD_UPDATE_EVENT_TAG | (uint32_t) count);
-
-       return count;
-}
-
-/*
- * Freelist management
- */
-static int savage_freelist_init(struct drm_device * dev)
-{
-       drm_savage_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *buf;
-       drm_savage_buf_priv_t *entry;
-       int i;
-       DRM_DEBUG("count=%d\n", dma->buf_count);
-
-       dev_priv->head.next = &dev_priv->tail;
-       dev_priv->head.prev = NULL;
-       dev_priv->head.buf = NULL;
-
-       dev_priv->tail.next = NULL;
-       dev_priv->tail.prev = &dev_priv->head;
-       dev_priv->tail.buf = NULL;
-
-       for (i = 0; i < dma->buf_count; i++) {
-               buf = dma->buflist[i];
-               entry = buf->dev_private;
-
-               SET_AGE(&entry->age, 0, 0);
-               entry->buf = buf;
-
-               entry->next = dev_priv->head.next;
-               entry->prev = &dev_priv->head;
-               dev_priv->head.next->prev = entry;
-               dev_priv->head.next = entry;
-       }
-
-       return 0;
-}
-
-static struct drm_buf *savage_freelist_get(struct drm_device * dev)
-{
-       drm_savage_private_t *dev_priv = dev->dev_private;
-       drm_savage_buf_priv_t *tail = dev_priv->tail.prev;
-       uint16_t event;
-       unsigned int wrap;
-       DRM_DEBUG("\n");
-
-       UPDATE_EVENT_COUNTER();
-       if (dev_priv->status_ptr)
-               event = dev_priv->status_ptr[1] & 0xffff;
-       else
-               event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
-       wrap = dev_priv->event_wrap;
-       if (event > dev_priv->event_counter)
-               wrap--;         /* hardware hasn't passed the last wrap yet */
-
-       DRM_DEBUG("   tail=0x%04x %d\n", tail->age.event, tail->age.wrap);
-       DRM_DEBUG("   head=0x%04x %d\n", event, wrap);
-
-       if (tail->buf && (TEST_AGE(&tail->age, event, wrap) || event == 0)) {
-               drm_savage_buf_priv_t *next = tail->next;
-               drm_savage_buf_priv_t *prev = tail->prev;
-               prev->next = next;
-               next->prev = prev;
-               tail->next = tail->prev = NULL;
-               return tail->buf;
-       }
-
-       DRM_DEBUG("returning NULL, tail->buf=%p!\n", tail->buf);
-       return NULL;
-}
-
-void savage_freelist_put(struct drm_device * dev, struct drm_buf * buf)
-{
-       drm_savage_private_t *dev_priv = dev->dev_private;
-       drm_savage_buf_priv_t *entry = buf->dev_private, *prev, *next;
-
-       DRM_DEBUG("age=0x%04x wrap=%d\n", entry->age.event, entry->age.wrap);
-
-       if (entry->next != NULL || entry->prev != NULL) {
-               DRM_ERROR("entry already on freelist.\n");
-               return;
-       }
-
-       prev = &dev_priv->head;
-       next = prev->next;
-       prev->next = entry;
-       next->prev = entry;
-       entry->prev = prev;
-       entry->next = next;
-}
-
-/*
- * Command DMA
- */
-static int savage_dma_init(drm_savage_private_t * dev_priv)
-{
-       unsigned int i;
-
-       dev_priv->nr_dma_pages = dev_priv->cmd_dma->size /
-           (SAVAGE_DMA_PAGE_SIZE * 4);
-       dev_priv->dma_pages = drm_alloc(sizeof(drm_savage_dma_page_t) *
-                                       dev_priv->nr_dma_pages, DRM_MEM_DRIVER);
-       if (dev_priv->dma_pages == NULL)
-               return -ENOMEM;
-
-       for (i = 0; i < dev_priv->nr_dma_pages; ++i) {
-               SET_AGE(&dev_priv->dma_pages[i].age, 0, 0);
-               dev_priv->dma_pages[i].used = 0;
-               dev_priv->dma_pages[i].flushed = 0;
-       }
-       SET_AGE(&dev_priv->last_dma_age, 0, 0);
-
-       dev_priv->first_dma_page = 0;
-       dev_priv->current_dma_page = 0;
-
-       return 0;
-}
-
-void savage_dma_reset(drm_savage_private_t * dev_priv)
-{
-       uint16_t event;
-       unsigned int wrap, i;
-       event = savage_bci_emit_event(dev_priv, 0);
-       wrap = dev_priv->event_wrap;
-       for (i = 0; i < dev_priv->nr_dma_pages; ++i) {
-               SET_AGE(&dev_priv->dma_pages[i].age, event, wrap);
-               dev_priv->dma_pages[i].used = 0;
-               dev_priv->dma_pages[i].flushed = 0;
-       }
-       SET_AGE(&dev_priv->last_dma_age, event, wrap);
-       dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
-}
-
-void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page)
-{
-       uint16_t event;
-       unsigned int wrap;
-
-       /* Faked DMA buffer pages don't age. */
-       if (dev_priv->cmd_dma == &dev_priv->fake_dma)
-               return;
-
-       UPDATE_EVENT_COUNTER();
-       if (dev_priv->status_ptr)
-               event = dev_priv->status_ptr[1] & 0xffff;
-       else
-               event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
-       wrap = dev_priv->event_wrap;
-       if (event > dev_priv->event_counter)
-               wrap--;         /* hardware hasn't passed the last wrap yet */
-
-       if (dev_priv->dma_pages[page].age.wrap > wrap ||
-           (dev_priv->dma_pages[page].age.wrap == wrap &&
-            dev_priv->dma_pages[page].age.event > event)) {
-               if (dev_priv->wait_evnt(dev_priv,
-                                       dev_priv->dma_pages[page].age.event)
-                   < 0)
-                       DRM_ERROR("wait_evnt failed!\n");
-       }
-}
-
-uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv, unsigned int n)
-{
-       unsigned int cur = dev_priv->current_dma_page;
-       unsigned int rest = SAVAGE_DMA_PAGE_SIZE -
-           dev_priv->dma_pages[cur].used;
-       unsigned int nr_pages = (n - rest + SAVAGE_DMA_PAGE_SIZE - 1) /
-           SAVAGE_DMA_PAGE_SIZE;
-       uint32_t *dma_ptr;
-       unsigned int i;
-
-       DRM_DEBUG("cur=%u, cur->used=%u, n=%u, rest=%u, nr_pages=%u\n",
-                 cur, dev_priv->dma_pages[cur].used, n, rest, nr_pages);
-
-       if (cur + nr_pages < dev_priv->nr_dma_pages) {
-               dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle +
-                   cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used;
-               if (n < rest)
-                       rest = n;
-               dev_priv->dma_pages[cur].used += rest;
-               n -= rest;
-               cur++;
-       } else {
-               dev_priv->dma_flush(dev_priv);
-               nr_pages =
-                   (n + SAVAGE_DMA_PAGE_SIZE - 1) / SAVAGE_DMA_PAGE_SIZE;
-               for (i = cur; i < dev_priv->nr_dma_pages; ++i) {
-                       dev_priv->dma_pages[i].age = dev_priv->last_dma_age;
-                       dev_priv->dma_pages[i].used = 0;
-                       dev_priv->dma_pages[i].flushed = 0;
-               }
-               dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle;
-               dev_priv->first_dma_page = cur = 0;
-       }
-       for (i = cur; nr_pages > 0; ++i, --nr_pages) {
-#if SAVAGE_DMA_DEBUG
-               if (dev_priv->dma_pages[i].used) {
-                       DRM_ERROR("unflushed page %u: used=%u\n",
-                                 i, dev_priv->dma_pages[i].used);
-               }
-#endif
-               if (n > SAVAGE_DMA_PAGE_SIZE)
-                       dev_priv->dma_pages[i].used = SAVAGE_DMA_PAGE_SIZE;
-               else
-                       dev_priv->dma_pages[i].used = n;
-               n -= SAVAGE_DMA_PAGE_SIZE;
-       }
-       dev_priv->current_dma_page = --i;
-
-       DRM_DEBUG("cur=%u, cur->used=%u, n=%u\n",
-                 i, dev_priv->dma_pages[i].used, n);
-
-       savage_dma_wait(dev_priv, dev_priv->current_dma_page);
-
-       return dma_ptr;
-}
-
-static void savage_dma_flush(drm_savage_private_t * dev_priv)
-{
-       unsigned int first = dev_priv->first_dma_page;
-       unsigned int cur = dev_priv->current_dma_page;
-       uint16_t event;
-       unsigned int wrap, pad, align, len, i;
-       unsigned long phys_addr;
-       BCI_LOCALS;
-
-       if (first == cur &&
-           dev_priv->dma_pages[cur].used == dev_priv->dma_pages[cur].flushed)
-               return;
-
-       /* pad length to multiples of 2 entries
-        * align start of next DMA block to multiles of 8 entries */
-       pad = -dev_priv->dma_pages[cur].used & 1;
-       align = -(dev_priv->dma_pages[cur].used + pad) & 7;
-
-       DRM_DEBUG("first=%u, cur=%u, first->flushed=%u, cur->used=%u, "
-                 "pad=%u, align=%u\n",
-                 first, cur, dev_priv->dma_pages[first].flushed,
-                 dev_priv->dma_pages[cur].used, pad, align);
-
-       /* pad with noops */
-       if (pad) {
-               uint32_t *dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle +
-                   cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used;
-               dev_priv->dma_pages[cur].used += pad;
-               while (pad != 0) {
-                       *dma_ptr++ = BCI_CMD_WAIT;
-                       pad--;
-               }
-       }
-
-       DRM_MEMORYBARRIER();
-
-       /* do flush ... */
-       phys_addr = dev_priv->cmd_dma->offset +
-           (first * SAVAGE_DMA_PAGE_SIZE +
-            dev_priv->dma_pages[first].flushed) * 4;
-       len = (cur - first) * SAVAGE_DMA_PAGE_SIZE +
-           dev_priv->dma_pages[cur].used - dev_priv->dma_pages[first].flushed;
-
-       DRM_DEBUG("phys_addr=%lx, len=%u\n",
-                 phys_addr | dev_priv->dma_type, len);
-
-       BEGIN_BCI(3);
-       BCI_SET_REGISTERS(SAVAGE_DMABUFADDR, 1);
-       BCI_WRITE(phys_addr | dev_priv->dma_type);
-       BCI_DMA(len);
-
-       /* fix alignment of the start of the next block */
-       dev_priv->dma_pages[cur].used += align;
-
-       /* age DMA pages */
-       event = savage_bci_emit_event(dev_priv, 0);
-       wrap = dev_priv->event_wrap;
-       for (i = first; i < cur; ++i) {
-               SET_AGE(&dev_priv->dma_pages[i].age, event, wrap);
-               dev_priv->dma_pages[i].used = 0;
-               dev_priv->dma_pages[i].flushed = 0;
-       }
-       /* age the current page only when it's full */
-       if (dev_priv->dma_pages[cur].used == SAVAGE_DMA_PAGE_SIZE) {
-               SET_AGE(&dev_priv->dma_pages[cur].age, event, wrap);
-               dev_priv->dma_pages[cur].used = 0;
-               dev_priv->dma_pages[cur].flushed = 0;
-               /* advance to next page */
-               cur++;
-               if (cur == dev_priv->nr_dma_pages)
-                       cur = 0;
-               dev_priv->first_dma_page = dev_priv->current_dma_page = cur;
-       } else {
-               dev_priv->first_dma_page = cur;
-               dev_priv->dma_pages[cur].flushed = dev_priv->dma_pages[i].used;
-       }
-       SET_AGE(&dev_priv->last_dma_age, event, wrap);
-
-       DRM_DEBUG("first=cur=%u, cur->used=%u, cur->flushed=%u\n", cur,
-                 dev_priv->dma_pages[cur].used,
-                 dev_priv->dma_pages[cur].flushed);
-}
-
-static void savage_fake_dma_flush(drm_savage_private_t * dev_priv)
-{
-       unsigned int i, j;
-       BCI_LOCALS;
-
-       if (dev_priv->first_dma_page == dev_priv->current_dma_page &&
-           dev_priv->dma_pages[dev_priv->current_dma_page].used == 0)
-               return;
-
-       DRM_DEBUG("first=%u, cur=%u, cur->used=%u\n",
-                 dev_priv->first_dma_page, dev_priv->current_dma_page,
-                 dev_priv->dma_pages[dev_priv->current_dma_page].used);
-
-       for (i = dev_priv->first_dma_page;
-            i <= dev_priv->current_dma_page && dev_priv->dma_pages[i].used;
-            ++i) {
-               uint32_t *dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle +
-                   i * SAVAGE_DMA_PAGE_SIZE;
-#if SAVAGE_DMA_DEBUG
-               /* Sanity check: all pages except the last one must be full. */
-               if (i < dev_priv->current_dma_page &&
-                   dev_priv->dma_pages[i].used != SAVAGE_DMA_PAGE_SIZE) {
-                       DRM_ERROR("partial DMA page %u: used=%u",
-                                 i, dev_priv->dma_pages[i].used);
-               }
-#endif
-               BEGIN_BCI(dev_priv->dma_pages[i].used);
-               for (j = 0; j < dev_priv->dma_pages[i].used; ++j) {
-                       BCI_WRITE(dma_ptr[j]);
-               }
-               dev_priv->dma_pages[i].used = 0;
-       }
-
-       /* reset to first page */
-       dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
-}
-
-int savage_driver_load(struct drm_device *dev, unsigned long chipset)
-{
-       drm_savage_private_t *dev_priv;
-
-       dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
-       if (dev_priv == NULL)
-               return -ENOMEM;
-
-       memset(dev_priv, 0, sizeof(drm_savage_private_t));
-       dev->dev_private = (void *)dev_priv;
-
-       dev_priv->chipset = (enum savage_family)chipset;
-
-       return 0;
-}
-
-
-/*
- * Initalize mappings. On Savage4 and SavageIX the alignment
- * and size of the aperture is not suitable for automatic MTRR setup
- * in drm_addmap. Therefore we add them manually before the maps are
- * initialized, and tear them down on last close.
- */
-int savage_driver_firstopen(struct drm_device *dev)
-{
-       drm_savage_private_t *dev_priv = dev->dev_private;
-       unsigned long mmio_base, fb_base, fb_size, aperture_base;
-       /* fb_rsrc and aper_rsrc aren't really used currently, but still exist
-        * in case we decide we need information on the BAR for BSD in the
-        * future.
-        */
-       unsigned int fb_rsrc, aper_rsrc;
-       int ret = 0;
-
-       dev_priv->mtrr[0].handle = -1;
-       dev_priv->mtrr[1].handle = -1;
-       dev_priv->mtrr[2].handle = -1;
-       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
-               fb_rsrc = 0;
-               fb_base = drm_get_resource_start(dev, 0);
-               fb_size = SAVAGE_FB_SIZE_S3;
-               mmio_base = fb_base + SAVAGE_FB_SIZE_S3;
-               aper_rsrc = 0;
-               aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
-               /* this should always be true */
-               if (drm_get_resource_len(dev, 0) == 0x08000000) {
-                       /* Don't make MMIO write-cobining! We need 3
-                        * MTRRs. */
-                       dev_priv->mtrr[0].base = fb_base;
-                       dev_priv->mtrr[0].size = 0x01000000;
-                       dev_priv->mtrr[0].handle =
-                           drm_mtrr_add(dev_priv->mtrr[0].base,
-                                        dev_priv->mtrr[0].size, DRM_MTRR_WC);
-                       dev_priv->mtrr[1].base = fb_base + 0x02000000;
-                       dev_priv->mtrr[1].size = 0x02000000;
-                       dev_priv->mtrr[1].handle =
-                           drm_mtrr_add(dev_priv->mtrr[1].base,
-                                        dev_priv->mtrr[1].size, DRM_MTRR_WC);
-                       dev_priv->mtrr[2].base = fb_base + 0x04000000;
-                       dev_priv->mtrr[2].size = 0x04000000;
-                       dev_priv->mtrr[2].handle =
-                           drm_mtrr_add(dev_priv->mtrr[2].base,
-                                        dev_priv->mtrr[2].size, DRM_MTRR_WC);
-               } else {
-                       DRM_ERROR("strange pci_resource_len %08lx\n",
-                                 drm_get_resource_len(dev, 0));
-               }
-       } else if (dev_priv->chipset != S3_SUPERSAVAGE &&
-                  dev_priv->chipset != S3_SAVAGE2000) {
-               mmio_base = drm_get_resource_start(dev, 0);
-               fb_rsrc = 1;
-               fb_base = drm_get_resource_start(dev, 1);
-               fb_size = SAVAGE_FB_SIZE_S4;
-               aper_rsrc = 1;
-               aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
-               /* this should always be true */
-               if (drm_get_resource_len(dev, 1) == 0x08000000) {
-                       /* Can use one MTRR to cover both fb and
-                        * aperture. */
-                       dev_priv->mtrr[0].base = fb_base;
-                       dev_priv->mtrr[0].size = 0x08000000;
-                       dev_priv->mtrr[0].handle =
-                           drm_mtrr_add(dev_priv->mtrr[0].base,
-                                        dev_priv->mtrr[0].size, DRM_MTRR_WC);
-               } else {
-                       DRM_ERROR("strange pci_resource_len %08lx\n",
-                                 drm_get_resource_len(dev, 1));
-               }
-       } else {
-               mmio_base = drm_get_resource_start(dev, 0);
-               fb_rsrc = 1;
-               fb_base = drm_get_resource_start(dev, 1);
-               fb_size = drm_get_resource_len(dev, 1);
-               aper_rsrc = 2;
-               aperture_base = drm_get_resource_start(dev, 2);
-               /* Automatic MTRR setup will do the right thing. */
-       }
-
-       ret = drm_addmap(dev, mmio_base, SAVAGE_MMIO_SIZE, _DRM_REGISTERS,
-                        _DRM_READ_ONLY, &dev_priv->mmio);
-       if (ret)
-               return ret;
-
-       ret = drm_addmap(dev, fb_base, fb_size, _DRM_FRAME_BUFFER,
-                        _DRM_WRITE_COMBINING, &dev_priv->fb);
-       if (ret)
-               return ret;
-
-       ret = drm_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE,
-                        _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING,
-                        &dev_priv->aperture);
-       if (ret)
-               return ret;
-
-       return ret;
-}
-
-/*
- * Delete MTRRs and free device-private data.
- */
-void savage_driver_lastclose(struct drm_device *dev)
-{
-       drm_savage_private_t *dev_priv = dev->dev_private;
-       int i;
-
-       for (i = 0; i < 3; ++i)
-               if (dev_priv->mtrr[i].handle >= 0)
-                       drm_mtrr_del(dev_priv->mtrr[i].handle,
-                                dev_priv->mtrr[i].base,
-                                dev_priv->mtrr[i].size, DRM_MTRR_WC);
-}
-
-int savage_driver_unload(struct drm_device *dev)
-{
-       drm_savage_private_t *dev_priv = dev->dev_private;
-
-       drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
-
-       return 0;
-}
-
-static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init)
-{
-       drm_savage_private_t *dev_priv = dev->dev_private;
-
-       if (init->fb_bpp != 16 && init->fb_bpp != 32) {
-               DRM_ERROR("invalid frame buffer bpp %d!\n", init->fb_bpp);
-               return -EINVAL;
-       }
-       if (init->depth_bpp != 16 && init->depth_bpp != 32) {
-               DRM_ERROR("invalid depth buffer bpp %d!\n", init->fb_bpp);
-               return -EINVAL;
-       }
-       if (init->dma_type != SAVAGE_DMA_AGP &&
-           init->dma_type != SAVAGE_DMA_PCI) {
-               DRM_ERROR("invalid dma memory type %d!\n", init->dma_type);
-               return -EINVAL;
-       }
-
-       dev_priv->cob_size = init->cob_size;
-       dev_priv->bci_threshold_lo = init->bci_threshold_lo;
-       dev_priv->bci_threshold_hi = init->bci_threshold_hi;
-       dev_priv->dma_type = init->dma_type;
-
-       dev_priv->fb_bpp = init->fb_bpp;
-       dev_priv->front_offset = init->front_offset;
-       dev_priv->front_pitch = init->front_pitch;
-       dev_priv->back_offset = init->back_offset;
-       dev_priv->back_pitch = init->back_pitch;
-       dev_priv->depth_bpp = init->depth_bpp;
-       dev_priv->depth_offset = init->depth_offset;
-       dev_priv->depth_pitch = init->depth_pitch;
-
-       dev_priv->texture_offset = init->texture_offset;
-       dev_priv->texture_size = init->texture_size;
-
-       dev_priv->sarea = drm_getsarea(dev);
-       if (!dev_priv->sarea) {
-               DRM_ERROR("could not find sarea!\n");
-               savage_do_cleanup_bci(dev);
-               return -EINVAL;
-       }
-       if (init->status_offset != 0) {
-               dev_priv->status = drm_core_findmap(dev, init->status_offset);
-               if (!dev_priv->status) {
-                       DRM_ERROR("could not find shadow status region!\n");
-                       savage_do_cleanup_bci(dev);
-                       return -EINVAL;
-               }
-       } else {
-               dev_priv->status = NULL;
-       }
-       if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) {
-               dev->agp_buffer_token = init->buffers_offset;
-               dev->agp_buffer_map = drm_core_findmap(dev,
-                                                      init->buffers_offset);
-               if (!dev->agp_buffer_map) {
-                       DRM_ERROR("could not find DMA buffer region!\n");
-                       savage_do_cleanup_bci(dev);
-                       return -EINVAL;
-               }
-               drm_core_ioremap(dev->agp_buffer_map, dev);
-               if (!dev->agp_buffer_map) {
-                       DRM_ERROR("failed to ioremap DMA buffer region!\n");
-                       savage_do_cleanup_bci(dev);
-                       return -ENOMEM;
-               }
-       }
-       if (init->agp_textures_offset) {
-               dev_priv->agp_textures =
-                   drm_core_findmap(dev, init->agp_textures_offset);
-               if (!dev_priv->agp_textures) {
-                       DRM_ERROR("could not find agp texture region!\n");
-                       savage_do_cleanup_bci(dev);
-                       return -EINVAL;
-               }
-       } else {
-               dev_priv->agp_textures = NULL;
-       }
-
-       if (init->cmd_dma_offset) {
-               if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
-                       DRM_ERROR("command DMA not supported on "
-                                 "Savage3D/MX/IX.\n");
-                       savage_do_cleanup_bci(dev);
-                       return -EINVAL;
-               }
-               if (dev->dma && dev->dma->buflist) {
-                       DRM_ERROR("command and vertex DMA not supported "
-                                 "at the same time.\n");
-                       savage_do_cleanup_bci(dev);
-                       return -EINVAL;
-               }
-               dev_priv->cmd_dma = drm_core_findmap(dev, init->cmd_dma_offset);
-               if (!dev_priv->cmd_dma) {
-                       DRM_ERROR("could not find command DMA region!\n");
-                       savage_do_cleanup_bci(dev);
-                       return -EINVAL;
-               }
-               if (dev_priv->dma_type == SAVAGE_DMA_AGP) {
-                       if (dev_priv->cmd_dma->type != _DRM_AGP) {
-                               DRM_ERROR("AGP command DMA region is not a "
-                                         "_DRM_AGP map!\n");
-                               savage_do_cleanup_bci(dev);
-                               return -EINVAL;
-                       }
-                       drm_core_ioremap(dev_priv->cmd_dma, dev);
-                       if (!dev_priv->cmd_dma->handle) {
-                               DRM_ERROR("failed to ioremap command "
-                                         "DMA region!\n");
-                               savage_do_cleanup_bci(dev);
-                               return -ENOMEM;
-                       }
-               } else if (dev_priv->cmd_dma->type != _DRM_CONSISTENT) {
-                       DRM_ERROR("PCI command DMA region is not a "
-                                 "_DRM_CONSISTENT map!\n");
-                       savage_do_cleanup_bci(dev);
-                       return -EINVAL;
-               }
-       } else {
-               dev_priv->cmd_dma = NULL;
-       }
-
-       dev_priv->dma_flush = savage_dma_flush;
-       if (!dev_priv->cmd_dma) {
-               DRM_DEBUG("falling back to faked command DMA.\n");
-               dev_priv->fake_dma.offset = 0;
-               dev_priv->fake_dma.size = SAVAGE_FAKE_DMA_SIZE;
-               dev_priv->fake_dma.type = _DRM_SHM;
-               dev_priv->fake_dma.handle = drm_alloc(SAVAGE_FAKE_DMA_SIZE,
-                                                     DRM_MEM_DRIVER);
-               if (!dev_priv->fake_dma.handle) {
-                       DRM_ERROR("could not allocate faked DMA buffer!\n");
-                       savage_do_cleanup_bci(dev);
-                       return -ENOMEM;
-               }
-               dev_priv->cmd_dma = &dev_priv->fake_dma;
-               dev_priv->dma_flush = savage_fake_dma_flush;
-       }
-
-       dev_priv->sarea_priv =
-           (drm_savage_sarea_t *) ((uint8_t *) dev_priv->sarea->handle +
-                                   init->sarea_priv_offset);
-
-       /* setup bitmap descriptors */
-       {
-               unsigned int color_tile_format;
-               unsigned int depth_tile_format;
-               unsigned int front_stride, back_stride, depth_stride;
-               if (dev_priv->chipset <= S3_SAVAGE4) {
-                       color_tile_format = dev_priv->fb_bpp == 16 ?
-                           SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
-                       depth_tile_format = dev_priv->depth_bpp == 16 ?
-                           SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
-               } else {
-                       color_tile_format = SAVAGE_BD_TILE_DEST;
-                       depth_tile_format = SAVAGE_BD_TILE_DEST;
-               }
-               front_stride = dev_priv->front_pitch / (dev_priv->fb_bpp / 8);
-               back_stride = dev_priv->back_pitch / (dev_priv->fb_bpp / 8);
-               depth_stride =
-                   dev_priv->depth_pitch / (dev_priv->depth_bpp / 8);
-
-               dev_priv->front_bd = front_stride | SAVAGE_BD_BW_DISABLE |
-                   (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
-                   (color_tile_format << SAVAGE_BD_TILE_SHIFT);
-
-               dev_priv->back_bd = back_stride | SAVAGE_BD_BW_DISABLE |
-                   (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
-                   (color_tile_format << SAVAGE_BD_TILE_SHIFT);
-
-               dev_priv->depth_bd = depth_stride | SAVAGE_BD_BW_DISABLE |
-                   (dev_priv->depth_bpp << SAVAGE_BD_BPP_SHIFT) |
-                   (depth_tile_format << SAVAGE_BD_TILE_SHIFT);
-       }
-
-       /* setup status and bci ptr */
-       dev_priv->event_counter = 0;
-       dev_priv->event_wrap = 0;
-       dev_priv->bci_ptr = (volatile uint32_t *)
-           ((uint8_t *) dev_priv->mmio->handle + SAVAGE_BCI_OFFSET);
-       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
-               dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S3D;
-       } else {
-               dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S4;
-       }
-       if (dev_priv->status != NULL) {
-               dev_priv->status_ptr =
-                   (volatile uint32_t *)dev_priv->status->handle;
-               dev_priv->wait_fifo = savage_bci_wait_fifo_shadow;
-               dev_priv->wait_evnt = savage_bci_wait_event_shadow;
-               dev_priv->status_ptr[1023] = dev_priv->event_counter;
-       } else {
-               dev_priv->status_ptr = NULL;
-               if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
-                       dev_priv->wait_fifo = savage_bci_wait_fifo_s3d;
-               } else {
-                       dev_priv->wait_fifo = savage_bci_wait_fifo_s4;
-               }
-               dev_priv->wait_evnt = savage_bci_wait_event_reg;
-       }
-
-       /* cliprect functions */
-       if (S3_SAVAGE3D_SERIES(dev_priv->chipset))
-               dev_priv->emit_clip_rect = savage_emit_clip_rect_s3d;
-       else
-               dev_priv->emit_clip_rect = savage_emit_clip_rect_s4;
-
-       if (savage_freelist_init(dev) < 0) {
-               DRM_ERROR("could not initialize freelist\n");
-               savage_do_cleanup_bci(dev);
-               return -ENOMEM;
-       }
-
-       if (savage_dma_init(dev_priv) < 0) {
-               DRM_ERROR("could not initialize command DMA\n");
-               savage_do_cleanup_bci(dev);
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-static int savage_do_cleanup_bci(struct drm_device * dev)
-{
-       drm_savage_private_t *dev_priv = dev->dev_private;
-
-       if (dev_priv->cmd_dma == &dev_priv->fake_dma) {
-               if (dev_priv->fake_dma.handle)
-                       drm_free(dev_priv->fake_dma.handle,
-                                SAVAGE_FAKE_DMA_SIZE, DRM_MEM_DRIVER);
-       } else if (dev_priv->cmd_dma && dev_priv->cmd_dma->handle &&
-                  dev_priv->cmd_dma->type == _DRM_AGP &&
-                  dev_priv->dma_type == SAVAGE_DMA_AGP)
-               drm_core_ioremapfree(dev_priv->cmd_dma, dev);
-
-       if (dev_priv->dma_type == SAVAGE_DMA_AGP &&
-           dev->agp_buffer_map && dev->agp_buffer_map->handle) {
-               drm_core_ioremapfree(dev->agp_buffer_map, dev);
-               /* make sure the next instance (which may be running
-                * in PCI mode) doesn't try to use an old
-                * agp_buffer_map. */
-               dev->agp_buffer_map = NULL;
-       }
-
-       if (dev_priv->dma_pages)
-               drm_free(dev_priv->dma_pages,
-                        sizeof(drm_savage_dma_page_t) * dev_priv->nr_dma_pages,
-                        DRM_MEM_DRIVER);
-
-       return 0;
-}
-
-static int savage_bci_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_savage_init_t *init = data;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       switch (init->func) {
-       case SAVAGE_INIT_BCI:
-               return savage_do_init_bci(dev, init);
-       case SAVAGE_CLEANUP_BCI:
-               return savage_do_cleanup_bci(dev);
-       }
-
-       return -EINVAL;
-}
-
-static int savage_bci_event_emit(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_savage_private_t *dev_priv = dev->dev_private;
-       drm_savage_event_emit_t *event = data;
-
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       event->count = savage_bci_emit_event(dev_priv, event->flags);
-       event->count |= dev_priv->event_wrap << 16;
-
-       return 0;
-}
-
-static int savage_bci_event_wait(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_savage_private_t *dev_priv = dev->dev_private;
-       drm_savage_event_wait_t *event = data;
-       unsigned int event_e, hw_e;
-       unsigned int event_w, hw_w;
-
-       DRM_DEBUG("\n");
-
-       UPDATE_EVENT_COUNTER();
-       if (dev_priv->status_ptr)
-               hw_e = dev_priv->status_ptr[1] & 0xffff;
-       else
-               hw_e = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
-       hw_w = dev_priv->event_wrap;
-       if (hw_e > dev_priv->event_counter)
-               hw_w--;         /* hardware hasn't passed the last wrap yet */
-
-       event_e = event->count & 0xffff;
-       event_w = event->count >> 16;
-
-       /* Don't need to wait if
-        * - event counter wrapped since the event was emitted or
-        * - the hardware has advanced up to or over the event to wait for.
-        */
-       if (event_w < hw_w || (event_w == hw_w && event_e <= hw_e))
-               return 0;
-       else
-               return dev_priv->wait_evnt(dev_priv, event_e);
-}
-
-/*
- * DMA buffer management
- */
-
-static int savage_bci_get_buffers(struct drm_device *dev,
-                                 struct drm_file *file_priv,
-                                 struct drm_dma *d)
-{
-       struct drm_buf *buf;
-       int i;
-
-       for (i = d->granted_count; i < d->request_count; i++) {
-               buf = savage_freelist_get(dev);
-               if (!buf)
-                       return -EAGAIN;
-
-               buf->file_priv = file_priv;
-
-               if (DRM_COPY_TO_USER(&d->request_indices[i],
-                                    &buf->idx, sizeof(buf->idx)))
-                       return -EFAULT;
-               if (DRM_COPY_TO_USER(&d->request_sizes[i],
-                                    &buf->total, sizeof(buf->total)))
-                       return -EFAULT;
-
-               d->granted_count++;
-       }
-       return 0;
-}
-
-int savage_bci_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_dma *d = data;
-       int ret = 0;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       /* Please don't send us buffers.
-        */
-       if (d->send_count != 0) {
-               DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
-                         DRM_CURRENTPID, d->send_count);
-               return -EINVAL;
-       }
-
-       /* We'll send you buffers.
-        */
-       if (d->request_count < 0 || d->request_count > dma->buf_count) {
-               DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
-                         DRM_CURRENTPID, d->request_count, dma->buf_count);
-               return -EINVAL;
-       }
-
-       d->granted_count = 0;
-
-       if (d->request_count) {
-               ret = savage_bci_get_buffers(dev, file_priv, d);
-       }
-
-       return ret;
-}
-
-void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
-{
-       struct drm_device_dma *dma = dev->dma;
-       drm_savage_private_t *dev_priv = dev->dev_private;
-       int i;
-
-       if (!dma)
-               return;
-       if (!dev_priv)
-               return;
-       if (!dma->buflist)
-               return;
-
-       /*i830_flush_queue(dev); */
-
-       for (i = 0; i < dma->buf_count; i++) {
-               struct drm_buf *buf = dma->buflist[i];
-               drm_savage_buf_priv_t *buf_priv = buf->dev_private;
-
-               if (buf->file_priv == file_priv && buf_priv &&
-                   buf_priv->next == NULL && buf_priv->prev == NULL) {
-                       uint16_t event;
-                       DRM_DEBUG("reclaimed from client\n");
-                       event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D);
-                       SET_AGE(&buf_priv->age, event, dev_priv->event_wrap);
-                       savage_freelist_put(dev, buf);
-               }
-       }
-
-       drm_core_reclaim_buffers(dev, file_priv);
-}
-
-struct drm_ioctl_desc savage_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_INIT, savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_CMDBUF, savage_bci_cmdbuf, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_EVENT_EMIT, savage_bci_event_emit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_EVENT_WAIT, savage_bci_event_wait, DRM_AUTH),
-};
-
-int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls);
diff --git a/drivers/char/drm/savage_drm.h b/drivers/char/drm/savage_drm.h
deleted file mode 100644 (file)
index 8a576ef..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/* savage_drm.h -- Public header for the savage driver
- *
- * Copyright 2004  Felix Kuehling
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __SAVAGE_DRM_H__
-#define __SAVAGE_DRM_H__
-
-#ifndef __SAVAGE_SAREA_DEFINES__
-#define __SAVAGE_SAREA_DEFINES__
-
-/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
- * regions, subject to a minimum region size of (1<<16) == 64k.
- *
- * Clients may subdivide regions internally, but when sharing between
- * clients, the region size is the minimum granularity.
- */
-
-#define SAVAGE_CARD_HEAP               0
-#define SAVAGE_AGP_HEAP                        1
-#define SAVAGE_NR_TEX_HEAPS            2
-#define SAVAGE_NR_TEX_REGIONS          16
-#define SAVAGE_LOG_MIN_TEX_REGION_SIZE 16
-
-#endif                         /* __SAVAGE_SAREA_DEFINES__ */
-
-typedef struct _drm_savage_sarea {
-       /* LRU lists for texture memory in agp space and on the card.
-        */
-       struct drm_tex_region texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS +
-                                                     1];
-       unsigned int texAge[SAVAGE_NR_TEX_HEAPS];
-
-       /* Mechanism to validate card state.
-        */
-       int ctxOwner;
-} drm_savage_sarea_t, *drm_savage_sarea_ptr;
-
-/* Savage-specific ioctls
- */
-#define DRM_SAVAGE_BCI_INIT            0x00
-#define DRM_SAVAGE_BCI_CMDBUF           0x01
-#define DRM_SAVAGE_BCI_EVENT_EMIT      0x02
-#define DRM_SAVAGE_BCI_EVENT_WAIT      0x03
-
-#define DRM_IOCTL_SAVAGE_INIT          DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t)
-#define DRM_IOCTL_SAVAGE_CMDBUF                DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t)
-#define DRM_IOCTL_SAVAGE_EVENT_EMIT    DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t)
-#define DRM_IOCTL_SAVAGE_EVENT_WAIT    DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t)
-
-#define SAVAGE_DMA_PCI 1
-#define SAVAGE_DMA_AGP 3
-typedef struct drm_savage_init {
-       enum {
-               SAVAGE_INIT_BCI = 1,
-               SAVAGE_CLEANUP_BCI = 2
-       } func;
-       unsigned int sarea_priv_offset;
-
-       /* some parameters */
-       unsigned int cob_size;
-       unsigned int bci_threshold_lo, bci_threshold_hi;
-       unsigned int dma_type;
-
-       /* frame buffer layout */
-       unsigned int fb_bpp;
-       unsigned int front_offset, front_pitch;
-       unsigned int back_offset, back_pitch;
-       unsigned int depth_bpp;
-       unsigned int depth_offset, depth_pitch;
-
-       /* local textures */
-       unsigned int texture_offset;
-       unsigned int texture_size;
-
-       /* physical locations of non-permanent maps */
-       unsigned long status_offset;
-       unsigned long buffers_offset;
-       unsigned long agp_textures_offset;
-       unsigned long cmd_dma_offset;
-} drm_savage_init_t;
-
-typedef union drm_savage_cmd_header drm_savage_cmd_header_t;
-typedef struct drm_savage_cmdbuf {
-       /* command buffer in client's address space */
-       drm_savage_cmd_header_t __user *cmd_addr;
-       unsigned int size;      /* size of the command buffer in 64bit units */
-
-       unsigned int dma_idx;   /* DMA buffer index to use */
-       int discard;            /* discard DMA buffer when done */
-       /* vertex buffer in client's address space */
-       unsigned int __user *vb_addr;
-       unsigned int vb_size;   /* size of client vertex buffer in bytes */
-       unsigned int vb_stride; /* stride of vertices in 32bit words */
-       /* boxes in client's address space */
-       struct drm_clip_rect __user *box_addr;
-       unsigned int nbox;      /* number of clipping boxes */
-} drm_savage_cmdbuf_t;
-
-#define SAVAGE_WAIT_2D  0x1    /* wait for 2D idle before updating event tag */
-#define SAVAGE_WAIT_3D  0x2    /* wait for 3D idle before updating event tag */
-#define SAVAGE_WAIT_IRQ 0x4    /* emit or wait for IRQ, not implemented yet */
-typedef struct drm_savage_event {
-       unsigned int count;
-       unsigned int flags;
-} drm_savage_event_emit_t, drm_savage_event_wait_t;
-
-/* Commands for the cmdbuf ioctl
- */
-#define SAVAGE_CMD_STATE       0       /* a range of state registers */
-#define SAVAGE_CMD_DMA_PRIM    1       /* vertices from DMA buffer */
-#define SAVAGE_CMD_VB_PRIM     2       /* vertices from client vertex buffer */
-#define SAVAGE_CMD_DMA_IDX     3       /* indexed vertices from DMA buffer */
-#define SAVAGE_CMD_VB_IDX      4       /* indexed vertices client vertex buffer */
-#define SAVAGE_CMD_CLEAR       5       /* clear buffers */
-#define SAVAGE_CMD_SWAP                6       /* swap buffers */
-
-/* Primitive types
-*/
-#define SAVAGE_PRIM_TRILIST    0       /* triangle list */
-#define SAVAGE_PRIM_TRISTRIP   1       /* triangle strip */
-#define SAVAGE_PRIM_TRIFAN     2       /* triangle fan */
-#define SAVAGE_PRIM_TRILIST_201        3       /* reorder verts for correct flat
-                                        * shading on s3d */
-
-/* Skip flags (vertex format)
- */
-#define SAVAGE_SKIP_Z          0x01
-#define SAVAGE_SKIP_W          0x02
-#define SAVAGE_SKIP_C0         0x04
-#define SAVAGE_SKIP_C1         0x08
-#define SAVAGE_SKIP_S0         0x10
-#define SAVAGE_SKIP_T0         0x20
-#define SAVAGE_SKIP_ST0                0x30
-#define SAVAGE_SKIP_S1         0x40
-#define SAVAGE_SKIP_T1         0x80
-#define SAVAGE_SKIP_ST1                0xc0
-#define SAVAGE_SKIP_ALL_S3D    0x3f
-#define SAVAGE_SKIP_ALL_S4     0xff
-
-/* Buffer names for clear command
- */
-#define SAVAGE_FRONT           0x1
-#define SAVAGE_BACK            0x2
-#define SAVAGE_DEPTH           0x4
-
-/* 64-bit command header
- */
-union drm_savage_cmd_header {
-       struct {
-               unsigned char cmd;      /* command */
-               unsigned char pad0;
-               unsigned short pad1;
-               unsigned short pad2;
-               unsigned short pad3;
-       } cmd;                  /* generic */
-       struct {
-               unsigned char cmd;
-               unsigned char global;   /* need idle engine? */
-               unsigned short count;   /* number of consecutive registers */
-               unsigned short start;   /* first register */
-               unsigned short pad3;
-       } state;                /* SAVAGE_CMD_STATE */
-       struct {
-               unsigned char cmd;
-               unsigned char prim;     /* primitive type */
-               unsigned short skip;    /* vertex format (skip flags) */
-               unsigned short count;   /* number of vertices */
-               unsigned short start;   /* first vertex in DMA/vertex buffer */
-       } prim;                 /* SAVAGE_CMD_DMA_PRIM, SAVAGE_CMD_VB_PRIM */
-       struct {
-               unsigned char cmd;
-               unsigned char prim;
-               unsigned short skip;
-               unsigned short count;   /* number of indices that follow */
-               unsigned short pad3;
-       } idx;                  /* SAVAGE_CMD_DMA_IDX, SAVAGE_CMD_VB_IDX */
-       struct {
-               unsigned char cmd;
-               unsigned char pad0;
-               unsigned short pad1;
-               unsigned int flags;
-       } clear0;               /* SAVAGE_CMD_CLEAR */
-       struct {
-               unsigned int mask;
-               unsigned int value;
-       } clear1;               /* SAVAGE_CMD_CLEAR data */
-};
-
-#endif
diff --git a/drivers/char/drm/savage_drv.c b/drivers/char/drm/savage_drv.c
deleted file mode 100644 (file)
index eee52aa..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/* savage_drv.c -- Savage driver for Linux
- *
- * Copyright 2004  Felix Kuehling
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "savage_drm.h"
-#include "savage_drv.h"
-
-#include "drm_pciids.h"
-
-static struct pci_device_id pciidlist[] = {
-       savage_PCI_IDS
-};
-
-static struct drm_driver driver = {
-       .driver_features =
-           DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_PCI_DMA,
-       .dev_priv_size = sizeof(drm_savage_buf_priv_t),
-       .load = savage_driver_load,
-       .firstopen = savage_driver_firstopen,
-       .lastclose = savage_driver_lastclose,
-       .unload = savage_driver_unload,
-       .reclaim_buffers = savage_reclaim_buffers,
-       .get_map_ofs = drm_core_get_map_ofs,
-       .get_reg_ofs = drm_core_get_reg_ofs,
-       .ioctls = savage_ioctls,
-       .dma_ioctl = savage_bci_buffers,
-       .fops = {
-                .owner = THIS_MODULE,
-                .open = drm_open,
-                .release = drm_release,
-                .ioctl = drm_ioctl,
-                .mmap = drm_mmap,
-                .poll = drm_poll,
-                .fasync = drm_fasync,
-       },
-
-       .pci_driver = {
-                .name = DRIVER_NAME,
-                .id_table = pciidlist,
-       },
-
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int __init savage_init(void)
-{
-       driver.num_ioctls = savage_max_ioctl;
-       return drm_init(&driver);
-}
-
-static void __exit savage_exit(void)
-{
-       drm_exit(&driver);
-}
-
-module_init(savage_init);
-module_exit(savage_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h
deleted file mode 100644 (file)
index df2aac6..0000000
+++ /dev/null
@@ -1,575 +0,0 @@
-/* savage_drv.h -- Private header for the savage driver */
-/*
- * Copyright 2004  Felix Kuehling
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __SAVAGE_DRV_H__
-#define __SAVAGE_DRV_H__
-
-#define DRIVER_AUTHOR  "Felix Kuehling"
-
-#define DRIVER_NAME    "savage"
-#define DRIVER_DESC    "Savage3D/MX/IX, Savage4, SuperSavage, Twister, ProSavage[DDR]"
-#define DRIVER_DATE    "20050313"
-
-#define DRIVER_MAJOR           2
-#define DRIVER_MINOR           4
-#define DRIVER_PATCHLEVEL      1
-/* Interface history:
- *
- * 1.x   The DRM driver from the VIA/S3 code drop, basically a dummy
- * 2.0   The first real DRM
- * 2.1   Scissors registers managed by the DRM, 3D operations clipped by
- *       cliprects of the cmdbuf ioctl
- * 2.2   Implemented SAVAGE_CMD_DMA_IDX and SAVAGE_CMD_VB_IDX
- * 2.3   Event counters used by BCI_EVENT_EMIT/WAIT ioctls are now 32 bits
- *       wide and thus very long lived (unlikely to ever wrap). The size
- *       in the struct was 32 bits before, but only 16 bits were used
- * 2.4   Implemented command DMA. Now drm_savage_init_t.cmd_dma_offset is
- *       actually used
- */
-
-typedef struct drm_savage_age {
-       uint16_t event;
-       unsigned int wrap;
-} drm_savage_age_t;
-
-typedef struct drm_savage_buf_priv {
-       struct drm_savage_buf_priv *next;
-       struct drm_savage_buf_priv *prev;
-       drm_savage_age_t age;
-       struct drm_buf *buf;
-} drm_savage_buf_priv_t;
-
-typedef struct drm_savage_dma_page {
-       drm_savage_age_t age;
-       unsigned int used, flushed;
-} drm_savage_dma_page_t;
-#define SAVAGE_DMA_PAGE_SIZE 1024      /* in dwords */
-/* Fake DMA buffer size in bytes. 4 pages. Allows a maximum command
- * size of 16kbytes or 4k entries. Minimum requirement would be
- * 10kbytes for 255 40-byte vertices in one drawing command. */
-#define SAVAGE_FAKE_DMA_SIZE (SAVAGE_DMA_PAGE_SIZE*4*4)
-
-/* interesting bits of hardware state that are saved in dev_priv */
-typedef union {
-       struct drm_savage_common_state {
-               uint32_t vbaddr;
-       } common;
-       struct {
-               unsigned char pad[sizeof(struct drm_savage_common_state)];
-               uint32_t texctrl, texaddr;
-               uint32_t scstart, new_scstart;
-               uint32_t scend, new_scend;
-       } s3d;
-       struct {
-               unsigned char pad[sizeof(struct drm_savage_common_state)];
-               uint32_t texdescr, texaddr0, texaddr1;
-               uint32_t drawctrl0, new_drawctrl0;
-               uint32_t drawctrl1, new_drawctrl1;
-       } s4;
-} drm_savage_state_t;
-
-/* these chip tags should match the ones in the 2D driver in savage_regs.h. */
-enum savage_family {
-       S3_UNKNOWN = 0,
-       S3_SAVAGE3D,
-       S3_SAVAGE_MX,
-       S3_SAVAGE4,
-       S3_PROSAVAGE,
-       S3_TWISTER,
-       S3_PROSAVAGEDDR,
-       S3_SUPERSAVAGE,
-       S3_SAVAGE2000,
-       S3_LAST
-};
-
-extern struct drm_ioctl_desc savage_ioctls[];
-extern int savage_max_ioctl;
-
-#define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
-
-#define S3_SAVAGE4_SERIES(chip)  ((chip==S3_SAVAGE4)            \
-                                  || (chip==S3_PROSAVAGE)       \
-                                  || (chip==S3_TWISTER)         \
-                                  || (chip==S3_PROSAVAGEDDR))
-
-#define        S3_SAVAGE_MOBILE_SERIES(chip)   ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
-
-#define S3_SAVAGE_SERIES(chip)    ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
-
-#define S3_MOBILE_TWISTER_SERIES(chip)   ((chip==S3_TWISTER)    \
-                                          ||(chip==S3_PROSAVAGEDDR))
-
-/* flags */
-#define SAVAGE_IS_AGP 1
-
-typedef struct drm_savage_private {
-       drm_savage_sarea_t *sarea_priv;
-
-       drm_savage_buf_priv_t head, tail;
-
-       /* who am I? */
-       enum savage_family chipset;
-
-       unsigned int cob_size;
-       unsigned int bci_threshold_lo, bci_threshold_hi;
-       unsigned int dma_type;
-
-       /* frame buffer layout */
-       unsigned int fb_bpp;
-       unsigned int front_offset, front_pitch;
-       unsigned int back_offset, back_pitch;
-       unsigned int depth_bpp;
-       unsigned int depth_offset, depth_pitch;
-
-       /* bitmap descriptors for swap and clear */
-       unsigned int front_bd, back_bd, depth_bd;
-
-       /* local textures */
-       unsigned int texture_offset;
-       unsigned int texture_size;
-
-       /* memory regions in physical memory */
-       drm_local_map_t *sarea;
-       drm_local_map_t *mmio;
-       drm_local_map_t *fb;
-       drm_local_map_t *aperture;
-       drm_local_map_t *status;
-       drm_local_map_t *agp_textures;
-       drm_local_map_t *cmd_dma;
-       drm_local_map_t fake_dma;
-
-       struct {
-               int handle;
-               unsigned long base, size;
-       } mtrr[3];
-
-       /* BCI and status-related stuff */
-       volatile uint32_t *status_ptr, *bci_ptr;
-       uint32_t status_used_mask;
-       uint16_t event_counter;
-       unsigned int event_wrap;
-
-       /* Savage4 command DMA */
-       drm_savage_dma_page_t *dma_pages;
-       unsigned int nr_dma_pages, first_dma_page, current_dma_page;
-       drm_savage_age_t last_dma_age;
-
-       /* saved hw state for global/local check on S3D */
-       uint32_t hw_draw_ctrl, hw_zbuf_ctrl;
-       /* and for scissors (global, so don't emit if not changed) */
-       uint32_t hw_scissors_start, hw_scissors_end;
-
-       drm_savage_state_t state;
-
-       /* after emitting a wait cmd Savage3D needs 63 nops before next DMA */
-       unsigned int waiting;
-
-       /* config/hardware-dependent function pointers */
-       int (*wait_fifo) (struct drm_savage_private * dev_priv, unsigned int n);
-       int (*wait_evnt) (struct drm_savage_private * dev_priv, uint16_t e);
-       /* Err, there is a macro wait_event in include/linux/wait.h.
-        * Avoid unwanted macro expansion. */
-       void (*emit_clip_rect) (struct drm_savage_private * dev_priv,
-                               const struct drm_clip_rect * pbox);
-       void (*dma_flush) (struct drm_savage_private * dev_priv);
-} drm_savage_private_t;
-
-/* ioctls */
-extern int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int savage_bci_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
-
-/* BCI functions */
-extern uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv,
-                                     unsigned int flags);
-extern void savage_freelist_put(struct drm_device * dev, struct drm_buf * buf);
-extern void savage_dma_reset(drm_savage_private_t * dev_priv);
-extern void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page);
-extern uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv,
-                                 unsigned int n);
-extern int savage_driver_load(struct drm_device *dev, unsigned long chipset);
-extern int savage_driver_firstopen(struct drm_device *dev);
-extern void savage_driver_lastclose(struct drm_device *dev);
-extern int savage_driver_unload(struct drm_device *dev);
-extern void savage_reclaim_buffers(struct drm_device *dev,
-                                  struct drm_file *file_priv);
-
-/* state functions */
-extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
-                                     const struct drm_clip_rect * pbox);
-extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
-                                    const struct drm_clip_rect * pbox);
-
-#define SAVAGE_FB_SIZE_S3      0x01000000      /*  16MB */
-#define SAVAGE_FB_SIZE_S4      0x02000000      /*  32MB */
-#define SAVAGE_MMIO_SIZE        0x00080000     /* 512kB */
-#define SAVAGE_APERTURE_OFFSET  0x02000000     /*  32MB */
-#define SAVAGE_APERTURE_SIZE    0x05000000     /* 5 tiled surfaces, 16MB each */
-
-#define SAVAGE_BCI_OFFSET       0x00010000     /* offset of the BCI region
-                                                * inside the MMIO region */
-#define SAVAGE_BCI_FIFO_SIZE   32      /* number of entries in on-chip
-                                        * BCI FIFO */
-
-/*
- * MMIO registers
- */
-#define SAVAGE_STATUS_WORD0            0x48C00
-#define SAVAGE_STATUS_WORD1            0x48C04
-#define SAVAGE_ALT_STATUS_WORD0        0x48C60
-
-#define SAVAGE_FIFO_USED_MASK_S3D      0x0001ffff
-#define SAVAGE_FIFO_USED_MASK_S4       0x001fffff
-
-/* Copied from savage_bci.h in the 2D driver with some renaming. */
-
-/* Bitmap descriptors */
-#define SAVAGE_BD_STRIDE_SHIFT 0
-#define SAVAGE_BD_BPP_SHIFT   16
-#define SAVAGE_BD_TILE_SHIFT  24
-#define SAVAGE_BD_BW_DISABLE  (1<<28)
-/* common: */
-#define        SAVAGE_BD_TILE_LINEAR           0
-/* savage4, MX, IX, 3D */
-#define        SAVAGE_BD_TILE_16BPP            2
-#define        SAVAGE_BD_TILE_32BPP            3
-/* twister, prosavage, DDR, supersavage, 2000 */
-#define        SAVAGE_BD_TILE_DEST             1
-#define        SAVAGE_BD_TILE_TEXTURE          2
-/* GBD - BCI enable */
-/* savage4, MX, IX, 3D */
-#define SAVAGE_GBD_BCI_ENABLE                    8
-/* twister, prosavage, DDR, supersavage, 2000 */
-#define SAVAGE_GBD_BCI_ENABLE_TWISTER            0
-
-#define SAVAGE_GBD_BIG_ENDIAN                    4
-#define SAVAGE_GBD_LITTLE_ENDIAN                 0
-#define SAVAGE_GBD_64                            1
-
-/*  Global Bitmap Descriptor */
-#define SAVAGE_BCI_GLB_BD_LOW             0x8168
-#define SAVAGE_BCI_GLB_BD_HIGH            0x816C
-
-/*
- * BCI registers
- */
-/* Savage4/Twister/ProSavage 3D registers */
-#define SAVAGE_DRAWLOCALCTRL_S4                0x1e
-#define SAVAGE_TEXPALADDR_S4           0x1f
-#define SAVAGE_TEXCTRL0_S4             0x20
-#define SAVAGE_TEXCTRL1_S4             0x21
-#define SAVAGE_TEXADDR0_S4             0x22
-#define SAVAGE_TEXADDR1_S4             0x23
-#define SAVAGE_TEXBLEND0_S4            0x24
-#define SAVAGE_TEXBLEND1_S4            0x25
-#define SAVAGE_TEXXPRCLR_S4            0x26    /* never used */
-#define SAVAGE_TEXDESCR_S4             0x27
-#define SAVAGE_FOGTABLE_S4             0x28
-#define SAVAGE_FOGCTRL_S4              0x30
-#define SAVAGE_STENCILCTRL_S4          0x31
-#define SAVAGE_ZBUFCTRL_S4             0x32
-#define SAVAGE_ZBUFOFF_S4              0x33
-#define SAVAGE_DESTCTRL_S4             0x34
-#define SAVAGE_DRAWCTRL0_S4            0x35
-#define SAVAGE_DRAWCTRL1_S4            0x36
-#define SAVAGE_ZWATERMARK_S4           0x37
-#define SAVAGE_DESTTEXRWWATERMARK_S4   0x38
-#define SAVAGE_TEXBLENDCOLOR_S4                0x39
-/* Savage3D/MX/IX 3D registers */
-#define SAVAGE_TEXPALADDR_S3D          0x18
-#define SAVAGE_TEXXPRCLR_S3D           0x19    /* never used */
-#define SAVAGE_TEXADDR_S3D             0x1A
-#define SAVAGE_TEXDESCR_S3D            0x1B
-#define SAVAGE_TEXCTRL_S3D             0x1C
-#define SAVAGE_FOGTABLE_S3D            0x20
-#define SAVAGE_FOGCTRL_S3D             0x30
-#define SAVAGE_DRAWCTRL_S3D            0x31
-#define SAVAGE_ZBUFCTRL_S3D            0x32
-#define SAVAGE_ZBUFOFF_S3D             0x33
-#define SAVAGE_DESTCTRL_S3D            0x34
-#define SAVAGE_SCSTART_S3D             0x35
-#define SAVAGE_SCEND_S3D               0x36
-#define SAVAGE_ZWATERMARK_S3D          0x37
-#define SAVAGE_DESTTEXRWWATERMARK_S3D  0x38
-/* common stuff */
-#define SAVAGE_VERTBUFADDR             0x3e
-#define SAVAGE_BITPLANEWTMASK          0xd7
-#define SAVAGE_DMABUFADDR              0x51
-
-/* texture enable bits (needed for tex addr checking) */
-#define SAVAGE_TEXCTRL_TEXEN_MASK      0x00010000      /* S3D */
-#define SAVAGE_TEXDESCR_TEX0EN_MASK    0x02000000      /* S4 */
-#define SAVAGE_TEXDESCR_TEX1EN_MASK    0x04000000      /* S4 */
-
-/* Global fields in Savage4/Twister/ProSavage 3D registers:
- *
- * All texture registers and DrawLocalCtrl are local. All other
- * registers are global. */
-
-/* Global fields in Savage3D/MX/IX 3D registers:
- *
- * All texture registers are local. DrawCtrl and ZBufCtrl are
- * partially local. All other registers are global.
- *
- * DrawCtrl global fields: cullMode, alphaTestCmpFunc, alphaTestEn, alphaRefVal
- * ZBufCtrl global fields: zCmpFunc, zBufEn
- */
-#define SAVAGE_DRAWCTRL_S3D_GLOBAL     0x03f3c00c
-#define SAVAGE_ZBUFCTRL_S3D_GLOBAL     0x00000027
-
-/* Masks for scissor bits (drawCtrl[01] on s4, scissorStart/End on s3d)
- */
-#define SAVAGE_SCISSOR_MASK_S4         0x00fff7ff
-#define SAVAGE_SCISSOR_MASK_S3D                0x07ff07ff
-
-/*
- * BCI commands
- */
-#define BCI_CMD_NOP                  0x40000000
-#define BCI_CMD_RECT                 0x48000000
-#define BCI_CMD_RECT_XP              0x01000000
-#define BCI_CMD_RECT_YP              0x02000000
-#define BCI_CMD_SCANLINE             0x50000000
-#define BCI_CMD_LINE                 0x5C000000
-#define BCI_CMD_LINE_LAST_PIXEL      0x58000000
-#define BCI_CMD_BYTE_TEXT            0x63000000
-#define BCI_CMD_NT_BYTE_TEXT         0x67000000
-#define BCI_CMD_BIT_TEXT             0x6C000000
-#define BCI_CMD_GET_ROP(cmd)         (((cmd) >> 16) & 0xFF)
-#define BCI_CMD_SET_ROP(cmd, rop)    ((cmd) |= ((rop & 0xFF) << 16))
-#define BCI_CMD_SEND_COLOR           0x00008000
-
-#define BCI_CMD_CLIP_NONE            0x00000000
-#define BCI_CMD_CLIP_CURRENT         0x00002000
-#define BCI_CMD_CLIP_LR              0x00004000
-#define BCI_CMD_CLIP_NEW             0x00006000
-
-#define BCI_CMD_DEST_GBD             0x00000000
-#define BCI_CMD_DEST_PBD             0x00000800
-#define BCI_CMD_DEST_PBD_NEW         0x00000C00
-#define BCI_CMD_DEST_SBD             0x00001000
-#define BCI_CMD_DEST_SBD_NEW         0x00001400
-
-#define BCI_CMD_SRC_TRANSPARENT      0x00000200
-#define BCI_CMD_SRC_SOLID            0x00000000
-#define BCI_CMD_SRC_GBD              0x00000020
-#define BCI_CMD_SRC_COLOR            0x00000040
-#define BCI_CMD_SRC_MONO             0x00000060
-#define BCI_CMD_SRC_PBD_COLOR        0x00000080
-#define BCI_CMD_SRC_PBD_MONO         0x000000A0
-#define BCI_CMD_SRC_PBD_COLOR_NEW    0x000000C0
-#define BCI_CMD_SRC_PBD_MONO_NEW     0x000000E0
-#define BCI_CMD_SRC_SBD_COLOR        0x00000100
-#define BCI_CMD_SRC_SBD_MONO         0x00000120
-#define BCI_CMD_SRC_SBD_COLOR_NEW    0x00000140
-#define BCI_CMD_SRC_SBD_MONO_NEW     0x00000160
-
-#define BCI_CMD_PAT_TRANSPARENT      0x00000010
-#define BCI_CMD_PAT_NONE             0x00000000
-#define BCI_CMD_PAT_COLOR            0x00000002
-#define BCI_CMD_PAT_MONO             0x00000003
-#define BCI_CMD_PAT_PBD_COLOR        0x00000004
-#define BCI_CMD_PAT_PBD_MONO         0x00000005
-#define BCI_CMD_PAT_PBD_COLOR_NEW    0x00000006
-#define BCI_CMD_PAT_PBD_MONO_NEW     0x00000007
-#define BCI_CMD_PAT_SBD_COLOR        0x00000008
-#define BCI_CMD_PAT_SBD_MONO         0x00000009
-#define BCI_CMD_PAT_SBD_COLOR_NEW    0x0000000A
-#define BCI_CMD_PAT_SBD_MONO_NEW     0x0000000B
-
-#define BCI_BD_BW_DISABLE            0x10000000
-#define BCI_BD_TILE_MASK             0x03000000
-#define BCI_BD_TILE_NONE             0x00000000
-#define BCI_BD_TILE_16               0x02000000
-#define BCI_BD_TILE_32               0x03000000
-#define BCI_BD_GET_BPP(bd)           (((bd) >> 16) & 0xFF)
-#define BCI_BD_SET_BPP(bd, bpp)      ((bd) |= (((bpp) & 0xFF) << 16))
-#define BCI_BD_GET_STRIDE(bd)        ((bd) & 0xFFFF)
-#define BCI_BD_SET_STRIDE(bd, st)    ((bd) |= ((st) & 0xFFFF))
-
-#define BCI_CMD_SET_REGISTER            0x96000000
-
-#define BCI_CMD_WAIT                    0xC0000000
-#define BCI_CMD_WAIT_3D                 0x00010000
-#define BCI_CMD_WAIT_2D                 0x00020000
-
-#define BCI_CMD_UPDATE_EVENT_TAG        0x98000000
-
-#define BCI_CMD_DRAW_PRIM               0x80000000
-#define BCI_CMD_DRAW_INDEXED_PRIM       0x88000000
-#define BCI_CMD_DRAW_CONT               0x01000000
-#define BCI_CMD_DRAW_TRILIST            0x00000000
-#define BCI_CMD_DRAW_TRISTRIP           0x02000000
-#define BCI_CMD_DRAW_TRIFAN             0x04000000
-#define BCI_CMD_DRAW_SKIPFLAGS          0x000000ff
-#define BCI_CMD_DRAW_NO_Z              0x00000001
-#define BCI_CMD_DRAW_NO_W              0x00000002
-#define BCI_CMD_DRAW_NO_CD             0x00000004
-#define BCI_CMD_DRAW_NO_CS             0x00000008
-#define BCI_CMD_DRAW_NO_U0             0x00000010
-#define BCI_CMD_DRAW_NO_V0             0x00000020
-#define BCI_CMD_DRAW_NO_UV0            0x00000030
-#define BCI_CMD_DRAW_NO_U1             0x00000040
-#define BCI_CMD_DRAW_NO_V1             0x00000080
-#define BCI_CMD_DRAW_NO_UV1            0x000000c0
-
-#define BCI_CMD_DMA                    0xa8000000
-
-#define BCI_W_H(w, h)                ((((h) << 16) | (w)) & 0x0FFF0FFF)
-#define BCI_X_Y(x, y)                ((((y) << 16) | (x)) & 0x0FFF0FFF)
-#define BCI_X_W(x, y)                ((((w) << 16) | (x)) & 0x0FFF0FFF)
-#define BCI_CLIP_LR(l, r)            ((((r) << 16) | (l)) & 0x0FFF0FFF)
-#define BCI_CLIP_TL(t, l)            ((((t) << 16) | (l)) & 0x0FFF0FFF)
-#define BCI_CLIP_BR(b, r)            ((((b) << 16) | (r)) & 0x0FFF0FFF)
-
-#define BCI_LINE_X_Y(x, y)           (((y) << 16) | ((x) & 0xFFFF))
-#define BCI_LINE_STEPS(diag, axi)    (((axi) << 16) | ((diag) & 0xFFFF))
-#define BCI_LINE_MISC(maj, ym, xp, yp, err) \
-       (((maj) & 0x1FFF) | \
-       ((ym) ? 1<<13 : 0) | \
-       ((xp) ? 1<<14 : 0) | \
-       ((yp) ? 1<<15 : 0) | \
-       ((err) << 16))
-
-/*
- * common commands
- */
-#define BCI_SET_REGISTERS( first, n )                  \
-       BCI_WRITE(BCI_CMD_SET_REGISTER |                \
-                 ((uint32_t)(n) & 0xff) << 16 |        \
-                 ((uint32_t)(first) & 0xffff))
-#define DMA_SET_REGISTERS( first, n )                  \
-       DMA_WRITE(BCI_CMD_SET_REGISTER |                \
-                 ((uint32_t)(n) & 0xff) << 16 |        \
-                 ((uint32_t)(first) & 0xffff))
-
-#define BCI_DRAW_PRIMITIVE(n, type, skip)         \
-        BCI_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \
-                 ((n) << 16))
-#define DMA_DRAW_PRIMITIVE(n, type, skip)         \
-        DMA_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \
-                 ((n) << 16))
-
-#define BCI_DRAW_INDICES_S3D(n, type, i0)         \
-        BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) |  \
-                 ((n) << 16) | (i0))
-
-#define BCI_DRAW_INDICES_S4(n, type, skip)        \
-        BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) |  \
-                  (skip) | ((n) << 16))
-
-#define BCI_DMA(n)     \
-       BCI_WRITE(BCI_CMD_DMA | (((n) >> 1) - 1))
-
-/*
- * access to MMIO
- */
-#define SAVAGE_READ(reg)       DRM_READ32(  dev_priv->mmio, (reg) )
-#define SAVAGE_WRITE(reg)      DRM_WRITE32( dev_priv->mmio, (reg) )
-
-/*
- * access to the burst command interface (BCI)
- */
-#define SAVAGE_BCI_DEBUG 1
-
-#define BCI_LOCALS    volatile uint32_t *bci_ptr;
-
-#define BEGIN_BCI( n ) do {                    \
-       dev_priv->wait_fifo(dev_priv, (n));     \
-       bci_ptr = dev_priv->bci_ptr;            \
-} while(0)
-
-#define BCI_WRITE( val ) *bci_ptr++ = (uint32_t)(val)
-
-/*
- * command DMA support
- */
-#define SAVAGE_DMA_DEBUG 1
-
-#define DMA_LOCALS   uint32_t *dma_ptr;
-
-#define BEGIN_DMA( n ) do {                                            \
-       unsigned int cur = dev_priv->current_dma_page;                  \
-       unsigned int rest = SAVAGE_DMA_PAGE_SIZE -                      \
-               dev_priv->dma_pages[cur].used;                          \
-       if ((n) > rest) {                                               \
-               dma_ptr = savage_dma_alloc(dev_priv, (n));              \
-       } else { /* fast path for small allocations */                  \
-               dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +       \
-                       cur * SAVAGE_DMA_PAGE_SIZE +                    \
-                       dev_priv->dma_pages[cur].used;                  \
-               if (dev_priv->dma_pages[cur].used == 0)                 \
-                       savage_dma_wait(dev_priv, cur);                 \
-               dev_priv->dma_pages[cur].used += (n);                   \
-       }                                                               \
-} while(0)
-
-#define DMA_WRITE( val ) *dma_ptr++ = (uint32_t)(val)
-
-#define DMA_COPY(src, n) do {                                  \
-       memcpy(dma_ptr, (src), (n)*4);                          \
-       dma_ptr += n;                                           \
-} while(0)
-
-#if SAVAGE_DMA_DEBUG
-#define DMA_COMMIT() do {                                              \
-       unsigned int cur = dev_priv->current_dma_page;                  \
-       uint32_t *expected = (uint32_t *)dev_priv->cmd_dma->handle +    \
-                       cur * SAVAGE_DMA_PAGE_SIZE +                    \
-                       dev_priv->dma_pages[cur].used;                  \
-       if (dma_ptr != expected) {                                      \
-               DRM_ERROR("DMA allocation and use don't match: "        \
-                         "%p != %p\n", expected, dma_ptr);             \
-               savage_dma_reset(dev_priv);                             \
-       }                                                               \
-} while(0)
-#else
-#define DMA_COMMIT() do {/* nothing */} while(0)
-#endif
-
-#define DMA_FLUSH() dev_priv->dma_flush(dev_priv)
-
-/* Buffer aging via event tag
- */
-
-#define UPDATE_EVENT_COUNTER( ) do {                   \
-       if (dev_priv->status_ptr) {                     \
-               uint16_t count;                         \
-               /* coordinate with Xserver */           \
-               count = dev_priv->status_ptr[1023];     \
-               if (count < dev_priv->event_counter)    \
-                       dev_priv->event_wrap++;         \
-               dev_priv->event_counter = count;        \
-       }                                               \
-} while(0)
-
-#define SET_AGE( age, e, w ) do {      \
-       (age)->event = e;               \
-       (age)->wrap = w;                \
-} while(0)
-
-#define TEST_AGE( age, e, w )                          \
-       ( (age)->wrap < (w) || ( (age)->wrap == (w) && (age)->event <= (e) ) )
-
-#endif                         /* __SAVAGE_DRV_H__ */
diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c
deleted file mode 100644 (file)
index 5f6238f..0000000
+++ /dev/null
@@ -1,1163 +0,0 @@
-/* savage_state.c -- State and drawing support for Savage
- *
- * Copyright 2004  Felix Kuehling
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-#include "drmP.h"
-#include "savage_drm.h"
-#include "savage_drv.h"
-
-void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
-                              const struct drm_clip_rect * pbox)
-{
-       uint32_t scstart = dev_priv->state.s3d.new_scstart;
-       uint32_t scend = dev_priv->state.s3d.new_scend;
-       scstart = (scstart & ~SAVAGE_SCISSOR_MASK_S3D) |
-           ((uint32_t) pbox->x1 & 0x000007ff) |
-           (((uint32_t) pbox->y1 << 16) & 0x07ff0000);
-       scend = (scend & ~SAVAGE_SCISSOR_MASK_S3D) |
-           (((uint32_t) pbox->x2 - 1) & 0x000007ff) |
-           ((((uint32_t) pbox->y2 - 1) << 16) & 0x07ff0000);
-       if (scstart != dev_priv->state.s3d.scstart ||
-           scend != dev_priv->state.s3d.scend) {
-               DMA_LOCALS;
-               BEGIN_DMA(4);
-               DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
-               DMA_SET_REGISTERS(SAVAGE_SCSTART_S3D, 2);
-               DMA_WRITE(scstart);
-               DMA_WRITE(scend);
-               dev_priv->state.s3d.scstart = scstart;
-               dev_priv->state.s3d.scend = scend;
-               dev_priv->waiting = 1;
-               DMA_COMMIT();
-       }
-}
-
-void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
-                             const struct drm_clip_rect * pbox)
-{
-       uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;
-       uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;
-       drawctrl0 = (drawctrl0 & ~SAVAGE_SCISSOR_MASK_S4) |
-           ((uint32_t) pbox->x1 & 0x000007ff) |
-           (((uint32_t) pbox->y1 << 12) & 0x00fff000);
-       drawctrl1 = (drawctrl1 & ~SAVAGE_SCISSOR_MASK_S4) |
-           (((uint32_t) pbox->x2 - 1) & 0x000007ff) |
-           ((((uint32_t) pbox->y2 - 1) << 12) & 0x00fff000);
-       if (drawctrl0 != dev_priv->state.s4.drawctrl0 ||
-           drawctrl1 != dev_priv->state.s4.drawctrl1) {
-               DMA_LOCALS;
-               BEGIN_DMA(4);
-               DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
-               DMA_SET_REGISTERS(SAVAGE_DRAWCTRL0_S4, 2);
-               DMA_WRITE(drawctrl0);
-               DMA_WRITE(drawctrl1);
-               dev_priv->state.s4.drawctrl0 = drawctrl0;
-               dev_priv->state.s4.drawctrl1 = drawctrl1;
-               dev_priv->waiting = 1;
-               DMA_COMMIT();
-       }
-}
-
-static int savage_verify_texaddr(drm_savage_private_t * dev_priv, int unit,
-                                uint32_t addr)
-{
-       if ((addr & 6) != 2) {  /* reserved bits */
-               DRM_ERROR("bad texAddr%d %08x (reserved bits)\n", unit, addr);
-               return -EINVAL;
-       }
-       if (!(addr & 1)) {      /* local */
-               addr &= ~7;
-               if (addr < dev_priv->texture_offset ||
-                   addr >= dev_priv->texture_offset + dev_priv->texture_size) {
-                       DRM_ERROR
-                           ("bad texAddr%d %08x (local addr out of range)\n",
-                            unit, addr);
-                       return -EINVAL;
-               }
-       } else {                /* AGP */
-               if (!dev_priv->agp_textures) {
-                       DRM_ERROR("bad texAddr%d %08x (AGP not available)\n",
-                                 unit, addr);
-                       return -EINVAL;
-               }
-               addr &= ~7;
-               if (addr < dev_priv->agp_textures->offset ||
-                   addr >= (dev_priv->agp_textures->offset +
-                            dev_priv->agp_textures->size)) {
-                       DRM_ERROR
-                           ("bad texAddr%d %08x (AGP addr out of range)\n",
-                            unit, addr);
-                       return -EINVAL;
-               }
-       }
-       return 0;
-}
-
-#define SAVE_STATE(reg,where)                  \
-       if(start <= reg && start+count > reg)   \
-               dev_priv->state.where = regs[reg - start]
-#define SAVE_STATE_MASK(reg,where,mask) do {                   \
-       if(start <= reg && start+count > reg) {                 \
-               uint32_t tmp;                                   \
-               tmp = regs[reg - start];                        \
-               dev_priv->state.where = (tmp & (mask)) |        \
-                       (dev_priv->state.where & ~(mask));      \
-       }                                                       \
-} while (0)
-
-static int savage_verify_state_s3d(drm_savage_private_t * dev_priv,
-                                  unsigned int start, unsigned int count,
-                                  const uint32_t *regs)
-{
-       if (start < SAVAGE_TEXPALADDR_S3D ||
-           start + count - 1 > SAVAGE_DESTTEXRWWATERMARK_S3D) {
-               DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
-                         start, start + count - 1);
-               return -EINVAL;
-       }
-
-       SAVE_STATE_MASK(SAVAGE_SCSTART_S3D, s3d.new_scstart,
-                       ~SAVAGE_SCISSOR_MASK_S3D);
-       SAVE_STATE_MASK(SAVAGE_SCEND_S3D, s3d.new_scend,
-                       ~SAVAGE_SCISSOR_MASK_S3D);
-
-       /* if any texture regs were changed ... */
-       if (start <= SAVAGE_TEXCTRL_S3D &&
-           start + count > SAVAGE_TEXPALADDR_S3D) {
-               /* ... check texture state */
-               SAVE_STATE(SAVAGE_TEXCTRL_S3D, s3d.texctrl);
-               SAVE_STATE(SAVAGE_TEXADDR_S3D, s3d.texaddr);
-               if (dev_priv->state.s3d.texctrl & SAVAGE_TEXCTRL_TEXEN_MASK)
-                       return savage_verify_texaddr(dev_priv, 0,
-                                               dev_priv->state.s3d.texaddr);
-       }
-
-       return 0;
-}
-
-static int savage_verify_state_s4(drm_savage_private_t * dev_priv,
-                                 unsigned int start, unsigned int count,
-                                 const uint32_t *regs)
-{
-       int ret = 0;
-
-       if (start < SAVAGE_DRAWLOCALCTRL_S4 ||
-           start + count - 1 > SAVAGE_TEXBLENDCOLOR_S4) {
-               DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
-                         start, start + count - 1);
-               return -EINVAL;
-       }
-
-       SAVE_STATE_MASK(SAVAGE_DRAWCTRL0_S4, s4.new_drawctrl0,
-                       ~SAVAGE_SCISSOR_MASK_S4);
-       SAVE_STATE_MASK(SAVAGE_DRAWCTRL1_S4, s4.new_drawctrl1,
-                       ~SAVAGE_SCISSOR_MASK_S4);
-
-       /* if any texture regs were changed ... */
-       if (start <= SAVAGE_TEXDESCR_S4 &&
-           start + count > SAVAGE_TEXPALADDR_S4) {
-               /* ... check texture state */
-               SAVE_STATE(SAVAGE_TEXDESCR_S4, s4.texdescr);
-               SAVE_STATE(SAVAGE_TEXADDR0_S4, s4.texaddr0);
-               SAVE_STATE(SAVAGE_TEXADDR1_S4, s4.texaddr1);
-               if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX0EN_MASK)
-                       ret |= savage_verify_texaddr(dev_priv, 0,
-                                               dev_priv->state.s4.texaddr0);
-               if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX1EN_MASK)
-                       ret |= savage_verify_texaddr(dev_priv, 1,
-                                               dev_priv->state.s4.texaddr1);
-       }
-
-       return ret;
-}
-
-#undef SAVE_STATE
-#undef SAVE_STATE_MASK
-
-static int savage_dispatch_state(drm_savage_private_t * dev_priv,
-                                const drm_savage_cmd_header_t * cmd_header,
-                                const uint32_t *regs)
-{
-       unsigned int count = cmd_header->state.count;
-       unsigned int start = cmd_header->state.start;
-       unsigned int count2 = 0;
-       unsigned int bci_size;
-       int ret;
-       DMA_LOCALS;
-
-       if (!count)
-               return 0;
-
-       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
-               ret = savage_verify_state_s3d(dev_priv, start, count, regs);
-               if (ret != 0)
-                       return ret;
-               /* scissor regs are emitted in savage_dispatch_draw */
-               if (start < SAVAGE_SCSTART_S3D) {
-                       if (start + count > SAVAGE_SCEND_S3D + 1)
-                               count2 = count - (SAVAGE_SCEND_S3D + 1 - start);
-                       if (start + count > SAVAGE_SCSTART_S3D)
-                               count = SAVAGE_SCSTART_S3D - start;
-               } else if (start <= SAVAGE_SCEND_S3D) {
-                       if (start + count > SAVAGE_SCEND_S3D + 1) {
-                               count -= SAVAGE_SCEND_S3D + 1 - start;
-                               start = SAVAGE_SCEND_S3D + 1;
-                       } else
-                               return 0;
-               }
-       } else {
-               ret = savage_verify_state_s4(dev_priv, start, count, regs);
-               if (ret != 0)
-                       return ret;
-               /* scissor regs are emitted in savage_dispatch_draw */
-               if (start < SAVAGE_DRAWCTRL0_S4) {
-                       if (start + count > SAVAGE_DRAWCTRL1_S4 + 1)
-                               count2 = count -
-                                        (SAVAGE_DRAWCTRL1_S4 + 1 - start);
-                       if (start + count > SAVAGE_DRAWCTRL0_S4)
-                               count = SAVAGE_DRAWCTRL0_S4 - start;
-               } else if (start <= SAVAGE_DRAWCTRL1_S4) {
-                       if (start + count > SAVAGE_DRAWCTRL1_S4 + 1) {
-                               count -= SAVAGE_DRAWCTRL1_S4 + 1 - start;
-                               start = SAVAGE_DRAWCTRL1_S4 + 1;
-                       } else
-                               return 0;
-               }
-       }
-
-       bci_size = count + (count + 254) / 255 + count2 + (count2 + 254) / 255;
-
-       if (cmd_header->state.global) {
-               BEGIN_DMA(bci_size + 1);
-               DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
-               dev_priv->waiting = 1;
-       } else {
-               BEGIN_DMA(bci_size);
-       }
-
-       do {
-               while (count > 0) {
-                       unsigned int n = count < 255 ? count : 255;
-                       DMA_SET_REGISTERS(start, n);
-                       DMA_COPY(regs, n);
-                       count -= n;
-                       start += n;
-                       regs += n;
-               }
-               start += 2;
-               regs += 2;
-               count = count2;
-               count2 = 0;
-       } while (count);
-
-       DMA_COMMIT();
-
-       return 0;
-}
-
-static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv,
-                                   const drm_savage_cmd_header_t * cmd_header,
-                                   const struct drm_buf * dmabuf)
-{
-       unsigned char reorder = 0;
-       unsigned int prim = cmd_header->prim.prim;
-       unsigned int skip = cmd_header->prim.skip;
-       unsigned int n = cmd_header->prim.count;
-       unsigned int start = cmd_header->prim.start;
-       unsigned int i;
-       BCI_LOCALS;
-
-       if (!dmabuf) {
-               DRM_ERROR("called without dma buffers!\n");
-               return -EINVAL;
-       }
-
-       if (!n)
-               return 0;
-
-       switch (prim) {
-       case SAVAGE_PRIM_TRILIST_201:
-               reorder = 1;
-               prim = SAVAGE_PRIM_TRILIST;
-       case SAVAGE_PRIM_TRILIST:
-               if (n % 3 != 0) {
-                       DRM_ERROR("wrong number of vertices %u in TRILIST\n",
-                                 n);
-                       return -EINVAL;
-               }
-               break;
-       case SAVAGE_PRIM_TRISTRIP:
-       case SAVAGE_PRIM_TRIFAN:
-               if (n < 3) {
-                       DRM_ERROR
-                           ("wrong number of vertices %u in TRIFAN/STRIP\n",
-                            n);
-                       return -EINVAL;
-               }
-               break;
-       default:
-               DRM_ERROR("invalid primitive type %u\n", prim);
-               return -EINVAL;
-       }
-
-       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
-               if (skip != 0) {
-                       DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
-                       return -EINVAL;
-               }
-       } else {
-               unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
-                   (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
-                   (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
-               if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
-                       DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
-                       return -EINVAL;
-               }
-               if (reorder) {
-                       DRM_ERROR("TRILIST_201 used on Savage4 hardware\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (start + n > dmabuf->total / 32) {
-               DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
-                         start, start + n - 1, dmabuf->total / 32);
-               return -EINVAL;
-       }
-
-       /* Vertex DMA doesn't work with command DMA at the same time,
-        * so we use BCI_... to submit commands here. Flush buffered
-        * faked DMA first. */
-       DMA_FLUSH();
-
-       if (dmabuf->bus_address != dev_priv->state.common.vbaddr) {
-               BEGIN_BCI(2);
-               BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1);
-               BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type);
-               dev_priv->state.common.vbaddr = dmabuf->bus_address;
-       }
-       if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) {
-               /* Workaround for what looks like a hardware bug. If a
-                * WAIT_3D_IDLE was emitted some time before the
-                * indexed drawing command then the engine will lock
-                * up. There are two known workarounds:
-                * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */
-               BEGIN_BCI(63);
-               for (i = 0; i < 63; ++i)
-                       BCI_WRITE(BCI_CMD_WAIT);
-               dev_priv->waiting = 0;
-       }
-
-       prim <<= 25;
-       while (n != 0) {
-               /* Can emit up to 255 indices (85 triangles) at once. */
-               unsigned int count = n > 255 ? 255 : n;
-               if (reorder) {
-                       /* Need to reorder indices for correct flat
-                        * shading while preserving the clock sense
-                        * for correct culling. Only on Savage3D. */
-                       int reorder[3] = { -1, -1, -1 };
-                       reorder[start % 3] = 2;
-
-                       BEGIN_BCI((count + 1 + 1) / 2);
-                       BCI_DRAW_INDICES_S3D(count, prim, start + 2);
-
-                       for (i = start + 1; i + 1 < start + count; i += 2)
-                               BCI_WRITE((i + reorder[i % 3]) |
-                                         ((i + 1 +
-                                           reorder[(i + 1) % 3]) << 16));
-                       if (i < start + count)
-                               BCI_WRITE(i + reorder[i % 3]);
-               } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
-                       BEGIN_BCI((count + 1 + 1) / 2);
-                       BCI_DRAW_INDICES_S3D(count, prim, start);
-
-                       for (i = start + 1; i + 1 < start + count; i += 2)
-                               BCI_WRITE(i | ((i + 1) << 16));
-                       if (i < start + count)
-                               BCI_WRITE(i);
-               } else {
-                       BEGIN_BCI((count + 2 + 1) / 2);
-                       BCI_DRAW_INDICES_S4(count, prim, skip);
-
-                       for (i = start; i + 1 < start + count; i += 2)
-                               BCI_WRITE(i | ((i + 1) << 16));
-                       if (i < start + count)
-                               BCI_WRITE(i);
-               }
-
-               start += count;
-               n -= count;
-
-               prim |= BCI_CMD_DRAW_CONT;
-       }
-
-       return 0;
-}
-
-static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv,
-                                  const drm_savage_cmd_header_t * cmd_header,
-                                  const uint32_t *vtxbuf, unsigned int vb_size,
-                                  unsigned int vb_stride)
-{
-       unsigned char reorder = 0;
-       unsigned int prim = cmd_header->prim.prim;
-       unsigned int skip = cmd_header->prim.skip;
-       unsigned int n = cmd_header->prim.count;
-       unsigned int start = cmd_header->prim.start;
-       unsigned int vtx_size;
-       unsigned int i;
-       DMA_LOCALS;
-
-       if (!n)
-               return 0;
-
-       switch (prim) {
-       case SAVAGE_PRIM_TRILIST_201:
-               reorder = 1;
-               prim = SAVAGE_PRIM_TRILIST;
-       case SAVAGE_PRIM_TRILIST:
-               if (n % 3 != 0) {
-                       DRM_ERROR("wrong number of vertices %u in TRILIST\n",
-                                 n);
-                       return -EINVAL;
-               }
-               break;
-       case SAVAGE_PRIM_TRISTRIP:
-       case SAVAGE_PRIM_TRIFAN:
-               if (n < 3) {
-                       DRM_ERROR
-                           ("wrong number of vertices %u in TRIFAN/STRIP\n",
-                            n);
-                       return -EINVAL;
-               }
-               break;
-       default:
-               DRM_ERROR("invalid primitive type %u\n", prim);
-               return -EINVAL;
-       }
-
-       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
-               if (skip > SAVAGE_SKIP_ALL_S3D) {
-                       DRM_ERROR("invalid skip flags 0x%04x\n", skip);
-                       return -EINVAL;
-               }
-               vtx_size = 8;   /* full vertex */
-       } else {
-               if (skip > SAVAGE_SKIP_ALL_S4) {
-                       DRM_ERROR("invalid skip flags 0x%04x\n", skip);
-                       return -EINVAL;
-               }
-               vtx_size = 10;  /* full vertex */
-       }
-
-       vtx_size -= (skip & 1) + (skip >> 1 & 1) +
-           (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
-           (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
-
-       if (vtx_size > vb_stride) {
-               DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
-                         vtx_size, vb_stride);
-               return -EINVAL;
-       }
-
-       if (start + n > vb_size / (vb_stride * 4)) {
-               DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
-                         start, start + n - 1, vb_size / (vb_stride * 4));
-               return -EINVAL;
-       }
-
-       prim <<= 25;
-       while (n != 0) {
-               /* Can emit up to 255 vertices (85 triangles) at once. */
-               unsigned int count = n > 255 ? 255 : n;
-               if (reorder) {
-                       /* Need to reorder vertices for correct flat
-                        * shading while preserving the clock sense
-                        * for correct culling. Only on Savage3D. */
-                       int reorder[3] = { -1, -1, -1 };
-                       reorder[start % 3] = 2;
-
-                       BEGIN_DMA(count * vtx_size + 1);
-                       DMA_DRAW_PRIMITIVE(count, prim, skip);
-
-                       for (i = start; i < start + count; ++i) {
-                               unsigned int j = i + reorder[i % 3];
-                               DMA_COPY(&vtxbuf[vb_stride * j], vtx_size);
-                       }
-
-                       DMA_COMMIT();
-               } else {
-                       BEGIN_DMA(count * vtx_size + 1);
-                       DMA_DRAW_PRIMITIVE(count, prim, skip);
-
-                       if (vb_stride == vtx_size) {
-                               DMA_COPY(&vtxbuf[vb_stride * start],
-                                        vtx_size * count);
-                       } else {
-                               for (i = start; i < start + count; ++i) {
-                                       DMA_COPY(&vtxbuf [vb_stride * i],
-                                                vtx_size);
-                               }
-                       }
-
-                       DMA_COMMIT();
-               }
-
-               start += count;
-               n -= count;
-
-               prim |= BCI_CMD_DRAW_CONT;
-       }
-
-       return 0;
-}
-
-static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
-                                  const drm_savage_cmd_header_t * cmd_header,
-                                  const uint16_t *idx,
-                                  const struct drm_buf * dmabuf)
-{
-       unsigned char reorder = 0;
-       unsigned int prim = cmd_header->idx.prim;
-       unsigned int skip = cmd_header->idx.skip;
-       unsigned int n = cmd_header->idx.count;
-       unsigned int i;
-       BCI_LOCALS;
-
-       if (!dmabuf) {
-               DRM_ERROR("called without dma buffers!\n");
-               return -EINVAL;
-       }
-
-       if (!n)
-               return 0;
-
-       switch (prim) {
-       case SAVAGE_PRIM_TRILIST_201:
-               reorder = 1;
-               prim = SAVAGE_PRIM_TRILIST;
-       case SAVAGE_PRIM_TRILIST:
-               if (n % 3 != 0) {
-                       DRM_ERROR("wrong number of indices %u in TRILIST\n", n);
-                       return -EINVAL;
-               }
-               break;
-       case SAVAGE_PRIM_TRISTRIP:
-       case SAVAGE_PRIM_TRIFAN:
-               if (n < 3) {
-                       DRM_ERROR
-                           ("wrong number of indices %u in TRIFAN/STRIP\n", n);
-                       return -EINVAL;
-               }
-               break;
-       default:
-               DRM_ERROR("invalid primitive type %u\n", prim);
-               return -EINVAL;
-       }
-
-       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
-               if (skip != 0) {
-                       DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
-                       return -EINVAL;
-               }
-       } else {
-               unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
-                   (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
-                   (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
-               if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
-                       DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
-                       return -EINVAL;
-               }
-               if (reorder) {
-                       DRM_ERROR("TRILIST_201 used on Savage4 hardware\n");
-                       return -EINVAL;
-               }
-       }
-
-       /* Vertex DMA doesn't work with command DMA at the same time,
-        * so we use BCI_... to submit commands here. Flush buffered
-        * faked DMA first. */
-       DMA_FLUSH();
-
-       if (dmabuf->bus_address != dev_priv->state.common.vbaddr) {
-               BEGIN_BCI(2);
-               BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1);
-               BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type);
-               dev_priv->state.common.vbaddr = dmabuf->bus_address;
-       }
-       if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) {
-               /* Workaround for what looks like a hardware bug. If a
-                * WAIT_3D_IDLE was emitted some time before the
-                * indexed drawing command then the engine will lock
-                * up. There are two known workarounds:
-                * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */
-               BEGIN_BCI(63);
-               for (i = 0; i < 63; ++i)
-                       BCI_WRITE(BCI_CMD_WAIT);
-               dev_priv->waiting = 0;
-       }
-
-       prim <<= 25;
-       while (n != 0) {
-               /* Can emit up to 255 indices (85 triangles) at once. */
-               unsigned int count = n > 255 ? 255 : n;
-
-               /* check indices */
-               for (i = 0; i < count; ++i) {
-                       if (idx[i] > dmabuf->total / 32) {
-                               DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
-                                         i, idx[i], dmabuf->total / 32);
-                               return -EINVAL;
-                       }
-               }
-
-               if (reorder) {
-                       /* Need to reorder indices for correct flat
-                        * shading while preserving the clock sense
-                        * for correct culling. Only on Savage3D. */
-                       int reorder[3] = { 2, -1, -1 };
-
-                       BEGIN_BCI((count + 1 + 1) / 2);
-                       BCI_DRAW_INDICES_S3D(count, prim, idx[2]);
-
-                       for (i = 1; i + 1 < count; i += 2)
-                               BCI_WRITE(idx[i + reorder[i % 3]] |
-                                         (idx[i + 1 +
-                                          reorder[(i + 1) % 3]] << 16));
-                       if (i < count)
-                               BCI_WRITE(idx[i + reorder[i % 3]]);
-               } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
-                       BEGIN_BCI((count + 1 + 1) / 2);
-                       BCI_DRAW_INDICES_S3D(count, prim, idx[0]);
-
-                       for (i = 1; i + 1 < count; i += 2)
-                               BCI_WRITE(idx[i] | (idx[i + 1] << 16));
-                       if (i < count)
-                               BCI_WRITE(idx[i]);
-               } else {
-                       BEGIN_BCI((count + 2 + 1) / 2);
-                       BCI_DRAW_INDICES_S4(count, prim, skip);
-
-                       for (i = 0; i + 1 < count; i += 2)
-                               BCI_WRITE(idx[i] | (idx[i + 1] << 16));
-                       if (i < count)
-                               BCI_WRITE(idx[i]);
-               }
-
-               idx += count;
-               n -= count;
-
-               prim |= BCI_CMD_DRAW_CONT;
-       }
-
-       return 0;
-}
-
-static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,
-                                 const drm_savage_cmd_header_t * cmd_header,
-                                 const uint16_t *idx,
-                                 const uint32_t *vtxbuf,
-                                 unsigned int vb_size, unsigned int vb_stride)
-{
-       unsigned char reorder = 0;
-       unsigned int prim = cmd_header->idx.prim;
-       unsigned int skip = cmd_header->idx.skip;
-       unsigned int n = cmd_header->idx.count;
-       unsigned int vtx_size;
-       unsigned int i;
-       DMA_LOCALS;
-
-       if (!n)
-               return 0;
-
-       switch (prim) {
-       case SAVAGE_PRIM_TRILIST_201:
-               reorder = 1;
-               prim = SAVAGE_PRIM_TRILIST;
-       case SAVAGE_PRIM_TRILIST:
-               if (n % 3 != 0) {
-                       DRM_ERROR("wrong number of indices %u in TRILIST\n", n);
-                       return -EINVAL;
-               }
-               break;
-       case SAVAGE_PRIM_TRISTRIP:
-       case SAVAGE_PRIM_TRIFAN:
-               if (n < 3) {
-                       DRM_ERROR
-                           ("wrong number of indices %u in TRIFAN/STRIP\n", n);
-                       return -EINVAL;
-               }
-               break;
-       default:
-               DRM_ERROR("invalid primitive type %u\n", prim);
-               return -EINVAL;
-       }
-
-       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
-               if (skip > SAVAGE_SKIP_ALL_S3D) {
-                       DRM_ERROR("invalid skip flags 0x%04x\n", skip);
-                       return -EINVAL;
-               }
-               vtx_size = 8;   /* full vertex */
-       } else {
-               if (skip > SAVAGE_SKIP_ALL_S4) {
-                       DRM_ERROR("invalid skip flags 0x%04x\n", skip);
-                       return -EINVAL;
-               }
-               vtx_size = 10;  /* full vertex */
-       }
-
-       vtx_size -= (skip & 1) + (skip >> 1 & 1) +
-           (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
-           (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
-
-       if (vtx_size > vb_stride) {
-               DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
-                         vtx_size, vb_stride);
-               return -EINVAL;
-       }
-
-       prim <<= 25;
-       while (n != 0) {
-               /* Can emit up to 255 vertices (85 triangles) at once. */
-               unsigned int count = n > 255 ? 255 : n;
-
-               /* Check indices */
-               for (i = 0; i < count; ++i) {
-                       if (idx[i] > vb_size / (vb_stride * 4)) {
-                               DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
-                                         i, idx[i], vb_size / (vb_stride * 4));
-                               return -EINVAL;
-                       }
-               }
-
-               if (reorder) {
-                       /* Need to reorder vertices for correct flat
-                        * shading while preserving the clock sense
-                        * for correct culling. Only on Savage3D. */
-                       int reorder[3] = { 2, -1, -1 };
-
-                       BEGIN_DMA(count * vtx_size + 1);
-                       DMA_DRAW_PRIMITIVE(count, prim, skip);
-
-                       for (i = 0; i < count; ++i) {
-                               unsigned int j = idx[i + reorder[i % 3]];
-                               DMA_COPY(&vtxbuf[vb_stride * j], vtx_size);
-                       }
-
-                       DMA_COMMIT();
-               } else {
-                       BEGIN_DMA(count * vtx_size + 1);
-                       DMA_DRAW_PRIMITIVE(count, prim, skip);
-
-                       for (i = 0; i < count; ++i) {
-                               unsigned int j = idx[i];
-                               DMA_COPY(&vtxbuf[vb_stride * j], vtx_size);
-                       }
-
-                       DMA_COMMIT();
-               }
-
-               idx += count;
-               n -= count;
-
-               prim |= BCI_CMD_DRAW_CONT;
-       }
-
-       return 0;
-}
-
-static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
-                                const drm_savage_cmd_header_t * cmd_header,
-                                const drm_savage_cmd_header_t *data,
-                                unsigned int nbox,
-                                const struct drm_clip_rect *boxes)
-{
-       unsigned int flags = cmd_header->clear0.flags;
-       unsigned int clear_cmd;
-       unsigned int i, nbufs;
-       DMA_LOCALS;
-
-       if (nbox == 0)
-               return 0;
-
-       clear_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
-           BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW;
-       BCI_CMD_SET_ROP(clear_cmd, 0xCC);
-
-       nbufs = ((flags & SAVAGE_FRONT) ? 1 : 0) +
-           ((flags & SAVAGE_BACK) ? 1 : 0) + ((flags & SAVAGE_DEPTH) ? 1 : 0);
-       if (nbufs == 0)
-               return 0;
-
-       if (data->clear1.mask != 0xffffffff) {
-               /* set mask */
-               BEGIN_DMA(2);
-               DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
-               DMA_WRITE(data->clear1.mask);
-               DMA_COMMIT();
-       }
-       for (i = 0; i < nbox; ++i) {
-               unsigned int x, y, w, h;
-               unsigned int buf;
-               x = boxes[i].x1, y = boxes[i].y1;
-               w = boxes[i].x2 - boxes[i].x1;
-               h = boxes[i].y2 - boxes[i].y1;
-               BEGIN_DMA(nbufs * 6);
-               for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) {
-                       if (!(flags & buf))
-                               continue;
-                       DMA_WRITE(clear_cmd);
-                       switch (buf) {
-                       case SAVAGE_FRONT:
-                               DMA_WRITE(dev_priv->front_offset);
-                               DMA_WRITE(dev_priv->front_bd);
-                               break;
-                       case SAVAGE_BACK:
-                               DMA_WRITE(dev_priv->back_offset);
-                               DMA_WRITE(dev_priv->back_bd);
-                               break;
-                       case SAVAGE_DEPTH:
-                               DMA_WRITE(dev_priv->depth_offset);
-                               DMA_WRITE(dev_priv->depth_bd);
-                               break;
-                       }
-                       DMA_WRITE(data->clear1.value);
-                       DMA_WRITE(BCI_X_Y(x, y));
-                       DMA_WRITE(BCI_W_H(w, h));
-               }
-               DMA_COMMIT();
-       }
-       if (data->clear1.mask != 0xffffffff) {
-               /* reset mask */
-               BEGIN_DMA(2);
-               DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
-               DMA_WRITE(0xffffffff);
-               DMA_COMMIT();
-       }
-
-       return 0;
-}
-
-static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
-                               unsigned int nbox, const struct drm_clip_rect *boxes)
-{
-       unsigned int swap_cmd;
-       unsigned int i;
-       DMA_LOCALS;
-
-       if (nbox == 0)
-               return 0;
-
-       swap_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
-           BCI_CMD_SRC_PBD_COLOR_NEW | BCI_CMD_DEST_GBD;
-       BCI_CMD_SET_ROP(swap_cmd, 0xCC);
-
-       for (i = 0; i < nbox; ++i) {
-               BEGIN_DMA(6);
-               DMA_WRITE(swap_cmd);
-               DMA_WRITE(dev_priv->back_offset);
-               DMA_WRITE(dev_priv->back_bd);
-               DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1));
-               DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1));
-               DMA_WRITE(BCI_W_H(boxes[i].x2 - boxes[i].x1,
-                                 boxes[i].y2 - boxes[i].y1));
-               DMA_COMMIT();
-       }
-
-       return 0;
-}
-
-static int savage_dispatch_draw(drm_savage_private_t * dev_priv,
-                               const drm_savage_cmd_header_t *start,
-                               const drm_savage_cmd_header_t *end,
-                               const struct drm_buf * dmabuf,
-                               const unsigned int *vtxbuf,
-                               unsigned int vb_size, unsigned int vb_stride,
-                               unsigned int nbox,
-                               const struct drm_clip_rect *boxes)
-{
-       unsigned int i, j;
-       int ret;
-
-       for (i = 0; i < nbox; ++i) {
-               const drm_savage_cmd_header_t *cmdbuf;
-               dev_priv->emit_clip_rect(dev_priv, &boxes[i]);
-
-               cmdbuf = start;
-               while (cmdbuf < end) {
-                       drm_savage_cmd_header_t cmd_header;
-                       cmd_header = *cmdbuf;
-                       cmdbuf++;
-                       switch (cmd_header.cmd.cmd) {
-                       case SAVAGE_CMD_DMA_PRIM:
-                               ret = savage_dispatch_dma_prim(
-                                       dev_priv, &cmd_header, dmabuf);
-                               break;
-                       case SAVAGE_CMD_VB_PRIM:
-                               ret = savage_dispatch_vb_prim(
-                                       dev_priv, &cmd_header,
-                                       vtxbuf, vb_size, vb_stride);
-                               break;
-                       case SAVAGE_CMD_DMA_IDX:
-                               j = (cmd_header.idx.count + 3) / 4;
-                               /* j was check in savage_bci_cmdbuf */
-                               ret = savage_dispatch_dma_idx(dev_priv,
-                                       &cmd_header, (const uint16_t *)cmdbuf,
-                                       dmabuf);
-                               cmdbuf += j;
-                               break;
-                       case SAVAGE_CMD_VB_IDX:
-                               j = (cmd_header.idx.count + 3) / 4;
-                               /* j was check in savage_bci_cmdbuf */
-                               ret = savage_dispatch_vb_idx(dev_priv,
-                                       &cmd_header, (const uint16_t *)cmdbuf,
-                                       (const uint32_t *)vtxbuf, vb_size,
-                                       vb_stride);
-                               cmdbuf += j;
-                               break;
-                       default:
-                               /* What's the best return code? EFAULT? */
-                               DRM_ERROR("IMPLEMENTATION ERROR: "
-                                         "non-drawing-command %d\n",
-                                         cmd_header.cmd.cmd);
-                               return -EINVAL;
-                       }
-
-                       if (ret != 0)
-                               return ret;
-               }
-       }
-
-       return 0;
-}
-
-int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_savage_private_t *dev_priv = dev->dev_private;
-       struct drm_device_dma *dma = dev->dma;
-       struct drm_buf *dmabuf;
-       drm_savage_cmdbuf_t *cmdbuf = data;
-       drm_savage_cmd_header_t *kcmd_addr = NULL;
-       drm_savage_cmd_header_t *first_draw_cmd;
-       unsigned int *kvb_addr = NULL;
-       struct drm_clip_rect *kbox_addr = NULL;
-       unsigned int i, j;
-       int ret = 0;
-
-       DRM_DEBUG("\n");
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       if (dma && dma->buflist) {
-               if (cmdbuf->dma_idx > dma->buf_count) {
-                       DRM_ERROR
-                           ("vertex buffer index %u out of range (0-%u)\n",
-                            cmdbuf->dma_idx, dma->buf_count - 1);
-                       return -EINVAL;
-               }
-               dmabuf = dma->buflist[cmdbuf->dma_idx];
-       } else {
-               dmabuf = NULL;
-       }
-
-       /* Copy the user buffers into kernel temporary areas.  This hasn't been
-        * a performance loss compared to VERIFYAREA_READ/
-        * COPY_FROM_USER_UNCHECKED when done in other drivers, and is correct
-        * for locking on FreeBSD.
-        */
-       if (cmdbuf->size) {
-               kcmd_addr = drm_alloc(cmdbuf->size * 8, DRM_MEM_DRIVER);
-               if (kcmd_addr == NULL)
-                       return -ENOMEM;
-
-               if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf->cmd_addr,
-                                      cmdbuf->size * 8))
-               {
-                       drm_free(kcmd_addr, cmdbuf->size * 8, DRM_MEM_DRIVER);
-                       return -EFAULT;
-               }
-               cmdbuf->cmd_addr = kcmd_addr;
-       }
-       if (cmdbuf->vb_size) {
-               kvb_addr = drm_alloc(cmdbuf->vb_size, DRM_MEM_DRIVER);
-               if (kvb_addr == NULL) {
-                       ret = -ENOMEM;
-                       goto done;
-               }
-
-               if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf->vb_addr,
-                                      cmdbuf->vb_size)) {
-                       ret = -EFAULT;
-                       goto done;
-               }
-               cmdbuf->vb_addr = kvb_addr;
-       }
-       if (cmdbuf->nbox) {
-               kbox_addr = drm_alloc(cmdbuf->nbox * sizeof(struct drm_clip_rect),
-                                      DRM_MEM_DRIVER);
-               if (kbox_addr == NULL) {
-                       ret = -ENOMEM;
-                       goto done;
-               }
-
-               if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf->box_addr,
-                                      cmdbuf->nbox * sizeof(struct drm_clip_rect))) {
-                       ret = -EFAULT;
-                       goto done;
-               }
-       cmdbuf->box_addr = kbox_addr;
-       }
-
-       /* Make sure writes to DMA buffers are finished before sending
-        * DMA commands to the graphics hardware. */
-       DRM_MEMORYBARRIER();
-
-       /* Coming from user space. Don't know if the Xserver has
-        * emitted wait commands. Assuming the worst. */
-       dev_priv->waiting = 1;
-
-       i = 0;
-       first_draw_cmd = NULL;
-       while (i < cmdbuf->size) {
-               drm_savage_cmd_header_t cmd_header;
-               cmd_header = *(drm_savage_cmd_header_t *)cmdbuf->cmd_addr;
-               cmdbuf->cmd_addr++;
-               i++;
-
-               /* Group drawing commands with same state to minimize
-                * iterations over clip rects. */
-               j = 0;
-               switch (cmd_header.cmd.cmd) {
-               case SAVAGE_CMD_DMA_IDX:
-               case SAVAGE_CMD_VB_IDX:
-                       j = (cmd_header.idx.count + 3) / 4;
-                       if (i + j > cmdbuf->size) {
-                               DRM_ERROR("indexed drawing command extends "
-                                         "beyond end of command buffer\n");
-                               DMA_FLUSH();
-                               return -EINVAL;
-                       }
-                       /* fall through */
-               case SAVAGE_CMD_DMA_PRIM:
-               case SAVAGE_CMD_VB_PRIM:
-                       if (!first_draw_cmd)
-                               first_draw_cmd = cmdbuf->cmd_addr - 1;
-                       cmdbuf->cmd_addr += j;
-                       i += j;
-                       break;
-               default:
-                       if (first_draw_cmd) {
-                               ret = savage_dispatch_draw(
-                                     dev_priv, first_draw_cmd,
-                                     cmdbuf->cmd_addr - 1,
-                                     dmabuf, cmdbuf->vb_addr, cmdbuf->vb_size,
-                                     cmdbuf->vb_stride,
-                                     cmdbuf->nbox, cmdbuf->box_addr);
-                               if (ret != 0)
-                                       return ret;
-                               first_draw_cmd = NULL;
-                       }
-               }
-               if (first_draw_cmd)
-                       continue;
-
-               switch (cmd_header.cmd.cmd) {
-               case SAVAGE_CMD_STATE:
-                       j = (cmd_header.state.count + 1) / 2;
-                       if (i + j > cmdbuf->size) {
-                               DRM_ERROR("command SAVAGE_CMD_STATE extends "
-                                         "beyond end of command buffer\n");
-                               DMA_FLUSH();
-                               ret = -EINVAL;
-                               goto done;
-                       }
-                       ret = savage_dispatch_state(dev_priv, &cmd_header,
-                               (const uint32_t *)cmdbuf->cmd_addr);
-                       cmdbuf->cmd_addr += j;
-                       i += j;
-                       break;
-               case SAVAGE_CMD_CLEAR:
-                       if (i + 1 > cmdbuf->size) {
-                               DRM_ERROR("command SAVAGE_CMD_CLEAR extends "
-                                         "beyond end of command buffer\n");
-                               DMA_FLUSH();
-                               ret = -EINVAL;
-                               goto done;
-                       }
-                       ret = savage_dispatch_clear(dev_priv, &cmd_header,
-                                                   cmdbuf->cmd_addr,
-                                                   cmdbuf->nbox,
-                                                   cmdbuf->box_addr);
-                       cmdbuf->cmd_addr++;
-                       i++;
-                       break;
-               case SAVAGE_CMD_SWAP:
-                       ret = savage_dispatch_swap(dev_priv, cmdbuf->nbox,
-                                                  cmdbuf->box_addr);
-                       break;
-               default:
-                       DRM_ERROR("invalid command 0x%x\n",
-                                 cmd_header.cmd.cmd);
-                       DMA_FLUSH();
-                       ret = -EINVAL;
-                       goto done;
-               }
-
-               if (ret != 0) {
-                       DMA_FLUSH();
-                       goto done;
-               }
-       }
-
-       if (first_draw_cmd) {
-               ret = savage_dispatch_draw (
-                       dev_priv, first_draw_cmd, cmdbuf->cmd_addr, dmabuf,
-                       cmdbuf->vb_addr, cmdbuf->vb_size, cmdbuf->vb_stride,
-                       cmdbuf->nbox, cmdbuf->box_addr);
-               if (ret != 0) {
-                       DMA_FLUSH();
-                       goto done;
-               }
-       }
-
-       DMA_FLUSH();
-
-       if (dmabuf && cmdbuf->discard) {
-               drm_savage_buf_priv_t *buf_priv = dmabuf->dev_private;
-               uint16_t event;
-               event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D);
-               SET_AGE(&buf_priv->age, event, dev_priv->event_wrap);
-               savage_freelist_put(dev, dmabuf);
-       }
-
-done:
-       /* If we didn't need to allocate them, these'll be NULL */
-       drm_free(kcmd_addr, cmdbuf->size * 8, DRM_MEM_DRIVER);
-       drm_free(kvb_addr, cmdbuf->vb_size, DRM_MEM_DRIVER);
-       drm_free(kbox_addr, cmdbuf->nbox * sizeof(struct drm_clip_rect),
-                DRM_MEM_DRIVER);
-
-       return ret;
-}
diff --git a/drivers/char/drm/sis_drm.h b/drivers/char/drm/sis_drm.h
deleted file mode 100644 (file)
index 30f7b38..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */
-/*
- * Copyright 2005 Eric Anholt
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#ifndef __SIS_DRM_H__
-#define __SIS_DRM_H__
-
-/* SiS specific ioctls */
-#define NOT_USED_0_3
-#define DRM_SIS_FB_ALLOC       0x04
-#define DRM_SIS_FB_FREE                0x05
-#define NOT_USED_6_12
-#define DRM_SIS_AGP_INIT       0x13
-#define DRM_SIS_AGP_ALLOC      0x14
-#define DRM_SIS_AGP_FREE       0x15
-#define DRM_SIS_FB_INIT                0x16
-
-#define DRM_IOCTL_SIS_FB_ALLOC         DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_FB_ALLOC, drm_sis_mem_t)
-#define DRM_IOCTL_SIS_FB_FREE          DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_FREE, drm_sis_mem_t)
-#define DRM_IOCTL_SIS_AGP_INIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_INIT, drm_sis_agp_t)
-#define DRM_IOCTL_SIS_AGP_ALLOC                DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_ALLOC, drm_sis_mem_t)
-#define DRM_IOCTL_SIS_AGP_FREE         DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_AGP_FREE, drm_sis_mem_t)
-#define DRM_IOCTL_SIS_FB_INIT          DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_INIT, drm_sis_fb_t)
-/*
-#define DRM_IOCTL_SIS_FLIP             DRM_IOW( 0x48, drm_sis_flip_t)
-#define DRM_IOCTL_SIS_FLIP_INIT                DRM_IO(  0x49)
-#define DRM_IOCTL_SIS_FLIP_FINAL       DRM_IO(  0x50)
-*/
-
-typedef struct {
-       int context;
-       unsigned int offset;
-       unsigned int size;
-       unsigned long free;
-} drm_sis_mem_t;
-
-typedef struct {
-       unsigned int offset, size;
-} drm_sis_agp_t;
-
-typedef struct {
-       unsigned int offset, size;
-} drm_sis_fb_t;
-
-#endif                         /* __SIS_DRM_H__ */
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
deleted file mode 100644 (file)
index 7dacc64..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/* sis.c -- sis driver -*- linux-c -*-
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "drmP.h"
-#include "sis_drm.h"
-#include "sis_drv.h"
-
-#include "drm_pciids.h"
-
-static struct pci_device_id pciidlist[] = {
-       sisdrv_PCI_IDS
-};
-
-static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
-{
-       drm_sis_private_t *dev_priv;
-       int ret;
-
-       dev_priv = drm_calloc(1, sizeof(drm_sis_private_t), DRM_MEM_DRIVER);
-       if (dev_priv == NULL)
-               return -ENOMEM;
-
-       dev->dev_private = (void *)dev_priv;
-       dev_priv->chipset = chipset;
-       ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
-       if (ret) {
-               drm_free(dev_priv, sizeof(dev_priv), DRM_MEM_DRIVER);
-       }
-
-       return ret;
-}
-
-static int sis_driver_unload(struct drm_device *dev)
-{
-       drm_sis_private_t *dev_priv = dev->dev_private;
-
-       drm_sman_takedown(&dev_priv->sman);
-       drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
-
-       return 0;
-}
-
-static struct drm_driver driver = {
-       .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR,
-       .load = sis_driver_load,
-       .unload = sis_driver_unload,
-       .context_dtor = NULL,
-       .dma_quiescent = sis_idle,
-       .reclaim_buffers = NULL,
-       .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked,
-       .lastclose = sis_lastclose,
-       .get_map_ofs = drm_core_get_map_ofs,
-       .get_reg_ofs = drm_core_get_reg_ofs,
-       .ioctls = sis_ioctls,
-       .fops = {
-                .owner = THIS_MODULE,
-                .open = drm_open,
-                .release = drm_release,
-                .ioctl = drm_ioctl,
-                .mmap = drm_mmap,
-                .poll = drm_poll,
-                .fasync = drm_fasync,
-       },
-       .pci_driver = {
-                .name = DRIVER_NAME,
-                .id_table = pciidlist,
-       },
-
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int __init sis_init(void)
-{
-       driver.num_ioctls = sis_max_ioctl;
-       return drm_init(&driver);
-}
-
-static void __exit sis_exit(void)
-{
-       drm_exit(&driver);
-}
-
-module_init(sis_init);
-module_exit(sis_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
deleted file mode 100644 (file)
index ef940ba..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */
-/*
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-
-#ifndef _SIS_DRV_H_
-#define _SIS_DRV_H_
-
-/* General customization:
- */
-
-#define DRIVER_AUTHOR          "SIS, Tungsten Graphics"
-#define DRIVER_NAME            "sis"
-#define DRIVER_DESC            "SIS 300/630/540 and XGI V3XE/V5/V8"
-#define DRIVER_DATE            "20070626"
-#define DRIVER_MAJOR           1
-#define DRIVER_MINOR           3
-#define DRIVER_PATCHLEVEL      0
-
-enum sis_family {
-       SIS_OTHER = 0,
-       SIS_CHIP_315 = 1,
-};
-
-#include "drm_sman.h"
-
-
-#define SIS_BASE (dev_priv->mmio)
-#define SIS_READ(reg)         DRM_READ32(SIS_BASE, reg);
-#define SIS_WRITE(reg, val)   DRM_WRITE32(SIS_BASE, reg, val);
-
-typedef struct drm_sis_private {
-       drm_local_map_t *mmio;
-       unsigned int idle_fault;
-       struct drm_sman sman;
-       unsigned int chipset;
-       int vram_initialized;
-       int agp_initialized;
-       unsigned long vram_offset;
-       unsigned long agp_offset;
-} drm_sis_private_t;
-
-extern int sis_idle(struct drm_device *dev);
-extern void sis_reclaim_buffers_locked(struct drm_device *dev,
-                                      struct drm_file *file_priv);
-extern void sis_lastclose(struct drm_device *dev);
-
-extern struct drm_ioctl_desc sis_ioctls[];
-extern int sis_max_ioctl;
-
-#endif
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
deleted file mode 100644 (file)
index b387877..0000000
+++ /dev/null
@@ -1,333 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- **************************************************************************/
-
-/*
- * Authors:
- *    Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#include "drmP.h"
-#include "sis_drm.h"
-#include "sis_drv.h"
-
-#include <video/sisfb.h>
-
-#define VIDEO_TYPE 0
-#define AGP_TYPE 1
-
-
-#if defined(CONFIG_FB_SIS)
-/* fb management via fb device */
-
-#define SIS_MM_ALIGN_SHIFT 0
-#define SIS_MM_ALIGN_MASK 0
-
-static void *sis_sman_mm_allocate(void *private, unsigned long size,
-                                 unsigned alignment)
-{
-       struct sis_memreq req;
-
-       req.size = size;
-       sis_malloc(&req);
-       if (req.size == 0)
-               return NULL;
-       else
-               return (void *)~req.offset;
-}
-
-static void sis_sman_mm_free(void *private, void *ref)
-{
-       sis_free(~((unsigned long)ref));
-}
-
-static void sis_sman_mm_destroy(void *private)
-{
-       ;
-}
-
-static unsigned long sis_sman_mm_offset(void *private, void *ref)
-{
-       return ~((unsigned long)ref);
-}
-
-#else /* CONFIG_FB_SIS */
-
-#define SIS_MM_ALIGN_SHIFT 4
-#define SIS_MM_ALIGN_MASK ( (1 << SIS_MM_ALIGN_SHIFT) - 1)
-
-#endif /* CONFIG_FB_SIS */
-
-static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_fb_t *fb = data;
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-#if defined(CONFIG_FB_SIS)
-       {
-               struct drm_sman_mm sman_mm;
-               sman_mm.private = (void *)0xFFFFFFFF;
-               sman_mm.allocate = sis_sman_mm_allocate;
-               sman_mm.free = sis_sman_mm_free;
-               sman_mm.destroy = sis_sman_mm_destroy;
-               sman_mm.offset = sis_sman_mm_offset;
-               ret =
-                   drm_sman_set_manager(&dev_priv->sman, VIDEO_TYPE, &sman_mm);
-       }
-#else
-       ret = drm_sman_set_range(&dev_priv->sman, VIDEO_TYPE, 0,
-                                fb->size >> SIS_MM_ALIGN_SHIFT);
-#endif
-
-       if (ret) {
-               DRM_ERROR("VRAM memory manager initialisation error\n");
-               mutex_unlock(&dev->struct_mutex);
-               return ret;
-       }
-
-       dev_priv->vram_initialized = 1;
-       dev_priv->vram_offset = fb->offset;
-
-       mutex_unlock(&dev->struct_mutex);
-       DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
-
-       return 0;
-}
-
-static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file_priv,
-                        void *data, int pool)
-{
-       drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_mem_t *mem = data;
-       int retval = 0;
-       struct drm_memblock_item *item;
-
-       mutex_lock(&dev->struct_mutex);
-
-       if (0 == ((pool == 0) ? dev_priv->vram_initialized :
-                     dev_priv->agp_initialized)) {
-               DRM_ERROR
-                   ("Attempt to allocate from uninitialized memory manager.\n");
-               mutex_unlock(&dev->struct_mutex);
-               return -EINVAL;
-       }
-
-       mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
-       item = drm_sman_alloc(&dev_priv->sman, pool, mem->size, 0,
-                             (unsigned long)file_priv);
-
-       mutex_unlock(&dev->struct_mutex);
-       if (item) {
-               mem->offset = ((pool == 0) ?
-                             dev_priv->vram_offset : dev_priv->agp_offset) +
-                   (item->mm->
-                    offset(item->mm, item->mm_info) << SIS_MM_ALIGN_SHIFT);
-               mem->free = item->user_hash.key;
-               mem->size = mem->size << SIS_MM_ALIGN_SHIFT;
-       } else {
-               mem->offset = 0;
-               mem->size = 0;
-               mem->free = 0;
-               retval = -ENOMEM;
-       }
-
-       DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size,
-                 mem->offset);
-
-       return retval;
-}
-
-static int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_mem_t *mem = data;
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-       ret = drm_sman_free_key(&dev_priv->sman, mem->free);
-       mutex_unlock(&dev->struct_mutex);
-       DRM_DEBUG("free = 0x%lx\n", mem->free);
-
-       return ret;
-}
-
-static int sis_fb_alloc(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv)
-{
-       return sis_drm_alloc(dev, file_priv, data, VIDEO_TYPE);
-}
-
-static int sis_ioctl_agp_init(struct drm_device *dev, void *data,
-                             struct drm_file *file_priv)
-{
-       drm_sis_private_t *dev_priv = dev->dev_private;
-       drm_sis_agp_t *agp = data;
-       int ret;
-       dev_priv = dev->dev_private;
-
-       mutex_lock(&dev->struct_mutex);
-       ret = drm_sman_set_range(&dev_priv->sman, AGP_TYPE, 0,
-                                agp->size >> SIS_MM_ALIGN_SHIFT);
-
-       if (ret) {
-               DRM_ERROR("AGP memory manager initialisation error\n");
-               mutex_unlock(&dev->struct_mutex);
-               return ret;
-       }
-
-       dev_priv->agp_initialized = 1;
-       dev_priv->agp_offset = agp->offset;
-       mutex_unlock(&dev->struct_mutex);
-
-       DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
-       return 0;
-}
-
-static int sis_ioctl_agp_alloc(struct drm_device *dev, void *data,
-                              struct drm_file *file_priv)
-{
-
-       return sis_drm_alloc(dev, file_priv, data, AGP_TYPE);
-}
-
-static drm_local_map_t *sis_reg_init(struct drm_device *dev)
-{
-       struct drm_map_list *entry;
-       drm_local_map_t *map;
-
-       list_for_each_entry(entry, &dev->maplist, head) {
-               map = entry->map;
-               if (!map)
-                       continue;
-               if (map->type == _DRM_REGISTERS) {
-                       return map;
-               }
-       }
-       return NULL;
-}
-
-int sis_idle(struct drm_device *dev)
-{
-       drm_sis_private_t *dev_priv = dev->dev_private;
-       uint32_t idle_reg;
-       unsigned long end;
-       int i;
-
-       if (dev_priv->idle_fault)
-               return 0;
-
-       if (dev_priv->mmio == NULL) {
-               dev_priv->mmio = sis_reg_init(dev);
-               if (dev_priv->mmio == NULL) {
-                       DRM_ERROR("Could not find register map.\n");
-                       return 0;
-               }
-       }
-
-       /*
-        * Implement a device switch here if needed
-        */
-
-       if (dev_priv->chipset != SIS_CHIP_315)
-               return 0;
-
-       /*
-        * Timeout after 3 seconds. We cannot use DRM_WAIT_ON here
-        * because its polling frequency is too low.
-        */
-
-       end = jiffies + (DRM_HZ * 3);
-
-       for (i=0; i<4; ++i) {
-               do {
-                       idle_reg = SIS_READ(0x85cc);
-               } while ( !time_after_eq(jiffies, end) &&
-                         ((idle_reg & 0x80000000) != 0x80000000));
-       }
-
-       if (time_after_eq(jiffies, end)) {
-               DRM_ERROR("Graphics engine idle timeout. "
-                         "Disabling idle check\n");
-               dev_priv->idle_fault = 1;
-       }
-
-       /*
-        * The caller never sees an error code. It gets trapped
-        * in libdrm.
-        */
-
-       return 0;
-}
-
-
-void sis_lastclose(struct drm_device *dev)
-{
-       drm_sis_private_t *dev_priv = dev->dev_private;
-
-       if (!dev_priv)
-               return;
-
-       mutex_lock(&dev->struct_mutex);
-       drm_sman_cleanup(&dev_priv->sman);
-       dev_priv->vram_initialized = 0;
-       dev_priv->agp_initialized = 0;
-       dev_priv->mmio = NULL;
-       mutex_unlock(&dev->struct_mutex);
-}
-
-void sis_reclaim_buffers_locked(struct drm_device * dev,
-                               struct drm_file *file_priv)
-{
-       drm_sis_private_t *dev_priv = dev->dev_private;
-
-       mutex_lock(&dev->struct_mutex);
-       if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) {
-               mutex_unlock(&dev->struct_mutex);
-               return;
-       }
-
-       if (dev->driver->dma_quiescent) {
-               dev->driver->dma_quiescent(dev);
-       }
-
-       drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv);
-       mutex_unlock(&dev->struct_mutex);
-       return;
-}
-
-struct drm_ioctl_desc sis_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_SIS_FB_FREE, sis_drm_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
-       DRM_IOCTL_DEF(DRM_SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_SIS_AGP_FREE, sis_drm_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_SIS_FB_INIT, sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
-};
-
-int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c
deleted file mode 100644 (file)
index 012ff2e..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/* tdfx_drv.c -- tdfx driver -*- linux-c -*-
- * Created: Thu Oct  7 10:38:32 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Daryll Strauss <daryll@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#include "drmP.h"
-#include "tdfx_drv.h"
-
-#include "drm_pciids.h"
-
-static struct pci_device_id pciidlist[] = {
-       tdfx_PCI_IDS
-};
-
-static struct drm_driver driver = {
-       .driver_features = DRIVER_USE_MTRR,
-       .reclaim_buffers = drm_core_reclaim_buffers,
-       .get_map_ofs = drm_core_get_map_ofs,
-       .get_reg_ofs = drm_core_get_reg_ofs,
-       .fops = {
-                .owner = THIS_MODULE,
-                .open = drm_open,
-                .release = drm_release,
-                .ioctl = drm_ioctl,
-                .mmap = drm_mmap,
-                .poll = drm_poll,
-                .fasync = drm_fasync,
-       },
-       .pci_driver = {
-                .name = DRIVER_NAME,
-                .id_table = pciidlist,
-       },
-
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int __init tdfx_init(void)
-{
-       return drm_init(&driver);
-}
-
-static void __exit tdfx_exit(void)
-{
-       drm_exit(&driver);
-}
-
-module_init(tdfx_init);
-module_exit(tdfx_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/tdfx_drv.h b/drivers/char/drm/tdfx_drv.h
deleted file mode 100644 (file)
index 84204ec..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/* tdfx.h -- 3dfx DRM template customization -*- linux-c -*-
- * Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com
- */
-/*
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-#ifndef __TDFX_H__
-#define __TDFX_H__
-
-/* General customization:
- */
-
-#define DRIVER_AUTHOR          "VA Linux Systems Inc."
-
-#define DRIVER_NAME            "tdfx"
-#define DRIVER_DESC            "3dfx Banshee/Voodoo3+"
-#define DRIVER_DATE            "20010216"
-
-#define DRIVER_MAJOR           1
-#define DRIVER_MINOR           0
-#define DRIVER_PATCHLEVEL      0
-
-#endif
diff --git a/drivers/char/drm/via_3d_reg.h b/drivers/char/drm/via_3d_reg.h
deleted file mode 100644 (file)
index 462375d..0000000
+++ /dev/null
@@ -1,1650 +0,0 @@
-/*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef VIA_3D_REG_H
-#define VIA_3D_REG_H
-#define HC_REG_BASE             0x0400
-
-#define HC_REG_TRANS_SPACE      0x0040
-
-#define HC_ParaN_MASK           0xffffffff
-#define HC_Para_MASK            0x00ffffff
-#define HC_SubA_MASK            0xff000000
-#define HC_SubA_SHIFT           24
-/* Transmission Setting
- */
-#define HC_REG_TRANS_SET        0x003c
-#define HC_ParaSubType_MASK     0xff000000
-#define HC_ParaType_MASK        0x00ff0000
-#define HC_ParaOS_MASK          0x0000ff00
-#define HC_ParaAdr_MASK         0x000000ff
-#define HC_ParaSubType_SHIFT    24
-#define HC_ParaType_SHIFT       16
-#define HC_ParaOS_SHIFT         8
-#define HC_ParaAdr_SHIFT        0
-
-#define HC_ParaType_CmdVdata    0x0000
-#define HC_ParaType_NotTex      0x0001
-#define HC_ParaType_Tex         0x0002
-#define HC_ParaType_Palette     0x0003
-#define HC_ParaType_PreCR       0x0010
-#define HC_ParaType_Auto        0x00fe
-
-/* Transmission Space
- */
-#define HC_REG_Hpara0           0x0040
-#define HC_REG_HpataAF          0x02fc
-
-/* Read
- */
-#define HC_REG_HREngSt          0x0000
-#define HC_REG_HRFIFOempty      0x0004
-#define HC_REG_HRFIFOfull       0x0008
-#define HC_REG_HRErr            0x000c
-#define HC_REG_FIFOstatus       0x0010
-/* HC_REG_HREngSt          0x0000
- */
-#define HC_HDASZC_MASK          0x00010000
-#define HC_HSGEMI_MASK          0x0000f000
-#define HC_HLGEMISt_MASK        0x00000f00
-#define HC_HCRSt_MASK           0x00000080
-#define HC_HSE0St_MASK          0x00000040
-#define HC_HSE1St_MASK          0x00000020
-#define HC_HPESt_MASK           0x00000010
-#define HC_HXESt_MASK           0x00000008
-#define HC_HBESt_MASK           0x00000004
-#define HC_HE2St_MASK           0x00000002
-#define HC_HE3St_MASK           0x00000001
-/* HC_REG_HRFIFOempty      0x0004
- */
-#define HC_HRZDempty_MASK       0x00000010
-#define HC_HRTXAempty_MASK      0x00000008
-#define HC_HRTXDempty_MASK      0x00000004
-#define HC_HWZDempty_MASK       0x00000002
-#define HC_HWCDempty_MASK       0x00000001
-/* HC_REG_HRFIFOfull       0x0008
- */
-#define HC_HRZDfull_MASK        0x00000010
-#define HC_HRTXAfull_MASK       0x00000008
-#define HC_HRTXDfull_MASK       0x00000004
-#define HC_HWZDfull_MASK        0x00000002
-#define HC_HWCDfull_MASK        0x00000001
-/* HC_REG_HRErr            0x000c
- */
-#define HC_HAGPCMErr_MASK       0x80000000
-#define HC_HAGPCMErrC_MASK      0x70000000
-/* HC_REG_FIFOstatus       0x0010
- */
-#define HC_HRFIFOATall_MASK     0x80000000
-#define HC_HRFIFOATbusy_MASK    0x40000000
-#define HC_HRATFGMDo_MASK       0x00000100
-#define HC_HRATFGMDi_MASK       0x00000080
-#define HC_HRATFRZD_MASK        0x00000040
-#define HC_HRATFRTXA_MASK       0x00000020
-#define HC_HRATFRTXD_MASK       0x00000010
-#define HC_HRATFWZD_MASK        0x00000008
-#define HC_HRATFWCD_MASK        0x00000004
-#define HC_HRATTXTAG_MASK       0x00000002
-#define HC_HRATTXCH_MASK        0x00000001
-
-/* AGP Command Setting
- */
-#define HC_SubA_HAGPBstL        0x0060
-#define HC_SubA_HAGPBendL       0x0061
-#define HC_SubA_HAGPCMNT        0x0062
-#define HC_SubA_HAGPBpL         0x0063
-#define HC_SubA_HAGPBpH         0x0064
-/* HC_SubA_HAGPCMNT        0x0062
- */
-#define HC_HAGPCMNT_MASK        0x00800000
-#define HC_HCmdErrClr_MASK      0x00400000
-#define HC_HAGPBendH_MASK       0x0000ff00
-#define HC_HAGPBstH_MASK        0x000000ff
-#define HC_HAGPBendH_SHIFT      8
-#define HC_HAGPBstH_SHIFT       0
-/* HC_SubA_HAGPBpL         0x0063
- */
-#define HC_HAGPBpL_MASK         0x00fffffc
-#define HC_HAGPBpID_MASK        0x00000003
-#define HC_HAGPBpID_PAUSE       0x00000000
-#define HC_HAGPBpID_JUMP        0x00000001
-#define HC_HAGPBpID_STOP        0x00000002
-/* HC_SubA_HAGPBpH         0x0064
- */
-#define HC_HAGPBpH_MASK         0x00ffffff
-
-/* Miscellaneous Settings
- */
-#define HC_SubA_HClipTB         0x0070
-#define HC_SubA_HClipLR         0x0071
-#define HC_SubA_HFPClipTL       0x0072
-#define HC_SubA_HFPClipBL       0x0073
-#define HC_SubA_HFPClipLL       0x0074
-#define HC_SubA_HFPClipRL       0x0075
-#define HC_SubA_HFPClipTBH      0x0076
-#define HC_SubA_HFPClipLRH      0x0077
-#define HC_SubA_HLP             0x0078
-#define HC_SubA_HLPRF           0x0079
-#define HC_SubA_HSolidCL        0x007a
-#define HC_SubA_HPixGC          0x007b
-#define HC_SubA_HSPXYOS         0x007c
-#define HC_SubA_HVertexCNT      0x007d
-
-#define HC_HClipT_MASK          0x00fff000
-#define HC_HClipT_SHIFT         12
-#define HC_HClipB_MASK          0x00000fff
-#define HC_HClipB_SHIFT         0
-#define HC_HClipL_MASK          0x00fff000
-#define HC_HClipL_SHIFT         12
-#define HC_HClipR_MASK          0x00000fff
-#define HC_HClipR_SHIFT         0
-#define HC_HFPClipBH_MASK       0x0000ff00
-#define HC_HFPClipBH_SHIFT      8
-#define HC_HFPClipTH_MASK       0x000000ff
-#define HC_HFPClipTH_SHIFT      0
-#define HC_HFPClipRH_MASK       0x0000ff00
-#define HC_HFPClipRH_SHIFT      8
-#define HC_HFPClipLH_MASK       0x000000ff
-#define HC_HFPClipLH_SHIFT      0
-#define HC_HSolidCH_MASK        0x000000ff
-#define HC_HPixGC_MASK          0x00800000
-#define HC_HSPXOS_MASK          0x00fff000
-#define HC_HSPXOS_SHIFT         12
-#define HC_HSPYOS_MASK          0x00000fff
-
-/* Command
- * Command A
- */
-#define HC_HCmdHeader_MASK      0xfe000000     /*0xffe00000 */
-#define HC_HE3Fire_MASK         0x00100000
-#define HC_HPMType_MASK         0x000f0000
-#define HC_HEFlag_MASK          0x0000e000
-#define HC_HShading_MASK        0x00001c00
-#define HC_HPMValidN_MASK       0x00000200
-#define HC_HPLEND_MASK          0x00000100
-#define HC_HVCycle_MASK         0x000000ff
-#define HC_HVCycle_Style_MASK   0x000000c0
-#define HC_HVCycle_ChgA_MASK    0x00000030
-#define HC_HVCycle_ChgB_MASK    0x0000000c
-#define HC_HVCycle_ChgC_MASK    0x00000003
-#define HC_HPMType_Point        0x00000000
-#define HC_HPMType_Line         0x00010000
-#define HC_HPMType_Tri          0x00020000
-#define HC_HPMType_TriWF        0x00040000
-#define HC_HEFlag_NoAA          0x00000000
-#define HC_HEFlag_ab            0x00008000
-#define HC_HEFlag_bc            0x00004000
-#define HC_HEFlag_ca            0x00002000
-#define HC_HShading_Solid       0x00000000
-#define HC_HShading_FlatA       0x00000400
-#define HC_HShading_FlatB       0x00000800
-#define HC_HShading_FlatC       0x00000c00
-#define HC_HShading_Gouraud     0x00001000
-#define HC_HVCycle_Full         0x00000000
-#define HC_HVCycle_AFP          0x00000040
-#define HC_HVCycle_One          0x000000c0
-#define HC_HVCycle_NewA         0x00000000
-#define HC_HVCycle_AA           0x00000010
-#define HC_HVCycle_AB           0x00000020
-#define HC_HVCycle_AC           0x00000030
-#define HC_HVCycle_NewB         0x00000000
-#define HC_HVCycle_BA           0x00000004
-#define HC_HVCycle_BB           0x00000008
-#define HC_HVCycle_BC           0x0000000c
-#define HC_HVCycle_NewC         0x00000000
-#define HC_HVCycle_CA           0x00000001
-#define HC_HVCycle_CB           0x00000002
-#define HC_HVCycle_CC           0x00000003
-
-/* Command B
- */
-#define HC_HLPrst_MASK          0x00010000
-#define HC_HLLastP_MASK         0x00008000
-#define HC_HVPMSK_MASK          0x00007f80
-#define HC_HBFace_MASK          0x00000040
-#define HC_H2nd1VT_MASK         0x0000003f
-#define HC_HVPMSK_X             0x00004000
-#define HC_HVPMSK_Y             0x00002000
-#define HC_HVPMSK_Z             0x00001000
-#define HC_HVPMSK_W             0x00000800
-#define HC_HVPMSK_Cd            0x00000400
-#define HC_HVPMSK_Cs            0x00000200
-#define HC_HVPMSK_S             0x00000100
-#define HC_HVPMSK_T             0x00000080
-
-/* Enable Setting
- */
-#define HC_SubA_HEnable         0x0000
-#define HC_HenTXEnvMap_MASK     0x00200000
-#define HC_HenVertexCNT_MASK    0x00100000
-#define HC_HenCPUDAZ_MASK       0x00080000
-#define HC_HenDASZWC_MASK       0x00040000
-#define HC_HenFBCull_MASK       0x00020000
-#define HC_HenCW_MASK           0x00010000
-#define HC_HenAA_MASK           0x00008000
-#define HC_HenST_MASK           0x00004000
-#define HC_HenZT_MASK           0x00002000
-#define HC_HenZW_MASK           0x00001000
-#define HC_HenAT_MASK           0x00000800
-#define HC_HenAW_MASK           0x00000400
-#define HC_HenSP_MASK           0x00000200
-#define HC_HenLP_MASK           0x00000100
-#define HC_HenTXCH_MASK         0x00000080
-#define HC_HenTXMP_MASK         0x00000040
-#define HC_HenTXPP_MASK         0x00000020
-#define HC_HenTXTR_MASK         0x00000010
-#define HC_HenCS_MASK           0x00000008
-#define HC_HenFOG_MASK          0x00000004
-#define HC_HenABL_MASK          0x00000002
-#define HC_HenDT_MASK           0x00000001
-
-/* Z Setting
- */
-#define HC_SubA_HZWBBasL        0x0010
-#define HC_SubA_HZWBBasH        0x0011
-#define HC_SubA_HZWBType        0x0012
-#define HC_SubA_HZBiasL         0x0013
-#define HC_SubA_HZWBend         0x0014
-#define HC_SubA_HZWTMD          0x0015
-#define HC_SubA_HZWCDL          0x0016
-#define HC_SubA_HZWCTAGnum      0x0017
-#define HC_SubA_HZCYNum         0x0018
-#define HC_SubA_HZWCFire        0x0019
-/* HC_SubA_HZWBType
- */
-#define HC_HZWBType_MASK        0x00800000
-#define HC_HZBiasedWB_MASK      0x00400000
-#define HC_HZONEasFF_MASK       0x00200000
-#define HC_HZOONEasFF_MASK      0x00100000
-#define HC_HZWBFM_MASK          0x00030000
-#define HC_HZWBLoc_MASK         0x0000c000
-#define HC_HZWBPit_MASK         0x00003fff
-#define HC_HZWBFM_16            0x00000000
-#define HC_HZWBFM_32            0x00020000
-#define HC_HZWBFM_24            0x00030000
-#define HC_HZWBLoc_Local        0x00000000
-#define HC_HZWBLoc_SyS          0x00004000
-/* HC_SubA_HZWBend
- */
-#define HC_HZWBend_MASK         0x00ffe000
-#define HC_HZBiasH_MASK         0x000000ff
-#define HC_HZWBend_SHIFT        10
-/* HC_SubA_HZWTMD
- */
-#define HC_HZWTMD_MASK          0x00070000
-#define HC_HEBEBias_MASK        0x00007f00
-#define HC_HZNF_MASK            0x000000ff
-#define HC_HZWTMD_NeverPass     0x00000000
-#define HC_HZWTMD_LT            0x00010000
-#define HC_HZWTMD_EQ            0x00020000
-#define HC_HZWTMD_LE            0x00030000
-#define HC_HZWTMD_GT            0x00040000
-#define HC_HZWTMD_NE            0x00050000
-#define HC_HZWTMD_GE            0x00060000
-#define HC_HZWTMD_AllPass       0x00070000
-#define HC_HEBEBias_SHIFT       8
-/* HC_SubA_HZWCDL          0x0016
- */
-#define HC_HZWCDL_MASK          0x00ffffff
-/* HC_SubA_HZWCTAGnum      0x0017
- */
-#define HC_HZWCTAGnum_MASK      0x00ff0000
-#define HC_HZWCTAGnum_SHIFT     16
-#define HC_HZWCDH_MASK          0x000000ff
-#define HC_HZWCDH_SHIFT         0
-/* HC_SubA_HZCYNum         0x0018
- */
-#define HC_HZCYNum_MASK         0x00030000
-#define HC_HZCYNum_SHIFT        16
-#define HC_HZWCQWnum_MASK       0x00003fff
-#define HC_HZWCQWnum_SHIFT      0
-/* HC_SubA_HZWCFire        0x0019
- */
-#define HC_ZWCFire_MASK         0x00010000
-#define HC_HZWCQWnumLast_MASK   0x00003fff
-#define HC_HZWCQWnumLast_SHIFT  0
-
-/* Stencil Setting
- */
-#define HC_SubA_HSTREF          0x0023
-#define HC_SubA_HSTMD           0x0024
-/* HC_SubA_HSBFM
- */
-#define HC_HSBFM_MASK           0x00030000
-#define HC_HSBLoc_MASK          0x0000c000
-#define HC_HSBPit_MASK          0x00003fff
-/* HC_SubA_HSTREF
- */
-#define HC_HSTREF_MASK          0x00ff0000
-#define HC_HSTOPMSK_MASK        0x0000ff00
-#define HC_HSTBMSK_MASK         0x000000ff
-#define HC_HSTREF_SHIFT         16
-#define HC_HSTOPMSK_SHIFT       8
-/* HC_SubA_HSTMD
- */
-#define HC_HSTMD_MASK           0x00070000
-#define HC_HSTOPSF_MASK         0x000001c0
-#define HC_HSTOPSPZF_MASK       0x00000038
-#define HC_HSTOPSPZP_MASK       0x00000007
-#define HC_HSTMD_NeverPass      0x00000000
-#define HC_HSTMD_LT             0x00010000
-#define HC_HSTMD_EQ             0x00020000
-#define HC_HSTMD_LE             0x00030000
-#define HC_HSTMD_GT             0x00040000
-#define HC_HSTMD_NE             0x00050000
-#define HC_HSTMD_GE             0x00060000
-#define HC_HSTMD_AllPass        0x00070000
-#define HC_HSTOPSF_KEEP         0x00000000
-#define HC_HSTOPSF_ZERO         0x00000040
-#define HC_HSTOPSF_REPLACE      0x00000080
-#define HC_HSTOPSF_INCRSAT      0x000000c0
-#define HC_HSTOPSF_DECRSAT      0x00000100
-#define HC_HSTOPSF_INVERT       0x00000140
-#define HC_HSTOPSF_INCR         0x00000180
-#define HC_HSTOPSF_DECR         0x000001c0
-#define HC_HSTOPSPZF_KEEP       0x00000000
-#define HC_HSTOPSPZF_ZERO       0x00000008
-#define HC_HSTOPSPZF_REPLACE    0x00000010
-#define HC_HSTOPSPZF_INCRSAT    0x00000018
-#define HC_HSTOPSPZF_DECRSAT    0x00000020
-#define HC_HSTOPSPZF_INVERT     0x00000028
-#define HC_HSTOPSPZF_INCR       0x00000030
-#define HC_HSTOPSPZF_DECR       0x00000038
-#define HC_HSTOPSPZP_KEEP       0x00000000
-#define HC_HSTOPSPZP_ZERO       0x00000001
-#define HC_HSTOPSPZP_REPLACE    0x00000002
-#define HC_HSTOPSPZP_INCRSAT    0x00000003
-#define HC_HSTOPSPZP_DECRSAT    0x00000004
-#define HC_HSTOPSPZP_INVERT     0x00000005
-#define HC_HSTOPSPZP_INCR       0x00000006
-#define HC_HSTOPSPZP_DECR       0x00000007
-
-/* Alpha Setting
- */
-#define HC_SubA_HABBasL         0x0030
-#define HC_SubA_HABBasH         0x0031
-#define HC_SubA_HABFM           0x0032
-#define HC_SubA_HATMD           0x0033
-#define HC_SubA_HABLCsat        0x0034
-#define HC_SubA_HABLCop         0x0035
-#define HC_SubA_HABLAsat        0x0036
-#define HC_SubA_HABLAop         0x0037
-#define HC_SubA_HABLRCa         0x0038
-#define HC_SubA_HABLRFCa        0x0039
-#define HC_SubA_HABLRCbias      0x003a
-#define HC_SubA_HABLRCb         0x003b
-#define HC_SubA_HABLRFCb        0x003c
-#define HC_SubA_HABLRAa         0x003d
-#define HC_SubA_HABLRAb         0x003e
-/* HC_SubA_HABFM
- */
-#define HC_HABFM_MASK           0x00030000
-#define HC_HABLoc_MASK          0x0000c000
-#define HC_HABPit_MASK          0x000007ff
-/* HC_SubA_HATMD
- */
-#define HC_HATMD_MASK           0x00000700
-#define HC_HATREF_MASK          0x000000ff
-#define HC_HATMD_NeverPass      0x00000000
-#define HC_HATMD_LT             0x00000100
-#define HC_HATMD_EQ             0x00000200
-#define HC_HATMD_LE             0x00000300
-#define HC_HATMD_GT             0x00000400
-#define HC_HATMD_NE             0x00000500
-#define HC_HATMD_GE             0x00000600
-#define HC_HATMD_AllPass        0x00000700
-/* HC_SubA_HABLCsat
- */
-#define HC_HABLCsat_MASK        0x00010000
-#define HC_HABLCa_MASK          0x0000fc00
-#define HC_HABLCa_C_MASK        0x0000c000
-#define HC_HABLCa_OPC_MASK      0x00003c00
-#define HC_HABLFCa_MASK         0x000003f0
-#define HC_HABLFCa_C_MASK       0x00000300
-#define HC_HABLFCa_OPC_MASK     0x000000f0
-#define HC_HABLCbias_MASK       0x0000000f
-#define HC_HABLCbias_C_MASK     0x00000008
-#define HC_HABLCbias_OPC_MASK   0x00000007
-/*-- Define the input color.
- */
-#define HC_XC_Csrc              0x00000000
-#define HC_XC_Cdst              0x00000001
-#define HC_XC_Asrc              0x00000002
-#define HC_XC_Adst              0x00000003
-#define HC_XC_Fog               0x00000004
-#define HC_XC_HABLRC            0x00000005
-#define HC_XC_minSrcDst         0x00000006
-#define HC_XC_maxSrcDst         0x00000007
-#define HC_XC_mimAsrcInvAdst    0x00000008
-#define HC_XC_OPC               0x00000000
-#define HC_XC_InvOPC            0x00000010
-#define HC_XC_OPCp5             0x00000020
-/*-- Define the input Alpha
- */
-#define HC_XA_OPA               0x00000000
-#define HC_XA_InvOPA            0x00000010
-#define HC_XA_OPAp5             0x00000020
-#define HC_XA_0                 0x00000000
-#define HC_XA_Asrc              0x00000001
-#define HC_XA_Adst              0x00000002
-#define HC_XA_Fog               0x00000003
-#define HC_XA_minAsrcFog        0x00000004
-#define HC_XA_minAsrcAdst       0x00000005
-#define HC_XA_maxAsrcFog        0x00000006
-#define HC_XA_maxAsrcAdst       0x00000007
-#define HC_XA_HABLRA            0x00000008
-#define HC_XA_minAsrcInvAdst    0x00000008
-#define HC_XA_HABLFRA           0x00000009
-/*--
- */
-#define HC_HABLCa_OPC           (HC_XC_OPC << 10)
-#define HC_HABLCa_InvOPC        (HC_XC_InvOPC << 10)
-#define HC_HABLCa_OPCp5         (HC_XC_OPCp5 << 10)
-#define HC_HABLCa_Csrc          (HC_XC_Csrc << 10)
-#define HC_HABLCa_Cdst          (HC_XC_Cdst << 10)
-#define HC_HABLCa_Asrc          (HC_XC_Asrc << 10)
-#define HC_HABLCa_Adst          (HC_XC_Adst << 10)
-#define HC_HABLCa_Fog           (HC_XC_Fog << 10)
-#define HC_HABLCa_HABLRCa       (HC_XC_HABLRC << 10)
-#define HC_HABLCa_minSrcDst     (HC_XC_minSrcDst << 10)
-#define HC_HABLCa_maxSrcDst     (HC_XC_maxSrcDst << 10)
-#define HC_HABLFCa_OPC              (HC_XC_OPC << 4)
-#define HC_HABLFCa_InvOPC           (HC_XC_InvOPC << 4)
-#define HC_HABLFCa_OPCp5            (HC_XC_OPCp5 << 4)
-#define HC_HABLFCa_Csrc             (HC_XC_Csrc << 4)
-#define HC_HABLFCa_Cdst             (HC_XC_Cdst << 4)
-#define HC_HABLFCa_Asrc             (HC_XC_Asrc << 4)
-#define HC_HABLFCa_Adst             (HC_XC_Adst << 4)
-#define HC_HABLFCa_Fog              (HC_XC_Fog << 4)
-#define HC_HABLFCa_HABLRCa          (HC_XC_HABLRC << 4)
-#define HC_HABLFCa_minSrcDst        (HC_XC_minSrcDst << 4)
-#define HC_HABLFCa_maxSrcDst        (HC_XC_maxSrcDst << 4)
-#define HC_HABLFCa_mimAsrcInvAdst   (HC_XC_mimAsrcInvAdst << 4)
-#define HC_HABLCbias_HABLRCbias 0x00000000
-#define HC_HABLCbias_Asrc       0x00000001
-#define HC_HABLCbias_Adst       0x00000002
-#define HC_HABLCbias_Fog        0x00000003
-#define HC_HABLCbias_Cin        0x00000004
-/* HC_SubA_HABLCop         0x0035
- */
-#define HC_HABLdot_MASK         0x00010000
-#define HC_HABLCop_MASK         0x00004000
-#define HC_HABLCb_MASK          0x00003f00
-#define HC_HABLCb_C_MASK        0x00003000
-#define HC_HABLCb_OPC_MASK      0x00000f00
-#define HC_HABLFCb_MASK         0x000000fc
-#define HC_HABLFCb_C_MASK       0x000000c0
-#define HC_HABLFCb_OPC_MASK     0x0000003c
-#define HC_HABLCshift_MASK      0x00000003
-#define HC_HABLCb_OPC           (HC_XC_OPC << 8)
-#define HC_HABLCb_InvOPC        (HC_XC_InvOPC << 8)
-#define HC_HABLCb_OPCp5         (HC_XC_OPCp5 << 8)
-#define HC_HABLCb_Csrc          (HC_XC_Csrc << 8)
-#define HC_HABLCb_Cdst          (HC_XC_Cdst << 8)
-#define HC_HABLCb_Asrc          (HC_XC_Asrc << 8)
-#define HC_HABLCb_Adst          (HC_XC_Adst << 8)
-#define HC_HABLCb_Fog           (HC_XC_Fog << 8)
-#define HC_HABLCb_HABLRCa       (HC_XC_HABLRC << 8)
-#define HC_HABLCb_minSrcDst     (HC_XC_minSrcDst << 8)
-#define HC_HABLCb_maxSrcDst     (HC_XC_maxSrcDst << 8)
-#define HC_HABLFCb_OPC              (HC_XC_OPC << 2)
-#define HC_HABLFCb_InvOPC           (HC_XC_InvOPC << 2)
-#define HC_HABLFCb_OPCp5            (HC_XC_OPCp5 << 2)
-#define HC_HABLFCb_Csrc             (HC_XC_Csrc << 2)
-#define HC_HABLFCb_Cdst             (HC_XC_Cdst << 2)
-#define HC_HABLFCb_Asrc             (HC_XC_Asrc << 2)
-#define HC_HABLFCb_Adst             (HC_XC_Adst << 2)
-#define HC_HABLFCb_Fog              (HC_XC_Fog << 2)
-#define HC_HABLFCb_HABLRCb          (HC_XC_HABLRC << 2)
-#define HC_HABLFCb_minSrcDst        (HC_XC_minSrcDst << 2)
-#define HC_HABLFCb_maxSrcDst        (HC_XC_maxSrcDst << 2)
-#define HC_HABLFCb_mimAsrcInvAdst   (HC_XC_mimAsrcInvAdst << 2)
-/* HC_SubA_HABLAsat        0x0036
- */
-#define HC_HABLAsat_MASK        0x00010000
-#define HC_HABLAa_MASK          0x0000fc00
-#define HC_HABLAa_A_MASK        0x0000c000
-#define HC_HABLAa_OPA_MASK      0x00003c00
-#define HC_HABLFAa_MASK         0x000003f0
-#define HC_HABLFAa_A_MASK       0x00000300
-#define HC_HABLFAa_OPA_MASK     0x000000f0
-#define HC_HABLAbias_MASK       0x0000000f
-#define HC_HABLAbias_A_MASK     0x00000008
-#define HC_HABLAbias_OPA_MASK   0x00000007
-#define HC_HABLAa_OPA           (HC_XA_OPA << 10)
-#define HC_HABLAa_InvOPA        (HC_XA_InvOPA << 10)
-#define HC_HABLAa_OPAp5         (HC_XA_OPAp5 << 10)
-#define HC_HABLAa_0             (HC_XA_0 << 10)
-#define HC_HABLAa_Asrc          (HC_XA_Asrc << 10)
-#define HC_HABLAa_Adst          (HC_XA_Adst << 10)
-#define HC_HABLAa_Fog           (HC_XA_Fog << 10)
-#define HC_HABLAa_minAsrcFog    (HC_XA_minAsrcFog << 10)
-#define HC_HABLAa_minAsrcAdst   (HC_XA_minAsrcAdst << 10)
-#define HC_HABLAa_maxAsrcFog    (HC_XA_maxAsrcFog << 10)
-#define HC_HABLAa_maxAsrcAdst   (HC_XA_maxAsrcAdst << 10)
-#define HC_HABLAa_HABLRA        (HC_XA_HABLRA << 10)
-#define HC_HABLFAa_OPA          (HC_XA_OPA << 4)
-#define HC_HABLFAa_InvOPA       (HC_XA_InvOPA << 4)
-#define HC_HABLFAa_OPAp5        (HC_XA_OPAp5 << 4)
-#define HC_HABLFAa_0            (HC_XA_0 << 4)
-#define HC_HABLFAa_Asrc         (HC_XA_Asrc << 4)
-#define HC_HABLFAa_Adst         (HC_XA_Adst << 4)
-#define HC_HABLFAa_Fog          (HC_XA_Fog << 4)
-#define HC_HABLFAa_minAsrcFog   (HC_XA_minAsrcFog << 4)
-#define HC_HABLFAa_minAsrcAdst  (HC_XA_minAsrcAdst << 4)
-#define HC_HABLFAa_maxAsrcFog   (HC_XA_maxAsrcFog << 4)
-#define HC_HABLFAa_maxAsrcAdst  (HC_XA_maxAsrcAdst << 4)
-#define HC_HABLFAa_minAsrcInvAdst   (HC_XA_minAsrcInvAdst << 4)
-#define HC_HABLFAa_HABLFRA          (HC_XA_HABLFRA << 4)
-#define HC_HABLAbias_HABLRAbias 0x00000000
-#define HC_HABLAbias_Asrc       0x00000001
-#define HC_HABLAbias_Adst       0x00000002
-#define HC_HABLAbias_Fog        0x00000003
-#define HC_HABLAbias_Aaa        0x00000004
-/* HC_SubA_HABLAop         0x0037
- */
-#define HC_HABLAop_MASK         0x00004000
-#define HC_HABLAb_MASK          0x00003f00
-#define HC_HABLAb_OPA_MASK      0x00000f00
-#define HC_HABLFAb_MASK         0x000000fc
-#define HC_HABLFAb_OPA_MASK     0x0000003c
-#define HC_HABLAshift_MASK      0x00000003
-#define HC_HABLAb_OPA           (HC_XA_OPA << 8)
-#define HC_HABLAb_InvOPA        (HC_XA_InvOPA << 8)
-#define HC_HABLAb_OPAp5         (HC_XA_OPAp5 << 8)
-#define HC_HABLAb_0             (HC_XA_0 << 8)
-#define HC_HABLAb_Asrc          (HC_XA_Asrc << 8)
-#define HC_HABLAb_Adst          (HC_XA_Adst << 8)
-#define HC_HABLAb_Fog           (HC_XA_Fog << 8)
-#define HC_HABLAb_minAsrcFog    (HC_XA_minAsrcFog << 8)
-#define HC_HABLAb_minAsrcAdst   (HC_XA_minAsrcAdst << 8)
-#define HC_HABLAb_maxAsrcFog    (HC_XA_maxAsrcFog << 8)
-#define HC_HABLAb_maxAsrcAdst   (HC_XA_maxAsrcAdst << 8)
-#define HC_HABLAb_HABLRA        (HC_XA_HABLRA << 8)
-#define HC_HABLFAb_OPA          (HC_XA_OPA << 2)
-#define HC_HABLFAb_InvOPA       (HC_XA_InvOPA << 2)
-#define HC_HABLFAb_OPAp5        (HC_XA_OPAp5 << 2)
-#define HC_HABLFAb_0            (HC_XA_0 << 2)
-#define HC_HABLFAb_Asrc         (HC_XA_Asrc << 2)
-#define HC_HABLFAb_Adst         (HC_XA_Adst << 2)
-#define HC_HABLFAb_Fog          (HC_XA_Fog << 2)
-#define HC_HABLFAb_minAsrcFog   (HC_XA_minAsrcFog << 2)
-#define HC_HABLFAb_minAsrcAdst  (HC_XA_minAsrcAdst << 2)
-#define HC_HABLFAb_maxAsrcFog   (HC_XA_maxAsrcFog << 2)
-#define HC_HABLFAb_maxAsrcAdst  (HC_XA_maxAsrcAdst << 2)
-#define HC_HABLFAb_minAsrcInvAdst   (HC_XA_minAsrcInvAdst << 2)
-#define HC_HABLFAb_HABLFRA          (HC_XA_HABLFRA << 2)
-/* HC_SubA_HABLRAa         0x003d
- */
-#define HC_HABLRAa_MASK         0x00ff0000
-#define HC_HABLRFAa_MASK        0x0000ff00
-#define HC_HABLRAbias_MASK      0x000000ff
-#define HC_HABLRAa_SHIFT        16
-#define HC_HABLRFAa_SHIFT       8
-/* HC_SubA_HABLRAb         0x003e
- */
-#define HC_HABLRAb_MASK         0x0000ff00
-#define HC_HABLRFAb_MASK        0x000000ff
-#define HC_HABLRAb_SHIFT        8
-
-/* Destination Setting
- */
-#define HC_SubA_HDBBasL         0x0040
-#define HC_SubA_HDBBasH         0x0041
-#define HC_SubA_HDBFM           0x0042
-#define HC_SubA_HFBBMSKL        0x0043
-#define HC_SubA_HROP            0x0044
-/* HC_SubA_HDBFM           0x0042
- */
-#define HC_HDBFM_MASK           0x001f0000
-#define HC_HDBLoc_MASK          0x0000c000
-#define HC_HDBPit_MASK          0x00003fff
-#define HC_HDBFM_RGB555         0x00000000
-#define HC_HDBFM_RGB565         0x00010000
-#define HC_HDBFM_ARGB4444       0x00020000
-#define HC_HDBFM_ARGB1555       0x00030000
-#define HC_HDBFM_BGR555         0x00040000
-#define HC_HDBFM_BGR565         0x00050000
-#define HC_HDBFM_ABGR4444       0x00060000
-#define HC_HDBFM_ABGR1555       0x00070000
-#define HC_HDBFM_ARGB0888       0x00080000
-#define HC_HDBFM_ARGB8888       0x00090000
-#define HC_HDBFM_ABGR0888       0x000a0000
-#define HC_HDBFM_ABGR8888       0x000b0000
-#define HC_HDBLoc_Local         0x00000000
-#define HC_HDBLoc_Sys           0x00004000
-/* HC_SubA_HROP            0x0044
- */
-#define HC_HROP_MASK            0x00000f00
-#define HC_HFBBMSKH_MASK        0x000000ff
-#define HC_HROP_BLACK           0x00000000
-#define HC_HROP_DPon            0x00000100
-#define HC_HROP_DPna            0x00000200
-#define HC_HROP_Pn              0x00000300
-#define HC_HROP_PDna            0x00000400
-#define HC_HROP_Dn              0x00000500
-#define HC_HROP_DPx             0x00000600
-#define HC_HROP_DPan            0x00000700
-#define HC_HROP_DPa             0x00000800
-#define HC_HROP_DPxn            0x00000900
-#define HC_HROP_D               0x00000a00
-#define HC_HROP_DPno            0x00000b00
-#define HC_HROP_P               0x00000c00
-#define HC_HROP_PDno            0x00000d00
-#define HC_HROP_DPo             0x00000e00
-#define HC_HROP_WHITE           0x00000f00
-
-/* Fog Setting
- */
-#define HC_SubA_HFogLF          0x0050
-#define HC_SubA_HFogCL          0x0051
-#define HC_SubA_HFogCH          0x0052
-#define HC_SubA_HFogStL         0x0053
-#define HC_SubA_HFogStH         0x0054
-#define HC_SubA_HFogOOdMF       0x0055
-#define HC_SubA_HFogOOdEF       0x0056
-#define HC_SubA_HFogEndL        0x0057
-#define HC_SubA_HFogDenst       0x0058
-/* HC_SubA_FogLF           0x0050
- */
-#define HC_FogLF_MASK           0x00000010
-#define HC_FogEq_MASK           0x00000008
-#define HC_FogMD_MASK           0x00000007
-#define HC_FogMD_LocalFog        0x00000000
-#define HC_FogMD_LinearFog       0x00000002
-#define HC_FogMD_ExponentialFog  0x00000004
-#define HC_FogMD_Exponential2Fog 0x00000005
-/* #define HC_FogMD_FogTable       0x00000003 */
-
-/* HC_SubA_HFogDenst        0x0058
- */
-#define HC_FogDenst_MASK        0x001fff00
-#define HC_FogEndL_MASK         0x000000ff
-
-/* Texture subtype definitions
- */
-#define HC_SubType_Tex0         0x00000000
-#define HC_SubType_Tex1         0x00000001
-#define HC_SubType_TexGeneral   0x000000fe
-
-/* Attribute of texture n
- */
-#define HC_SubA_HTXnL0BasL      0x0000
-#define HC_SubA_HTXnL1BasL      0x0001
-#define HC_SubA_HTXnL2BasL      0x0002
-#define HC_SubA_HTXnL3BasL      0x0003
-#define HC_SubA_HTXnL4BasL      0x0004
-#define HC_SubA_HTXnL5BasL      0x0005
-#define HC_SubA_HTXnL6BasL      0x0006
-#define HC_SubA_HTXnL7BasL      0x0007
-#define HC_SubA_HTXnL8BasL      0x0008
-#define HC_SubA_HTXnL9BasL      0x0009
-#define HC_SubA_HTXnLaBasL      0x000a
-#define HC_SubA_HTXnLbBasL      0x000b
-#define HC_SubA_HTXnLcBasL      0x000c
-#define HC_SubA_HTXnLdBasL      0x000d
-#define HC_SubA_HTXnLeBasL      0x000e
-#define HC_SubA_HTXnLfBasL      0x000f
-#define HC_SubA_HTXnL10BasL     0x0010
-#define HC_SubA_HTXnL11BasL     0x0011
-#define HC_SubA_HTXnL012BasH    0x0020
-#define HC_SubA_HTXnL345BasH    0x0021
-#define HC_SubA_HTXnL678BasH    0x0022
-#define HC_SubA_HTXnL9abBasH    0x0023
-#define HC_SubA_HTXnLcdeBasH    0x0024
-#define HC_SubA_HTXnLf1011BasH  0x0025
-#define HC_SubA_HTXnL0Pit       0x002b
-#define HC_SubA_HTXnL1Pit       0x002c
-#define HC_SubA_HTXnL2Pit       0x002d
-#define HC_SubA_HTXnL3Pit       0x002e
-#define HC_SubA_HTXnL4Pit       0x002f
-#define HC_SubA_HTXnL5Pit       0x0030
-#define HC_SubA_HTXnL6Pit       0x0031
-#define HC_SubA_HTXnL7Pit       0x0032
-#define HC_SubA_HTXnL8Pit       0x0033
-#define HC_SubA_HTXnL9Pit       0x0034
-#define HC_SubA_HTXnLaPit       0x0035
-#define HC_SubA_HTXnLbPit       0x0036
-#define HC_SubA_HTXnLcPit       0x0037
-#define HC_SubA_HTXnLdPit       0x0038
-#define HC_SubA_HTXnLePit       0x0039
-#define HC_SubA_HTXnLfPit       0x003a
-#define HC_SubA_HTXnL10Pit      0x003b
-#define HC_SubA_HTXnL11Pit      0x003c
-#define HC_SubA_HTXnL0_5WE      0x004b
-#define HC_SubA_HTXnL6_bWE      0x004c
-#define HC_SubA_HTXnLc_11WE     0x004d
-#define HC_SubA_HTXnL0_5HE      0x0051
-#define HC_SubA_HTXnL6_bHE      0x0052
-#define HC_SubA_HTXnLc_11HE     0x0053
-#define HC_SubA_HTXnL0OS        0x0077
-#define HC_SubA_HTXnTB          0x0078
-#define HC_SubA_HTXnMPMD        0x0079
-#define HC_SubA_HTXnCLODu       0x007a
-#define HC_SubA_HTXnFM          0x007b
-#define HC_SubA_HTXnTRCH        0x007c
-#define HC_SubA_HTXnTRCL        0x007d
-#define HC_SubA_HTXnTBC         0x007e
-#define HC_SubA_HTXnTRAH        0x007f
-#define HC_SubA_HTXnTBLCsat     0x0080
-#define HC_SubA_HTXnTBLCop      0x0081
-#define HC_SubA_HTXnTBLMPfog    0x0082
-#define HC_SubA_HTXnTBLAsat     0x0083
-#define HC_SubA_HTXnTBLRCa      0x0085
-#define HC_SubA_HTXnTBLRCb      0x0086
-#define HC_SubA_HTXnTBLRCc      0x0087
-#define HC_SubA_HTXnTBLRCbias   0x0088
-#define HC_SubA_HTXnTBLRAa      0x0089
-#define HC_SubA_HTXnTBLRFog     0x008a
-#define HC_SubA_HTXnBumpM00     0x0090
-#define HC_SubA_HTXnBumpM01     0x0091
-#define HC_SubA_HTXnBumpM10     0x0092
-#define HC_SubA_HTXnBumpM11     0x0093
-#define HC_SubA_HTXnLScale      0x0094
-#define HC_SubA_HTXSMD          0x0000
-/* HC_SubA_HTXnL012BasH    0x0020
- */
-#define HC_HTXnL0BasH_MASK      0x000000ff
-#define HC_HTXnL1BasH_MASK      0x0000ff00
-#define HC_HTXnL2BasH_MASK      0x00ff0000
-#define HC_HTXnL1BasH_SHIFT     8
-#define HC_HTXnL2BasH_SHIFT     16
-/* HC_SubA_HTXnL345BasH    0x0021
- */
-#define HC_HTXnL3BasH_MASK      0x000000ff
-#define HC_HTXnL4BasH_MASK      0x0000ff00
-#define HC_HTXnL5BasH_MASK      0x00ff0000
-#define HC_HTXnL4BasH_SHIFT     8
-#define HC_HTXnL5BasH_SHIFT     16
-/* HC_SubA_HTXnL678BasH    0x0022
- */
-#define HC_HTXnL6BasH_MASK      0x000000ff
-#define HC_HTXnL7BasH_MASK      0x0000ff00
-#define HC_HTXnL8BasH_MASK      0x00ff0000
-#define HC_HTXnL7BasH_SHIFT     8
-#define HC_HTXnL8BasH_SHIFT     16
-/* HC_SubA_HTXnL9abBasH    0x0023
- */
-#define HC_HTXnL9BasH_MASK      0x000000ff
-#define HC_HTXnLaBasH_MASK      0x0000ff00
-#define HC_HTXnLbBasH_MASK      0x00ff0000
-#define HC_HTXnLaBasH_SHIFT     8
-#define HC_HTXnLbBasH_SHIFT     16
-/* HC_SubA_HTXnLcdeBasH    0x0024
- */
-#define HC_HTXnLcBasH_MASK      0x000000ff
-#define HC_HTXnLdBasH_MASK      0x0000ff00
-#define HC_HTXnLeBasH_MASK      0x00ff0000
-#define HC_HTXnLdBasH_SHIFT     8
-#define HC_HTXnLeBasH_SHIFT     16
-/* HC_SubA_HTXnLcdeBasH    0x0025
- */
-#define HC_HTXnLfBasH_MASK      0x000000ff
-#define HC_HTXnL10BasH_MASK      0x0000ff00
-#define HC_HTXnL11BasH_MASK      0x00ff0000
-#define HC_HTXnL10BasH_SHIFT     8
-#define HC_HTXnL11BasH_SHIFT     16
-/* HC_SubA_HTXnL0Pit       0x002b
- */
-#define HC_HTXnLnPit_MASK       0x00003fff
-#define HC_HTXnEnPit_MASK       0x00080000
-#define HC_HTXnLnPitE_MASK      0x00f00000
-#define HC_HTXnLnPitE_SHIFT     20
-/* HC_SubA_HTXnL0_5WE      0x004b
- */
-#define HC_HTXnL0WE_MASK        0x0000000f
-#define HC_HTXnL1WE_MASK        0x000000f0
-#define HC_HTXnL2WE_MASK        0x00000f00
-#define HC_HTXnL3WE_MASK        0x0000f000
-#define HC_HTXnL4WE_MASK        0x000f0000
-#define HC_HTXnL5WE_MASK        0x00f00000
-#define HC_HTXnL1WE_SHIFT       4
-#define HC_HTXnL2WE_SHIFT       8
-#define HC_HTXnL3WE_SHIFT       12
-#define HC_HTXnL4WE_SHIFT       16
-#define HC_HTXnL5WE_SHIFT       20
-/* HC_SubA_HTXnL6_bWE      0x004c
- */
-#define HC_HTXnL6WE_MASK        0x0000000f
-#define HC_HTXnL7WE_MASK        0x000000f0
-#define HC_HTXnL8WE_MASK        0x00000f00
-#define HC_HTXnL9WE_MASK        0x0000f000
-#define HC_HTXnLaWE_MASK        0x000f0000
-#define HC_HTXnLbWE_MASK        0x00f00000
-#define HC_HTXnL7WE_SHIFT       4
-#define HC_HTXnL8WE_SHIFT       8
-#define HC_HTXnL9WE_SHIFT       12
-#define HC_HTXnLaWE_SHIFT       16
-#define HC_HTXnLbWE_SHIFT       20
-/* HC_SubA_HTXnLc_11WE      0x004d
- */
-#define HC_HTXnLcWE_MASK        0x0000000f
-#define HC_HTXnLdWE_MASK        0x000000f0
-#define HC_HTXnLeWE_MASK        0x00000f00
-#define HC_HTXnLfWE_MASK        0x0000f000
-#define HC_HTXnL10WE_MASK       0x000f0000
-#define HC_HTXnL11WE_MASK       0x00f00000
-#define HC_HTXnLdWE_SHIFT       4
-#define HC_HTXnLeWE_SHIFT       8
-#define HC_HTXnLfWE_SHIFT       12
-#define HC_HTXnL10WE_SHIFT      16
-#define HC_HTXnL11WE_SHIFT      20
-/* HC_SubA_HTXnL0_5HE      0x0051
- */
-#define HC_HTXnL0HE_MASK        0x0000000f
-#define HC_HTXnL1HE_MASK        0x000000f0
-#define HC_HTXnL2HE_MASK        0x00000f00
-#define HC_HTXnL3HE_MASK        0x0000f000
-#define HC_HTXnL4HE_MASK        0x000f0000
-#define HC_HTXnL5HE_MASK        0x00f00000
-#define HC_HTXnL1HE_SHIFT       4
-#define HC_HTXnL2HE_SHIFT       8
-#define HC_HTXnL3HE_SHIFT       12
-#define HC_HTXnL4HE_SHIFT       16
-#define HC_HTXnL5HE_SHIFT       20
-/* HC_SubA_HTXnL6_bHE      0x0052
- */
-#define HC_HTXnL6HE_MASK        0x0000000f
-#define HC_HTXnL7HE_MASK        0x000000f0
-#define HC_HTXnL8HE_MASK        0x00000f00
-#define HC_HTXnL9HE_MASK        0x0000f000
-#define HC_HTXnLaHE_MASK        0x000f0000
-#define HC_HTXnLbHE_MASK        0x00f00000
-#define HC_HTXnL7HE_SHIFT       4
-#define HC_HTXnL8HE_SHIFT       8
-#define HC_HTXnL9HE_SHIFT       12
-#define HC_HTXnLaHE_SHIFT       16
-#define HC_HTXnLbHE_SHIFT       20
-/* HC_SubA_HTXnLc_11HE      0x0053
- */
-#define HC_HTXnLcHE_MASK        0x0000000f
-#define HC_HTXnLdHE_MASK        0x000000f0
-#define HC_HTXnLeHE_MASK        0x00000f00
-#define HC_HTXnLfHE_MASK        0x0000f000
-#define HC_HTXnL10HE_MASK       0x000f0000
-#define HC_HTXnL11HE_MASK       0x00f00000
-#define HC_HTXnLdHE_SHIFT       4
-#define HC_HTXnLeHE_SHIFT       8
-#define HC_HTXnLfHE_SHIFT       12
-#define HC_HTXnL10HE_SHIFT      16
-#define HC_HTXnL11HE_SHIFT      20
-/* HC_SubA_HTXnL0OS        0x0077
- */
-#define HC_HTXnL0OS_MASK        0x003ff000
-#define HC_HTXnLVmax_MASK       0x00000fc0
-#define HC_HTXnLVmin_MASK       0x0000003f
-#define HC_HTXnL0OS_SHIFT       12
-#define HC_HTXnLVmax_SHIFT      6
-/* HC_SubA_HTXnTB          0x0078
- */
-#define HC_HTXnTB_MASK          0x00f00000
-#define HC_HTXnFLSe_MASK        0x0000e000
-#define HC_HTXnFLSs_MASK        0x00001c00
-#define HC_HTXnFLTe_MASK        0x00000380
-#define HC_HTXnFLTs_MASK        0x00000070
-#define HC_HTXnFLDs_MASK        0x0000000f
-#define HC_HTXnTB_NoTB          0x00000000
-#define HC_HTXnTB_TBC_S         0x00100000
-#define HC_HTXnTB_TBC_T         0x00200000
-#define HC_HTXnTB_TB_S          0x00400000
-#define HC_HTXnTB_TB_T          0x00800000
-#define HC_HTXnFLSe_Nearest     0x00000000
-#define HC_HTXnFLSe_Linear      0x00002000
-#define HC_HTXnFLSe_NonLinear   0x00004000
-#define HC_HTXnFLSe_Sharp       0x00008000
-#define HC_HTXnFLSe_Flat_Gaussian_Cubic 0x0000c000
-#define HC_HTXnFLSs_Nearest     0x00000000
-#define HC_HTXnFLSs_Linear      0x00000400
-#define HC_HTXnFLSs_NonLinear   0x00000800
-#define HC_HTXnFLSs_Flat_Gaussian_Cubic 0x00001800
-#define HC_HTXnFLTe_Nearest     0x00000000
-#define HC_HTXnFLTe_Linear      0x00000080
-#define HC_HTXnFLTe_NonLinear   0x00000100
-#define HC_HTXnFLTe_Sharp       0x00000180
-#define HC_HTXnFLTe_Flat_Gaussian_Cubic 0x00000300
-#define HC_HTXnFLTs_Nearest     0x00000000
-#define HC_HTXnFLTs_Linear      0x00000010
-#define HC_HTXnFLTs_NonLinear   0x00000020
-#define HC_HTXnFLTs_Flat_Gaussian_Cubic 0x00000060
-#define HC_HTXnFLDs_Tex0        0x00000000
-#define HC_HTXnFLDs_Nearest     0x00000001
-#define HC_HTXnFLDs_Linear      0x00000002
-#define HC_HTXnFLDs_NonLinear   0x00000003
-#define HC_HTXnFLDs_Dither      0x00000004
-#define HC_HTXnFLDs_ConstLOD    0x00000005
-#define HC_HTXnFLDs_Ani         0x00000006
-#define HC_HTXnFLDs_AniDither   0x00000007
-/* HC_SubA_HTXnMPMD        0x0079
- */
-#define HC_HTXnMPMD_SMASK       0x00070000
-#define HC_HTXnMPMD_TMASK       0x00380000
-#define HC_HTXnLODDTf_MASK      0x00000007
-#define HC_HTXnXY2ST_MASK       0x00000008
-#define HC_HTXnMPMD_Tsingle     0x00000000
-#define HC_HTXnMPMD_Tclamp      0x00080000
-#define HC_HTXnMPMD_Trepeat     0x00100000
-#define HC_HTXnMPMD_Tmirror     0x00180000
-#define HC_HTXnMPMD_Twrap       0x00200000
-#define HC_HTXnMPMD_Ssingle     0x00000000
-#define HC_HTXnMPMD_Sclamp      0x00010000
-#define HC_HTXnMPMD_Srepeat     0x00020000
-#define HC_HTXnMPMD_Smirror     0x00030000
-#define HC_HTXnMPMD_Swrap       0x00040000
-/* HC_SubA_HTXnCLODu       0x007a
- */
-#define HC_HTXnCLODu_MASK       0x000ffc00
-#define HC_HTXnCLODd_MASK       0x000003ff
-#define HC_HTXnCLODu_SHIFT      10
-/* HC_SubA_HTXnFM          0x007b
- */
-#define HC_HTXnFM_MASK          0x00ff0000
-#define HC_HTXnLoc_MASK         0x00000003
-#define HC_HTXnFM_INDEX         0x00000000
-#define HC_HTXnFM_Intensity     0x00080000
-#define HC_HTXnFM_Lum           0x00100000
-#define HC_HTXnFM_Alpha         0x00180000
-#define HC_HTXnFM_DX            0x00280000
-#define HC_HTXnFM_ARGB16        0x00880000
-#define HC_HTXnFM_ARGB32        0x00980000
-#define HC_HTXnFM_ABGR16        0x00a80000
-#define HC_HTXnFM_ABGR32        0x00b80000
-#define HC_HTXnFM_RGBA16        0x00c80000
-#define HC_HTXnFM_RGBA32        0x00d80000
-#define HC_HTXnFM_BGRA16        0x00e80000
-#define HC_HTXnFM_BGRA32        0x00f80000
-#define HC_HTXnFM_BUMPMAP       0x00380000
-#define HC_HTXnFM_Index1        (HC_HTXnFM_INDEX     | 0x00000000)
-#define HC_HTXnFM_Index2        (HC_HTXnFM_INDEX     | 0x00010000)
-#define HC_HTXnFM_Index4        (HC_HTXnFM_INDEX     | 0x00020000)
-#define HC_HTXnFM_Index8        (HC_HTXnFM_INDEX     | 0x00030000)
-#define HC_HTXnFM_T1            (HC_HTXnFM_Intensity | 0x00000000)
-#define HC_HTXnFM_T2            (HC_HTXnFM_Intensity | 0x00010000)
-#define HC_HTXnFM_T4            (HC_HTXnFM_Intensity | 0x00020000)
-#define HC_HTXnFM_T8            (HC_HTXnFM_Intensity | 0x00030000)
-#define HC_HTXnFM_L1            (HC_HTXnFM_Lum       | 0x00000000)
-#define HC_HTXnFM_L2            (HC_HTXnFM_Lum       | 0x00010000)
-#define HC_HTXnFM_L4            (HC_HTXnFM_Lum       | 0x00020000)
-#define HC_HTXnFM_L8            (HC_HTXnFM_Lum       | 0x00030000)
-#define HC_HTXnFM_AL44          (HC_HTXnFM_Lum       | 0x00040000)
-#define HC_HTXnFM_AL88          (HC_HTXnFM_Lum       | 0x00050000)
-#define HC_HTXnFM_A1            (HC_HTXnFM_Alpha     | 0x00000000)
-#define HC_HTXnFM_A2            (HC_HTXnFM_Alpha     | 0x00010000)
-#define HC_HTXnFM_A4            (HC_HTXnFM_Alpha     | 0x00020000)
-#define HC_HTXnFM_A8            (HC_HTXnFM_Alpha     | 0x00030000)
-#define HC_HTXnFM_DX1           (HC_HTXnFM_DX        | 0x00010000)
-#define HC_HTXnFM_DX23          (HC_HTXnFM_DX        | 0x00020000)
-#define HC_HTXnFM_DX45          (HC_HTXnFM_DX        | 0x00030000)
-#define HC_HTXnFM_RGB555        (HC_HTXnFM_ARGB16    | 0x00000000)
-#define HC_HTXnFM_RGB565        (HC_HTXnFM_ARGB16    | 0x00010000)
-#define HC_HTXnFM_ARGB1555      (HC_HTXnFM_ARGB16    | 0x00020000)
-#define HC_HTXnFM_ARGB4444      (HC_HTXnFM_ARGB16    | 0x00030000)
-#define HC_HTXnFM_ARGB0888      (HC_HTXnFM_ARGB32    | 0x00000000)
-#define HC_HTXnFM_ARGB8888      (HC_HTXnFM_ARGB32    | 0x00010000)
-#define HC_HTXnFM_BGR555        (HC_HTXnFM_ABGR16    | 0x00000000)
-#define HC_HTXnFM_BGR565        (HC_HTXnFM_ABGR16    | 0x00010000)
-#define HC_HTXnFM_ABGR1555      (HC_HTXnFM_ABGR16    | 0x00020000)
-#define HC_HTXnFM_ABGR4444      (HC_HTXnFM_ABGR16    | 0x00030000)
-#define HC_HTXnFM_ABGR0888      (HC_HTXnFM_ABGR32    | 0x00000000)
-#define HC_HTXnFM_ABGR8888      (HC_HTXnFM_ABGR32    | 0x00010000)
-#define HC_HTXnFM_RGBA5550      (HC_HTXnFM_RGBA16    | 0x00000000)
-#define HC_HTXnFM_RGBA5551      (HC_HTXnFM_RGBA16    | 0x00020000)
-#define HC_HTXnFM_RGBA4444      (HC_HTXnFM_RGBA16    | 0x00030000)
-#define HC_HTXnFM_RGBA8880      (HC_HTXnFM_RGBA32    | 0x00000000)
-#define HC_HTXnFM_RGBA8888      (HC_HTXnFM_RGBA32    | 0x00010000)
-#define HC_HTXnFM_BGRA5550      (HC_HTXnFM_BGRA16    | 0x00000000)
-#define HC_HTXnFM_BGRA5551      (HC_HTXnFM_BGRA16    | 0x00020000)
-#define HC_HTXnFM_BGRA4444      (HC_HTXnFM_BGRA16    | 0x00030000)
-#define HC_HTXnFM_BGRA8880      (HC_HTXnFM_BGRA32    | 0x00000000)
-#define HC_HTXnFM_BGRA8888      (HC_HTXnFM_BGRA32    | 0x00010000)
-#define HC_HTXnFM_VU88          (HC_HTXnFM_BUMPMAP   | 0x00000000)
-#define HC_HTXnFM_LVU655        (HC_HTXnFM_BUMPMAP   | 0x00010000)
-#define HC_HTXnFM_LVU888        (HC_HTXnFM_BUMPMAP   | 0x00020000)
-#define HC_HTXnLoc_Local        0x00000000
-#define HC_HTXnLoc_Sys          0x00000002
-#define HC_HTXnLoc_AGP          0x00000003
-/* HC_SubA_HTXnTRAH        0x007f
- */
-#define HC_HTXnTRAH_MASK        0x00ff0000
-#define HC_HTXnTRAL_MASK        0x0000ff00
-#define HC_HTXnTBA_MASK         0x000000ff
-#define HC_HTXnTRAH_SHIFT       16
-#define HC_HTXnTRAL_SHIFT       8
-/* HC_SubA_HTXnTBLCsat     0x0080
- *-- Define the input texture.
- */
-#define HC_XTC_TOPC             0x00000000
-#define HC_XTC_InvTOPC          0x00000010
-#define HC_XTC_TOPCp5           0x00000020
-#define HC_XTC_Cbias            0x00000000
-#define HC_XTC_InvCbias         0x00000010
-#define HC_XTC_0                0x00000000
-#define HC_XTC_Dif              0x00000001
-#define HC_XTC_Spec             0x00000002
-#define HC_XTC_Tex              0x00000003
-#define HC_XTC_Cur              0x00000004
-#define HC_XTC_Adif             0x00000005
-#define HC_XTC_Fog              0x00000006
-#define HC_XTC_Atex             0x00000007
-#define HC_XTC_Acur             0x00000008
-#define HC_XTC_HTXnTBLRC        0x00000009
-#define HC_XTC_Ctexnext         0x0000000a
-/*--
- */
-#define HC_HTXnTBLCsat_MASK     0x00800000
-#define HC_HTXnTBLCa_MASK       0x000fc000
-#define HC_HTXnTBLCb_MASK       0x00001f80
-#define HC_HTXnTBLCc_MASK       0x0000003f
-#define HC_HTXnTBLCa_TOPC       (HC_XTC_TOPC << 14)
-#define HC_HTXnTBLCa_InvTOPC    (HC_XTC_InvTOPC << 14)
-#define HC_HTXnTBLCa_TOPCp5     (HC_XTC_TOPCp5 << 14)
-#define HC_HTXnTBLCa_0          (HC_XTC_0 << 14)
-#define HC_HTXnTBLCa_Dif        (HC_XTC_Dif << 14)
-#define HC_HTXnTBLCa_Spec       (HC_XTC_Spec << 14)
-#define HC_HTXnTBLCa_Tex        (HC_XTC_Tex << 14)
-#define HC_HTXnTBLCa_Cur        (HC_XTC_Cur << 14)
-#define HC_HTXnTBLCa_Adif       (HC_XTC_Adif << 14)
-#define HC_HTXnTBLCa_Fog        (HC_XTC_Fog << 14)
-#define HC_HTXnTBLCa_Atex       (HC_XTC_Atex << 14)
-#define HC_HTXnTBLCa_Acur       (HC_XTC_Acur << 14)
-#define HC_HTXnTBLCa_HTXnTBLRC  (HC_XTC_HTXnTBLRC << 14)
-#define HC_HTXnTBLCa_Ctexnext   (HC_XTC_Ctexnext << 14)
-#define HC_HTXnTBLCb_TOPC       (HC_XTC_TOPC << 7)
-#define HC_HTXnTBLCb_InvTOPC    (HC_XTC_InvTOPC << 7)
-#define HC_HTXnTBLCb_TOPCp5     (HC_XTC_TOPCp5 << 7)
-#define HC_HTXnTBLCb_0          (HC_XTC_0 << 7)
-#define HC_HTXnTBLCb_Dif        (HC_XTC_Dif << 7)
-#define HC_HTXnTBLCb_Spec       (HC_XTC_Spec << 7)
-#define HC_HTXnTBLCb_Tex        (HC_XTC_Tex << 7)
-#define HC_HTXnTBLCb_Cur        (HC_XTC_Cur << 7)
-#define HC_HTXnTBLCb_Adif       (HC_XTC_Adif << 7)
-#define HC_HTXnTBLCb_Fog        (HC_XTC_Fog << 7)
-#define HC_HTXnTBLCb_Atex       (HC_XTC_Atex << 7)
-#define HC_HTXnTBLCb_Acur       (HC_XTC_Acur << 7)
-#define HC_HTXnTBLCb_HTXnTBLRC  (HC_XTC_HTXnTBLRC << 7)
-#define HC_HTXnTBLCb_Ctexnext   (HC_XTC_Ctexnext << 7)
-#define HC_HTXnTBLCc_TOPC       (HC_XTC_TOPC << 0)
-#define HC_HTXnTBLCc_InvTOPC    (HC_XTC_InvTOPC << 0)
-#define HC_HTXnTBLCc_TOPCp5     (HC_XTC_TOPCp5 << 0)
-#define HC_HTXnTBLCc_0          (HC_XTC_0 << 0)
-#define HC_HTXnTBLCc_Dif        (HC_XTC_Dif << 0)
-#define HC_HTXnTBLCc_Spec       (HC_XTC_Spec << 0)
-#define HC_HTXnTBLCc_Tex        (HC_XTC_Tex << 0)
-#define HC_HTXnTBLCc_Cur        (HC_XTC_Cur << 0)
-#define HC_HTXnTBLCc_Adif       (HC_XTC_Adif << 0)
-#define HC_HTXnTBLCc_Fog        (HC_XTC_Fog << 0)
-#define HC_HTXnTBLCc_Atex       (HC_XTC_Atex << 0)
-#define HC_HTXnTBLCc_Acur       (HC_XTC_Acur << 0)
-#define HC_HTXnTBLCc_HTXnTBLRC  (HC_XTC_HTXnTBLRC << 0)
-#define HC_HTXnTBLCc_Ctexnext   (HC_XTC_Ctexnext << 0)
-/* HC_SubA_HTXnTBLCop      0x0081
- */
-#define HC_HTXnTBLdot_MASK      0x00c00000
-#define HC_HTXnTBLCop_MASK      0x00380000
-#define HC_HTXnTBLCbias_MASK    0x0007c000
-#define HC_HTXnTBLCshift_MASK   0x00001800
-#define HC_HTXnTBLAop_MASK      0x00000380
-#define HC_HTXnTBLAbias_MASK    0x00000078
-#define HC_HTXnTBLAshift_MASK   0x00000003
-#define HC_HTXnTBLCop_Add       0x00000000
-#define HC_HTXnTBLCop_Sub       0x00080000
-#define HC_HTXnTBLCop_Min       0x00100000
-#define HC_HTXnTBLCop_Max       0x00180000
-#define HC_HTXnTBLCop_Mask      0x00200000
-#define HC_HTXnTBLCbias_Cbias           (HC_XTC_Cbias << 14)
-#define HC_HTXnTBLCbias_InvCbias        (HC_XTC_InvCbias << 14)
-#define HC_HTXnTBLCbias_0               (HC_XTC_0 << 14)
-#define HC_HTXnTBLCbias_Dif             (HC_XTC_Dif << 14)
-#define HC_HTXnTBLCbias_Spec            (HC_XTC_Spec << 14)
-#define HC_HTXnTBLCbias_Tex             (HC_XTC_Tex << 14)
-#define HC_HTXnTBLCbias_Cur             (HC_XTC_Cur << 14)
-#define HC_HTXnTBLCbias_Adif            (HC_XTC_Adif << 14)
-#define HC_HTXnTBLCbias_Fog             (HC_XTC_Fog << 14)
-#define HC_HTXnTBLCbias_Atex            (HC_XTC_Atex << 14)
-#define HC_HTXnTBLCbias_Acur            (HC_XTC_Acur << 14)
-#define HC_HTXnTBLCbias_HTXnTBLRC       (HC_XTC_HTXnTBLRC << 14)
-#define HC_HTXnTBLCshift_1      0x00000000
-#define HC_HTXnTBLCshift_2      0x00000800
-#define HC_HTXnTBLCshift_No     0x00001000
-#define HC_HTXnTBLCshift_DotP   0x00001800
-/*=* John Sheng [2003.7.18] texture combine *=*/
-#define HC_HTXnTBLDOT3   0x00080000
-#define HC_HTXnTBLDOT4   0x000C0000
-
-#define HC_HTXnTBLAop_Add       0x00000000
-#define HC_HTXnTBLAop_Sub       0x00000080
-#define HC_HTXnTBLAop_Min       0x00000100
-#define HC_HTXnTBLAop_Max       0x00000180
-#define HC_HTXnTBLAop_Mask      0x00000200
-#define HC_HTXnTBLAbias_Inv             0x00000040
-#define HC_HTXnTBLAbias_Adif            0x00000000
-#define HC_HTXnTBLAbias_Fog             0x00000008
-#define HC_HTXnTBLAbias_Acur            0x00000010
-#define HC_HTXnTBLAbias_HTXnTBLRAbias   0x00000018
-#define HC_HTXnTBLAbias_Atex            0x00000020
-#define HC_HTXnTBLAshift_1      0x00000000
-#define HC_HTXnTBLAshift_2      0x00000001
-#define HC_HTXnTBLAshift_No     0x00000002
-/* #define HC_HTXnTBLAshift_DotP   0x00000003 */
-/* HC_SubA_HTXnTBLMPFog    0x0082
- */
-#define HC_HTXnTBLMPfog_MASK    0x00e00000
-#define HC_HTXnTBLMPfog_0       0x00000000
-#define HC_HTXnTBLMPfog_Adif    0x00200000
-#define HC_HTXnTBLMPfog_Fog     0x00400000
-#define HC_HTXnTBLMPfog_Atex    0x00600000
-#define HC_HTXnTBLMPfog_Acur    0x00800000
-#define HC_HTXnTBLMPfog_GHTXnTBLRFog    0x00a00000
-/* HC_SubA_HTXnTBLAsat     0x0083
- *-- Define the texture alpha input.
- */
-#define HC_XTA_TOPA             0x00000000
-#define HC_XTA_InvTOPA          0x00000008
-#define HC_XTA_TOPAp5           0x00000010
-#define HC_XTA_Adif             0x00000000
-#define HC_XTA_Fog              0x00000001
-#define HC_XTA_Acur             0x00000002
-#define HC_XTA_HTXnTBLRA        0x00000003
-#define HC_XTA_Atex             0x00000004
-#define HC_XTA_Atexnext         0x00000005
-/*--
- */
-#define HC_HTXnTBLAsat_MASK     0x00800000
-#define HC_HTXnTBLAMB_MASK      0x00700000
-#define HC_HTXnTBLAa_MASK       0x0007c000
-#define HC_HTXnTBLAb_MASK       0x00000f80
-#define HC_HTXnTBLAc_MASK       0x0000001f
-#define HC_HTXnTBLAMB_SHIFT     20
-#define HC_HTXnTBLAa_TOPA       (HC_XTA_TOPA << 14)
-#define HC_HTXnTBLAa_InvTOPA    (HC_XTA_InvTOPA << 14)
-#define HC_HTXnTBLAa_TOPAp5     (HC_XTA_TOPAp5 << 14)
-#define HC_HTXnTBLAa_Adif       (HC_XTA_Adif << 14)
-#define HC_HTXnTBLAa_Fog        (HC_XTA_Fog << 14)
-#define HC_HTXnTBLAa_Acur       (HC_XTA_Acur << 14)
-#define HC_HTXnTBLAa_HTXnTBLRA  (HC_XTA_HTXnTBLRA << 14)
-#define HC_HTXnTBLAa_Atex       (HC_XTA_Atex << 14)
-#define HC_HTXnTBLAa_Atexnext   (HC_XTA_Atexnext << 14)
-#define HC_HTXnTBLAb_TOPA       (HC_XTA_TOPA << 7)
-#define HC_HTXnTBLAb_InvTOPA    (HC_XTA_InvTOPA << 7)
-#define HC_HTXnTBLAb_TOPAp5     (HC_XTA_TOPAp5 << 7)
-#define HC_HTXnTBLAb_Adif       (HC_XTA_Adif << 7)
-#define HC_HTXnTBLAb_Fog        (HC_XTA_Fog << 7)
-#define HC_HTXnTBLAb_Acur       (HC_XTA_Acur << 7)
-#define HC_HTXnTBLAb_HTXnTBLRA  (HC_XTA_HTXnTBLRA << 7)
-#define HC_HTXnTBLAb_Atex       (HC_XTA_Atex << 7)
-#define HC_HTXnTBLAb_Atexnext   (HC_XTA_Atexnext << 7)
-#define HC_HTXnTBLAc_TOPA       (HC_XTA_TOPA << 0)
-#define HC_HTXnTBLAc_InvTOPA    (HC_XTA_InvTOPA << 0)
-#define HC_HTXnTBLAc_TOPAp5     (HC_XTA_TOPAp5 << 0)
-#define HC_HTXnTBLAc_Adif       (HC_XTA_Adif << 0)
-#define HC_HTXnTBLAc_Fog        (HC_XTA_Fog << 0)
-#define HC_HTXnTBLAc_Acur       (HC_XTA_Acur << 0)
-#define HC_HTXnTBLAc_HTXnTBLRA  (HC_XTA_HTXnTBLRA << 0)
-#define HC_HTXnTBLAc_Atex       (HC_XTA_Atex << 0)
-#define HC_HTXnTBLAc_Atexnext   (HC_XTA_Atexnext << 0)
-/* HC_SubA_HTXnTBLRAa      0x0089
- */
-#define HC_HTXnTBLRAa_MASK      0x00ff0000
-#define HC_HTXnTBLRAb_MASK      0x0000ff00
-#define HC_HTXnTBLRAc_MASK      0x000000ff
-#define HC_HTXnTBLRAa_SHIFT     16
-#define HC_HTXnTBLRAb_SHIFT     8
-#define HC_HTXnTBLRAc_SHIFT     0
-/* HC_SubA_HTXnTBLRFog     0x008a
- */
-#define HC_HTXnTBLRFog_MASK     0x0000ff00
-#define HC_HTXnTBLRAbias_MASK   0x000000ff
-#define HC_HTXnTBLRFog_SHIFT    8
-#define HC_HTXnTBLRAbias_SHIFT  0
-/* HC_SubA_HTXnLScale      0x0094
- */
-#define HC_HTXnLScale_MASK      0x0007fc00
-#define HC_HTXnLOff_MASK        0x000001ff
-#define HC_HTXnLScale_SHIFT     10
-/* HC_SubA_HTXSMD          0x0000
- */
-#define HC_HTXSMD_MASK          0x00000080
-#define HC_HTXTMD_MASK          0x00000040
-#define HC_HTXNum_MASK          0x00000038
-#define HC_HTXTRMD_MASK         0x00000006
-#define HC_HTXCHCLR_MASK        0x00000001
-#define HC_HTXNum_SHIFT         3
-
-/* Texture Palette n
- */
-#define HC_SubType_TexPalette0  0x00000000
-#define HC_SubType_TexPalette1  0x00000001
-#define HC_SubType_FogTable     0x00000010
-#define HC_SubType_Stipple      0x00000014
-/* HC_SubA_TexPalette0     0x0000
- */
-#define HC_HTPnA_MASK           0xff000000
-#define HC_HTPnR_MASK           0x00ff0000
-#define HC_HTPnG_MASK           0x0000ff00
-#define HC_HTPnB_MASK           0x000000ff
-/* HC_SubA_FogTable        0x0010
- */
-#define HC_HFPn3_MASK           0xff000000
-#define HC_HFPn2_MASK           0x00ff0000
-#define HC_HFPn1_MASK           0x0000ff00
-#define HC_HFPn_MASK            0x000000ff
-#define HC_HFPn3_SHIFT          24
-#define HC_HFPn2_SHIFT          16
-#define HC_HFPn1_SHIFT          8
-
-/* Auto Testing & Security
- */
-#define HC_SubA_HenFIFOAT       0x0000
-#define HC_SubA_HFBDrawFirst    0x0004
-#define HC_SubA_HFBBasL         0x0005
-#define HC_SubA_HFBDst          0x0006
-/* HC_SubA_HenFIFOAT       0x0000
- */
-#define HC_HenFIFOAT_MASK       0x00000020
-#define HC_HenGEMILock_MASK     0x00000010
-#define HC_HenFBASwap_MASK      0x00000008
-#define HC_HenOT_MASK           0x00000004
-#define HC_HenCMDQ_MASK         0x00000002
-#define HC_HenTXCTSU_MASK       0x00000001
-/* HC_SubA_HFBDrawFirst    0x0004
- */
-#define HC_HFBDrawFirst_MASK    0x00000800
-#define HC_HFBQueue_MASK        0x00000400
-#define HC_HFBLock_MASK         0x00000200
-#define HC_HEOF_MASK            0x00000100
-#define HC_HFBBasH_MASK         0x000000ff
-
-/* GEMI Setting
- */
-#define HC_SubA_HTArbRCM        0x0008
-#define HC_SubA_HTArbRZ         0x000a
-#define HC_SubA_HTArbWZ         0x000b
-#define HC_SubA_HTArbRTX        0x000c
-#define HC_SubA_HTArbRCW        0x000d
-#define HC_SubA_HTArbE2         0x000e
-#define HC_SubA_HArbRQCM        0x0010
-#define HC_SubA_HArbWQCM        0x0011
-#define HC_SubA_HGEMITout       0x0020
-#define HC_SubA_HFthRTXD        0x0040
-#define HC_SubA_HFthRTXA        0x0044
-#define HC_SubA_HCMDQstL        0x0050
-#define HC_SubA_HCMDQendL       0x0051
-#define HC_SubA_HCMDQLen        0x0052
-/* HC_SubA_HTArbRCM        0x0008
- */
-#define HC_HTArbRCM_MASK        0x0000ffff
-/* HC_SubA_HTArbRZ         0x000a
- */
-#define HC_HTArbRZ_MASK         0x0000ffff
-/* HC_SubA_HTArbWZ         0x000b
- */
-#define HC_HTArbWZ_MASK         0x0000ffff
-/* HC_SubA_HTArbRTX        0x000c
- */
-#define HC_HTArbRTX_MASK        0x0000ffff
-/* HC_SubA_HTArbRCW        0x000d
- */
-#define HC_HTArbRCW_MASK        0x0000ffff
-/* HC_SubA_HTArbE2         0x000e
- */
-#define HC_HTArbE2_MASK         0x0000ffff
-/* HC_SubA_HArbRQCM        0x0010
- */
-#define HC_HTArbRQCM_MASK       0x0000ffff
-/* HC_SubA_HArbWQCM        0x0011
- */
-#define HC_HArbWQCM_MASK        0x0000ffff
-/* HC_SubA_HGEMITout       0x0020
- */
-#define HC_HGEMITout_MASK       0x000f0000
-#define HC_HNPArbZC_MASK        0x0000ffff
-#define HC_HGEMITout_SHIFT      16
-/* HC_SubA_HFthRTXD        0x0040
- */
-#define HC_HFthRTXD_MASK        0x00ff0000
-#define HC_HFthRZD_MASK         0x0000ff00
-#define HC_HFthWZD_MASK         0x000000ff
-#define HC_HFthRTXD_SHIFT       16
-#define HC_HFthRZD_SHIFT        8
-/* HC_SubA_HFthRTXA        0x0044
- */
-#define HC_HFthRTXA_MASK        0x000000ff
-
-/******************************************************************************
-** Define the Halcyon Internal register access constants. For simulator only.
-******************************************************************************/
-#define HC_SIMA_HAGPBstL        0x0000
-#define HC_SIMA_HAGPBendL       0x0001
-#define HC_SIMA_HAGPCMNT        0x0002
-#define HC_SIMA_HAGPBpL         0x0003
-#define HC_SIMA_HAGPBpH         0x0004
-#define HC_SIMA_HClipTB         0x0005
-#define HC_SIMA_HClipLR         0x0006
-#define HC_SIMA_HFPClipTL       0x0007
-#define HC_SIMA_HFPClipBL       0x0008
-#define HC_SIMA_HFPClipLL       0x0009
-#define HC_SIMA_HFPClipRL       0x000a
-#define HC_SIMA_HFPClipTBH      0x000b
-#define HC_SIMA_HFPClipLRH      0x000c
-#define HC_SIMA_HLP             0x000d
-#define HC_SIMA_HLPRF           0x000e
-#define HC_SIMA_HSolidCL        0x000f
-#define HC_SIMA_HPixGC          0x0010
-#define HC_SIMA_HSPXYOS         0x0011
-#define HC_SIMA_HCmdA           0x0012
-#define HC_SIMA_HCmdB           0x0013
-#define HC_SIMA_HEnable         0x0014
-#define HC_SIMA_HZWBBasL        0x0015
-#define HC_SIMA_HZWBBasH        0x0016
-#define HC_SIMA_HZWBType        0x0017
-#define HC_SIMA_HZBiasL         0x0018
-#define HC_SIMA_HZWBend         0x0019
-#define HC_SIMA_HZWTMD          0x001a
-#define HC_SIMA_HZWCDL          0x001b
-#define HC_SIMA_HZWCTAGnum      0x001c
-#define HC_SIMA_HZCYNum         0x001d
-#define HC_SIMA_HZWCFire        0x001e
-/* #define HC_SIMA_HSBBasL         0x001d */
-/* #define HC_SIMA_HSBBasH         0x001e */
-/* #define HC_SIMA_HSBFM           0x001f */
-#define HC_SIMA_HSTREF          0x0020
-#define HC_SIMA_HSTMD           0x0021
-#define HC_SIMA_HABBasL         0x0022
-#define HC_SIMA_HABBasH         0x0023
-#define HC_SIMA_HABFM           0x0024
-#define HC_SIMA_HATMD           0x0025
-#define HC_SIMA_HABLCsat        0x0026
-#define HC_SIMA_HABLCop         0x0027
-#define HC_SIMA_HABLAsat        0x0028
-#define HC_SIMA_HABLAop         0x0029
-#define HC_SIMA_HABLRCa         0x002a
-#define HC_SIMA_HABLRFCa        0x002b
-#define HC_SIMA_HABLRCbias      0x002c
-#define HC_SIMA_HABLRCb         0x002d
-#define HC_SIMA_HABLRFCb        0x002e
-#define HC_SIMA_HABLRAa         0x002f
-#define HC_SIMA_HABLRAb         0x0030
-#define HC_SIMA_HDBBasL         0x0031
-#define HC_SIMA_HDBBasH         0x0032
-#define HC_SIMA_HDBFM           0x0033
-#define HC_SIMA_HFBBMSKL        0x0034
-#define HC_SIMA_HROP            0x0035
-#define HC_SIMA_HFogLF          0x0036
-#define HC_SIMA_HFogCL          0x0037
-#define HC_SIMA_HFogCH          0x0038
-#define HC_SIMA_HFogStL         0x0039
-#define HC_SIMA_HFogStH         0x003a
-#define HC_SIMA_HFogOOdMF       0x003b
-#define HC_SIMA_HFogOOdEF       0x003c
-#define HC_SIMA_HFogEndL        0x003d
-#define HC_SIMA_HFogDenst       0x003e
-/*---- start of texture 0 setting ----
- */
-#define HC_SIMA_HTX0L0BasL      0x0040
-#define HC_SIMA_HTX0L1BasL      0x0041
-#define HC_SIMA_HTX0L2BasL      0x0042
-#define HC_SIMA_HTX0L3BasL      0x0043
-#define HC_SIMA_HTX0L4BasL      0x0044
-#define HC_SIMA_HTX0L5BasL      0x0045
-#define HC_SIMA_HTX0L6BasL      0x0046
-#define HC_SIMA_HTX0L7BasL      0x0047
-#define HC_SIMA_HTX0L8BasL      0x0048
-#define HC_SIMA_HTX0L9BasL      0x0049
-#define HC_SIMA_HTX0LaBasL      0x004a
-#define HC_SIMA_HTX0LbBasL      0x004b
-#define HC_SIMA_HTX0LcBasL      0x004c
-#define HC_SIMA_HTX0LdBasL      0x004d
-#define HC_SIMA_HTX0LeBasL      0x004e
-#define HC_SIMA_HTX0LfBasL      0x004f
-#define HC_SIMA_HTX0L10BasL     0x0050
-#define HC_SIMA_HTX0L11BasL     0x0051
-#define HC_SIMA_HTX0L012BasH    0x0052
-#define HC_SIMA_HTX0L345BasH    0x0053
-#define HC_SIMA_HTX0L678BasH    0x0054
-#define HC_SIMA_HTX0L9abBasH    0x0055
-#define HC_SIMA_HTX0LcdeBasH    0x0056
-#define HC_SIMA_HTX0Lf1011BasH  0x0057
-#define HC_SIMA_HTX0L0Pit       0x0058
-#define HC_SIMA_HTX0L1Pit       0x0059
-#define HC_SIMA_HTX0L2Pit       0x005a
-#define HC_SIMA_HTX0L3Pit       0x005b
-#define HC_SIMA_HTX0L4Pit       0x005c
-#define HC_SIMA_HTX0L5Pit       0x005d
-#define HC_SIMA_HTX0L6Pit       0x005e
-#define HC_SIMA_HTX0L7Pit       0x005f
-#define HC_SIMA_HTX0L8Pit       0x0060
-#define HC_SIMA_HTX0L9Pit       0x0061
-#define HC_SIMA_HTX0LaPit       0x0062
-#define HC_SIMA_HTX0LbPit       0x0063
-#define HC_SIMA_HTX0LcPit       0x0064
-#define HC_SIMA_HTX0LdPit       0x0065
-#define HC_SIMA_HTX0LePit       0x0066
-#define HC_SIMA_HTX0LfPit       0x0067
-#define HC_SIMA_HTX0L10Pit      0x0068
-#define HC_SIMA_HTX0L11Pit      0x0069
-#define HC_SIMA_HTX0L0_5WE      0x006a
-#define HC_SIMA_HTX0L6_bWE      0x006b
-#define HC_SIMA_HTX0Lc_11WE     0x006c
-#define HC_SIMA_HTX0L0_5HE      0x006d
-#define HC_SIMA_HTX0L6_bHE      0x006e
-#define HC_SIMA_HTX0Lc_11HE     0x006f
-#define HC_SIMA_HTX0L0OS        0x0070
-#define HC_SIMA_HTX0TB          0x0071
-#define HC_SIMA_HTX0MPMD        0x0072
-#define HC_SIMA_HTX0CLODu       0x0073
-#define HC_SIMA_HTX0FM          0x0074
-#define HC_SIMA_HTX0TRCH        0x0075
-#define HC_SIMA_HTX0TRCL        0x0076
-#define HC_SIMA_HTX0TBC         0x0077
-#define HC_SIMA_HTX0TRAH        0x0078
-#define HC_SIMA_HTX0TBLCsat     0x0079
-#define HC_SIMA_HTX0TBLCop      0x007a
-#define HC_SIMA_HTX0TBLMPfog    0x007b
-#define HC_SIMA_HTX0TBLAsat     0x007c
-#define HC_SIMA_HTX0TBLRCa      0x007d
-#define HC_SIMA_HTX0TBLRCb      0x007e
-#define HC_SIMA_HTX0TBLRCc      0x007f
-#define HC_SIMA_HTX0TBLRCbias   0x0080
-#define HC_SIMA_HTX0TBLRAa      0x0081
-#define HC_SIMA_HTX0TBLRFog     0x0082
-#define HC_SIMA_HTX0BumpM00     0x0083
-#define HC_SIMA_HTX0BumpM01     0x0084
-#define HC_SIMA_HTX0BumpM10     0x0085
-#define HC_SIMA_HTX0BumpM11     0x0086
-#define HC_SIMA_HTX0LScale      0x0087
-/*---- end of texture 0 setting ----      0x008f
- */
-#define HC_SIMA_TX0TX1_OFF      0x0050
-/*---- start of texture 1 setting ----
- */
-#define HC_SIMA_HTX1L0BasL      (HC_SIMA_HTX0L0BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L1BasL      (HC_SIMA_HTX0L1BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L2BasL      (HC_SIMA_HTX0L2BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L3BasL      (HC_SIMA_HTX0L3BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L4BasL      (HC_SIMA_HTX0L4BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L5BasL      (HC_SIMA_HTX0L5BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L6BasL      (HC_SIMA_HTX0L6BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L7BasL      (HC_SIMA_HTX0L7BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L8BasL      (HC_SIMA_HTX0L8BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L9BasL      (HC_SIMA_HTX0L9BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LaBasL      (HC_SIMA_HTX0LaBasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LbBasL      (HC_SIMA_HTX0LbBasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LcBasL      (HC_SIMA_HTX0LcBasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LdBasL      (HC_SIMA_HTX0LdBasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LeBasL      (HC_SIMA_HTX0LeBasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LfBasL      (HC_SIMA_HTX0LfBasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L10BasL     (HC_SIMA_HTX0L10BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L11BasL     (HC_SIMA_HTX0L11BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L012BasH    (HC_SIMA_HTX0L012BasH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L345BasH    (HC_SIMA_HTX0L345BasH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L678BasH    (HC_SIMA_HTX0L678BasH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L9abBasH    (HC_SIMA_HTX0L9abBasH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LcdeBasH    (HC_SIMA_HTX0LcdeBasH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1Lf1011BasH  (HC_SIMA_HTX0Lf1011BasH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L0Pit       (HC_SIMA_HTX0L0Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L1Pit       (HC_SIMA_HTX0L1Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L2Pit       (HC_SIMA_HTX0L2Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L3Pit       (HC_SIMA_HTX0L3Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L4Pit       (HC_SIMA_HTX0L4Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L5Pit       (HC_SIMA_HTX0L5Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L6Pit       (HC_SIMA_HTX0L6Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L7Pit       (HC_SIMA_HTX0L7Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L8Pit       (HC_SIMA_HTX0L8Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L9Pit       (HC_SIMA_HTX0L9Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LaPit       (HC_SIMA_HTX0LaPit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LbPit       (HC_SIMA_HTX0LbPit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LcPit       (HC_SIMA_HTX0LcPit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LdPit       (HC_SIMA_HTX0LdPit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LePit       (HC_SIMA_HTX0LePit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LfPit       (HC_SIMA_HTX0LfPit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L10Pit      (HC_SIMA_HTX0L10Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L11Pit      (HC_SIMA_HTX0L11Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L0_5WE      (HC_SIMA_HTX0L0_5WE + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L6_bWE      (HC_SIMA_HTX0L6_bWE + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1Lc_11WE     (HC_SIMA_HTX0Lc_11WE + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L0_5HE      (HC_SIMA_HTX0L0_5HE + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L6_bHE      (HC_SIMA_HTX0L6_bHE + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1Lc_11HE      (HC_SIMA_HTX0Lc_11HE + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L0OS        (HC_SIMA_HTX0L0OS + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TB          (HC_SIMA_HTX0TB + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1MPMD        (HC_SIMA_HTX0MPMD + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1CLODu       (HC_SIMA_HTX0CLODu + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1FM          (HC_SIMA_HTX0FM + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TRCH        (HC_SIMA_HTX0TRCH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TRCL        (HC_SIMA_HTX0TRCL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBC         (HC_SIMA_HTX0TBC + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TRAH        (HC_SIMA_HTX0TRAH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LTC         (HC_SIMA_HTX0LTC + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LTA         (HC_SIMA_HTX0LTA + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLCsat     (HC_SIMA_HTX0TBLCsat + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLCop      (HC_SIMA_HTX0TBLCop + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLMPfog    (HC_SIMA_HTX0TBLMPfog + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLAsat     (HC_SIMA_HTX0TBLAsat + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLRCa      (HC_SIMA_HTX0TBLRCa + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLRCb      (HC_SIMA_HTX0TBLRCb + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLRCc      (HC_SIMA_HTX0TBLRCc + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLRCbias   (HC_SIMA_HTX0TBLRCbias + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLRAa      (HC_SIMA_HTX0TBLRAa + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLRFog     (HC_SIMA_HTX0TBLRFog + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1BumpM00     (HC_SIMA_HTX0BumpM00 + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1BumpM01     (HC_SIMA_HTX0BumpM01 + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1BumpM10     (HC_SIMA_HTX0BumpM10 + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1BumpM11     (HC_SIMA_HTX0BumpM11 + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LScale      (HC_SIMA_HTX0LScale + HC_SIMA_TX0TX1_OFF)
-/*---- end of texture 1 setting ---- 0xaf
- */
-#define HC_SIMA_HTXSMD          0x00b0
-#define HC_SIMA_HenFIFOAT       0x00b1
-#define HC_SIMA_HFBDrawFirst    0x00b2
-#define HC_SIMA_HFBBasL         0x00b3
-#define HC_SIMA_HTArbRCM        0x00b4
-#define HC_SIMA_HTArbRZ         0x00b5
-#define HC_SIMA_HTArbWZ         0x00b6
-#define HC_SIMA_HTArbRTX        0x00b7
-#define HC_SIMA_HTArbRCW        0x00b8
-#define HC_SIMA_HTArbE2         0x00b9
-#define HC_SIMA_HGEMITout       0x00ba
-#define HC_SIMA_HFthRTXD        0x00bb
-#define HC_SIMA_HFthRTXA        0x00bc
-/* Define the texture palette 0
- */
-#define HC_SIMA_HTP0            0x0100
-#define HC_SIMA_HTP1            0x0200
-#define HC_SIMA_FOGTABLE        0x0300
-#define HC_SIMA_STIPPLE         0x0400
-#define HC_SIMA_HE3Fire         0x0440
-#define HC_SIMA_TRANS_SET       0x0441
-#define HC_SIMA_HREngSt         0x0442
-#define HC_SIMA_HRFIFOempty     0x0443
-#define HC_SIMA_HRFIFOfull      0x0444
-#define HC_SIMA_HRErr           0x0445
-#define HC_SIMA_FIFOstatus      0x0446
-
-/******************************************************************************
-** Define the AGP command header.
-******************************************************************************/
-#define HC_ACMD_MASK            0xfe000000
-#define HC_ACMD_SUB_MASK        0x0c000000
-#define HC_ACMD_HCmdA           0xee000000
-#define HC_ACMD_HCmdB           0xec000000
-#define HC_ACMD_HCmdC           0xea000000
-#define HC_ACMD_H1              0xf0000000
-#define HC_ACMD_H2              0xf2000000
-#define HC_ACMD_H3              0xf4000000
-#define HC_ACMD_H4              0xf6000000
-
-#define HC_ACMD_H1IO_MASK       0x000001ff
-#define HC_ACMD_H2IO1_MASK      0x001ff000
-#define HC_ACMD_H2IO2_MASK      0x000001ff
-#define HC_ACMD_H2IO1_SHIFT     12
-#define HC_ACMD_H2IO2_SHIFT     0
-#define HC_ACMD_H3IO_MASK       0x000001ff
-#define HC_ACMD_H3COUNT_MASK    0x01fff000
-#define HC_ACMD_H3COUNT_SHIFT   12
-#define HC_ACMD_H4ID_MASK       0x000001ff
-#define HC_ACMD_H4COUNT_MASK    0x01fffe00
-#define HC_ACMD_H4COUNT_SHIFT   9
-
-/********************************************************************************
-** Define Header
-********************************************************************************/
-#define HC_HEADER2             0xF210F110
-
-/********************************************************************************
-** Define Dummy Value
-********************************************************************************/
-#define HC_DUMMY               0xCCCCCCCC
-/********************************************************************************
-** Define for DMA use
-********************************************************************************/
-#define HALCYON_HEADER2     0XF210F110
-#define HALCYON_FIRECMD     0XEE100000
-#define HALCYON_FIREMASK    0XFFF00000
-#define HALCYON_CMDB        0XEC000000
-#define HALCYON_CMDBMASK    0XFFFE0000
-#define HALCYON_SUB_ADDR0   0X00000000
-#define HALCYON_HEADER1MASK 0XFFFFFC00
-#define HALCYON_HEADER1     0XF0000000
-#define HC_SubA_HAGPBstL        0x0060
-#define HC_SubA_HAGPBendL       0x0061
-#define HC_SubA_HAGPCMNT        0x0062
-#define HC_SubA_HAGPBpL         0x0063
-#define HC_SubA_HAGPBpH         0x0064
-#define HC_HAGPCMNT_MASK        0x00800000
-#define HC_HCmdErrClr_MASK      0x00400000
-#define HC_HAGPBendH_MASK       0x0000ff00
-#define HC_HAGPBstH_MASK        0x000000ff
-#define HC_HAGPBendH_SHIFT      8
-#define HC_HAGPBstH_SHIFT       0
-#define HC_HAGPBpL_MASK         0x00fffffc
-#define HC_HAGPBpID_MASK        0x00000003
-#define HC_HAGPBpID_PAUSE       0x00000000
-#define HC_HAGPBpID_JUMP        0x00000001
-#define HC_HAGPBpID_STOP        0x00000002
-#define HC_HAGPBpH_MASK         0x00ffffff
-
-#define VIA_VIDEO_HEADER5       0xFE040000
-#define VIA_VIDEO_HEADER6       0xFE050000
-#define VIA_VIDEO_HEADER7       0xFE060000
-#define VIA_VIDEOMASK           0xFFFF0000
-#endif
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
deleted file mode 100644 (file)
index 7a339db..0000000
+++ /dev/null
@@ -1,755 +0,0 @@
-/* via_dma.c -- DMA support for the VIA Unichrome/Pro
- *
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A.
- * All Rights Reserved.
- *
- * Copyright 2004 The Unichrome project.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Tungsten Graphics,
- *    Erdi Chen,
- *    Thomas Hellstrom.
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "via_drm.h"
-#include "via_drv.h"
-#include "via_3d_reg.h"
-
-#define CMDBUF_ALIGNMENT_SIZE   (0x100)
-#define CMDBUF_ALIGNMENT_MASK   (0x0ff)
-
-/* defines for VIA 3D registers */
-#define VIA_REG_STATUS          0x400
-#define VIA_REG_TRANSET         0x43C
-#define VIA_REG_TRANSPACE       0x440
-
-/* VIA_REG_STATUS(0x400): Engine Status */
-#define VIA_CMD_RGTR_BUSY       0x00000080     /* Command Regulator is busy */
-#define VIA_2D_ENG_BUSY         0x00000001     /* 2D Engine is busy */
-#define VIA_3D_ENG_BUSY         0x00000002     /* 3D Engine is busy */
-#define VIA_VR_QUEUE_BUSY       0x00020000     /* Virtual Queue is busy */
-
-#define SetReg2DAGP(nReg, nData) {                             \
-       *((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1;  \
-       *((uint32_t *)(vb) + 1) = (nData);                      \
-       vb = ((uint32_t *)vb) + 2;                              \
-       dev_priv->dma_low +=8;                                  \
-}
-
-#define via_flush_write_combine() DRM_MEMORYBARRIER()
-
-#define VIA_OUT_RING_QW(w1,w2)                 \
-       *vb++ = (w1);                           \
-       *vb++ = (w2);                           \
-       dev_priv->dma_low += 8;
-
-static void via_cmdbuf_start(drm_via_private_t * dev_priv);
-static void via_cmdbuf_pause(drm_via_private_t * dev_priv);
-static void via_cmdbuf_reset(drm_via_private_t * dev_priv);
-static void via_cmdbuf_rewind(drm_via_private_t * dev_priv);
-static int via_wait_idle(drm_via_private_t * dev_priv);
-static void via_pad_cache(drm_via_private_t * dev_priv, int qwords);
-
-/*
- * Free space in command buffer.
- */
-
-static uint32_t via_cmdbuf_space(drm_via_private_t * dev_priv)
-{
-       uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
-       uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
-
-       return ((hw_addr <= dev_priv->dma_low) ?
-               (dev_priv->dma_high + hw_addr - dev_priv->dma_low) :
-               (hw_addr - dev_priv->dma_low));
-}
-
-/*
- * How much does the command regulator lag behind?
- */
-
-static uint32_t via_cmdbuf_lag(drm_via_private_t * dev_priv)
-{
-       uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
-       uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
-
-       return ((hw_addr <= dev_priv->dma_low) ?
-               (dev_priv->dma_low - hw_addr) :
-               (dev_priv->dma_wrap + dev_priv->dma_low - hw_addr));
-}
-
-/*
- * Check that the given size fits in the buffer, otherwise wait.
- */
-
-static inline int
-via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size)
-{
-       uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
-       uint32_t cur_addr, hw_addr, next_addr;
-       volatile uint32_t *hw_addr_ptr;
-       uint32_t count;
-       hw_addr_ptr = dev_priv->hw_addr_ptr;
-       cur_addr = dev_priv->dma_low;
-       next_addr = cur_addr + size + 512 * 1024;
-       count = 1000000;
-       do {
-               hw_addr = *hw_addr_ptr - agp_base;
-               if (count-- == 0) {
-                       DRM_ERROR
-                           ("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n",
-                            hw_addr, cur_addr, next_addr);
-                       return -1;
-               }
-               if  ((cur_addr < hw_addr) && (next_addr >= hw_addr))
-                       msleep(1);
-       } while ((cur_addr < hw_addr) && (next_addr >= hw_addr));
-       return 0;
-}
-
-/*
- * Checks whether buffer head has reach the end. Rewind the ring buffer
- * when necessary.
- *
- * Returns virtual pointer to ring buffer.
- */
-
-static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv,
-                                     unsigned int size)
-{
-       if ((dev_priv->dma_low + size + 4 * CMDBUF_ALIGNMENT_SIZE) >
-           dev_priv->dma_high) {
-               via_cmdbuf_rewind(dev_priv);
-       }
-       if (via_cmdbuf_wait(dev_priv, size) != 0) {
-               return NULL;
-       }
-
-       return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
-}
-
-int via_dma_cleanup(struct drm_device * dev)
-{
-       if (dev->dev_private) {
-               drm_via_private_t *dev_priv =
-                   (drm_via_private_t *) dev->dev_private;
-
-               if (dev_priv->ring.virtual_start) {
-                       via_cmdbuf_reset(dev_priv);
-
-                       drm_core_ioremapfree(&dev_priv->ring.map, dev);
-                       dev_priv->ring.virtual_start = NULL;
-               }
-
-       }
-
-       return 0;
-}
-
-static int via_initialize(struct drm_device * dev,
-                         drm_via_private_t * dev_priv,
-                         drm_via_dma_init_t * init)
-{
-       if (!dev_priv || !dev_priv->mmio) {
-               DRM_ERROR("via_dma_init called before via_map_init\n");
-               return -EFAULT;
-       }
-
-       if (dev_priv->ring.virtual_start != NULL) {
-               DRM_ERROR("called again without calling cleanup\n");
-               return -EFAULT;
-       }
-
-       if (!dev->agp || !dev->agp->base) {
-               DRM_ERROR("called with no agp memory available\n");
-               return -EFAULT;
-       }
-
-       if (dev_priv->chipset == VIA_DX9_0) {
-               DRM_ERROR("AGP DMA is not supported on this chip\n");
-               return -EINVAL;
-       }
-
-       dev_priv->ring.map.offset = dev->agp->base + init->offset;
-       dev_priv->ring.map.size = init->size;
-       dev_priv->ring.map.type = 0;
-       dev_priv->ring.map.flags = 0;
-       dev_priv->ring.map.mtrr = 0;
-
-       drm_core_ioremap(&dev_priv->ring.map, dev);
-
-       if (dev_priv->ring.map.handle == NULL) {
-               via_dma_cleanup(dev);
-               DRM_ERROR("can not ioremap virtual address for"
-                         " ring buffer\n");
-               return -ENOMEM;
-       }
-
-       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
-
-       dev_priv->dma_ptr = dev_priv->ring.virtual_start;
-       dev_priv->dma_low = 0;
-       dev_priv->dma_high = init->size;
-       dev_priv->dma_wrap = init->size;
-       dev_priv->dma_offset = init->offset;
-       dev_priv->last_pause_ptr = NULL;
-       dev_priv->hw_addr_ptr =
-               (volatile uint32_t *)((char *)dev_priv->mmio->handle +
-               init->reg_pause_addr);
-
-       via_cmdbuf_start(dev_priv);
-
-       return 0;
-}
-
-static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       drm_via_dma_init_t *init = data;
-       int retcode = 0;
-
-       switch (init->func) {
-       case VIA_INIT_DMA:
-               if (!DRM_SUSER(DRM_CURPROC))
-                       retcode = -EPERM;
-               else
-                       retcode = via_initialize(dev, dev_priv, init);
-               break;
-       case VIA_CLEANUP_DMA:
-               if (!DRM_SUSER(DRM_CURPROC))
-                       retcode = -EPERM;
-               else
-                       retcode = via_dma_cleanup(dev);
-               break;
-       case VIA_DMA_INITIALIZED:
-               retcode = (dev_priv->ring.virtual_start != NULL) ?
-                       0 : -EFAULT;
-               break;
-       default:
-               retcode = -EINVAL;
-               break;
-       }
-
-       return retcode;
-}
-
-static int via_dispatch_cmdbuffer(struct drm_device * dev, drm_via_cmdbuffer_t * cmd)
-{
-       drm_via_private_t *dev_priv;
-       uint32_t *vb;
-       int ret;
-
-       dev_priv = (drm_via_private_t *) dev->dev_private;
-
-       if (dev_priv->ring.virtual_start == NULL) {
-               DRM_ERROR("called without initializing AGP ring buffer.\n");
-               return -EFAULT;
-       }
-
-       if (cmd->size > VIA_PCI_BUF_SIZE) {
-               return -ENOMEM;
-       }
-
-       if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
-               return -EFAULT;
-
-       /*
-        * Running this function on AGP memory is dead slow. Therefore
-        * we run it on a temporary cacheable system memory buffer and
-        * copy it to AGP memory when ready.
-        */
-
-       if ((ret =
-            via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
-                                      cmd->size, dev, 1))) {
-               return ret;
-       }
-
-       vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
-       if (vb == NULL) {
-               return -EAGAIN;
-       }
-
-       memcpy(vb, dev_priv->pci_buf, cmd->size);
-
-       dev_priv->dma_low += cmd->size;
-
-       /*
-        * Small submissions somehow stalls the CPU. (AGP cache effects?)
-        * pad to greater size.
-        */
-
-       if (cmd->size < 0x100)
-               via_pad_cache(dev_priv, (0x100 - cmd->size) >> 3);
-       via_cmdbuf_pause(dev_priv);
-
-       return 0;
-}
-
-int via_driver_dma_quiescent(struct drm_device * dev)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-
-       if (!via_wait_idle(dev_priv)) {
-               return -EBUSY;
-       }
-       return 0;
-}
-
-static int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       return via_driver_dma_quiescent(dev);
-}
-
-static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_cmdbuffer_t *cmdbuf = data;
-       int ret;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size);
-
-       ret = via_dispatch_cmdbuffer(dev, cmdbuf);
-       if (ret) {
-               return ret;
-       }
-
-       return 0;
-}
-
-static int via_dispatch_pci_cmdbuffer(struct drm_device * dev,
-                                     drm_via_cmdbuffer_t * cmd)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-       int ret;
-
-       if (cmd->size > VIA_PCI_BUF_SIZE) {
-               return -ENOMEM;
-       }
-       if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
-               return -EFAULT;
-
-       if ((ret =
-            via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
-                                      cmd->size, dev, 0))) {
-               return ret;
-       }
-
-       ret =
-           via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf,
-                                    cmd->size);
-       return ret;
-}
-
-static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_cmdbuffer_t *cmdbuf = data;
-       int ret;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size);
-
-       ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf);
-       if (ret) {
-               return ret;
-       }
-
-       return 0;
-}
-
-static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv,
-                                        uint32_t * vb, int qw_count)
-{
-       for (; qw_count > 0; --qw_count) {
-               VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY);
-       }
-       return vb;
-}
-
-/*
- * This function is used internally by ring buffer management code.
- *
- * Returns virtual pointer to ring buffer.
- */
-static inline uint32_t *via_get_dma(drm_via_private_t * dev_priv)
-{
-       return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
-}
-
-/*
- * Hooks a segment of data into the tail of the ring-buffer by
- * modifying the pause address stored in the buffer itself. If
- * the regulator has already paused, restart it.
- */
-static int via_hook_segment(drm_via_private_t * dev_priv,
-                           uint32_t pause_addr_hi, uint32_t pause_addr_lo,
-                           int no_pci_fire)
-{
-       int paused, count;
-       volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
-       uint32_t reader,ptr;
-       uint32_t diff;
-
-       paused = 0;
-       via_flush_write_combine();
-       (void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1);
-
-       *paused_at = pause_addr_lo;
-       via_flush_write_combine();
-       (void) *paused_at;
-
-       reader = *(dev_priv->hw_addr_ptr);
-       ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
-               dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
-
-       dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
-
-       /*
-        * If there is a possibility that the command reader will 
-        * miss the new pause address and pause on the old one,
-        * In that case we need to program the new start address
-        * using PCI.
-        */
-
-       diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
-       count = 10000000;
-       while(diff == 0 && count--) {
-               paused = (VIA_READ(0x41c) & 0x80000000);
-               if (paused) 
-                       break;
-               reader = *(dev_priv->hw_addr_ptr);
-               diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
-       }
-
-       paused = VIA_READ(0x41c) & 0x80000000;
-
-       if (paused && !no_pci_fire) {
-               reader = *(dev_priv->hw_addr_ptr);
-               diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
-               diff &= (dev_priv->dma_high - 1);
-               if (diff != 0 && diff < (dev_priv->dma_high >> 1)) {
-                       DRM_ERROR("Paused at incorrect address. "
-                                 "0x%08x, 0x%08x 0x%08x\n",
-                                 ptr, reader, dev_priv->dma_diff);
-               } else if (diff == 0) {
-                       /*
-                        * There is a concern that these writes may stall the PCI bus
-                        * if the GPU is not idle. However, idling the GPU first
-                        * doesn't make a difference.
-                        */
-
-                       VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
-                       VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
-                       VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
-                       VIA_READ(VIA_REG_TRANSPACE);
-               }
-       }
-       return paused;
-}
-
-static int via_wait_idle(drm_via_private_t * dev_priv)
-{
-       int count = 10000000;
-
-       while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--);
-
-       while (count-- && (VIA_READ(VIA_REG_STATUS) &
-                          (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
-                           VIA_3D_ENG_BUSY))) ;
-       return count;
-}
-
-static uint32_t *via_align_cmd(drm_via_private_t * dev_priv, uint32_t cmd_type,
-                              uint32_t addr, uint32_t * cmd_addr_hi,
-                              uint32_t * cmd_addr_lo, int skip_wait)
-{
-       uint32_t agp_base;
-       uint32_t cmd_addr, addr_lo, addr_hi;
-       uint32_t *vb;
-       uint32_t qw_pad_count;
-
-       if (!skip_wait)
-               via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE);
-
-       vb = via_get_dma(dev_priv);
-       VIA_OUT_RING_QW(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
-                       (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16);
-       agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
-       qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
-           ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
-
-       cmd_addr = (addr) ? addr :
-           agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
-       addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) |
-                  (cmd_addr & HC_HAGPBpL_MASK));
-       addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24));
-
-       vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1);
-       VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi, *cmd_addr_lo = addr_lo);
-       return vb;
-}
-
-static void via_cmdbuf_start(drm_via_private_t * dev_priv)
-{
-       uint32_t pause_addr_lo, pause_addr_hi;
-       uint32_t start_addr, start_addr_lo;
-       uint32_t end_addr, end_addr_lo;
-       uint32_t command;
-       uint32_t agp_base;
-       uint32_t ptr;
-       uint32_t reader;
-       int count;
-
-       dev_priv->dma_low = 0;
-
-       agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
-       start_addr = agp_base;
-       end_addr = agp_base + dev_priv->dma_high;
-
-       start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF));
-       end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF));
-       command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
-                  ((end_addr & 0xff000000) >> 16));
-
-       dev_priv->last_pause_ptr =
-           via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0,
-                         &pause_addr_hi, &pause_addr_lo, 1) - 1;
-
-       via_flush_write_combine();
-       (void) *(volatile uint32_t *)dev_priv->last_pause_ptr;
-
-       VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
-       VIA_WRITE(VIA_REG_TRANSPACE, command);
-       VIA_WRITE(VIA_REG_TRANSPACE, start_addr_lo);
-       VIA_WRITE(VIA_REG_TRANSPACE, end_addr_lo);
-
-       VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
-       VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
-       DRM_WRITEMEMORYBARRIER();
-       VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
-       VIA_READ(VIA_REG_TRANSPACE);
-
-       dev_priv->dma_diff = 0;
-
-       count = 10000000;
-       while (!(VIA_READ(0x41c) & 0x80000000) && count--);
-
-       reader = *(dev_priv->hw_addr_ptr);
-       ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
-           dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
-
-       /*
-        * This is the difference between where we tell the
-        * command reader to pause and where it actually pauses.
-        * This differs between hw implementation so we need to
-        * detect it.
-        */
-
-       dev_priv->dma_diff = ptr - reader;
-}
-
-static void via_pad_cache(drm_via_private_t * dev_priv, int qwords)
-{
-       uint32_t *vb;
-
-       via_cmdbuf_wait(dev_priv, qwords + 2);
-       vb = via_get_dma(dev_priv);
-       VIA_OUT_RING_QW(HC_HEADER2, HC_ParaType_NotTex << 16);
-       via_align_buffer(dev_priv, vb, qwords);
-}
-
-static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
-{
-       uint32_t *vb = via_get_dma(dev_priv);
-       SetReg2DAGP(0x0C, (0 | (0 << 16)));
-       SetReg2DAGP(0x10, 0 | (0 << 16));
-       SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
-}
-
-static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
-{
-       uint32_t agp_base;
-       uint32_t pause_addr_lo, pause_addr_hi;
-       uint32_t jump_addr_lo, jump_addr_hi;
-       volatile uint32_t *last_pause_ptr;
-       uint32_t dma_low_save1, dma_low_save2;
-
-       agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
-       via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
-                     &jump_addr_lo, 0);
-
-       dev_priv->dma_wrap = dev_priv->dma_low;
-
-       /*
-        * Wrap command buffer to the beginning.
-        */
-
-       dev_priv->dma_low = 0;
-       if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) {
-               DRM_ERROR("via_cmdbuf_jump failed\n");
-       }
-
-       via_dummy_bitblt(dev_priv);
-       via_dummy_bitblt(dev_priv);
-
-       last_pause_ptr =
-           via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-                         &pause_addr_lo, 0) - 1;
-       via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-                     &pause_addr_lo, 0);
-
-       *last_pause_ptr = pause_addr_lo;
-       dma_low_save1 = dev_priv->dma_low;
-
-       /*
-        * Now, set a trap that will pause the regulator if it tries to rerun the old
-        * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
-        * and reissues the jump command over PCI, while the regulator has already taken the jump
-        * and actually paused at the current buffer end).
-        * There appears to be no other way to detect this condition, since the hw_addr_pointer
-        * does not seem to get updated immediately when a jump occurs.
-        */
-
-       last_pause_ptr =
-               via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-                             &pause_addr_lo, 0) - 1;
-       via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-                     &pause_addr_lo, 0);
-       *last_pause_ptr = pause_addr_lo;
-
-       dma_low_save2 = dev_priv->dma_low;
-       dev_priv->dma_low = dma_low_save1;
-       via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0);
-       dev_priv->dma_low = dma_low_save2;
-       via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
-}
-
-
-static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
-{
-       via_cmdbuf_jump(dev_priv);
-}
-
-static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
-{
-       uint32_t pause_addr_lo, pause_addr_hi;
-
-       via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0);
-       via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
-}
-
-static void via_cmdbuf_pause(drm_via_private_t * dev_priv)
-{
-       via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE);
-}
-
-static void via_cmdbuf_reset(drm_via_private_t * dev_priv)
-{
-       via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP);
-       via_wait_idle(dev_priv);
-}
-
-/*
- * User interface to the space and lag functions.
- */
-
-static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_cmdbuf_size_t *d_siz = data;
-       int ret = 0;
-       uint32_t tmp_size, count;
-       drm_via_private_t *dev_priv;
-
-       DRM_DEBUG("\n");
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       dev_priv = (drm_via_private_t *) dev->dev_private;
-
-       if (dev_priv->ring.virtual_start == NULL) {
-               DRM_ERROR("called without initializing AGP ring buffer.\n");
-               return -EFAULT;
-       }
-
-       count = 1000000;
-       tmp_size = d_siz->size;
-       switch (d_siz->func) {
-       case VIA_CMDBUF_SPACE:
-               while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size)
-                      && count--) {
-                       if (!d_siz->wait) {
-                               break;
-                       }
-               }
-               if (!count) {
-                       DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n");
-                       ret = -EAGAIN;
-               }
-               break;
-       case VIA_CMDBUF_LAG:
-               while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size)
-                      && count--) {
-                       if (!d_siz->wait) {
-                               break;
-                       }
-               }
-               if (!count) {
-                       DRM_ERROR("VIA_CMDBUF_LAG timed out.\n");
-                       ret = -EAGAIN;
-               }
-               break;
-       default:
-               ret = -EFAULT;
-       }
-       d_siz->size = tmp_size;
-
-       return ret;
-}
-
-struct drm_ioctl_desc via_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_FREEMEM, via_mem_free, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER),
-       DRM_IOCTL_DEF(DRM_VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER),
-       DRM_IOCTL_DEF(DRM_VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER),
-       DRM_IOCTL_DEF(DRM_VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_DMA_INIT, via_dma_init, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_FLUSH, via_flush_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_DMA_BLIT, via_dma_blit, DRM_AUTH),
-       DRM_IOCTL_DEF(DRM_VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH)
-};
-
-int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls);
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
deleted file mode 100644 (file)
index 409e00a..0000000
+++ /dev/null
@@ -1,816 +0,0 @@
-/* via_dmablit.c -- PCI DMA BitBlt support for the VIA Unichrome/Pro
- *
- * Copyright (C) 2005 Thomas Hellstrom, All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Thomas Hellstrom.
- *    Partially based on code obtained from Digeo Inc.
- */
-
-
-/*
- * Unmaps the DMA mappings.
- * FIXME: Is this a NoOp on x86? Also
- * FIXME: What happens if this one is called and a pending blit has previously done
- * the same DMA mappings?
- */
-
-#include "drmP.h"
-#include "via_drm.h"
-#include "via_drv.h"
-#include "via_dmablit.h"
-
-#include <linux/pagemap.h>
-
-#define VIA_PGDN(x)         (((unsigned long)(x)) & PAGE_MASK)
-#define VIA_PGOFF(x)       (((unsigned long)(x)) & ~PAGE_MASK)
-#define VIA_PFN(x)           ((unsigned long)(x) >> PAGE_SHIFT)
-
-typedef struct _drm_via_descriptor {
-       uint32_t mem_addr;
-       uint32_t dev_addr;
-       uint32_t size;
-       uint32_t next;
-} drm_via_descriptor_t;
-
-
-/*
- * Unmap a DMA mapping.
- */
-
-
-
-static void
-via_unmap_blit_from_device(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
-{
-       int num_desc = vsg->num_desc;
-       unsigned cur_descriptor_page = num_desc / vsg->descriptors_per_page;
-       unsigned descriptor_this_page = num_desc % vsg->descriptors_per_page;
-       drm_via_descriptor_t *desc_ptr = vsg->desc_pages[cur_descriptor_page] +
-               descriptor_this_page;
-       dma_addr_t next = vsg->chain_start;
-
-       while(num_desc--) {
-               if (descriptor_this_page-- == 0) {
-                       cur_descriptor_page--;
-                       descriptor_this_page = vsg->descriptors_per_page - 1;
-                       desc_ptr = vsg->desc_pages[cur_descriptor_page] +
-                               descriptor_this_page;
-               }
-               dma_unmap_single(&pdev->dev, next, sizeof(*desc_ptr), DMA_TO_DEVICE);
-               dma_unmap_page(&pdev->dev, desc_ptr->mem_addr, desc_ptr->size, vsg->direction);
-               next = (dma_addr_t) desc_ptr->next;
-               desc_ptr--;
-       }
-}
-
-/*
- * If mode = 0, count how many descriptors are needed.
- * If mode = 1, Map the DMA pages for the device, put together and map also the descriptors.
- * Descriptors are run in reverse order by the hardware because we are not allowed to update the
- * 'next' field without syncing calls when the descriptor is already mapped.
- */
-
-static void
-via_map_blit_for_device(struct pci_dev *pdev,
-                  const drm_via_dmablit_t *xfer,
-                  drm_via_sg_info_t *vsg,
-                  int mode)
-{
-       unsigned cur_descriptor_page = 0;
-       unsigned num_descriptors_this_page = 0;
-       unsigned char *mem_addr = xfer->mem_addr;
-       unsigned char *cur_mem;
-       unsigned char *first_addr = (unsigned char *)VIA_PGDN(mem_addr);
-       uint32_t fb_addr = xfer->fb_addr;
-       uint32_t cur_fb;
-       unsigned long line_len;
-       unsigned remaining_len;
-       int num_desc = 0;
-       int cur_line;
-       dma_addr_t next = 0 | VIA_DMA_DPR_EC;
-       drm_via_descriptor_t *desc_ptr = NULL;
-
-       if (mode == 1)
-               desc_ptr = vsg->desc_pages[cur_descriptor_page];
-
-       for (cur_line = 0; cur_line < xfer->num_lines; ++cur_line) {
-
-               line_len = xfer->line_length;
-               cur_fb = fb_addr;
-               cur_mem = mem_addr;
-
-               while (line_len > 0) {
-
-                       remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len);
-                       line_len -= remaining_len;
-
-                       if (mode == 1) {
-                               desc_ptr->mem_addr =
-                                       dma_map_page(&pdev->dev,
-                                                    vsg->pages[VIA_PFN(cur_mem) -
-                                                               VIA_PFN(first_addr)],
-                                                    VIA_PGOFF(cur_mem), remaining_len,
-                                                    vsg->direction);
-                               desc_ptr->dev_addr = cur_fb;
-
-                               desc_ptr->size = remaining_len;
-                               desc_ptr->next = (uint32_t) next;
-                               next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr),
-                                                     DMA_TO_DEVICE);
-                               desc_ptr++;
-                               if (++num_descriptors_this_page >= vsg->descriptors_per_page) {
-                                       num_descriptors_this_page = 0;
-                                       desc_ptr = vsg->desc_pages[++cur_descriptor_page];
-                               }
-                       }
-
-                       num_desc++;
-                       cur_mem += remaining_len;
-                       cur_fb += remaining_len;
-               }
-
-               mem_addr += xfer->mem_stride;
-               fb_addr += xfer->fb_stride;
-       }
-
-       if (mode == 1) {
-               vsg->chain_start = next;
-               vsg->state = dr_via_device_mapped;
-       }
-       vsg->num_desc = num_desc;
-}
-
-/*
- * Function that frees up all resources for a blit. It is usable even if the
- * blit info has only been partially built as long as the status enum is consistent
- * with the actual status of the used resources.
- */
-
-
-static void
-via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
-{
-       struct page *page;
-       int i;
-
-       switch(vsg->state) {
-       case dr_via_device_mapped:
-               via_unmap_blit_from_device(pdev, vsg);
-       case dr_via_desc_pages_alloc:
-               for (i=0; i<vsg->num_desc_pages; ++i) {
-                       if (vsg->desc_pages[i] != NULL)
-                         free_page((unsigned long)vsg->desc_pages[i]);
-               }
-               kfree(vsg->desc_pages);
-       case dr_via_pages_locked:
-               for (i=0; i<vsg->num_pages; ++i) {
-                       if ( NULL != (page = vsg->pages[i])) {
-                               if (! PageReserved(page) && (DMA_FROM_DEVICE == vsg->direction))
-                                       SetPageDirty(page);
-                               page_cache_release(page);
-                       }
-               }
-       case dr_via_pages_alloc:
-               vfree(vsg->pages);
-       default:
-               vsg->state = dr_via_sg_init;
-       }
-       if (vsg->bounce_buffer) {
-               vfree(vsg->bounce_buffer);
-               vsg->bounce_buffer = NULL;
-       }
-       vsg->free_on_sequence = 0;
-}
-
-/*
- * Fire a blit engine.
- */
-
-static void
-via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-
-       VIA_WRITE(VIA_PCI_DMA_MAR0 + engine*0x10, 0);
-       VIA_WRITE(VIA_PCI_DMA_DAR0 + engine*0x10, 0);
-       VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD |
-                 VIA_DMA_CSR_DE);
-       VIA_WRITE(VIA_PCI_DMA_MR0  + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);
-       VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0);
-       VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);
-       DRM_WRITEMEMORYBARRIER();
-       VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);
-       VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04);
-}
-
-/*
- * Obtain a page pointer array and lock all pages into system memory. A segmentation violation will
- * occur here if the calling user does not have access to the submitted address.
- */
-
-static int
-via_lock_all_dma_pages(drm_via_sg_info_t *vsg,  drm_via_dmablit_t *xfer)
-{
-       int ret;
-       unsigned long first_pfn = VIA_PFN(xfer->mem_addr);
-       vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride -1)) -
-               first_pfn + 1;
-
-       if (NULL == (vsg->pages = vmalloc(sizeof(struct page *) * vsg->num_pages)))
-               return -ENOMEM;
-       memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages);
-       down_read(&current->mm->mmap_sem);
-       ret = get_user_pages(current, current->mm,
-                            (unsigned long)xfer->mem_addr,
-                            vsg->num_pages,
-                            (vsg->direction == DMA_FROM_DEVICE),
-                            0, vsg->pages, NULL);
-
-       up_read(&current->mm->mmap_sem);
-       if (ret != vsg->num_pages) {
-               if (ret < 0)
-                       return ret;
-               vsg->state = dr_via_pages_locked;
-               return -EINVAL;
-       }
-       vsg->state = dr_via_pages_locked;
-       DRM_DEBUG("DMA pages locked\n");
-       return 0;
-}
-
-/*
- * Allocate DMA capable memory for the blit descriptor chain, and an array that keeps track of the
- * pages we allocate. We don't want to use kmalloc for the descriptor chain because it may be
- * quite large for some blits, and pages don't need to be contingous.
- */
-
-static int
-via_alloc_desc_pages(drm_via_sg_info_t *vsg)
-{
-       int i;
-
-       vsg->descriptors_per_page = PAGE_SIZE / sizeof( drm_via_descriptor_t);
-       vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) /
-               vsg->descriptors_per_page;
-
-       if (NULL ==  (vsg->desc_pages = kcalloc(vsg->num_desc_pages, sizeof(void *), GFP_KERNEL)))
-               return -ENOMEM;
-
-       vsg->state = dr_via_desc_pages_alloc;
-       for (i=0; i<vsg->num_desc_pages; ++i) {
-               if (NULL == (vsg->desc_pages[i] =
-                            (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL)))
-                       return -ENOMEM;
-       }
-       DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages,
-                 vsg->num_desc);
-       return 0;
-}
-
-static void
-via_abort_dmablit(struct drm_device *dev, int engine)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-
-       VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA);
-}
-
-static void
-via_dmablit_engine_off(struct drm_device *dev, int engine)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-
-       VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD);
-}
-
-
-
-/*
- * The dmablit part of the IRQ handler. Trying to do only reasonably fast things here.
- * The rest, like unmapping and freeing memory for done blits is done in a separate workqueue
- * task. Basically the task of the interrupt handler is to submit a new blit to the engine, while
- * the workqueue task takes care of processing associated with the old blit.
- */
-
-void
-via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-       drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
-       int cur;
-       int done_transfer;
-       unsigned long irqsave=0;
-       uint32_t status = 0;
-
-       DRM_DEBUG("DMA blit handler called. engine = %d, from_irq = %d, blitq = 0x%lx\n",
-                 engine, from_irq, (unsigned long) blitq);
-
-       if (from_irq) {
-               spin_lock(&blitq->blit_lock);
-       } else {
-               spin_lock_irqsave(&blitq->blit_lock, irqsave);
-       }
-
-       done_transfer = blitq->is_active &&
-         (( status = VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD);
-       done_transfer = done_transfer || ( blitq->aborting && !(status & VIA_DMA_CSR_DE));
-
-       cur = blitq->cur;
-       if (done_transfer) {
-
-               blitq->blits[cur]->aborted = blitq->aborting;
-               blitq->done_blit_handle++;
-               DRM_WAKEUP(blitq->blit_queue + cur);
-
-               cur++;
-               if (cur >= VIA_NUM_BLIT_SLOTS)
-                       cur = 0;
-               blitq->cur = cur;
-
-               /*
-                * Clear transfer done flag.
-                */
-
-               VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04,  VIA_DMA_CSR_TD);
-
-               blitq->is_active = 0;
-               blitq->aborting = 0;
-               schedule_work(&blitq->wq);
-
-       } else if (blitq->is_active && time_after_eq(jiffies, blitq->end)) {
-
-               /*
-                * Abort transfer after one second.
-                */
-
-               via_abort_dmablit(dev, engine);
-               blitq->aborting = 1;
-               blitq->end = jiffies + DRM_HZ;
-       }
-
-       if (!blitq->is_active) {
-               if (blitq->num_outstanding) {
-                       via_fire_dmablit(dev, blitq->blits[cur], engine);
-                       blitq->is_active = 1;
-                       blitq->cur = cur;
-                       blitq->num_outstanding--;
-                       blitq->end = jiffies + DRM_HZ;
-                       if (!timer_pending(&blitq->poll_timer))
-                               mod_timer(&blitq->poll_timer, jiffies + 1);
-               } else {
-                       if (timer_pending(&blitq->poll_timer)) {
-                               del_timer(&blitq->poll_timer);
-                       }
-                       via_dmablit_engine_off(dev, engine);
-               }
-       }
-
-       if (from_irq) {
-               spin_unlock(&blitq->blit_lock);
-       } else {
-               spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-       }
-}
-
-
-
-/*
- * Check whether this blit is still active, performing necessary locking.
- */
-
-static int
-via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_queue_head_t **queue)
-{
-       unsigned long irqsave;
-       uint32_t slot;
-       int active;
-
-       spin_lock_irqsave(&blitq->blit_lock, irqsave);
-
-       /*
-        * Allow for handle wraparounds.
-        */
-
-       active = ((blitq->done_blit_handle - handle) > (1 << 23)) &&
-               ((blitq->cur_blit_handle - handle) <= (1 << 23));
-
-       if (queue && active) {
-               slot = handle - blitq->done_blit_handle + blitq->cur -1;
-               if (slot >= VIA_NUM_BLIT_SLOTS) {
-                       slot -= VIA_NUM_BLIT_SLOTS;
-               }
-               *queue = blitq->blit_queue + slot;
-       }
-
-       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-
-       return active;
-}
-
-/*
- * Sync. Wait for at least three seconds for the blit to be performed.
- */
-
-static int
-via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine)
-{
-
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-       drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
-       wait_queue_head_t *queue;
-       int ret = 0;
-
-       if (via_dmablit_active(blitq, engine, handle, &queue)) {
-               DRM_WAIT_ON(ret, *queue, 3 * DRM_HZ,
-                           !via_dmablit_active(blitq, engine, handle, NULL));
-       }
-       DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n",
-                 handle, engine, ret);
-
-       return ret;
-}
-
-
-/*
- * A timer that regularly polls the blit engine in cases where we don't have interrupts:
- * a) Broken hardware (typically those that don't have any video capture facility).
- * b) Blit abort. The hardware doesn't send an interrupt when a blit is aborted.
- * The timer and hardware IRQ's can and do work in parallel. If the hardware has
- * irqs, it will shorten the latency somewhat.
- */
-
-
-
-static void
-via_dmablit_timer(unsigned long data)
-{
-       drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;
-       struct drm_device *dev = blitq->dev;
-       int engine = (int)
-               (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues);
-
-       DRM_DEBUG("Polling timer called for engine %d, jiffies %lu\n", engine,
-                 (unsigned long) jiffies);
-
-       via_dmablit_handler(dev, engine, 0);
-
-       if (!timer_pending(&blitq->poll_timer)) {
-               mod_timer(&blitq->poll_timer, jiffies + 1);
-
-              /*
-               * Rerun handler to delete timer if engines are off, and
-               * to shorten abort latency. This is a little nasty.
-               */
-
-              via_dmablit_handler(dev, engine, 0);
-
-       }
-}
-
-
-
-
-/*
- * Workqueue task that frees data and mappings associated with a blit.
- * Also wakes up waiting processes. Each of these tasks handles one
- * blit engine only and may not be called on each interrupt.
- */
-
-
-static void
-via_dmablit_workqueue(struct work_struct *work)
-{
-       drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq);
-       struct drm_device *dev = blitq->dev;
-       unsigned long irqsave;
-       drm_via_sg_info_t *cur_sg;
-       int cur_released;
-
-
-       DRM_DEBUG("Workqueue task called for blit engine %ld\n",(unsigned long)
-                 (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues));
-
-       spin_lock_irqsave(&blitq->blit_lock, irqsave);
-
-       while(blitq->serviced != blitq->cur) {
-
-               cur_released = blitq->serviced++;
-
-               DRM_DEBUG("Releasing blit slot %d\n", cur_released);
-
-               if (blitq->serviced >= VIA_NUM_BLIT_SLOTS)
-                       blitq->serviced = 0;
-
-               cur_sg = blitq->blits[cur_released];
-               blitq->num_free++;
-
-               spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-
-               DRM_WAKEUP(&blitq->busy_queue);
-
-               via_free_sg_info(dev->pdev, cur_sg);
-               kfree(cur_sg);
-
-               spin_lock_irqsave(&blitq->blit_lock, irqsave);
-       }
-
-       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-}
-
-
-/*
- * Init all blit engines. Currently we use two, but some hardware have 4.
- */
-
-
-void
-via_init_dmablit(struct drm_device *dev)
-{
-       int i,j;
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-       drm_via_blitq_t *blitq;
-
-       pci_set_master(dev->pdev);
-
-       for (i=0; i< VIA_NUM_BLIT_ENGINES; ++i) {
-               blitq = dev_priv->blit_queues + i;
-               blitq->dev = dev;
-               blitq->cur_blit_handle = 0;
-               blitq->done_blit_handle = 0;
-               blitq->head = 0;
-               blitq->cur = 0;
-               blitq->serviced = 0;
-               blitq->num_free = VIA_NUM_BLIT_SLOTS - 1;
-               blitq->num_outstanding = 0;
-               blitq->is_active = 0;
-               blitq->aborting = 0;
-               spin_lock_init(&blitq->blit_lock);
-               for (j=0; j<VIA_NUM_BLIT_SLOTS; ++j) {
-                       DRM_INIT_WAITQUEUE(blitq->blit_queue + j);
-               }
-               DRM_INIT_WAITQUEUE(&blitq->busy_queue);
-               INIT_WORK(&blitq->wq, via_dmablit_workqueue);
-               setup_timer(&blitq->poll_timer, via_dmablit_timer,
-                               (unsigned long)blitq);
-       }
-}
-
-/*
- * Build all info and do all mappings required for a blit.
- */
-
-
-static int
-via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
-{
-       int draw = xfer->to_fb;
-       int ret = 0;
-
-       vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
-       vsg->bounce_buffer = NULL;
-
-       vsg->state = dr_via_sg_init;
-
-       if (xfer->num_lines <= 0 || xfer->line_length <= 0) {
-               DRM_ERROR("Zero size bitblt.\n");
-               return -EINVAL;
-       }
-
-       /*
-        * Below check is a driver limitation, not a hardware one. We
-        * don't want to lock unused pages, and don't want to incoporate the
-        * extra logic of avoiding them. Make sure there are no.
-        * (Not a big limitation anyway.)
-        */
-
-       if ((xfer->mem_stride - xfer->line_length) > 2*PAGE_SIZE) {
-               DRM_ERROR("Too large system memory stride. Stride: %d, "
-                         "Length: %d\n", xfer->mem_stride, xfer->line_length);
-               return -EINVAL;
-       }
-
-       if ((xfer->mem_stride == xfer->line_length) &&
-          (xfer->fb_stride == xfer->line_length)) {
-               xfer->mem_stride *= xfer->num_lines;
-               xfer->line_length = xfer->mem_stride;
-               xfer->fb_stride = xfer->mem_stride;
-               xfer->num_lines = 1;
-       }
-
-       /*
-        * Don't lock an arbitrary large number of pages, since that causes a
-        * DOS security hole.
-        */
-
-       if (xfer->num_lines > 2048 || (xfer->num_lines*xfer->mem_stride > (2048*2048*4))) {
-               DRM_ERROR("Too large PCI DMA bitblt.\n");
-               return -EINVAL;
-       }
-
-       /*
-        * we allow a negative fb stride to allow flipping of images in
-        * transfer.
-        */
-
-       if (xfer->mem_stride < xfer->line_length ||
-               abs(xfer->fb_stride) < xfer->line_length) {
-               DRM_ERROR("Invalid frame-buffer / memory stride.\n");
-               return -EINVAL;
-       }
-
-       /*
-        * A hardware bug seems to be worked around if system memory addresses start on
-        * 16 byte boundaries. This seems a bit restrictive however. VIA is contacted
-        * about this. Meanwhile, impose the following restrictions:
-        */
-
-#ifdef VIA_BUGFREE
-       if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) ||
-           ((xfer->num_lines > 1) && ((xfer->mem_stride & 3) != (xfer->fb_stride & 3)))) {
-               DRM_ERROR("Invalid DRM bitblt alignment.\n");
-               return -EINVAL;
-       }
-#else
-       if ((((unsigned long)xfer->mem_addr & 15) ||
-             ((unsigned long)xfer->fb_addr & 3)) ||
-          ((xfer->num_lines > 1) &&
-          ((xfer->mem_stride & 15) || (xfer->fb_stride & 3)))) {
-               DRM_ERROR("Invalid DRM bitblt alignment.\n");
-               return -EINVAL;
-       }
-#endif
-
-       if (0 != (ret = via_lock_all_dma_pages(vsg, xfer))) {
-               DRM_ERROR("Could not lock DMA pages.\n");
-               via_free_sg_info(dev->pdev, vsg);
-               return ret;
-       }
-
-       via_map_blit_for_device(dev->pdev, xfer, vsg, 0);
-       if (0 != (ret = via_alloc_desc_pages(vsg))) {
-               DRM_ERROR("Could not allocate DMA descriptor pages.\n");
-               via_free_sg_info(dev->pdev, vsg);
-               return ret;
-       }
-       via_map_blit_for_device(dev->pdev, xfer, vsg, 1);
-
-       return 0;
-}
-
-
-/*
- * Reserve one free slot in the blit queue. Will wait for one second for one
- * to become available. Otherwise -EBUSY is returned.
- */
-
-static int
-via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine)
-{
-       int ret=0;
-       unsigned long irqsave;
-
-       DRM_DEBUG("Num free is %d\n", blitq->num_free);
-       spin_lock_irqsave(&blitq->blit_lock, irqsave);
-       while(blitq->num_free == 0) {
-               spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-
-               DRM_WAIT_ON(ret, blitq->busy_queue, DRM_HZ, blitq->num_free > 0);
-               if (ret) {
-                       return (-EINTR == ret) ? -EAGAIN : ret;
-               }
-
-               spin_lock_irqsave(&blitq->blit_lock, irqsave);
-       }
-
-       blitq->num_free--;
-       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-
-       return 0;
-}
-
-/*
- * Hand back a free slot if we changed our mind.
- */
-
-static void
-via_dmablit_release_slot(drm_via_blitq_t *blitq)
-{
-       unsigned long irqsave;
-
-       spin_lock_irqsave(&blitq->blit_lock, irqsave);
-       blitq->num_free++;
-       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-       DRM_WAKEUP( &blitq->busy_queue );
-}
-
-/*
- * Grab a free slot. Build blit info and queue a blit.
- */
-
-
-static int
-via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-       drm_via_sg_info_t *vsg;
-       drm_via_blitq_t *blitq;
-       int ret;
-       int engine;
-       unsigned long irqsave;
-
-       if (dev_priv == NULL) {
-               DRM_ERROR("Called without initialization.\n");
-               return -EINVAL;
-       }
-
-       engine = (xfer->to_fb) ? 0 : 1;
-       blitq = dev_priv->blit_queues + engine;
-       if (0 != (ret = via_dmablit_grab_slot(blitq, engine))) {
-               return ret;
-       }
-       if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) {
-               via_dmablit_release_slot(blitq);
-               return -ENOMEM;
-       }
-       if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) {
-               via_dmablit_release_slot(blitq);
-               kfree(vsg);
-               return ret;
-       }
-       spin_lock_irqsave(&blitq->blit_lock, irqsave);
-
-       blitq->blits[blitq->head++] = vsg;
-       if (blitq->head >= VIA_NUM_BLIT_SLOTS)
-               blitq->head = 0;
-       blitq->num_outstanding++;
-       xfer->sync.sync_handle = ++blitq->cur_blit_handle;
-
-       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-       xfer->sync.engine = engine;
-
-       via_dmablit_handler(dev, engine, 0);
-
-       return 0;
-}
-
-/*
- * Sync on a previously submitted blit. Note that the X server use signals extensively, and
- * that there is a very big probability that this IOCTL will be interrupted by a signal. In that
- * case it returns with -EAGAIN for the signal to be delivered.
- * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock().
- */
-
-int
-via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_priv )
-{
-       drm_via_blitsync_t *sync = data;
-       int err;
-
-       if (sync->engine >= VIA_NUM_BLIT_ENGINES)
-               return -EINVAL;
-
-       err = via_dmablit_sync(dev, sync->sync_handle, sync->engine);
-
-       if (-EINTR == err)
-               err = -EAGAIN;
-
-       return err;
-}
-
-
-/*
- * Queue a blit and hand back a handle to be used for sync. This IOCTL may be interrupted by a signal
- * while waiting for a free slot in the blit queue. In that case it returns with -EAGAIN and should
- * be reissued. See the above IOCTL code.
- */
-
-int
-via_dma_blit( struct drm_device *dev, void *data, struct drm_file *file_priv )
-{
-       drm_via_dmablit_t *xfer = data;
-       int err;
-
-       err = via_dmablit(dev, xfer);
-
-       return err;
-}
diff --git a/drivers/char/drm/via_dmablit.h b/drivers/char/drm/via_dmablit.h
deleted file mode 100644 (file)
index 7408a54..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/* via_dmablit.h -- PCI DMA BitBlt support for the VIA Unichrome/Pro
- *
- * Copyright 2005 Thomas Hellstrom.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Thomas Hellstrom.
- *    Register info from Digeo Inc.
- */
-
-#ifndef _VIA_DMABLIT_H
-#define _VIA_DMABLIT_H
-
-#include <linux/dma-mapping.h>
-
-#define VIA_NUM_BLIT_ENGINES 2
-#define VIA_NUM_BLIT_SLOTS 8
-
-struct _drm_via_descriptor;
-
-typedef struct _drm_via_sg_info {
-       struct page **pages;
-       unsigned long num_pages;
-       struct _drm_via_descriptor **desc_pages;
-       int num_desc_pages;
-       int num_desc;
-       enum dma_data_direction direction;
-       unsigned char *bounce_buffer;
-        dma_addr_t chain_start;
-       uint32_t free_on_sequence;
-        unsigned int descriptors_per_page;
-       int aborted;
-       enum {
-               dr_via_device_mapped,
-               dr_via_desc_pages_alloc,
-               dr_via_pages_locked,
-               dr_via_pages_alloc,
-               dr_via_sg_init
-       } state;
-} drm_via_sg_info_t;
-
-typedef struct _drm_via_blitq {
-       struct drm_device *dev;
-       uint32_t cur_blit_handle;
-       uint32_t done_blit_handle;
-       unsigned serviced;
-       unsigned head;
-       unsigned cur;
-       unsigned num_free;
-       unsigned num_outstanding;
-       unsigned long end;
-        int aborting;
-       int is_active;
-       drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS];
-       spinlock_t blit_lock;
-       wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS];
-       wait_queue_head_t busy_queue;
-       struct work_struct wq;
-       struct timer_list poll_timer;
-} drm_via_blitq_t;
-
-
-/*
- *  PCI DMA Registers
- *  Channels 2 & 3 don't seem to be implemented in hardware.
- */
-
-#define VIA_PCI_DMA_MAR0            0xE40   /* Memory Address Register of Channel 0 */
-#define VIA_PCI_DMA_DAR0            0xE44   /* Device Address Register of Channel 0 */
-#define VIA_PCI_DMA_BCR0            0xE48   /* Byte Count Register of Channel 0 */
-#define VIA_PCI_DMA_DPR0            0xE4C   /* Descriptor Pointer Register of Channel 0 */
-
-#define VIA_PCI_DMA_MAR1            0xE50   /* Memory Address Register of Channel 1 */
-#define VIA_PCI_DMA_DAR1            0xE54   /* Device Address Register of Channel 1 */
-#define VIA_PCI_DMA_BCR1            0xE58   /* Byte Count Register of Channel 1 */
-#define VIA_PCI_DMA_DPR1            0xE5C   /* Descriptor Pointer Register of Channel 1 */
-
-#define VIA_PCI_DMA_MAR2            0xE60   /* Memory Address Register of Channel 2 */
-#define VIA_PCI_DMA_DAR2            0xE64   /* Device Address Register of Channel 2 */
-#define VIA_PCI_DMA_BCR2            0xE68   /* Byte Count Register of Channel 2 */
-#define VIA_PCI_DMA_DPR2            0xE6C   /* Descriptor Pointer Register of Channel 2 */
-
-#define VIA_PCI_DMA_MAR3            0xE70   /* Memory Address Register of Channel 3 */
-#define VIA_PCI_DMA_DAR3            0xE74   /* Device Address Register of Channel 3 */
-#define VIA_PCI_DMA_BCR3            0xE78   /* Byte Count Register of Channel 3 */
-#define VIA_PCI_DMA_DPR3            0xE7C   /* Descriptor Pointer Register of Channel 3 */
-
-#define VIA_PCI_DMA_MR0             0xE80   /* Mode Register of Channel 0 */
-#define VIA_PCI_DMA_MR1             0xE84   /* Mode Register of Channel 1 */
-#define VIA_PCI_DMA_MR2             0xE88   /* Mode Register of Channel 2 */
-#define VIA_PCI_DMA_MR3             0xE8C   /* Mode Register of Channel 3 */
-
-#define VIA_PCI_DMA_CSR0            0xE90   /* Command/Status Register of Channel 0 */
-#define VIA_PCI_DMA_CSR1            0xE94   /* Command/Status Register of Channel 1 */
-#define VIA_PCI_DMA_CSR2            0xE98   /* Command/Status Register of Channel 2 */
-#define VIA_PCI_DMA_CSR3            0xE9C   /* Command/Status Register of Channel 3 */
-
-#define VIA_PCI_DMA_PTR             0xEA0   /* Priority Type Register */
-
-/* Define for DMA engine */
-/* DPR */
-#define VIA_DMA_DPR_EC         (1<<1)  /* end of chain */
-#define VIA_DMA_DPR_DDIE       (1<<2)  /* descriptor done interrupt enable */
-#define VIA_DMA_DPR_DT         (1<<3)  /* direction of transfer (RO) */
-
-/* MR */
-#define VIA_DMA_MR_CM          (1<<0)  /* chaining mode */
-#define VIA_DMA_MR_TDIE                (1<<1)  /* transfer done interrupt enable */
-#define VIA_DMA_MR_HENDMACMD           (1<<7) /* ? */
-
-/* CSR */
-#define VIA_DMA_CSR_DE         (1<<0)  /* DMA enable */
-#define VIA_DMA_CSR_TS         (1<<1)  /* transfer start */
-#define VIA_DMA_CSR_TA         (1<<2)  /* transfer abort */
-#define VIA_DMA_CSR_TD         (1<<3)  /* transfer done */
-#define VIA_DMA_CSR_DD         (1<<4)  /* descriptor done */
-#define VIA_DMA_DPR_EC          (1<<1)  /* end of chain */
-
-
-
-#endif
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
deleted file mode 100644 (file)
index a3b5c10..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#ifndef _VIA_DRM_H_
-#define _VIA_DRM_H_
-
-/* WARNING: These defines must be the same as what the Xserver uses.
- * if you change them, you must change the defines in the Xserver.
- */
-
-#ifndef _VIA_DEFINES_
-#define _VIA_DEFINES_
-
-#ifndef __KERNEL__
-#include "via_drmclient.h"
-#endif
-
-#define VIA_NR_SAREA_CLIPRECTS         8
-#define VIA_NR_XVMC_PORTS               10
-#define VIA_NR_XVMC_LOCKS               5
-#define VIA_MAX_CACHELINE_SIZE          64
-#define XVMCLOCKPTR(saPriv,lockNo)                                     \
-       ((volatile struct drm_hw_lock *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
-                                     (VIA_MAX_CACHELINE_SIZE - 1)) &   \
-                                    ~(VIA_MAX_CACHELINE_SIZE - 1)) +   \
-                                   VIA_MAX_CACHELINE_SIZE*(lockNo)))
-
-/* Each region is a minimum of 64k, and there are at most 64 of them.
- */
-#define VIA_NR_TEX_REGIONS 64
-#define VIA_LOG_MIN_TEX_REGION_SIZE 16
-#endif
-
-#define VIA_UPLOAD_TEX0IMAGE  0x1      /* handled clientside */
-#define VIA_UPLOAD_TEX1IMAGE  0x2      /* handled clientside */
-#define VIA_UPLOAD_CTX        0x4
-#define VIA_UPLOAD_BUFFERS    0x8
-#define VIA_UPLOAD_TEX0       0x10
-#define VIA_UPLOAD_TEX1       0x20
-#define VIA_UPLOAD_CLIPRECTS  0x40
-#define VIA_UPLOAD_ALL        0xff
-
-/* VIA specific ioctls */
-#define DRM_VIA_ALLOCMEM       0x00
-#define DRM_VIA_FREEMEM                0x01
-#define DRM_VIA_AGP_INIT       0x02
-#define DRM_VIA_FB_INIT                0x03
-#define DRM_VIA_MAP_INIT       0x04
-#define DRM_VIA_DEC_FUTEX       0x05
-#define NOT_USED
-#define DRM_VIA_DMA_INIT       0x07
-#define DRM_VIA_CMDBUFFER      0x08
-#define DRM_VIA_FLUSH          0x09
-#define DRM_VIA_PCICMD         0x0a
-#define DRM_VIA_CMDBUF_SIZE    0x0b
-#define NOT_USED
-#define DRM_VIA_WAIT_IRQ        0x0d
-#define DRM_VIA_DMA_BLIT        0x0e
-#define DRM_VIA_BLIT_SYNC       0x0f
-
-#define DRM_IOCTL_VIA_ALLOCMEM   DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t)
-#define DRM_IOCTL_VIA_FREEMEM    DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t)
-#define DRM_IOCTL_VIA_AGP_INIT   DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_AGP_INIT, drm_via_agp_t)
-#define DRM_IOCTL_VIA_FB_INIT    DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_FB_INIT, drm_via_fb_t)
-#define DRM_IOCTL_VIA_MAP_INIT   DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_MAP_INIT, drm_via_init_t)
-#define DRM_IOCTL_VIA_DEC_FUTEX   DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_DEC_FUTEX, drm_via_futex_t)
-#define DRM_IOCTL_VIA_DMA_INIT   DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_DMA_INIT, drm_via_dma_init_t)
-#define DRM_IOCTL_VIA_CMDBUFFER          DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_CMDBUFFER, drm_via_cmdbuffer_t)
-#define DRM_IOCTL_VIA_FLUSH      DRM_IO(  DRM_COMMAND_BASE + DRM_VIA_FLUSH)
-#define DRM_IOCTL_VIA_PCICMD     DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_PCICMD, drm_via_cmdbuffer_t)
-#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \
-                                           drm_via_cmdbuf_size_t)
-#define DRM_IOCTL_VIA_WAIT_IRQ    DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t)
-#define DRM_IOCTL_VIA_DMA_BLIT    DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t)
-#define DRM_IOCTL_VIA_BLIT_SYNC   DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t)
-
-/* Indices into buf.Setup where various bits of state are mirrored per
- * context and per buffer.  These can be fired at the card as a unit,
- * or in a piecewise fashion as required.
- */
-
-#define VIA_TEX_SETUP_SIZE 8
-
-/* Flags for clear ioctl
- */
-#define VIA_FRONT   0x1
-#define VIA_BACK    0x2
-#define VIA_DEPTH   0x4
-#define VIA_STENCIL 0x8
-#define VIA_MEM_VIDEO   0      /* matches drm constant */
-#define VIA_MEM_AGP     1      /* matches drm constant */
-#define VIA_MEM_SYSTEM  2
-#define VIA_MEM_MIXED   3
-#define VIA_MEM_UNKNOWN 4
-
-typedef struct {
-       uint32_t offset;
-       uint32_t size;
-} drm_via_agp_t;
-
-typedef struct {
-       uint32_t offset;
-       uint32_t size;
-} drm_via_fb_t;
-
-typedef struct {
-       uint32_t context;
-       uint32_t type;
-       uint32_t size;
-       unsigned long index;
-       unsigned long offset;
-} drm_via_mem_t;
-
-typedef struct _drm_via_init {
-       enum {
-               VIA_INIT_MAP = 0x01,
-               VIA_CLEANUP_MAP = 0x02
-       } func;
-
-       unsigned long sarea_priv_offset;
-       unsigned long fb_offset;
-       unsigned long mmio_offset;
-       unsigned long agpAddr;
-} drm_via_init_t;
-
-typedef struct _drm_via_futex {
-       enum {
-               VIA_FUTEX_WAIT = 0x00,
-               VIA_FUTEX_WAKE = 0X01
-       } func;
-       uint32_t ms;
-       uint32_t lock;
-       uint32_t val;
-} drm_via_futex_t;
-
-typedef struct _drm_via_dma_init {
-       enum {
-               VIA_INIT_DMA = 0x01,
-               VIA_CLEANUP_DMA = 0x02,
-               VIA_DMA_INITIALIZED = 0x03
-       } func;
-
-       unsigned long offset;
-       unsigned long size;
-       unsigned long reg_pause_addr;
-} drm_via_dma_init_t;
-
-typedef struct _drm_via_cmdbuffer {
-       char __user *buf;
-       unsigned long size;
-} drm_via_cmdbuffer_t;
-
-/* Warning: If you change the SAREA structure you must change the Xserver
- * structure as well */
-
-typedef struct _drm_via_tex_region {
-       unsigned char next, prev;       /* indices to form a circular LRU  */
-       unsigned char inUse;    /* owned by a client, or free? */
-       int age;                /* tracked by clients to update local LRU's */
-} drm_via_tex_region_t;
-
-typedef struct _drm_via_sarea {
-       unsigned int dirty;
-       unsigned int nbox;
-       struct drm_clip_rect boxes[VIA_NR_SAREA_CLIPRECTS];
-       drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1];
-       int texAge;             /* last time texture was uploaded */
-       int ctxOwner;           /* last context to upload state */
-       int vertexPrim;
-
-       /*
-        * Below is for XvMC.
-        * We want the lock integers alone on, and aligned to, a cache line.
-        * Therefore this somewhat strange construct.
-        */
-
-       char XvMCLockArea[VIA_MAX_CACHELINE_SIZE * (VIA_NR_XVMC_LOCKS + 1)];
-
-       unsigned int XvMCDisplaying[VIA_NR_XVMC_PORTS];
-       unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS];
-       unsigned int XvMCCtxNoGrabbed;  /* Last context to hold decoder */
-
-       /* Used by the 3d driver only at this point, for pageflipping:
-        */
-       unsigned int pfCurrentOffset;
-} drm_via_sarea_t;
-
-typedef struct _drm_via_cmdbuf_size {
-       enum {
-               VIA_CMDBUF_SPACE = 0x01,
-               VIA_CMDBUF_LAG = 0x02
-       } func;
-       int wait;
-       uint32_t size;
-} drm_via_cmdbuf_size_t;
-
-typedef enum {
-       VIA_IRQ_ABSOLUTE = 0x0,
-       VIA_IRQ_RELATIVE = 0x1,
-       VIA_IRQ_SIGNAL = 0x10000000,
-       VIA_IRQ_FORCE_SEQUENCE = 0x20000000
-} via_irq_seq_type_t;
-
-#define VIA_IRQ_FLAGS_MASK 0xF0000000
-
-enum drm_via_irqs {
-       drm_via_irq_hqv0 = 0,
-       drm_via_irq_hqv1,
-       drm_via_irq_dma0_dd,
-       drm_via_irq_dma0_td,
-       drm_via_irq_dma1_dd,
-       drm_via_irq_dma1_td,
-       drm_via_irq_num
-};
-
-struct drm_via_wait_irq_request {
-       unsigned irq;
-       via_irq_seq_type_t type;
-       uint32_t sequence;
-       uint32_t signal;
-};
-
-typedef union drm_via_irqwait {
-       struct drm_via_wait_irq_request request;
-       struct drm_wait_vblank_reply reply;
-} drm_via_irqwait_t;
-
-typedef struct drm_via_blitsync {
-       uint32_t sync_handle;
-       unsigned engine;
-} drm_via_blitsync_t;
-
-/* - * Below,"flags" is currently unused but will be used for possible future
- * extensions like kernel space bounce buffers for bad alignments and
- * blit engine busy-wait polling for better latency in the absence of
- * interrupts.
- */
-
-typedef struct drm_via_dmablit {
-       uint32_t num_lines;
-       uint32_t line_length;
-
-       uint32_t fb_addr;
-       uint32_t fb_stride;
-
-       unsigned char *mem_addr;
-       uint32_t mem_stride;
-
-       uint32_t flags;
-       int to_fb;
-
-       drm_via_blitsync_t sync;
-} drm_via_dmablit_t;
-
-#endif                         /* _VIA_DRM_H_ */
diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c
deleted file mode 100644 (file)
index 80c01cd..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include "drmP.h"
-#include "via_drm.h"
-#include "via_drv.h"
-
-#include "drm_pciids.h"
-
-static int dri_library_name(struct drm_device *dev, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "unichrome");
-}
-
-static struct pci_device_id pciidlist[] = {
-       viadrv_PCI_IDS
-};
-
-static struct drm_driver driver = {
-       .driver_features =
-           DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
-           DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
-       .load = via_driver_load,
-       .unload = via_driver_unload,
-       .context_dtor = via_final_context,
-       .vblank_wait = via_driver_vblank_wait,
-       .irq_preinstall = via_driver_irq_preinstall,
-       .irq_postinstall = via_driver_irq_postinstall,
-       .irq_uninstall = via_driver_irq_uninstall,
-       .irq_handler = via_driver_irq_handler,
-       .dma_quiescent = via_driver_dma_quiescent,
-       .dri_library_name = dri_library_name,
-       .reclaim_buffers = drm_core_reclaim_buffers,
-       .reclaim_buffers_locked = NULL,
-       .reclaim_buffers_idlelocked = via_reclaim_buffers_locked,
-       .lastclose = via_lastclose,
-       .get_map_ofs = drm_core_get_map_ofs,
-       .get_reg_ofs = drm_core_get_reg_ofs,
-       .ioctls = via_ioctls,
-       .fops = {
-                .owner = THIS_MODULE,
-                .open = drm_open,
-                .release = drm_release,
-                .ioctl = drm_ioctl,
-                .mmap = drm_mmap,
-                .poll = drm_poll,
-                .fasync = drm_fasync,
-       },
-       .pci_driver = {
-                .name = DRIVER_NAME,
-                .id_table = pciidlist,
-       },
-
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int __init via_init(void)
-{
-       driver.num_ioctls = via_max_ioctl;
-       via_init_command_verifier();
-       return drm_init(&driver);
-}
-
-static void __exit via_exit(void)
-{
-       drm_exit(&driver);
-}
-
-module_init(via_init);
-module_exit(via_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
deleted file mode 100644 (file)
index 2daae81..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#ifndef _VIA_DRV_H_
-#define _VIA_DRV_H_
-
-#include "drm_sman.h"
-#define DRIVER_AUTHOR  "Various"
-
-#define DRIVER_NAME            "via"
-#define DRIVER_DESC            "VIA Unichrome / Pro"
-#define DRIVER_DATE            "20070202"
-
-#define DRIVER_MAJOR           2
-#define DRIVER_MINOR           11
-#define DRIVER_PATCHLEVEL      1
-
-#include "via_verifier.h"
-
-#include "via_dmablit.h"
-
-#define VIA_PCI_BUF_SIZE 60000
-#define VIA_FIRE_BUF_SIZE  1024
-#define VIA_NUM_IRQS 4
-
-typedef struct drm_via_ring_buffer {
-       drm_local_map_t map;
-       char *virtual_start;
-} drm_via_ring_buffer_t;
-
-typedef uint32_t maskarray_t[5];
-
-typedef struct drm_via_irq {
-       atomic_t irq_received;
-       uint32_t pending_mask;
-       uint32_t enable_mask;
-       wait_queue_head_t irq_queue;
-} drm_via_irq_t;
-
-typedef struct drm_via_private {
-       drm_via_sarea_t *sarea_priv;
-       drm_local_map_t *sarea;
-       drm_local_map_t *fb;
-       drm_local_map_t *mmio;
-       unsigned long agpAddr;
-       wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
-       char *dma_ptr;
-       unsigned int dma_low;
-       unsigned int dma_high;
-       unsigned int dma_offset;
-       uint32_t dma_wrap;
-       volatile uint32_t *last_pause_ptr;
-       volatile uint32_t *hw_addr_ptr;
-       drm_via_ring_buffer_t ring;
-       struct timeval last_vblank;
-       int last_vblank_valid;
-       unsigned usec_per_vblank;
-       drm_via_state_t hc_state;
-       char pci_buf[VIA_PCI_BUF_SIZE];
-       const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
-       uint32_t num_fire_offsets;
-       int chipset;
-       drm_via_irq_t via_irqs[VIA_NUM_IRQS];
-       unsigned num_irqs;
-       maskarray_t *irq_masks;
-       uint32_t irq_enable_mask;
-       uint32_t irq_pending_mask;
-       int *irq_map;
-       unsigned int idle_fault;
-       struct drm_sman sman;
-       int vram_initialized;
-       int agp_initialized;
-       unsigned long vram_offset;
-       unsigned long agp_offset;
-       drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
-       uint32_t dma_diff;
-} drm_via_private_t;
-
-enum via_family {
-  VIA_OTHER = 0,     /* Baseline */
-  VIA_PRO_GROUP_A,   /* Another video engine and DMA commands */
-  VIA_DX9_0          /* Same video as pro_group_a, but 3D is unsupported */
-};
-
-/* VIA MMIO register access */
-#define VIA_BASE ((dev_priv->mmio))
-
-#define VIA_READ(reg)          DRM_READ32(VIA_BASE, reg)
-#define VIA_WRITE(reg,val)     DRM_WRITE32(VIA_BASE, reg, val)
-#define VIA_READ8(reg)         DRM_READ8(VIA_BASE, reg)
-#define VIA_WRITE8(reg,val)    DRM_WRITE8(VIA_BASE, reg, val)
-
-extern struct drm_ioctl_desc via_ioctls[];
-extern int via_max_ioctl;
-
-extern int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_priv );
-extern int via_dma_blit( struct drm_device *dev, void *data, struct drm_file *file_priv );
-
-extern int via_driver_load(struct drm_device *dev, unsigned long chipset);
-extern int via_driver_unload(struct drm_device *dev);
-
-extern int via_init_context(struct drm_device * dev, int context);
-extern int via_final_context(struct drm_device * dev, int context);
-
-extern int via_do_cleanup_map(struct drm_device * dev);
-extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
-
-extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
-extern void via_driver_irq_preinstall(struct drm_device * dev);
-extern void via_driver_irq_postinstall(struct drm_device * dev);
-extern void via_driver_irq_uninstall(struct drm_device * dev);
-
-extern int via_dma_cleanup(struct drm_device * dev);
-extern void via_init_command_verifier(void);
-extern int via_driver_dma_quiescent(struct drm_device * dev);
-extern void via_init_futex(drm_via_private_t * dev_priv);
-extern void via_cleanup_futex(drm_via_private_t * dev_priv);
-extern void via_release_futex(drm_via_private_t * dev_priv, int context);
-
-extern void via_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file_priv);
-extern void via_lastclose(struct drm_device *dev);
-
-extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
-extern void via_init_dmablit(struct drm_device *dev);
-
-#endif
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
deleted file mode 100644 (file)
index c6bb978..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-/* via_irq.c
- *
- * Copyright 2004 BEAM Ltd.
- * Copyright 2002 Tungsten Graphics, Inc.
- * Copyright 2005 Thomas Hellstrom.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BEAM LTD, TUNGSTEN GRAPHICS  AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Terry Barnaby <terry1@beam.ltd.uk>
- *    Keith Whitwell <keith@tungstengraphics.com>
- *    Thomas Hellstrom <unichrome@shipmail.org>
- *
- * This code provides standard DRM access to the Via Unichrome / Pro Vertical blank
- * interrupt, as well as an infrastructure to handle other interrupts of the chip.
- * The refresh rate is also calculated for video playback sync purposes.
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "via_drm.h"
-#include "via_drv.h"
-
-#define VIA_REG_INTERRUPT       0x200
-
-/* VIA_REG_INTERRUPT */
-#define VIA_IRQ_GLOBAL          (1 << 31)
-#define VIA_IRQ_VBLANK_ENABLE   (1 << 19)
-#define VIA_IRQ_VBLANK_PENDING  (1 << 3)
-#define VIA_IRQ_HQV0_ENABLE     (1 << 11)
-#define VIA_IRQ_HQV1_ENABLE     (1 << 25)
-#define VIA_IRQ_HQV0_PENDING    (1 << 9)
-#define VIA_IRQ_HQV1_PENDING    (1 << 10)
-#define VIA_IRQ_DMA0_DD_ENABLE  (1 << 20)
-#define VIA_IRQ_DMA0_TD_ENABLE  (1 << 21)
-#define VIA_IRQ_DMA1_DD_ENABLE  (1 << 22)
-#define VIA_IRQ_DMA1_TD_ENABLE  (1 << 23)
-#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
-#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
-#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
-#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
-
-
-/*
- * Device-specific IRQs go here. This type might need to be extended with
- * the register if there are multiple IRQ control registers.
- * Currently we activate the HQV interrupts of  Unichrome Pro group A.
- */
-
-static maskarray_t via_pro_group_a_irqs[] = {
-       {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
-        0x00000000},
-       {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
-        0x00000000},
-       {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
-        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
-       {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
-        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
-};
-static int via_num_pro_group_a =
-    sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);
-static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
-
-static maskarray_t via_unichrome_irqs[] = {
-       {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
-        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
-       {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
-        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
-};
-static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);
-static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
-
-static unsigned time_diff(struct timeval *now, struct timeval *then)
-{
-       return (now->tv_usec >= then->tv_usec) ?
-           now->tv_usec - then->tv_usec :
-           1000000 - (then->tv_usec - now->tv_usec);
-}
-
-irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
-{
-       struct drm_device *dev = (struct drm_device *) arg;
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       u32 status;
-       int handled = 0;
-       struct timeval cur_vblank;
-       drm_via_irq_t *cur_irq = dev_priv->via_irqs;
-       int i;
-
-       status = VIA_READ(VIA_REG_INTERRUPT);
-       if (status & VIA_IRQ_VBLANK_PENDING) {
-               atomic_inc(&dev->vbl_received);
-               if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
-                       do_gettimeofday(&cur_vblank);
-                       if (dev_priv->last_vblank_valid) {
-                               dev_priv->usec_per_vblank =
-                                   time_diff(&cur_vblank,
-                                             &dev_priv->last_vblank) >> 4;
-                       }
-                       dev_priv->last_vblank = cur_vblank;
-                       dev_priv->last_vblank_valid = 1;
-               }
-               if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
-                       DRM_DEBUG("US per vblank is: %u\n",
-                                 dev_priv->usec_per_vblank);
-               }
-               DRM_WAKEUP(&dev->vbl_queue);
-               drm_vbl_send_signals(dev);
-               handled = 1;
-       }
-
-       for (i = 0; i < dev_priv->num_irqs; ++i) {
-               if (status & cur_irq->pending_mask) {
-                       atomic_inc(&cur_irq->irq_received);
-                       DRM_WAKEUP(&cur_irq->irq_queue);
-                       handled = 1;
-                       if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) {
-                               via_dmablit_handler(dev, 0, 1);
-                       } else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) {
-                               via_dmablit_handler(dev, 1, 1);
-                       }
-               }
-               cur_irq++;
-       }
-
-       /* Acknowlege interrupts */
-       VIA_WRITE(VIA_REG_INTERRUPT, status);
-
-       if (handled)
-               return IRQ_HANDLED;
-       else
-               return IRQ_NONE;
-}
-
-static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
-{
-       u32 status;
-
-       if (dev_priv) {
-               /* Acknowlege interrupts */
-               status = VIA_READ(VIA_REG_INTERRUPT);
-               VIA_WRITE(VIA_REG_INTERRUPT, status |
-                         dev_priv->irq_pending_mask);
-       }
-}
-
-int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       unsigned int cur_vblank;
-       int ret = 0;
-
-       DRM_DEBUG("\n");
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       viadrv_acknowledge_irqs(dev_priv);
-
-       /* Assume that the user has missed the current sequence number
-        * by about a day rather than she wants to wait for years
-        * using vertical blanks...
-        */
-
-       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(&dev->vbl_received)) -
-                     *sequence) <= (1 << 23)));
-
-       *sequence = cur_vblank;
-       return ret;
-}
-
-static int
-via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequence,
-                   unsigned int *sequence)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       unsigned int cur_irq_sequence;
-       drm_via_irq_t *cur_irq;
-       int ret = 0;
-       maskarray_t *masks;
-       int real_irq;
-
-       DRM_DEBUG("\n");
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       if (irq >= drm_via_irq_num) {
-               DRM_ERROR("Trying to wait on unknown irq %d\n", irq);
-               return -EINVAL;
-       }
-
-       real_irq = dev_priv->irq_map[irq];
-
-       if (real_irq < 0) {
-               DRM_ERROR("Video IRQ %d not available on this hardware.\n",
-                         irq);
-               return -EINVAL;
-       }
-
-       masks = dev_priv->irq_masks;
-       cur_irq = dev_priv->via_irqs + real_irq;
-
-       if (masks[real_irq][2] && !force_sequence) {
-               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
-                           ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==
-                            masks[irq][4]));
-               cur_irq_sequence = atomic_read(&cur_irq->irq_received);
-       } else {
-               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
-                           (((cur_irq_sequence =
-                              atomic_read(&cur_irq->irq_received)) -
-                             *sequence) <= (1 << 23)));
-       }
-       *sequence = cur_irq_sequence;
-       return ret;
-}
-
-/*
- * drm_dma.h hooks
- */
-
-void via_driver_irq_preinstall(struct drm_device * dev)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       u32 status;
-       drm_via_irq_t *cur_irq;
-       int i;
-
-       DRM_DEBUG("dev_priv: %p\n", dev_priv);
-       if (dev_priv) {
-               cur_irq = dev_priv->via_irqs;
-
-               dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
-               dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
-
-               if (dev_priv->chipset == VIA_PRO_GROUP_A ||
-                   dev_priv->chipset == VIA_DX9_0) {
-                       dev_priv->irq_masks = via_pro_group_a_irqs;
-                       dev_priv->num_irqs = via_num_pro_group_a;
-                       dev_priv->irq_map = via_irqmap_pro_group_a;
-               } else {
-                       dev_priv->irq_masks = via_unichrome_irqs;
-                       dev_priv->num_irqs = via_num_unichrome;
-                       dev_priv->irq_map = via_irqmap_unichrome;
-               }
-
-               for (i = 0; i < dev_priv->num_irqs; ++i) {
-                       atomic_set(&cur_irq->irq_received, 0);
-                       cur_irq->enable_mask = dev_priv->irq_masks[i][0];
-                       cur_irq->pending_mask = dev_priv->irq_masks[i][1];
-                       DRM_INIT_WAITQUEUE(&cur_irq->irq_queue);
-                       dev_priv->irq_enable_mask |= cur_irq->enable_mask;
-                       dev_priv->irq_pending_mask |= cur_irq->pending_mask;
-                       cur_irq++;
-
-                       DRM_DEBUG("Initializing IRQ %d\n", i);
-               }
-
-               dev_priv->last_vblank_valid = 0;
-
-               /* Clear VSync interrupt regs */
-               status = VIA_READ(VIA_REG_INTERRUPT);
-               VIA_WRITE(VIA_REG_INTERRUPT, status &
-                         ~(dev_priv->irq_enable_mask));
-
-               /* Clear bits if they're already high */
-               viadrv_acknowledge_irqs(dev_priv);
-       }
-}
-
-void via_driver_irq_postinstall(struct drm_device * dev)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       u32 status;
-
-       DRM_DEBUG("\n");
-       if (dev_priv) {
-               status = VIA_READ(VIA_REG_INTERRUPT);
-               VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
-                         | dev_priv->irq_enable_mask);
-
-               /* Some magic, oh for some data sheets ! */
-
-               VIA_WRITE8(0x83d4, 0x11);
-               VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
-
-       }
-}
-
-void via_driver_irq_uninstall(struct drm_device * dev)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       u32 status;
-
-       DRM_DEBUG("\n");
-       if (dev_priv) {
-
-               /* Some more magic, oh for some data sheets ! */
-
-               VIA_WRITE8(0x83d4, 0x11);
-               VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
-
-               status = VIA_READ(VIA_REG_INTERRUPT);
-               VIA_WRITE(VIA_REG_INTERRUPT, status &
-                         ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
-       }
-}
-
-int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_irqwait_t *irqwait = data;
-       struct timeval now;
-       int ret = 0;
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       drm_via_irq_t *cur_irq = dev_priv->via_irqs;
-       int force_sequence;
-
-       if (!dev->irq)
-               return -EINVAL;
-
-       if (irqwait->request.irq >= dev_priv->num_irqs) {
-               DRM_ERROR("Trying to wait on unknown irq %d\n",
-                         irqwait->request.irq);
-               return -EINVAL;
-       }
-
-       cur_irq += irqwait->request.irq;
-
-       switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) {
-       case VIA_IRQ_RELATIVE:
-               irqwait->request.sequence += atomic_read(&cur_irq->irq_received);
-               irqwait->request.type &= ~_DRM_VBLANK_RELATIVE;
-       case VIA_IRQ_ABSOLUTE:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (irqwait->request.type & VIA_IRQ_SIGNAL) {
-               DRM_ERROR("Signals on Via IRQs not implemented yet.\n");
-               return -EINVAL;
-       }
-
-       force_sequence = (irqwait->request.type & VIA_IRQ_FORCE_SEQUENCE);
-
-       ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence,
-                                 &irqwait->request.sequence);
-       do_gettimeofday(&now);
-       irqwait->reply.tval_sec = now.tv_sec;
-       irqwait->reply.tval_usec = now.tv_usec;
-
-       return ret;
-}
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
deleted file mode 100644 (file)
index a967556..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#include "drmP.h"
-#include "via_drm.h"
-#include "via_drv.h"
-
-static int via_do_init_map(struct drm_device * dev, drm_via_init_t * init)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-
-       DRM_DEBUG("\n");
-
-       dev_priv->sarea = drm_getsarea(dev);
-       if (!dev_priv->sarea) {
-               DRM_ERROR("could not find sarea!\n");
-               dev->dev_private = (void *)dev_priv;
-               via_do_cleanup_map(dev);
-               return -EINVAL;
-       }
-
-       dev_priv->fb = drm_core_findmap(dev, init->fb_offset);
-       if (!dev_priv->fb) {
-               DRM_ERROR("could not find framebuffer!\n");
-               dev->dev_private = (void *)dev_priv;
-               via_do_cleanup_map(dev);
-               return -EINVAL;
-       }
-       dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
-       if (!dev_priv->mmio) {
-               DRM_ERROR("could not find mmio region!\n");
-               dev->dev_private = (void *)dev_priv;
-               via_do_cleanup_map(dev);
-               return -EINVAL;
-       }
-
-       dev_priv->sarea_priv =
-           (drm_via_sarea_t *) ((u8 *) dev_priv->sarea->handle +
-                                init->sarea_priv_offset);
-
-       dev_priv->agpAddr = init->agpAddr;
-
-       via_init_futex(dev_priv);
-
-       via_init_dmablit(dev);
-
-       dev->dev_private = (void *)dev_priv;
-       return 0;
-}
-
-int via_do_cleanup_map(struct drm_device * dev)
-{
-       via_dma_cleanup(dev);
-
-       return 0;
-}
-
-int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_init_t *init = data;
-
-       DRM_DEBUG("\n");
-
-       switch (init->func) {
-       case VIA_INIT_MAP:
-               return via_do_init_map(dev, init);
-       case VIA_CLEANUP_MAP:
-               return via_do_cleanup_map(dev);
-       }
-
-       return -EINVAL;
-}
-
-int via_driver_load(struct drm_device *dev, unsigned long chipset)
-{
-       drm_via_private_t *dev_priv;
-       int ret = 0;
-
-       dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
-       if (dev_priv == NULL)
-               return -ENOMEM;
-
-       dev->dev_private = (void *)dev_priv;
-
-       dev_priv->chipset = chipset;
-
-       ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
-       if (ret) {
-               drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
-       }
-       return ret;
-}
-
-int via_driver_unload(struct drm_device *dev)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-
-       drm_sman_takedown(&dev_priv->sman);
-
-       drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
-
-       return 0;
-}
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
deleted file mode 100644 (file)
index e640949..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-/*
- * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#include "drmP.h"
-#include "via_drm.h"
-#include "via_drv.h"
-#include "drm_sman.h"
-
-#define VIA_MM_ALIGN_SHIFT 4
-#define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1)
-
-int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_agp_t *agp = data;
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-       ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0,
-                                agp->size >> VIA_MM_ALIGN_SHIFT);
-
-       if (ret) {
-               DRM_ERROR("AGP memory manager initialisation error\n");
-               mutex_unlock(&dev->struct_mutex);
-               return ret;
-       }
-
-       dev_priv->agp_initialized = 1;
-       dev_priv->agp_offset = agp->offset;
-       mutex_unlock(&dev->struct_mutex);
-
-       DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
-       return 0;
-}
-
-int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_fb_t *fb = data;
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-       ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0,
-                                fb->size >> VIA_MM_ALIGN_SHIFT);
-
-       if (ret) {
-               DRM_ERROR("VRAM memory manager initialisation error\n");
-               mutex_unlock(&dev->struct_mutex);
-               return ret;
-       }
-
-       dev_priv->vram_initialized = 1;
-       dev_priv->vram_offset = fb->offset;
-
-       mutex_unlock(&dev->struct_mutex);
-       DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
-
-       return 0;
-
-}
-
-int via_final_context(struct drm_device *dev, int context)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-
-       via_release_futex(dev_priv, context);
-
-       /* Linux specific until context tracking code gets ported to BSD */
-       /* Last context, perform cleanup */
-       if (dev->ctx_count == 1 && dev->dev_private) {
-               DRM_DEBUG("Last Context\n");
-               if (dev->irq)
-                       drm_irq_uninstall(dev);
-               via_cleanup_futex(dev_priv);
-               via_do_cleanup_map(dev);
-       }
-       return 1;
-}
-
-void via_lastclose(struct drm_device *dev)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-
-       if (!dev_priv)
-               return;
-
-       mutex_lock(&dev->struct_mutex);
-       drm_sman_cleanup(&dev_priv->sman);
-       dev_priv->vram_initialized = 0;
-       dev_priv->agp_initialized = 0;
-       mutex_unlock(&dev->struct_mutex);
-}
-
-int via_mem_alloc(struct drm_device *dev, void *data,
-                 struct drm_file *file_priv)
-{
-       drm_via_mem_t *mem = data;
-       int retval = 0;
-       struct drm_memblock_item *item;
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       unsigned long tmpSize;
-
-       if (mem->type > VIA_MEM_AGP) {
-               DRM_ERROR("Unknown memory type allocation\n");
-               return -EINVAL;
-       }
-       mutex_lock(&dev->struct_mutex);
-       if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
-                     dev_priv->agp_initialized)) {
-               DRM_ERROR
-                   ("Attempt to allocate from uninitialized memory manager.\n");
-               mutex_unlock(&dev->struct_mutex);
-               return -EINVAL;
-       }
-
-       tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
-       item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0,
-                             (unsigned long)file_priv);
-       mutex_unlock(&dev->struct_mutex);
-       if (item) {
-               mem->offset = ((mem->type == VIA_MEM_VIDEO) ?
-                             dev_priv->vram_offset : dev_priv->agp_offset) +
-                   (item->mm->
-                    offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT);
-               mem->index = item->user_hash.key;
-       } else {
-               mem->offset = 0;
-               mem->size = 0;
-               mem->index = 0;
-               DRM_DEBUG("Video memory allocation failed\n");
-               retval = -ENOMEM;
-       }
-
-       return retval;
-}
-
-int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-       drm_via_mem_t *mem = data;
-       int ret;
-
-       mutex_lock(&dev->struct_mutex);
-       ret = drm_sman_free_key(&dev_priv->sman, mem->index);
-       mutex_unlock(&dev->struct_mutex);
-       DRM_DEBUG("free = 0x%lx\n", mem->index);
-
-       return ret;
-}
-
-
-void via_reclaim_buffers_locked(struct drm_device * dev,
-                               struct drm_file *file_priv)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-
-       mutex_lock(&dev->struct_mutex);
-       if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) {
-               mutex_unlock(&dev->struct_mutex);
-               return;
-       }
-
-       if (dev->driver->dma_quiescent) {
-               dev->driver->dma_quiescent(dev);
-       }
-
-       drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv);
-       mutex_unlock(&dev->struct_mutex);
-       return;
-}
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c
deleted file mode 100644 (file)
index 46a5791..0000000
+++ /dev/null
@@ -1,1116 +0,0 @@
-/*
- * Copyright 2004 The Unichrome Project. All Rights Reserved.
- * Copyright 2005 Thomas Hellstrom. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Thomas Hellstrom 2004, 2005.
- * This code was written using docs obtained under NDA from VIA Inc.
- *
- * Don't run this code directly on an AGP buffer. Due to cache problems it will
- * be very slow.
- */
-
-#include "via_3d_reg.h"
-#include "drmP.h"
-#include "drm.h"
-#include "via_drm.h"
-#include "via_verifier.h"
-#include "via_drv.h"
-
-typedef enum {
-       state_command,
-       state_header2,
-       state_header1,
-       state_vheader5,
-       state_vheader6,
-       state_error
-} verifier_state_t;
-
-typedef enum {
-       no_check = 0,
-       check_for_header2,
-       check_for_header1,
-       check_for_header2_err,
-       check_for_header1_err,
-       check_for_fire,
-       check_z_buffer_addr0,
-       check_z_buffer_addr1,
-       check_z_buffer_addr_mode,
-       check_destination_addr0,
-       check_destination_addr1,
-       check_destination_addr_mode,
-       check_for_dummy,
-       check_for_dd,
-       check_texture_addr0,
-       check_texture_addr1,
-       check_texture_addr2,
-       check_texture_addr3,
-       check_texture_addr4,
-       check_texture_addr5,
-       check_texture_addr6,
-       check_texture_addr7,
-       check_texture_addr8,
-       check_texture_addr_mode,
-       check_for_vertex_count,
-       check_number_texunits,
-       forbidden_command
-} hazard_t;
-
-/*
- * Associates each hazard above with a possible multi-command
- * sequence. For example an address that is split over multiple
- * commands and that needs to be checked at the first command
- * that does not include any part of the address.
- */
-
-static drm_via_sequence_t seqs[] = {
-       no_sequence,
-       no_sequence,
-       no_sequence,
-       no_sequence,
-       no_sequence,
-       no_sequence,
-       z_address,
-       z_address,
-       z_address,
-       dest_address,
-       dest_address,
-       dest_address,
-       no_sequence,
-       no_sequence,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       no_sequence
-};
-
-typedef struct {
-       unsigned int code;
-       hazard_t hz;
-} hz_init_t;
-
-static hz_init_t init_table1[] = {
-       {0xf2, check_for_header2_err},
-       {0xf0, check_for_header1_err},
-       {0xee, check_for_fire},
-       {0xcc, check_for_dummy},
-       {0xdd, check_for_dd},
-       {0x00, no_check},
-       {0x10, check_z_buffer_addr0},
-       {0x11, check_z_buffer_addr1},
-       {0x12, check_z_buffer_addr_mode},
-       {0x13, no_check},
-       {0x14, no_check},
-       {0x15, no_check},
-       {0x23, no_check},
-       {0x24, no_check},
-       {0x33, no_check},
-       {0x34, no_check},
-       {0x35, no_check},
-       {0x36, no_check},
-       {0x37, no_check},
-       {0x38, no_check},
-       {0x39, no_check},
-       {0x3A, no_check},
-       {0x3B, no_check},
-       {0x3C, no_check},
-       {0x3D, no_check},
-       {0x3E, no_check},
-       {0x40, check_destination_addr0},
-       {0x41, check_destination_addr1},
-       {0x42, check_destination_addr_mode},
-       {0x43, no_check},
-       {0x44, no_check},
-       {0x50, no_check},
-       {0x51, no_check},
-       {0x52, no_check},
-       {0x53, no_check},
-       {0x54, no_check},
-       {0x55, no_check},
-       {0x56, no_check},
-       {0x57, no_check},
-       {0x58, no_check},
-       {0x70, no_check},
-       {0x71, no_check},
-       {0x78, no_check},
-       {0x79, no_check},
-       {0x7A, no_check},
-       {0x7B, no_check},
-       {0x7C, no_check},
-       {0x7D, check_for_vertex_count}
-};
-
-static hz_init_t init_table2[] = {
-       {0xf2, check_for_header2_err},
-       {0xf0, check_for_header1_err},
-       {0xee, check_for_fire},
-       {0xcc, check_for_dummy},
-       {0x00, check_texture_addr0},
-       {0x01, check_texture_addr0},
-       {0x02, check_texture_addr0},
-       {0x03, check_texture_addr0},
-       {0x04, check_texture_addr0},
-       {0x05, check_texture_addr0},
-       {0x06, check_texture_addr0},
-       {0x07, check_texture_addr0},
-       {0x08, check_texture_addr0},
-       {0x09, check_texture_addr0},
-       {0x20, check_texture_addr1},
-       {0x21, check_texture_addr1},
-       {0x22, check_texture_addr1},
-       {0x23, check_texture_addr4},
-       {0x2B, check_texture_addr3},
-       {0x2C, check_texture_addr3},
-       {0x2D, check_texture_addr3},
-       {0x2E, check_texture_addr3},
-       {0x2F, check_texture_addr3},
-       {0x30, check_texture_addr3},
-       {0x31, check_texture_addr3},
-       {0x32, check_texture_addr3},
-       {0x33, check_texture_addr3},
-       {0x34, check_texture_addr3},
-       {0x4B, check_texture_addr5},
-       {0x4C, check_texture_addr6},
-       {0x51, check_texture_addr7},
-       {0x52, check_texture_addr8},
-       {0x77, check_texture_addr2},
-       {0x78, no_check},
-       {0x79, no_check},
-       {0x7A, no_check},
-       {0x7B, check_texture_addr_mode},
-       {0x7C, no_check},
-       {0x7D, no_check},
-       {0x7E, no_check},
-       {0x7F, no_check},
-       {0x80, no_check},
-       {0x81, no_check},
-       {0x82, no_check},
-       {0x83, no_check},
-       {0x85, no_check},
-       {0x86, no_check},
-       {0x87, no_check},
-       {0x88, no_check},
-       {0x89, no_check},
-       {0x8A, no_check},
-       {0x90, no_check},
-       {0x91, no_check},
-       {0x92, no_check},
-       {0x93, no_check}
-};
-
-static hz_init_t init_table3[] = {
-       {0xf2, check_for_header2_err},
-       {0xf0, check_for_header1_err},
-       {0xcc, check_for_dummy},
-       {0x00, check_number_texunits}
-};
-
-static hazard_t table1[256];
-static hazard_t table2[256];
-static hazard_t table3[256];
-
-static __inline__ int
-eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
-{
-       if ((buf_end - *buf) >= num_words) {
-               *buf += num_words;
-               return 0;
-       }
-       DRM_ERROR("Illegal termination of DMA command buffer\n");
-       return 1;
-}
-
-/*
- * Partially stolen from drm_memory.h
- */
-
-static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
-                                                   unsigned long offset,
-                                                   unsigned long size,
-                                                   struct drm_device * dev)
-{
-       struct drm_map_list *r_list;
-       drm_local_map_t *map = seq->map_cache;
-
-       if (map && map->offset <= offset
-           && (offset + size) <= (map->offset + map->size)) {
-               return map;
-       }
-
-       list_for_each_entry(r_list, &dev->maplist, head) {
-               map = r_list->map;
-               if (!map)
-                       continue;
-               if (map->offset <= offset
-                   && (offset + size) <= (map->offset + map->size)
-                   && !(map->flags & _DRM_RESTRICTED)
-                   && (map->type == _DRM_AGP)) {
-                       seq->map_cache = map;
-                       return map;
-               }
-       }
-       return NULL;
-}
-
-/*
- * Require that all AGP texture levels reside in the same AGP map which should
- * be mappable by the client. This is not a big restriction.
- * FIXME: To actually enforce this security policy strictly, drm_rmmap
- * would have to wait for dma quiescent before removing an AGP map.
- * The via_drm_lookup_agp_map call in reality seems to take
- * very little CPU time.
- */
-
-static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
-{
-       switch (cur_seq->unfinished) {
-       case z_address:
-               DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
-               break;
-       case dest_address:
-               DRM_DEBUG("Destination start address is 0x%x\n",
-                         cur_seq->d_addr);
-               break;
-       case tex_address:
-               if (cur_seq->agp_texture) {
-                       unsigned start =
-                           cur_seq->tex_level_lo[cur_seq->texture];
-                       unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
-                       unsigned long lo = ~0, hi = 0, tmp;
-                       uint32_t *addr, *pitch, *height, tex;
-                       unsigned i;
-                       int npot;
-
-                       if (end > 9)
-                               end = 9;
-                       if (start > 9)
-                               start = 9;
-
-                       addr =
-                           &(cur_seq->t_addr[tex = cur_seq->texture][start]);
-                       pitch = &(cur_seq->pitch[tex][start]);
-                       height = &(cur_seq->height[tex][start]);
-                       npot = cur_seq->tex_npot[tex];
-                       for (i = start; i <= end; ++i) {
-                               tmp = *addr++;
-                               if (tmp < lo)
-                                       lo = tmp;
-                               if (i == 0 && npot)
-                                       tmp += (*height++ * *pitch++);
-                               else
-                                       tmp += (*height++ << *pitch++);
-                               if (tmp > hi)
-                                       hi = tmp;
-                       }
-
-                       if (!via_drm_lookup_agp_map
-                           (cur_seq, lo, hi - lo, cur_seq->dev)) {
-                               DRM_ERROR
-                                   ("AGP texture is not in allowed map\n");
-                               return 2;
-                       }
-               }
-               break;
-       default:
-               break;
-       }
-       cur_seq->unfinished = no_sequence;
-       return 0;
-}
-
-static __inline__ int
-investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t * cur_seq)
-{
-       register uint32_t tmp, *tmp_addr;
-
-       if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
-               int ret;
-               if ((ret = finish_current_sequence(cur_seq)))
-                       return ret;
-       }
-
-       switch (hz) {
-       case check_for_header2:
-               if (cmd == HALCYON_HEADER2)
-                       return 1;
-               return 0;
-       case check_for_header1:
-               if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
-                       return 1;
-               return 0;
-       case check_for_header2_err:
-               if (cmd == HALCYON_HEADER2)
-                       return 1;
-               DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
-               break;
-       case check_for_header1_err:
-               if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
-                       return 1;
-               DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
-               break;
-       case check_for_fire:
-               if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD)
-                       return 1;
-               DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
-               break;
-       case check_for_dummy:
-               if (HC_DUMMY == cmd)
-                       return 0;
-               DRM_ERROR("Illegal DMA HC_DUMMY command\n");
-               break;
-       case check_for_dd:
-               if (0xdddddddd == cmd)
-                       return 0;
-               DRM_ERROR("Illegal DMA 0xdddddddd command\n");
-               break;
-       case check_z_buffer_addr0:
-               cur_seq->unfinished = z_address;
-               cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
-                   (cmd & 0x00FFFFFF);
-               return 0;
-       case check_z_buffer_addr1:
-               cur_seq->unfinished = z_address;
-               cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
-                   ((cmd & 0xFF) << 24);
-               return 0;
-       case check_z_buffer_addr_mode:
-               cur_seq->unfinished = z_address;
-               if ((cmd & 0x0000C000) == 0)
-                       return 0;
-               DRM_ERROR("Attempt to place Z buffer in system memory\n");
-               return 2;
-       case check_destination_addr0:
-               cur_seq->unfinished = dest_address;
-               cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
-                   (cmd & 0x00FFFFFF);
-               return 0;
-       case check_destination_addr1:
-               cur_seq->unfinished = dest_address;
-               cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
-                   ((cmd & 0xFF) << 24);
-               return 0;
-       case check_destination_addr_mode:
-               cur_seq->unfinished = dest_address;
-               if ((cmd & 0x0000C000) == 0)
-                       return 0;
-               DRM_ERROR
-                   ("Attempt to place 3D drawing buffer in system memory\n");
-               return 2;
-       case check_texture_addr0:
-               cur_seq->unfinished = tex_address;
-               tmp = (cmd >> 24);
-               tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
-               *tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF);
-               return 0;
-       case check_texture_addr1:
-               cur_seq->unfinished = tex_address;
-               tmp = ((cmd >> 24) - 0x20);
-               tmp += tmp << 1;
-               tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
-               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
-               tmp_addr++;
-               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16);
-               tmp_addr++;
-               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8);
-               return 0;
-       case check_texture_addr2:
-               cur_seq->unfinished = tex_address;
-               cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F;
-               cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6;
-               return 0;
-       case check_texture_addr3:
-               cur_seq->unfinished = tex_address;
-               tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit);
-               if (tmp == 0 &&
-                   (cmd & HC_HTXnEnPit_MASK)) {
-                       cur_seq->pitch[cur_seq->texture][tmp] =
-                               (cmd & HC_HTXnLnPit_MASK);
-                       cur_seq->tex_npot[cur_seq->texture] = 1;
-               } else {
-                       cur_seq->pitch[cur_seq->texture][tmp] =
-                               (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT;
-                       cur_seq->tex_npot[cur_seq->texture] = 0;
-                       if (cmd & 0x000FFFFF) {
-                               DRM_ERROR
-                                       ("Unimplemented texture level 0 pitch mode.\n");
-                               return 2;
-                       }
-               }
-               return 0;
-       case check_texture_addr4:
-               cur_seq->unfinished = tex_address;
-               tmp_addr = &cur_seq->t_addr[cur_seq->texture][9];
-               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
-               return 0;
-       case check_texture_addr5:
-       case check_texture_addr6:
-               cur_seq->unfinished = tex_address;
-               /*
-                * Texture width. We don't care since we have the pitch.
-                */
-               return 0;
-       case check_texture_addr7:
-               cur_seq->unfinished = tex_address;
-               tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
-               tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20);
-               tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16);
-               tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12);
-               tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8);
-               tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4);
-               tmp_addr[0] = 1 << (cmd & 0x0000000F);
-               return 0;
-       case check_texture_addr8:
-               cur_seq->unfinished = tex_address;
-               tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
-               tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
-               tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
-               tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
-               tmp_addr[6] = 1 << (cmd & 0x0000000F);
-               return 0;
-       case check_texture_addr_mode:
-               cur_seq->unfinished = tex_address;
-               if (2 == (tmp = cmd & 0x00000003)) {
-                       DRM_ERROR
-                           ("Attempt to fetch texture from system memory.\n");
-                       return 2;
-               }
-               cur_seq->agp_texture = (tmp == 3);
-               cur_seq->tex_palette_size[cur_seq->texture] =
-                   (cmd >> 16) & 0x000000007;
-               return 0;
-       case check_for_vertex_count:
-               cur_seq->vertex_count = cmd & 0x0000FFFF;
-               return 0;
-       case check_number_texunits:
-               cur_seq->multitex = (cmd >> 3) & 1;
-               return 0;
-       default:
-               DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
-               return 2;
-       }
-       return 2;
-}
-
-static __inline__ int
-via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,
-                   drm_via_state_t * cur_seq)
-{
-       drm_via_private_t *dev_priv =
-           (drm_via_private_t *) cur_seq->dev->dev_private;
-       uint32_t a_fire, bcmd, dw_count;
-       int ret = 0;
-       int have_fire;
-       const uint32_t *buf = *buffer;
-
-       while (buf < buf_end) {
-               have_fire = 0;
-               if ((buf_end - buf) < 2) {
-                       DRM_ERROR
-                           ("Unexpected termination of primitive list.\n");
-                       ret = 1;
-                       break;
-               }
-               if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB)
-                       break;
-               bcmd = *buf++;
-               if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
-                       DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
-                                 *buf);
-                       ret = 1;
-                       break;
-               }
-               a_fire =
-                   *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK |
-                   HC_HE3Fire_MASK;
-
-               /*
-                * How many dwords per vertex ?
-                */
-
-               if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
-                       DRM_ERROR("Illegal B command vertex data for AGP.\n");
-                       ret = 1;
-                       break;
-               }
-
-               dw_count = 0;
-               if (bcmd & (1 << 7))
-                       dw_count += (cur_seq->multitex) ? 2 : 1;
-               if (bcmd & (1 << 8))
-                       dw_count += (cur_seq->multitex) ? 2 : 1;
-               if (bcmd & (1 << 9))
-                       dw_count++;
-               if (bcmd & (1 << 10))
-                       dw_count++;
-               if (bcmd & (1 << 11))
-                       dw_count++;
-               if (bcmd & (1 << 12))
-                       dw_count++;
-               if (bcmd & (1 << 13))
-                       dw_count++;
-               if (bcmd & (1 << 14))
-                       dw_count++;
-
-               while (buf < buf_end) {
-                       if (*buf == a_fire) {
-                               if (dev_priv->num_fire_offsets >=
-                                   VIA_FIRE_BUF_SIZE) {
-                                       DRM_ERROR("Fire offset buffer full.\n");
-                                       ret = 1;
-                                       break;
-                               }
-                               dev_priv->fire_offsets[dev_priv->
-                                                      num_fire_offsets++] =
-                                   buf;
-                               have_fire = 1;
-                               buf++;
-                               if (buf < buf_end && *buf == a_fire)
-                                       buf++;
-                               break;
-                       }
-                       if ((*buf == HALCYON_HEADER2) ||
-                           ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
-                               DRM_ERROR("Missing Vertex Fire command, "
-                                         "Stray Vertex Fire command  or verifier "
-                                         "lost sync.\n");
-                               ret = 1;
-                               break;
-                       }
-                       if ((ret = eat_words(&buf, buf_end, dw_count)))
-                               break;
-               }
-               if (buf >= buf_end && !have_fire) {
-                       DRM_ERROR("Missing Vertex Fire command or verifier "
-                                 "lost sync.\n");
-                       ret = 1;
-                       break;
-               }
-               if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) {
-                       DRM_ERROR("AGP Primitive list end misaligned.\n");
-                       ret = 1;
-                       break;
-               }
-       }
-       *buffer = buf;
-       return ret;
-}
-
-static __inline__ verifier_state_t
-via_check_header2(uint32_t const **buffer, const uint32_t * buf_end,
-                 drm_via_state_t * hc_state)
-{
-       uint32_t cmd;
-       int hz_mode;
-       hazard_t hz;
-       const uint32_t *buf = *buffer;
-       const hazard_t *hz_table;
-
-       if ((buf_end - buf) < 2) {
-               DRM_ERROR
-                   ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
-               return state_error;
-       }
-       buf++;
-       cmd = (*buf++ & 0xFFFF0000) >> 16;
-
-       switch (cmd) {
-       case HC_ParaType_CmdVdata:
-               if (via_check_prim_list(&buf, buf_end, hc_state))
-                       return state_error;
-               *buffer = buf;
-               return state_command;
-       case HC_ParaType_NotTex:
-               hz_table = table1;
-               break;
-       case HC_ParaType_Tex:
-               hc_state->texture = 0;
-               hz_table = table2;
-               break;
-       case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)):
-               hc_state->texture = 1;
-               hz_table = table2;
-               break;
-       case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)):
-               hz_table = table3;
-               break;
-       case HC_ParaType_Auto:
-               if (eat_words(&buf, buf_end, 2))
-                       return state_error;
-               *buffer = buf;
-               return state_command;
-       case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)):
-               if (eat_words(&buf, buf_end, 32))
-                       return state_error;
-               *buffer = buf;
-               return state_command;
-       case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)):
-       case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)):
-               DRM_ERROR("Texture palettes are rejected because of "
-                         "lack of info how to determine their size.\n");
-               return state_error;
-       case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)):
-               DRM_ERROR("Fog factor palettes are rejected because of "
-                         "lack of info how to determine their size.\n");
-               return state_error;
-       default:
-
-               /*
-                * There are some unimplemented HC_ParaTypes here, that
-                * need to be implemented if the Mesa driver is extended.
-                */
-
-               DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
-                         "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
-                         cmd, *(buf - 2));
-               *buffer = buf;
-               return state_error;
-       }
-
-       while (buf < buf_end) {
-               cmd = *buf++;
-               if ((hz = hz_table[cmd >> 24])) {
-                       if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
-                               if (hz_mode == 1) {
-                                       buf--;
-                                       break;
-                               }
-                               return state_error;
-                       }
-               } else if (hc_state->unfinished &&
-                          finish_current_sequence(hc_state)) {
-                       return state_error;
-               }
-       }
-       if (hc_state->unfinished && finish_current_sequence(hc_state)) {
-               return state_error;
-       }
-       *buffer = buf;
-       return state_command;
-}
-
-static __inline__ verifier_state_t
-via_parse_header2(drm_via_private_t * dev_priv, uint32_t const **buffer,
-                 const uint32_t * buf_end, int *fire_count)
-{
-       uint32_t cmd;
-       const uint32_t *buf = *buffer;
-       const uint32_t *next_fire;
-       int burst = 0;
-
-       next_fire = dev_priv->fire_offsets[*fire_count];
-       buf++;
-       cmd = (*buf & 0xFFFF0000) >> 16;
-       VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
-       switch (cmd) {
-       case HC_ParaType_CmdVdata:
-               while ((buf < buf_end) &&
-                      (*fire_count < dev_priv->num_fire_offsets) &&
-                      (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
-                       while (buf <= next_fire) {
-                               VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
-                                         (burst & 63), *buf++);
-                               burst += 4;
-                       }
-                       if ((buf < buf_end)
-                           && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
-                               buf++;
-
-                       if (++(*fire_count) < dev_priv->num_fire_offsets)
-                               next_fire = dev_priv->fire_offsets[*fire_count];
-               }
-               break;
-       default:
-               while (buf < buf_end) {
-
-                       if (*buf == HC_HEADER2 ||
-                           (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
-                           (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
-                           (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
-                               break;
-
-                       VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
-                                 (burst & 63), *buf++);
-                       burst += 4;
-               }
-       }
-       *buffer = buf;
-       return state_command;
-}
-
-static __inline__ int verify_mmio_address(uint32_t address)
-{
-       if ((address > 0x3FF) && (address < 0xC00)) {
-               DRM_ERROR("Invalid VIDEO DMA command. "
-                         "Attempt to access 3D- or command burst area.\n");
-               return 1;
-       } else if ((address > 0xCFF) && (address < 0x1300)) {
-               DRM_ERROR("Invalid VIDEO DMA command. "
-                         "Attempt to access PCI DMA area.\n");
-               return 1;
-       } else if (address > 0x13FF) {
-               DRM_ERROR("Invalid VIDEO DMA command. "
-                         "Attempt to access VGA registers.\n");
-               return 1;
-       }
-       return 0;
-}
-
-static __inline__ int
-verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,
-                 uint32_t dwords)
-{
-       const uint32_t *buf = *buffer;
-
-       if (buf_end - buf < dwords) {
-               DRM_ERROR("Illegal termination of video command.\n");
-               return 1;
-       }
-       while (dwords--) {
-               if (*buf++) {
-                       DRM_ERROR("Illegal video command tail.\n");
-                       return 1;
-               }
-       }
-       *buffer = buf;
-       return 0;
-}
-
-static __inline__ verifier_state_t
-via_check_header1(uint32_t const **buffer, const uint32_t * buf_end)
-{
-       uint32_t cmd;
-       const uint32_t *buf = *buffer;
-       verifier_state_t ret = state_command;
-
-       while (buf < buf_end) {
-               cmd = *buf;
-               if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
-                   (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
-                       if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
-                               break;
-                       DRM_ERROR("Invalid HALCYON_HEADER1 command. "
-                                 "Attempt to access 3D- or command burst area.\n");
-                       ret = state_error;
-                       break;
-               } else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
-                       if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
-                               break;
-                       DRM_ERROR("Invalid HALCYON_HEADER1 command. "
-                                 "Attempt to access VGA registers.\n");
-                       ret = state_error;
-                       break;
-               } else {
-                       buf += 2;
-               }
-       }
-       *buffer = buf;
-       return ret;
-}
-
-static __inline__ verifier_state_t
-via_parse_header1(drm_via_private_t * dev_priv, uint32_t const **buffer,
-                 const uint32_t * buf_end)
-{
-       register uint32_t cmd;
-       const uint32_t *buf = *buffer;
-
-       while (buf < buf_end) {
-               cmd = *buf;
-               if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
-                       break;
-               VIA_WRITE((cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
-               buf++;
-       }
-       *buffer = buf;
-       return state_command;
-}
-
-static __inline__ verifier_state_t
-via_check_vheader5(uint32_t const **buffer, const uint32_t * buf_end)
-{
-       uint32_t data;
-       const uint32_t *buf = *buffer;
-
-       if (buf_end - buf < 4) {
-               DRM_ERROR("Illegal termination of video header5 command\n");
-               return state_error;
-       }
-
-       data = *buf++ & ~VIA_VIDEOMASK;
-       if (verify_mmio_address(data))
-               return state_error;
-
-       data = *buf++;
-       if (*buf++ != 0x00F50000) {
-               DRM_ERROR("Illegal header5 header data\n");
-               return state_error;
-       }
-       if (*buf++ != 0x00000000) {
-               DRM_ERROR("Illegal header5 header data\n");
-               return state_error;
-       }
-       if (eat_words(&buf, buf_end, data))
-               return state_error;
-       if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
-               return state_error;
-       *buffer = buf;
-       return state_command;
-
-}
-
-static __inline__ verifier_state_t
-via_parse_vheader5(drm_via_private_t * dev_priv, uint32_t const **buffer,
-                  const uint32_t * buf_end)
-{
-       uint32_t addr, count, i;
-       const uint32_t *buf = *buffer;
-
-       addr = *buf++ & ~VIA_VIDEOMASK;
-       i = count = *buf;
-       buf += 3;
-       while (i--) {
-               VIA_WRITE(addr, *buf++);
-       }
-       if (count & 3)
-               buf += 4 - (count & 3);
-       *buffer = buf;
-       return state_command;
-}
-
-static __inline__ verifier_state_t
-via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)
-{
-       uint32_t data;
-       const uint32_t *buf = *buffer;
-       uint32_t i;
-
-       if (buf_end - buf < 4) {
-               DRM_ERROR("Illegal termination of video header6 command\n");
-               return state_error;
-       }
-       buf++;
-       data = *buf++;
-       if (*buf++ != 0x00F60000) {
-               DRM_ERROR("Illegal header6 header data\n");
-               return state_error;
-       }
-       if (*buf++ != 0x00000000) {
-               DRM_ERROR("Illegal header6 header data\n");
-               return state_error;
-       }
-       if ((buf_end - buf) < (data << 1)) {
-               DRM_ERROR("Illegal termination of video header6 command\n");
-               return state_error;
-       }
-       for (i = 0; i < data; ++i) {
-               if (verify_mmio_address(*buf++))
-                       return state_error;
-               buf++;
-       }
-       data <<= 1;
-       if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
-               return state_error;
-       *buffer = buf;
-       return state_command;
-}
-
-static __inline__ verifier_state_t
-via_parse_vheader6(drm_via_private_t * dev_priv, uint32_t const **buffer,
-                  const uint32_t * buf_end)
-{
-
-       uint32_t addr, count, i;
-       const uint32_t *buf = *buffer;
-
-       i = count = *++buf;
-       buf += 3;
-       while (i--) {
-               addr = *buf++;
-               VIA_WRITE(addr, *buf++);
-       }
-       count <<= 1;
-       if (count & 3)
-               buf += 4 - (count & 3);
-       *buffer = buf;
-       return state_command;
-}
-
-int
-via_verify_command_stream(const uint32_t * buf, unsigned int size,
-                         struct drm_device * dev, int agp)
-{
-
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       drm_via_state_t *hc_state = &dev_priv->hc_state;
-       drm_via_state_t saved_state = *hc_state;
-       uint32_t cmd;
-       const uint32_t *buf_end = buf + (size >> 2);
-       verifier_state_t state = state_command;
-       int cme_video;
-       int supported_3d;
-
-       cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A ||
-                    dev_priv->chipset == VIA_DX9_0);
-
-       supported_3d = dev_priv->chipset != VIA_DX9_0;
-
-       hc_state->dev = dev;
-       hc_state->unfinished = no_sequence;
-       hc_state->map_cache = NULL;
-       hc_state->agp = agp;
-       hc_state->buf_start = buf;
-       dev_priv->num_fire_offsets = 0;
-
-       while (buf < buf_end) {
-
-               switch (state) {
-               case state_header2:
-                       state = via_check_header2(&buf, buf_end, hc_state);
-                       break;
-               case state_header1:
-                       state = via_check_header1(&buf, buf_end);
-                       break;
-               case state_vheader5:
-                       state = via_check_vheader5(&buf, buf_end);
-                       break;
-               case state_vheader6:
-                       state = via_check_vheader6(&buf, buf_end);
-                       break;
-               case state_command:
-                       if ((HALCYON_HEADER2 == (cmd = *buf)) &&
-                           supported_3d)
-                               state = state_header2;
-                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
-                               state = state_header1;
-                       else if (cme_video
-                                && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
-                               state = state_vheader5;
-                       else if (cme_video
-                                && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
-                               state = state_vheader6;
-                       else if ((cmd == HALCYON_HEADER2) && !supported_3d) {
-                               DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n");
-                               state = state_error;
-                       } else {
-                               DRM_ERROR
-                                   ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
-                                    cmd);
-                               state = state_error;
-                       }
-                       break;
-               case state_error:
-               default:
-                       *hc_state = saved_state;
-                       return -EINVAL;
-               }
-       }
-       if (state == state_error) {
-               *hc_state = saved_state;
-               return -EINVAL;
-       }
-       return 0;
-}
-
-int
-via_parse_command_stream(struct drm_device * dev, const uint32_t * buf,
-                        unsigned int size)
-{
-
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       uint32_t cmd;
-       const uint32_t *buf_end = buf + (size >> 2);
-       verifier_state_t state = state_command;
-       int fire_count = 0;
-
-       while (buf < buf_end) {
-
-               switch (state) {
-               case state_header2:
-                       state =
-                           via_parse_header2(dev_priv, &buf, buf_end,
-                                             &fire_count);
-                       break;
-               case state_header1:
-                       state = via_parse_header1(dev_priv, &buf, buf_end);
-                       break;
-               case state_vheader5:
-                       state = via_parse_vheader5(dev_priv, &buf, buf_end);
-                       break;
-               case state_vheader6:
-                       state = via_parse_vheader6(dev_priv, &buf, buf_end);
-                       break;
-               case state_command:
-                       if (HALCYON_HEADER2 == (cmd = *buf))
-                               state = state_header2;
-                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
-                               state = state_header1;
-                       else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
-                               state = state_vheader5;
-                       else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
-                               state = state_vheader6;
-                       else {
-                               DRM_ERROR
-                                   ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
-                                    cmd);
-                               state = state_error;
-                       }
-                       break;
-               case state_error:
-               default:
-                       return -EINVAL;
-               }
-       }
-       if (state == state_error) {
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static void
-setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
-{
-       int i;
-
-       for (i = 0; i < 256; ++i) {
-               table[i] = forbidden_command;
-       }
-
-       for (i = 0; i < size; ++i) {
-               table[init_table[i].code] = init_table[i].hz;
-       }
-}
-
-void via_init_command_verifier(void)
-{
-       setup_hazard_table(init_table1, table1,
-                          sizeof(init_table1) / sizeof(hz_init_t));
-       setup_hazard_table(init_table2, table2,
-                          sizeof(init_table2) / sizeof(hz_init_t));
-       setup_hazard_table(init_table3, table3,
-                          sizeof(init_table3) / sizeof(hz_init_t));
-}
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h
deleted file mode 100644 (file)
index d6f8214..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2004 The Unichrome Project. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE UNICHROME PROJECT, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Thomas Hellström 2004.
- */
-
-#ifndef _VIA_VERIFIER_H_
-#define _VIA_VERIFIER_H_
-
-typedef enum {
-       no_sequence = 0,
-       z_address,
-       dest_address,
-       tex_address
-} drm_via_sequence_t;
-
-typedef struct {
-       unsigned texture;
-       uint32_t z_addr;
-       uint32_t d_addr;
-       uint32_t t_addr[2][10];
-       uint32_t pitch[2][10];
-       uint32_t height[2][10];
-       uint32_t tex_level_lo[2];
-       uint32_t tex_level_hi[2];
-       uint32_t tex_palette_size[2];
-       uint32_t tex_npot[2];
-       drm_via_sequence_t unfinished;
-       int agp_texture;
-       int multitex;
-       struct drm_device *dev;
-       drm_local_map_t *map_cache;
-       uint32_t vertex_count;
-       int agp;
-       const uint32_t *buf_start;
-} drm_via_state_t;
-
-extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,
-                                    struct drm_device * dev, int agp);
-extern int via_parse_command_stream(struct drm_device *dev, const uint32_t *buf,
-                                   unsigned int size);
-
-#endif
diff --git a/drivers/char/drm/via_video.c b/drivers/char/drm/via_video.c
deleted file mode 100644 (file)
index 6ec04ac..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2005 Thomas Hellstrom. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Thomas Hellstrom 2005.
- *
- * Video and XvMC related functions.
- */
-
-#include "drmP.h"
-#include "via_drm.h"
-#include "via_drv.h"
-
-void via_init_futex(drm_via_private_t * dev_priv)
-{
-       unsigned int i;
-
-       DRM_DEBUG("\n");
-
-       for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
-               DRM_INIT_WAITQUEUE(&(dev_priv->decoder_queue[i]));
-               XVMCLOCKPTR(dev_priv->sarea_priv, i)->lock = 0;
-       }
-}
-
-void via_cleanup_futex(drm_via_private_t * dev_priv)
-{
-}
-
-void via_release_futex(drm_via_private_t * dev_priv, int context)
-{
-       unsigned int i;
-       volatile int *lock;
-
-       if (!dev_priv->sarea_priv)
-               return;
-
-       for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
-               lock = (volatile int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);
-               if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {
-                       if (_DRM_LOCK_IS_HELD(*lock)
-                           && (*lock & _DRM_LOCK_CONT)) {
-                               DRM_WAKEUP(&(dev_priv->decoder_queue[i]));
-                       }
-                       *lock = 0;
-               }
-       }
-}
-
-int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_futex_t *fx = data;
-       volatile int *lock;
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       drm_via_sarea_t *sAPriv = dev_priv->sarea_priv;
-       int ret = 0;
-
-       DRM_DEBUG("\n");
-
-       if (fx->lock > VIA_NR_XVMC_LOCKS)
-               return -EFAULT;
-
-       lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx->lock);
-
-       switch (fx->func) {
-       case VIA_FUTEX_WAIT:
-               DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock],
-                           (fx->ms / 10) * (DRM_HZ / 100), *lock != fx->val);
-               return ret;
-       case VIA_FUTEX_WAKE:
-               DRM_WAKEUP(&(dev_priv->decoder_queue[fx->lock]));
-               return 0;
-       }
-       return 0;
-}
index 1b9a8704781783d6e9f9f8416cc9ef6e07c280c6..0e6df289cb46e8202df710903278ebe6c1fb2a0c 100644 (file)
@@ -755,9 +755,8 @@ static ssize_t ipmi_write(struct file *file,
                rv = ipmi_heartbeat();
                if (rv)
                        return rv;
-               return 1;
        }
-       return 0;
+       return len;
 }
 
 static ssize_t ipmi_read(struct file *file,
index 4a933d4134231cd095a859f286a0d8c7e08e434e..59ca35156d8159699f960cdd1aac43a448dc023f 100644 (file)
@@ -32,8 +32,9 @@
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/bitrev.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/smp_lock.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
@@ -1405,11 +1406,11 @@ static void stop_monitor(struct cm4000_dev *dev)
        DEBUGP(3, dev, "<- stop_monitor\n");
 }
 
-static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-                    unsigned long arg)
+static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        struct cm4000_dev *dev = filp->private_data;
        unsigned int iobase = dev->p_dev->io.BasePort1;
+       struct inode *inode = filp->f_path.dentry->d_inode;
        struct pcmcia_device *link;
        int size;
        int rc;
@@ -1426,38 +1427,42 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        DEBUGP(3, dev, "cmm_ioctl(device=%d.%d) %s\n", imajor(inode),
               iminor(inode), ioctl_names[_IOC_NR(cmd)]);
 
+       lock_kernel();
+       rc = -ENODEV;
        link = dev_table[iminor(inode)];
        if (!pcmcia_dev_present(link)) {
                DEBUGP(4, dev, "DEV_OK false\n");
-               return -ENODEV;
+               goto out;
        }
 
        if (test_bit(IS_CMM_ABSENT, &dev->flags)) {
                DEBUGP(4, dev, "CMM_ABSENT flag set\n");
-               return -ENODEV;
+               goto out;
        }
+       rc = EINVAL;
 
        if (_IOC_TYPE(cmd) != CM_IOC_MAGIC) {
                DEBUGP(4, dev, "ioctype mismatch\n");
-               return -EINVAL;
+               goto out;
        }
        if (_IOC_NR(cmd) > CM_IOC_MAXNR) {
                DEBUGP(4, dev, "iocnr mismatch\n");
-               return -EINVAL;
+               goto out;
        }
        size = _IOC_SIZE(cmd);
-       rc = 0;
+       rc = -EFAULT;
        DEBUGP(4, dev, "iocdir=%.4x iocr=%.4x iocw=%.4x iocsize=%d cmd=%.4x\n",
              _IOC_DIR(cmd), _IOC_READ, _IOC_WRITE, size, cmd);
 
        if (_IOC_DIR(cmd) & _IOC_READ) {
                if (!access_ok(VERIFY_WRITE, argp, size))
-                       return -EFAULT;
+                       goto out;
        }
        if (_IOC_DIR(cmd) & _IOC_WRITE) {
                if (!access_ok(VERIFY_READ, argp, size))
-                       return -EFAULT;
+                       goto out;
        }
+       rc = 0;
 
        switch (cmd) {
        case CM_IOCGSTATUS:
@@ -1477,9 +1482,9 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        if (test_bit(IS_BAD_CARD, &dev->flags))
                                status |= CM_BAD_CARD;
                        if (copy_to_user(argp, &status, sizeof(int)))
-                               return -EFAULT;
+                               rc = -EFAULT;
                }
-               return 0;
+               break;
        case CM_IOCGATR:
                DEBUGP(4, dev, "... in CM_IOCGATR\n");
                {
@@ -1492,25 +1497,29 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                              || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags)
                                  != 0)))) {
                                if (filp->f_flags & O_NONBLOCK)
-                                       return -EAGAIN;
-                               return -ERESTARTSYS;
+                                       rc = -EAGAIN;
+                               else
+                                       rc = -ERESTARTSYS;
+                               break;
                        }
 
+                       rc = -EFAULT;
                        if (test_bit(IS_ATR_VALID, &dev->flags) == 0) {
                                tmp = -1;
                                if (copy_to_user(&(atreq->atr_len), &tmp,
                                                 sizeof(int)))
-                                       return -EFAULT;
+                                       break;
                        } else {
                                if (copy_to_user(atreq->atr, dev->atr,
                                                 dev->atr_len))
-                                       return -EFAULT;
+                                       break;
 
                                tmp = dev->atr_len;
                                if (copy_to_user(&(atreq->atr_len), &tmp, sizeof(int)))
-                                       return -EFAULT;
+                                       break;
                        }
-                       return 0;
+                       rc = 0;
+                       break;
                }
        case CM_IOCARDOFF:
 
@@ -1538,8 +1547,10 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                              || (test_and_set_bit(LOCK_IO, (void *)&dev->flags)
                                  == 0)))) {
                                if (filp->f_flags & O_NONBLOCK)
-                                       return -EAGAIN;
-                               return -ERESTARTSYS;
+                                       rc = -EAGAIN;
+                               else
+                                       rc = -ERESTARTSYS;
+                               break;
                        }
                        /* Set Flags0 = 0x42 */
                        DEBUGP(4, dev, "Set Flags0=0x42 \n");
@@ -1554,8 +1565,10 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                              || (test_bit(IS_ATR_VALID, (void *)&dev->flags) !=
                                  0)))) {
                                if (filp->f_flags & O_NONBLOCK)
-                                       return -EAGAIN;
-                               return -ERESTARTSYS;
+                                       rc = -EAGAIN;
+                               else
+                                       rc = -ERESTARTSYS;
+                               break;
                        }
                }
                /* release lock */
@@ -1568,8 +1581,10 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        struct ptsreq krnptsreq;
 
                        if (copy_from_user(&krnptsreq, argp,
-                                          sizeof(struct ptsreq)))
-                               return -EFAULT;
+                                          sizeof(struct ptsreq))) {
+                               rc = -EFAULT;
+                               break;
+                       }
 
                        rc = 0;
                        DEBUGP(4, dev, "... in CM_IOCSPTS\n");
@@ -1580,8 +1595,10 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                              || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags)
                                  != 0)))) {
                                if (filp->f_flags & O_NONBLOCK)
-                                       return -EAGAIN;
-                               return -ERESTARTSYS;
+                                       rc = -EAGAIN;
+                               else
+                                       rc = -ERESTARTSYS;
+                               break;
                        }
                        /* get IO lock */
                        if (wait_event_interruptible
@@ -1590,8 +1607,10 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                              || (test_and_set_bit(LOCK_IO, (void *)&dev->flags)
                                  == 0)))) {
                                if (filp->f_flags & O_NONBLOCK)
-                                       return -EAGAIN;
-                               return -ERESTARTSYS;
+                                       rc = -EAGAIN;
+                               else
+                                       rc = -ERESTARTSYS;
+                               break;
                        }
 
                        if ((rc = set_protocol(dev, &krnptsreq)) != 0) {
@@ -1604,7 +1623,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        wake_up_interruptible(&dev->ioq);
 
                }
-               return rc;
+               break;
 #ifdef PCMCIA_DEBUG
        case CM_IOSDBGLVL:      /* set debug log level */
                {
@@ -1612,18 +1631,20 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 
                        old_pc_debug = pc_debug;
                        if (copy_from_user(&pc_debug, argp, sizeof(int)))
-                               return -EFAULT;
-
-                       if (old_pc_debug != pc_debug)
+                               rc = -EFAULT;
+                       else if (old_pc_debug != pc_debug)
                                DEBUGP(0, dev, "Changed debug log level "
                                       "to %i\n", pc_debug);
                }
-               return rc;
+               break;
 #endif
        default:
                DEBUGP(4, dev, "... in default (unknown IOCTL code)\n");
-               return -EINVAL;
+               rc = -ENOTTY;
        }
+out:
+       unlock_kernel();
+       return rc;
 }
 
 static int cmm_open(struct inode *inode, struct file *filp)
@@ -1631,16 +1652,22 @@ static int cmm_open(struct inode *inode, struct file *filp)
        struct cm4000_dev *dev;
        struct pcmcia_device *link;
        int minor = iminor(inode);
+       int ret;
 
        if (minor >= CM4000_MAX_DEV)
                return -ENODEV;
 
+       lock_kernel();
        link = dev_table[minor];
-       if (link == NULL || !pcmcia_dev_present(link))
-               return -ENODEV;
+       if (link == NULL || !pcmcia_dev_present(link)) {
+               ret = -ENODEV;
+               goto out;
+       }
 
-       if (link->open)
-               return -EBUSY;
+       if (link->open) {
+               ret = -EBUSY;
+               goto out;
+       }
 
        dev = link->priv;
        filp->private_data = dev;
@@ -1660,8 +1687,10 @@ static int cmm_open(struct inode *inode, struct file *filp)
         * vaild = block until valid (or card
         * inserted)
         */
-       if (filp->f_flags & O_NONBLOCK)
-               return -EAGAIN;
+       if (filp->f_flags & O_NONBLOCK) {
+               ret = -EAGAIN;
+               goto out;
+       }
 
        dev->mdelay = T_50MSEC;
 
@@ -1671,7 +1700,10 @@ static int cmm_open(struct inode *inode, struct file *filp)
        link->open = 1;         /* only one open per device */
 
        DEBUGP(2, dev, "<- cmm_open\n");
-       return nonseekable_open(inode, filp);
+       ret = nonseekable_open(inode, filp);
+out:
+       unlock_kernel();
+       return ret;
 }
 
 static int cmm_close(struct inode *inode, struct file *filp)
@@ -1897,7 +1929,7 @@ static const struct file_operations cm4000_fops = {
        .owner  = THIS_MODULE,
        .read   = cmm_read,
        .write  = cmm_write,
-       .ioctl  = cmm_ioctl,
+       .unlocked_ioctl = cmm_ioctl,
        .open   = cmm_open,
        .release= cmm_close,
 };
index 035084c07329cd87bfa42da3a70e6fe624b3c201..6181f8a9b0bd0309cb4670dd0d572af91fc8689f 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/poll.h>
+#include <linux/smp_lock.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -448,23 +449,30 @@ static int cm4040_open(struct inode *inode, struct file *filp)
        struct reader_dev *dev;
        struct pcmcia_device *link;
        int minor = iminor(inode);
+       int ret;
 
        if (minor >= CM_MAX_DEV)
                return -ENODEV;
 
+       lock_kernel();
        link = dev_table[minor];
-       if (link == NULL || !pcmcia_dev_present(link))
-               return -ENODEV;
+       if (link == NULL || !pcmcia_dev_present(link)) {
+               ret = -ENODEV;
+               goto out;
+       }
 
-       if (link->open)
-               return -EBUSY;
+       if (link->open) {
+               ret = -EBUSY;
+               goto out;
+       }
 
        dev = link->priv;
        filp->private_data = dev;
 
        if (filp->f_flags & O_NONBLOCK) {
                DEBUGP(4, dev, "filep->f_flags O_NONBLOCK set\n");
-               return -EAGAIN;
+               ret = -EAGAIN;
+               goto out;
        }
 
        link->open = 1;
@@ -473,7 +481,10 @@ static int cm4040_open(struct inode *inode, struct file *filp)
        mod_timer(&dev->poll_timer, jiffies + POLL_PERIOD);
 
        DEBUGP(2, dev, "<- cm4040_open (successfully)\n");
-       return nonseekable_open(inode, filp);
+       ret = nonseekable_open(inode, filp);
+out:
+       unlock_kernel();
+       return ret;
 }
 
 static int cm4040_close(struct inode *inode, struct file *filp)
index ba6340ae98afa1f7a5f80bb33360270aa4cc7cc8..929101ecbae29c180889a1d10e8c7f0549bcd713 100644 (file)
@@ -590,8 +590,10 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw,
                packet = kmalloc(sizeof(struct ipw_rx_packet) +
                                old_packet->length + minimum_free_space,
                                GFP_ATOMIC);
-               if (!packet)
+               if (!packet) {
+                       kfree(old_packet);
                        return NULL;
+               }
                memcpy(packet, old_packet,
                                sizeof(struct ipw_rx_packet)
                                        + old_packet->length);
index 00c7f8407e3ecfcfaf3520e0dbdc99ec4ac7933c..cc7dcea2d2830599d05c955589456c14cf9aa37b 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/device_id.h>
 #include <pcmcia/ss.h>
index 5f80a9dff5735103b91cc16c40338aafa96f853a..909cac93fa2ad408caf695e253a4a4820cef659e 100644 (file)
@@ -678,12 +678,13 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
                if (arg != (1<<tmp))
                        return -EINVAL;
 
+               rtc_freq = arg;
+
                spin_lock_irqsave(&rtc_lock, flags);
                if (hpet_set_periodic_freq(arg)) {
                        spin_unlock_irqrestore(&rtc_lock, flags);
                        return 0;
                }
-               rtc_freq = arg;
 
                val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
                val |= (16 - tmp);
index 13a4bdd4e4d67ff73535cd6b1cb4dece7e3aba65..c7a977bc03e81e2b1f38830c62b2034672065538 100644 (file)
@@ -623,6 +623,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
        {"IFX0102", 0},         /* Infineon */
        {"BCM0101", 0},         /* Broadcom */
        {"NSC1200", 0},         /* National */
+       {"ICO0102", 0},         /* Intel */
        /* Add new here */
        {"", 0},                /* User Specified */
        {"", 0}                 /* Terminator */
index e94bee0323148548d9374852e7b140999af40b81..750131010af01875d06d1c5e11818112c02ecbd2 100644 (file)
@@ -3322,7 +3322,7 @@ static int send_break(struct tty_struct *tty, unsigned int duration)
                msleep_interruptible(duration);
        tty->ops->break_ctl(tty, 0);
        tty_write_unlock(tty);
-       if (!signal_pending(current))
+       if (signal_pending(current))
                return -EINTR;
        return 0;
 }
index 85e2ba7fcfbab1b4533079da8bd812f22203952d..bf4830082a135e126d9f35f1a72a7bf5b18fbecf 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/moduleparam.h>
 #include <linux/connector.h>
 #include <linux/mutex.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
 
 #include <net/sock.h>
 
@@ -403,6 +405,40 @@ static void cn_callback(void *data)
        mutex_unlock(&notify_lock);
 }
 
+static int cn_proc_show(struct seq_file *m, void *v)
+{
+       struct cn_queue_dev *dev = cdev.cbdev;
+       struct cn_callback_entry *cbq;
+
+       seq_printf(m, "Name            ID\n");
+
+       spin_lock_bh(&dev->queue_lock);
+
+       list_for_each_entry(cbq, &dev->queue_list, callback_entry) {
+               seq_printf(m, "%-15s %u:%u\n",
+                          cbq->id.name,
+                          cbq->id.id.idx,
+                          cbq->id.id.val);
+       }
+
+       spin_unlock_bh(&dev->queue_lock);
+
+       return 0;
+}
+
+static int cn_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, cn_proc_show, NULL);
+}
+
+static const struct file_operations cn_file_ops = {
+       .owner   = THIS_MODULE,
+       .open    = cn_proc_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = single_release
+};
+
 static int __devinit cn_init(void)
 {
        struct cn_dev *dev = &cdev;
@@ -434,6 +470,8 @@ static int __devinit cn_init(void)
                return -EINVAL;
        }
 
+       proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops);
+
        return 0;
 }
 
@@ -443,6 +481,8 @@ static void __devexit cn_fini(void)
 
        cn_already_initialized = 0;
 
+       proc_net_remove(&init_net, "connector");
+
        cn_del_callback(&dev->id);
        cn_queue_free_dev(dev->cbdev);
        netlink_kernel_release(dev->nls);
index b2458bb8e9cade2fd79fea620b60eb9edd0aa7e0..227d2e036cd812f4e259fd13413298a818d16d6f 100644 (file)
@@ -1051,7 +1051,8 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
                        break;
 
                case SBP2_CSR_LOGICAL_UNIT_DIRECTORY:
-                       if (sbp2_scan_logical_unit_dir(tgt, ci.p + value) < 0)
+                       /* Adjust for the increment in the iterator */
+                       if (sbp2_scan_logical_unit_dir(tgt, ci.p - 1 + value) < 0)
                                return -ENOMEM;
                        break;
                }
index bbd28342e771f415a4b7365653e3383757a398a2..008c38ba774f588f3a739983bb6f47e48ef618f5 100644 (file)
@@ -28,12 +28,18 @@ config DEBUG_GPIO
 comment "I2C GPIO expanders:"
 
 config GPIO_PCA953X
-       tristate "PCA953x I/O ports"
+       tristate "PCA953x, PCA955x, and MAX7310 I/O ports"
        depends on I2C
        help
-         Say yes here to support the PCA9534 (8-bit), PCA9535 (16-bit),
-         PCA9536 (4-bit), PCA9537 (4-bit), PCA9538 (8-bit), and PCA9539
-         (16-bit) I/O ports. These parts are made by NXP and TI.
+         Say yes here to provide access to several register-oriented
+         SMBus I/O expanders, made mostly by NXP or TI.  Compatible
+         models include:
+
+         4 bits:       pca9536, pca9537
+
+         8 bits:       max7310, pca9534, pca9538, pca9554, pca9557
+
+         16 bits:      pca9535, pca9539, pca9555
 
          This driver can also be built as a module.  If so, the module
          will be called pca953x.
index 7e40e8a55edf247968690de9cb5348969df5c75b..a380730b61abe49800af8e655eaf5735d0524ad0 100644 (file)
@@ -33,7 +33,7 @@ static const struct i2c_device_id pca953x_id[] = {
        { "pca9554", 8, },
        { "pca9555", 16, },
        { "pca9557", 8, },
-       /* REVISIT several pca955x parts should work here too */
+       { "max7310", 8, },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, pca953x_id);
diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
new file mode 100644 (file)
index 0000000..de566cf
--- /dev/null
@@ -0,0 +1 @@
+obj-y                  += drm/
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
new file mode 100644 (file)
index 0000000..610d6fd
--- /dev/null
@@ -0,0 +1,107 @@
+#
+# Drm device configuration
+#
+# This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+#
+menuconfig DRM
+       tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
+       depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG
+       help
+         Kernel-level support for the Direct Rendering Infrastructure (DRI)
+         introduced in XFree86 4.0. If you say Y here, you need to select
+         the module that's right for your graphics card from the list below.
+         These modules provide support for synchronization, security, and
+         DMA transfers. Please see <http://dri.sourceforge.net/> for more
+         details.  You should also select and configure AGP
+         (/dev/agpgart) support.
+
+config DRM_TDFX
+       tristate "3dfx Banshee/Voodoo3+"
+       depends on DRM && PCI
+       help
+         Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
+         graphics card.  If M is selected, the module will be called tdfx.
+
+config DRM_R128
+       tristate "ATI Rage 128"
+       depends on DRM && PCI
+       help
+         Choose this option if you have an ATI Rage 128 graphics card.  If M
+         is selected, the module will be called r128.  AGP support for
+         this card is strongly suggested (unless you have a PCI version).
+
+config DRM_RADEON
+       tristate "ATI Radeon"
+       depends on DRM && PCI
+       help
+         Choose this option if you have an ATI Radeon graphics card.  There
+         are both PCI and AGP versions.  You don't need to choose this to
+         run the Radeon in plain VGA mode.
+
+         If M is selected, the module will be called radeon.
+
+config DRM_I810
+       tristate "Intel I810"
+       depends on DRM && AGP && AGP_INTEL
+       help
+         Choose this option if you have an Intel I810 graphics card.  If M is
+         selected, the module will be called i810.  AGP support is required
+         for this driver to work.
+
+choice
+       prompt "Intel 830M, 845G, 852GM, 855GM, 865G"
+       depends on DRM && AGP && AGP_INTEL
+       optional
+
+config DRM_I830
+       tristate "i830 driver"
+       help
+         Choose this option if you have a system that has Intel 830M, 845G,
+         852GM, 855GM or 865G integrated graphics.  If M is selected, the
+         module will be called i830.  AGP support is required for this driver
+         to work. This driver is used by the older X releases X.org 6.7 and
+         XFree86 4.3. If unsure, build this and i915 as modules and the X server
+         will load the correct one.
+
+config DRM_I915
+       tristate "i915 driver"
+       help
+         Choose this option if you have a system that has Intel 830M, 845G,
+         852GM, 855GM 865G or 915G integrated graphics.  If M is selected, the
+         module will be called i915.  AGP support is required for this driver
+         to work. This driver is used by the Intel driver in X.org 6.8 and
+         XFree86 4.4 and above. If unsure, build this and i830 as modules and
+         the X server will load the correct one.
+
+endchoice
+
+config DRM_MGA
+       tristate "Matrox g200/g400"
+       depends on DRM
+       help
+         Choose this option if you have a Matrox G200, G400 or G450 graphics
+         card.  If M is selected, the module will be called mga.  AGP
+         support is required for this driver to work.
+
+config DRM_SIS
+       tristate "SiS video cards"
+       depends on DRM && AGP
+       help
+         Choose this option if you have a SiS 630 or compatible video
+          chipset. If M is selected the module will be called sis. AGP
+          support is required for this driver to work.
+
+config DRM_VIA
+       tristate "Via unichrome video cards"
+       depends on DRM
+       help
+         Choose this option if you have a Via unichrome or compatible video
+         chipset. If M is selected the module will be called via.
+
+config DRM_SAVAGE
+       tristate "Savage video cards"
+       depends on DRM
+       help
+         Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
+         chipset. If M is selected the module will be called savage.
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
new file mode 100644 (file)
index 0000000..e9f9a97
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+
+drm-y       := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
+               drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \
+               drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
+               drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
+               drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o
+
+drm-$(CONFIG_COMPAT) += drm_ioc32.o
+
+obj-$(CONFIG_DRM)      += drm.o
+obj-$(CONFIG_DRM_TDFX) += tdfx/
+obj-$(CONFIG_DRM_R128) += r128/
+obj-$(CONFIG_DRM_RADEON)+= radeon/
+obj-$(CONFIG_DRM_MGA)  += mga/
+obj-$(CONFIG_DRM_I810) += i810/
+obj-$(CONFIG_DRM_I830) += i830/
+obj-$(CONFIG_DRM_I915)  += i915/
+obj-$(CONFIG_DRM_SIS)   += sis/
+obj-$(CONFIG_DRM_SAVAGE)+= savage/
+obj-$(CONFIG_DRM_VIA)  +=via/
+
diff --git a/drivers/gpu/drm/README.drm b/drivers/gpu/drm/README.drm
new file mode 100644 (file)
index 0000000..b5b3327
--- /dev/null
@@ -0,0 +1,43 @@
+************************************************************
+* For the very latest on DRI development, please see:      *
+*     http://dri.freedesktop.org/                          *
+************************************************************
+
+The Direct Rendering Manager (drm) is a device-independent kernel-level
+device driver that provides support for the XFree86 Direct Rendering
+Infrastructure (DRI).
+
+The DRM supports the Direct Rendering Infrastructure (DRI) in four major
+ways:
+
+    1. The DRM provides synchronized access to the graphics hardware via
+       the use of an optimized two-tiered lock.
+
+    2. The DRM enforces the DRI security policy for access to the graphics
+       hardware by only allowing authenticated X11 clients access to
+       restricted regions of memory.
+
+    3. The DRM provides a generic DMA engine, complete with multiple
+       queues and the ability to detect the need for an OpenGL context
+       switch.
+
+    4. The DRM is extensible via the use of small device-specific modules
+       that rely extensively on the API exported by the DRM module.
+
+
+Documentation on the DRI is available from:
+    http://dri.freedesktop.org/wiki/Documentation
+    http://sourceforge.net/project/showfiles.php?group_id=387
+    http://dri.sourceforge.net/doc/
+
+For specific information about kernel-level support, see:
+
+    The Direct Rendering Manager, Kernel Support for the Direct Rendering
+    Infrastructure
+    http://dri.sourceforge.net/doc/drm_low_level.html
+
+    Hardware Locking for the Direct Rendering Infrastructure
+    http://dri.sourceforge.net/doc/hardware_locking_low_level.html
+
+    A Security Analysis of the Direct Rendering Infrastructure
+    http://dri.sourceforge.net/doc/security_low_level.html
diff --git a/drivers/gpu/drm/ati_pcigart.c b/drivers/gpu/drm/ati_pcigart.c
new file mode 100644 (file)
index 0000000..c533d0c
--- /dev/null
@@ -0,0 +1,181 @@
+/**
+ * \file ati_pcigart.c
+ * ATI PCI GART support
+ *
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+
+# define ATI_PCIGART_PAGE_SIZE         4096    /**< PCI GART page size */
+
+static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
+                                      struct drm_ati_pcigart_info *gart_info)
+{
+       gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size,
+                                               PAGE_SIZE,
+                                               gart_info->table_mask);
+       if (gart_info->table_handle == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void drm_ati_free_pcigart_table(struct drm_device *dev,
+                                      struct drm_ati_pcigart_info *gart_info)
+{
+       drm_pci_free(dev, gart_info->table_handle);
+       gart_info->table_handle = NULL;
+}
+
+int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
+{
+       struct drm_sg_mem *entry = dev->sg;
+       unsigned long pages;
+       int i;
+       int max_pages;
+
+       /* we need to support large memory configurations */
+       if (!entry) {
+               DRM_ERROR("no scatter/gather memory!\n");
+               return 0;
+       }
+
+       if (gart_info->bus_addr) {
+
+               max_pages = (gart_info->table_size / sizeof(u32));
+               pages = (entry->pages <= max_pages)
+                 ? entry->pages : max_pages;
+
+               for (i = 0; i < pages; i++) {
+                       if (!entry->busaddr[i])
+                               break;
+                       pci_unmap_page(dev->pdev, entry->busaddr[i],
+                                        PAGE_SIZE, PCI_DMA_TODEVICE);
+               }
+
+               if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
+                       gart_info->bus_addr = 0;
+       }
+
+       if (gart_info->gart_table_location == DRM_ATI_GART_MAIN &&
+           gart_info->table_handle) {
+               drm_ati_free_pcigart_table(dev, gart_info);
+       }
+
+       return 1;
+}
+EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
+
+int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
+{
+       struct drm_sg_mem *entry = dev->sg;
+       void *address = NULL;
+       unsigned long pages;
+       u32 *pci_gart, page_base;
+       dma_addr_t bus_address = 0;
+       int i, j, ret = 0;
+       int max_pages;
+
+       if (!entry) {
+               DRM_ERROR("no scatter/gather memory!\n");
+               goto done;
+       }
+
+       if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
+               DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
+
+               ret = drm_ati_alloc_pcigart_table(dev, gart_info);
+               if (ret) {
+                       DRM_ERROR("cannot allocate PCI GART page!\n");
+                       goto done;
+               }
+
+               address = gart_info->table_handle->vaddr;
+               bus_address = gart_info->table_handle->busaddr;
+       } else {
+               address = gart_info->addr;
+               bus_address = gart_info->bus_addr;
+               DRM_DEBUG("PCI: Gart Table: VRAM %08LX mapped at %08lX\n",
+                         (unsigned long long)bus_address,
+                         (unsigned long)address);
+       }
+
+       pci_gart = (u32 *) address;
+
+       max_pages = (gart_info->table_size / sizeof(u32));
+       pages = (entry->pages <= max_pages)
+           ? entry->pages : max_pages;
+
+       memset(pci_gart, 0, max_pages * sizeof(u32));
+
+       for (i = 0; i < pages; i++) {
+               /* we need to support large memory configurations */
+               entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i],
+                                                0, PAGE_SIZE, PCI_DMA_TODEVICE);
+               if (entry->busaddr[i] == 0) {
+                       DRM_ERROR("unable to map PCIGART pages!\n");
+                       drm_ati_pcigart_cleanup(dev, gart_info);
+                       address = NULL;
+                       bus_address = 0;
+                       goto done;
+               }
+               page_base = (u32) entry->busaddr[i];
+
+               for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
+                       switch(gart_info->gart_reg_if) {
+                       case DRM_ATI_GART_IGP:
+                               *pci_gart = cpu_to_le32((page_base) | 0xc);
+                               break;
+                       case DRM_ATI_GART_PCIE:
+                               *pci_gart = cpu_to_le32((page_base >> 8) | 0xc);
+                               break;
+                       default:
+                       case DRM_ATI_GART_PCI:
+                               *pci_gart = cpu_to_le32(page_base);
+                               break;
+                       }
+                       pci_gart++;
+                       page_base += ATI_PCIGART_PAGE_SIZE;
+               }
+       }
+       ret = 1;
+
+#if defined(__i386__) || defined(__x86_64__)
+       wbinvd();
+#else
+       mb();
+#endif
+
+      done:
+       gart_info->addr = address;
+       gart_info->bus_addr = bus_address;
+       return ret;
+}
+EXPORT_SYMBOL(drm_ati_pcigart_init);
diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c
new file mode 100644 (file)
index 0000000..aefa5ac
--- /dev/null
@@ -0,0 +1,455 @@
+/**
+ * \file drm_agpsupport.c
+ * DRM support for AGP/GART backend
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include <linux/module.h>
+
+#if __OS_HAS_AGP
+
+/**
+ * Get AGP information.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a (output) drm_agp_info structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been initialized and acquired and fills in the
+ * drm_agp_info structure with the information in drm_agp_head::agp_info.
+ */
+int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
+{
+       DRM_AGP_KERN *kern;
+
+       if (!dev->agp || !dev->agp->acquired)
+               return -EINVAL;
+
+       kern = &dev->agp->agp_info;
+       info->agp_version_major = kern->version.major;
+       info->agp_version_minor = kern->version.minor;
+       info->mode = kern->mode;
+       info->aperture_base = kern->aper_base;
+       info->aperture_size = kern->aper_size * 1024 * 1024;
+       info->memory_allowed = kern->max_memory << PAGE_SHIFT;
+       info->memory_used = kern->current_memory << PAGE_SHIFT;
+       info->id_vendor = kern->device->vendor;
+       info->id_device = kern->device->device;
+
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_agp_info);
+
+int drm_agp_info_ioctl(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       struct drm_agp_info *info = data;
+       int err;
+
+       err = drm_agp_info(dev, info);
+       if (err)
+               return err;
+
+       return 0;
+}
+
+/**
+ * Acquire the AGP device.
+ *
+ * \param dev DRM device that is to acquire AGP.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device hasn't been acquired before and calls
+ * \c agp_backend_acquire.
+ */
+int drm_agp_acquire(struct drm_device * dev)
+{
+       if (!dev->agp)
+               return -ENODEV;
+       if (dev->agp->acquired)
+               return -EBUSY;
+       if (!(dev->agp->bridge = agp_backend_acquire(dev->pdev)))
+               return -ENODEV;
+       dev->agp->acquired = 1;
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_agp_acquire);
+
+/**
+ * Acquire the AGP device (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device hasn't been acquired before and calls
+ * \c agp_backend_acquire.
+ */
+int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
+}
+
+/**
+ * Release the AGP device.
+ *
+ * \param dev DRM device that is to release AGP.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been acquired and calls \c agp_backend_release.
+ */
+int drm_agp_release(struct drm_device * dev)
+{
+       if (!dev->agp || !dev->agp->acquired)
+               return -EINVAL;
+       agp_backend_release(dev->agp->bridge);
+       dev->agp->acquired = 0;
+       return 0;
+}
+EXPORT_SYMBOL(drm_agp_release);
+
+int drm_agp_release_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       return drm_agp_release(dev);
+}
+
+/**
+ * Enable the AGP bus.
+ *
+ * \param dev DRM device that has previously acquired AGP.
+ * \param mode Requested AGP mode.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been acquired but not enabled, and calls
+ * \c agp_enable.
+ */
+int drm_agp_enable(struct drm_device * dev, struct drm_agp_mode mode)
+{
+       if (!dev->agp || !dev->agp->acquired)
+               return -EINVAL;
+
+       dev->agp->mode = mode.mode;
+       agp_enable(dev->agp->bridge, mode.mode);
+       dev->agp->enabled = 1;
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_agp_enable);
+
+int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       struct drm_agp_mode *mode = data;
+
+       return drm_agp_enable(dev, *mode);
+}
+
+/**
+ * Allocate AGP memory.
+ *
+ * \param inode device inode.
+ * \param file_priv file private pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_buffer structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and has been acquired, allocates the
+ * memory via alloc_agp() and creates a drm_agp_mem entry for it.
+ */
+int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
+{
+       struct drm_agp_mem *entry;
+       DRM_AGP_MEM *memory;
+       unsigned long pages;
+       u32 type;
+
+       if (!dev->agp || !dev->agp->acquired)
+               return -EINVAL;
+       if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
+               return -ENOMEM;
+
+       memset(entry, 0, sizeof(*entry));
+
+       pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
+       type = (u32) request->type;
+       if (!(memory = drm_alloc_agp(dev, pages, type))) {
+               drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+               return -ENOMEM;
+       }
+
+       entry->handle = (unsigned long)memory->key + 1;
+       entry->memory = memory;
+       entry->bound = 0;
+       entry->pages = pages;
+       list_add(&entry->head, &dev->agp->memory);
+
+       request->handle = entry->handle;
+       request->physical = memory->physical;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_agp_alloc);
+
+
+int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       struct drm_agp_buffer *request = data;
+
+       return drm_agp_alloc(dev, request);
+}
+
+/**
+ * Search for the AGP memory entry associated with a handle.
+ *
+ * \param dev DRM device structure.
+ * \param handle AGP memory handle.
+ * \return pointer to the drm_agp_mem structure associated with \p handle.
+ *
+ * Walks through drm_agp_head::memory until finding a matching handle.
+ */
+static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev,
+                                          unsigned long handle)
+{
+       struct drm_agp_mem *entry;
+
+       list_for_each_entry(entry, &dev->agp->memory, head) {
+               if (entry->handle == handle)
+                       return entry;
+       }
+       return NULL;
+}
+
+/**
+ * Unbind AGP memory from the GATT (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_binding structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and acquired, looks-up the AGP memory
+ * entry and passes it to the unbind_agp() function.
+ */
+int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
+{
+       struct drm_agp_mem *entry;
+       int ret;
+
+       if (!dev->agp || !dev->agp->acquired)
+               return -EINVAL;
+       if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
+               return -EINVAL;
+       if (!entry->bound)
+               return -EINVAL;
+       ret = drm_unbind_agp(entry->memory);
+       if (ret == 0)
+               entry->bound = 0;
+       return ret;
+}
+EXPORT_SYMBOL(drm_agp_unbind);
+
+
+int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       struct drm_agp_binding *request = data;
+
+       return drm_agp_unbind(dev, request);
+}
+
+/**
+ * Bind AGP memory into the GATT (ioctl)
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_binding structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and has been acquired and that no memory
+ * is currently bound into the GATT. Looks-up the AGP memory entry and passes
+ * it to bind_agp() function.
+ */
+int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
+{
+       struct drm_agp_mem *entry;
+       int retcode;
+       int page;
+
+       if (!dev->agp || !dev->agp->acquired)
+               return -EINVAL;
+       if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
+               return -EINVAL;
+       if (entry->bound)
+               return -EINVAL;
+       page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
+       if ((retcode = drm_bind_agp(entry->memory, page)))
+               return retcode;
+       entry->bound = dev->agp->base + (page << PAGE_SHIFT);
+       DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
+                 dev->agp->base, entry->bound);
+       return 0;
+}
+EXPORT_SYMBOL(drm_agp_bind);
+
+
+int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       struct drm_agp_binding *request = data;
+
+       return drm_agp_bind(dev, request);
+}
+
+/**
+ * Free AGP memory (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_buffer structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and has been acquired and looks up the
+ * AGP memory entry. If the memory it's currently bound, unbind it via
+ * unbind_agp(). Frees it via free_agp() as well as the entry itself
+ * and unlinks from the doubly linked list it's inserted in.
+ */
+int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
+{
+       struct drm_agp_mem *entry;
+
+       if (!dev->agp || !dev->agp->acquired)
+               return -EINVAL;
+       if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
+               return -EINVAL;
+       if (entry->bound)
+               drm_unbind_agp(entry->memory);
+
+       list_del(&entry->head);
+
+       drm_free_agp(entry->memory, entry->pages);
+       drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+       return 0;
+}
+EXPORT_SYMBOL(drm_agp_free);
+
+
+
+int drm_agp_free_ioctl(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       struct drm_agp_buffer *request = data;
+
+       return drm_agp_free(dev, request);
+}
+
+/**
+ * Initialize the AGP resources.
+ *
+ * \return pointer to a drm_agp_head structure.
+ *
+ * Gets the drm_agp_t structure which is made available by the agpgart module
+ * via the inter_module_* functions. Creates and initializes a drm_agp_head
+ * structure.
+ */
+struct drm_agp_head *drm_agp_init(struct drm_device *dev)
+{
+       struct drm_agp_head *head = NULL;
+
+       if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
+               return NULL;
+       memset((void *)head, 0, sizeof(*head));
+       head->bridge = agp_find_bridge(dev->pdev);
+       if (!head->bridge) {
+               if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
+                       drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
+                       return NULL;
+               }
+               agp_copy_info(head->bridge, &head->agp_info);
+               agp_backend_release(head->bridge);
+       } else {
+               agp_copy_info(head->bridge, &head->agp_info);
+       }
+       if (head->agp_info.chipset == NOT_SUPPORTED) {
+               drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
+               return NULL;
+       }
+       INIT_LIST_HEAD(&head->memory);
+       head->cant_use_aperture = head->agp_info.cant_use_aperture;
+       head->page_mask = head->agp_info.page_mask;
+       head->base = head->agp_info.aper_base;
+       return head;
+}
+
+/** Calls agp_allocate_memory() */
+DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data * bridge,
+                                    size_t pages, u32 type)
+{
+       return agp_allocate_memory(bridge, pages, type);
+}
+
+/** Calls agp_free_memory() */
+int drm_agp_free_memory(DRM_AGP_MEM * handle)
+{
+       if (!handle)
+               return 0;
+       agp_free_memory(handle);
+       return 1;
+}
+
+/** Calls agp_bind_memory() */
+int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start)
+{
+       if (!handle)
+               return -EINVAL;
+       return agp_bind_memory(handle, start);
+}
+
+/** Calls agp_unbind_memory() */
+int drm_agp_unbind_memory(DRM_AGP_MEM * handle)
+{
+       if (!handle)
+               return -EINVAL;
+       return agp_unbind_memory(handle);
+}
+
+#endif                         /* __OS_HAS_AGP */
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
new file mode 100644 (file)
index 0000000..a734627
--- /dev/null
@@ -0,0 +1,190 @@
+/**
+ * \file drm_auth.c
+ * IOCTLs for authentication
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+
+/**
+ * Find the file with the given magic number.
+ *
+ * \param dev DRM device.
+ * \param magic magic number.
+ *
+ * Searches in drm_device::magiclist within all files with the same hash key
+ * the one with matching magic number, while holding the drm_device::struct_mutex
+ * lock.
+ */
+static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic)
+{
+       struct drm_file *retval = NULL;
+       struct drm_magic_entry *pt;
+       struct drm_hash_item *hash;
+
+       mutex_lock(&dev->struct_mutex);
+       if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
+               pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
+               retval = pt->priv;
+       }
+       mutex_unlock(&dev->struct_mutex);
+       return retval;
+}
+
+/**
+ * Adds a magic number.
+ *
+ * \param dev DRM device.
+ * \param priv file private data.
+ * \param magic magic number.
+ *
+ * Creates a drm_magic_entry structure and appends to the linked list
+ * associated the magic number hash key in drm_device::magiclist, while holding
+ * the drm_device::struct_mutex lock.
+ */
+static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,
+                        drm_magic_t magic)
+{
+       struct drm_magic_entry *entry;
+
+       DRM_DEBUG("%d\n", magic);
+
+       entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC);
+       if (!entry)
+               return -ENOMEM;
+       memset(entry, 0, sizeof(*entry));
+       entry->priv = priv;
+
+       entry->hash_item.key = (unsigned long)magic;
+       mutex_lock(&dev->struct_mutex);
+       drm_ht_insert_item(&dev->magiclist, &entry->hash_item);
+       list_add_tail(&entry->head, &dev->magicfree);
+       mutex_unlock(&dev->struct_mutex);
+
+       return 0;
+}
+
+/**
+ * Remove a magic number.
+ *
+ * \param dev DRM device.
+ * \param magic magic number.
+ *
+ * Searches and unlinks the entry in drm_device::magiclist with the magic
+ * number hash key, while holding the drm_device::struct_mutex lock.
+ */
+static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic)
+{
+       struct drm_magic_entry *pt;
+       struct drm_hash_item *hash;
+
+       DRM_DEBUG("%d\n", magic);
+
+       mutex_lock(&dev->struct_mutex);
+       if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
+       }
+       pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);
+       drm_ht_remove_item(&dev->magiclist, hash);
+       list_del(&pt->head);
+       mutex_unlock(&dev->struct_mutex);
+
+       drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
+
+       return 0;
+}
+
+/**
+ * Get a unique magic number (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a resulting drm_auth structure.
+ * \return zero on success, or a negative number on failure.
+ *
+ * If there is a magic number in drm_file::magic then use it, otherwise
+ * searches an unique non-zero magic number and add it associating it with \p
+ * file_priv.
+ */
+int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       static drm_magic_t sequence = 0;
+       static DEFINE_SPINLOCK(lock);
+       struct drm_auth *auth = data;
+
+       /* Find unique magic */
+       if (file_priv->magic) {
+               auth->magic = file_priv->magic;
+       } else {
+               do {
+                       spin_lock(&lock);
+                       if (!sequence)
+                               ++sequence;     /* reserve 0 */
+                       auth->magic = sequence++;
+                       spin_unlock(&lock);
+               } while (drm_find_file(dev, auth->magic));
+               file_priv->magic = auth->magic;
+               drm_add_magic(dev, file_priv, auth->magic);
+       }
+
+       DRM_DEBUG("%u\n", auth->magic);
+
+       return 0;
+}
+
+/**
+ * Authenticate with a magic.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_auth structure.
+ * \return zero if authentication successed, or a negative number otherwise.
+ *
+ * Checks if \p file_priv is associated with the magic number passed in \arg.
+ */
+int drm_authmagic(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
+{
+       struct drm_auth *auth = data;
+       struct drm_file *file;
+
+       DRM_DEBUG("%u\n", auth->magic);
+       if ((file = drm_find_file(dev, auth->magic))) {
+               file->authenticated = 1;
+               drm_remove_magic(dev, auth->magic);
+               return 0;
+       }
+       return -EINVAL;
+}
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
new file mode 100644 (file)
index 0000000..bde64b8
--- /dev/null
@@ -0,0 +1,1601 @@
+/**
+ * \file drm_bufs.c
+ * Generic buffer template
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/vmalloc.h>
+#include "drmP.h"
+
+unsigned long drm_get_resource_start(struct drm_device *dev, unsigned int resource)
+{
+       return pci_resource_start(dev->pdev, resource);
+}
+EXPORT_SYMBOL(drm_get_resource_start);
+
+unsigned long drm_get_resource_len(struct drm_device *dev, unsigned int resource)
+{
+       return pci_resource_len(dev->pdev, resource);
+}
+
+EXPORT_SYMBOL(drm_get_resource_len);
+
+static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
+                                            drm_local_map_t *map)
+{
+       struct drm_map_list *entry;
+       list_for_each_entry(entry, &dev->maplist, head) {
+               if (entry->map && map->type == entry->map->type &&
+                   ((entry->map->offset == map->offset) ||
+                    (map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) {
+                       return entry;
+               }
+       }
+
+       return NULL;
+}
+
+static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
+                         unsigned long user_token, int hashed_handle)
+{
+       int use_hashed_handle;
+#if (BITS_PER_LONG == 64)
+       use_hashed_handle = ((user_token & 0xFFFFFFFF00000000UL) || hashed_handle);
+#elif (BITS_PER_LONG == 32)
+       use_hashed_handle = hashed_handle;
+#else
+#error Unsupported long size. Neither 64 nor 32 bits.
+#endif
+
+       if (!use_hashed_handle) {
+               int ret;
+               hash->key = user_token >> PAGE_SHIFT;
+               ret = drm_ht_insert_item(&dev->map_hash, hash);
+               if (ret != -EINVAL)
+                       return ret;
+       }
+       return drm_ht_just_insert_please(&dev->map_hash, hash,
+                                        user_token, 32 - PAGE_SHIFT - 3,
+                                        0, DRM_MAP_HASH_OFFSET >> PAGE_SHIFT);
+}
+
+/**
+ * Ioctl to specify a range of memory that is available for mapping by a non-root process.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_map structure.
+ * \return zero on success or a negative value on error.
+ *
+ * Adjusts the memory offset to its absolute value according to the mapping
+ * type.  Adds the map to the map list drm_device::maplist. Adds MTRR's where
+ * applicable and if supported by the kernel.
+ */
+static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
+                          unsigned int size, enum drm_map_type type,
+                          enum drm_map_flags flags,
+                          struct drm_map_list ** maplist)
+{
+       struct drm_map *map;
+       struct drm_map_list *list;
+       drm_dma_handle_t *dmah;
+       unsigned long user_token;
+       int ret;
+
+       map = drm_alloc(sizeof(*map), DRM_MEM_MAPS);
+       if (!map)
+               return -ENOMEM;
+
+       map->offset = offset;
+       map->size = size;
+       map->flags = flags;
+       map->type = type;
+
+       /* Only allow shared memory to be removable since we only keep enough
+        * book keeping information about shared memory to allow for removal
+        * when processes fork.
+        */
+       if ((map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM) {
+               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+               return -EINVAL;
+       }
+       DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n",
+                 map->offset, map->size, map->type);
+       if ((map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
+               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+               return -EINVAL;
+       }
+       map->mtrr = -1;
+       map->handle = NULL;
+
+       switch (map->type) {
+       case _DRM_REGISTERS:
+       case _DRM_FRAME_BUFFER:
+#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
+               if (map->offset + (map->size-1) < map->offset ||
+                   map->offset < virt_to_phys(high_memory)) {
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       return -EINVAL;
+               }
+#endif
+#ifdef __alpha__
+               map->offset += dev->hose->mem_space->start;
+#endif
+               /* Some drivers preinitialize some maps, without the X Server
+                * needing to be aware of it.  Therefore, we just return success
+                * when the server tries to create a duplicate map.
+                */
+               list = drm_find_matching_map(dev, map);
+               if (list != NULL) {
+                       if (list->map->size != map->size) {
+                               DRM_DEBUG("Matching maps of type %d with "
+                                         "mismatched sizes, (%ld vs %ld)\n",
+                                         map->type, map->size,
+                                         list->map->size);
+                               list->map->size = map->size;
+                       }
+
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       *maplist = list;
+                       return 0;
+               }
+
+               if (drm_core_has_MTRR(dev)) {
+                       if (map->type == _DRM_FRAME_BUFFER ||
+                           (map->flags & _DRM_WRITE_COMBINING)) {
+                               map->mtrr = mtrr_add(map->offset, map->size,
+                                                    MTRR_TYPE_WRCOMB, 1);
+                       }
+               }
+               if (map->type == _DRM_REGISTERS) {
+                       map->handle = ioremap(map->offset, map->size);
+                       if (!map->handle) {
+                               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                               return -ENOMEM;
+                       }
+               }
+
+               break;
+       case _DRM_SHM:
+               list = drm_find_matching_map(dev, map);
+               if (list != NULL) {
+                       if(list->map->size != map->size) {
+                               DRM_DEBUG("Matching maps of type %d with "
+                                         "mismatched sizes, (%ld vs %ld)\n",
+                                         map->type, map->size, list->map->size);
+                               list->map->size = map->size;
+                       }
+
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       *maplist = list;
+                       return 0;
+               }
+               map->handle = vmalloc_user(map->size);
+               DRM_DEBUG("%lu %d %p\n",
+                         map->size, drm_order(map->size), map->handle);
+               if (!map->handle) {
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       return -ENOMEM;
+               }
+               map->offset = (unsigned long)map->handle;
+               if (map->flags & _DRM_CONTAINS_LOCK) {
+                       /* Prevent a 2nd X Server from creating a 2nd lock */
+                       if (dev->lock.hw_lock != NULL) {
+                               vfree(map->handle);
+                               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                               return -EBUSY;
+                       }
+                       dev->sigdata.lock = dev->lock.hw_lock = map->handle;    /* Pointer to lock */
+               }
+               break;
+       case _DRM_AGP: {
+               struct drm_agp_mem *entry;
+               int valid = 0;
+
+               if (!drm_core_has_AGP(dev)) {
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       return -EINVAL;
+               }
+#ifdef __alpha__
+               map->offset += dev->hose->mem_space->start;
+#endif
+               /* In some cases (i810 driver), user space may have already
+                * added the AGP base itself, because dev->agp->base previously
+                * only got set during AGP enable.  So, only add the base
+                * address if the map's offset isn't already within the
+                * aperture.
+                */
+               if (map->offset < dev->agp->base ||
+                   map->offset > dev->agp->base +
+                   dev->agp->agp_info.aper_size * 1024 * 1024 - 1) {
+                       map->offset += dev->agp->base;
+               }
+               map->mtrr = dev->agp->agp_mtrr; /* for getmap */
+
+               /* This assumes the DRM is in total control of AGP space.
+                * It's not always the case as AGP can be in the control
+                * of user space (i.e. i810 driver). So this loop will get
+                * skipped and we double check that dev->agp->memory is
+                * actually set as well as being invalid before EPERM'ing
+                */
+               list_for_each_entry(entry, &dev->agp->memory, head) {
+                       if ((map->offset >= entry->bound) &&
+                           (map->offset + map->size <= entry->bound + entry->pages * PAGE_SIZE)) {
+                               valid = 1;
+                               break;
+                       }
+               }
+               if (!list_empty(&dev->agp->memory) && !valid) {
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       return -EPERM;
+               }
+               DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n", map->offset, map->size);
+
+               break;
+       }
+       case _DRM_SCATTER_GATHER:
+               if (!dev->sg) {
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       return -EINVAL;
+               }
+               map->offset += (unsigned long)dev->sg->virtual;
+               break;
+       case _DRM_CONSISTENT:
+               /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G,
+                * As we're limiting the address to 2^32-1 (or less),
+                * casting it down to 32 bits is no problem, but we
+                * need to point to a 64bit variable first. */
+               dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL);
+               if (!dmah) {
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       return -ENOMEM;
+               }
+               map->handle = dmah->vaddr;
+               map->offset = (unsigned long)dmah->busaddr;
+               kfree(dmah);
+               break;
+       default:
+               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+               return -EINVAL;
+       }
+
+       list = drm_alloc(sizeof(*list), DRM_MEM_MAPS);
+       if (!list) {
+               if (map->type == _DRM_REGISTERS)
+                       iounmap(map->handle);
+               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+               return -EINVAL;
+       }
+       memset(list, 0, sizeof(*list));
+       list->map = map;
+
+       mutex_lock(&dev->struct_mutex);
+       list_add(&list->head, &dev->maplist);
+
+       /* Assign a 32-bit handle */
+       /* We do it here so that dev->struct_mutex protects the increment */
+       user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle :
+               map->offset;
+       ret = drm_map_handle(dev, &list->hash, user_token, 0);
+       if (ret) {
+               if (map->type == _DRM_REGISTERS)
+                       iounmap(map->handle);
+               drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+               drm_free(list, sizeof(*list), DRM_MEM_MAPS);
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
+
+       list->user_token = list->hash.key << PAGE_SHIFT;
+       mutex_unlock(&dev->struct_mutex);
+
+       *maplist = list;
+       return 0;
+       }
+
+int drm_addmap(struct drm_device * dev, unsigned int offset,
+              unsigned int size, enum drm_map_type type,
+              enum drm_map_flags flags, drm_local_map_t ** map_ptr)
+{
+       struct drm_map_list *list;
+       int rc;
+
+       rc = drm_addmap_core(dev, offset, size, type, flags, &list);
+       if (!rc)
+               *map_ptr = list->map;
+       return rc;
+}
+
+EXPORT_SYMBOL(drm_addmap);
+
+int drm_addmap_ioctl(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
+{
+       struct drm_map *map = data;
+       struct drm_map_list *maplist;
+       int err;
+
+       if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP))
+               return -EPERM;
+
+       err = drm_addmap_core(dev, map->offset, map->size, map->type,
+                             map->flags, &maplist);
+
+       if (err)
+               return err;
+
+       /* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
+       map->handle = (void *)(unsigned long)maplist->user_token;
+       return 0;
+}
+
+/**
+ * Remove a map private from list and deallocate resources if the mapping
+ * isn't in use.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a struct drm_map structure.
+ * \return zero on success or a negative value on error.
+ *
+ * Searches the map on drm_device::maplist, removes it from the list, see if
+ * its being used, and free any associate resource (such as MTRR's) if it's not
+ * being on use.
+ *
+ * \sa drm_addmap
+ */
+int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
+{
+       struct drm_map_list *r_list = NULL, *list_t;
+       drm_dma_handle_t dmah;
+       int found = 0;
+
+       /* Find the list entry for the map and remove it */
+       list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
+               if (r_list->map == map) {
+                       list_del(&r_list->head);
+                       drm_ht_remove_key(&dev->map_hash,
+                                         r_list->user_token >> PAGE_SHIFT);
+                       drm_free(r_list, sizeof(*r_list), DRM_MEM_MAPS);
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (!found)
+               return -EINVAL;
+
+       switch (map->type) {
+       case _DRM_REGISTERS:
+               iounmap(map->handle);
+               /* FALLTHROUGH */
+       case _DRM_FRAME_BUFFER:
+               if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
+                       int retcode;
+                       retcode = mtrr_del(map->mtrr, map->offset, map->size);
+                       DRM_DEBUG("mtrr_del=%d\n", retcode);
+               }
+               break;
+       case _DRM_SHM:
+               vfree(map->handle);
+               break;
+       case _DRM_AGP:
+       case _DRM_SCATTER_GATHER:
+               break;
+       case _DRM_CONSISTENT:
+               dmah.vaddr = map->handle;
+               dmah.busaddr = map->offset;
+               dmah.size = map->size;
+               __drm_pci_free(dev, &dmah);
+               break;
+       }
+       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+
+       return 0;
+}
+
+int drm_rmmap(struct drm_device *dev, drm_local_map_t *map)
+{
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_rmmap_locked(dev, map);
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_rmmap);
+
+/* The rmmap ioctl appears to be unnecessary.  All mappings are torn down on
+ * the last close of the device, and this is necessary for cleanup when things
+ * exit uncleanly.  Therefore, having userland manually remove mappings seems
+ * like a pointless exercise since they're going away anyway.
+ *
+ * One use case might be after addmap is allowed for normal users for SHM and
+ * gets used by drivers that the server doesn't need to care about.  This seems
+ * unlikely.
+ */
+int drm_rmmap_ioctl(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
+{
+       struct drm_map *request = data;
+       drm_local_map_t *map = NULL;
+       struct drm_map_list *r_list;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       list_for_each_entry(r_list, &dev->maplist, head) {
+               if (r_list->map &&
+                   r_list->user_token == (unsigned long)request->handle &&
+                   r_list->map->flags & _DRM_REMOVABLE) {
+                       map = r_list->map;
+                       break;
+               }
+       }
+
+       /* List has wrapped around to the head pointer, or its empty we didn't
+        * find anything.
+        */
+       if (list_empty(&dev->maplist) || !map) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
+       }
+
+       /* Register and framebuffer maps are permanent */
+       if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) {
+               mutex_unlock(&dev->struct_mutex);
+               return 0;
+       }
+
+       ret = drm_rmmap_locked(dev, map);
+
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
+}
+
+/**
+ * Cleanup after an error on one of the addbufs() functions.
+ *
+ * \param dev DRM device.
+ * \param entry buffer entry where the error occurred.
+ *
+ * Frees any pages and buffers associated with the given entry.
+ */
+static void drm_cleanup_buf_error(struct drm_device * dev,
+                                 struct drm_buf_entry * entry)
+{
+       int i;
+
+       if (entry->seg_count) {
+               for (i = 0; i < entry->seg_count; i++) {
+                       if (entry->seglist[i]) {
+                               drm_pci_free(dev, entry->seglist[i]);
+                       }
+               }
+               drm_free(entry->seglist,
+                        entry->seg_count *
+                        sizeof(*entry->seglist), DRM_MEM_SEGS);
+
+               entry->seg_count = 0;
+       }
+
+       if (entry->buf_count) {
+               for (i = 0; i < entry->buf_count; i++) {
+                       if (entry->buflist[i].dev_private) {
+                               drm_free(entry->buflist[i].dev_private,
+                                        entry->buflist[i].dev_priv_size,
+                                        DRM_MEM_BUFS);
+                       }
+               }
+               drm_free(entry->buflist,
+                        entry->buf_count *
+                        sizeof(*entry->buflist), DRM_MEM_BUFS);
+
+               entry->buf_count = 0;
+       }
+}
+
+#if __OS_HAS_AGP
+/**
+ * Add AGP buffers for DMA transfers.
+ *
+ * \param dev struct drm_device to which the buffers are to be added.
+ * \param request pointer to a struct drm_buf_desc describing the request.
+ * \return zero on success or a negative number on failure.
+ *
+ * After some sanity checks creates a drm_buf structure for each buffer and
+ * reallocates the buffer list of the same size order to accommodate the new
+ * buffers.
+ */
+int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request)
+{
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf_entry *entry;
+       struct drm_agp_mem *agp_entry;
+       struct drm_buf *buf;
+       unsigned long offset;
+       unsigned long agp_offset;
+       int count;
+       int order;
+       int size;
+       int alignment;
+       int page_order;
+       int total;
+       int byte_count;
+       int i, valid;
+       struct drm_buf **temp_buflist;
+
+       if (!dma)
+               return -EINVAL;
+
+       count = request->count;
+       order = drm_order(request->size);
+       size = 1 << order;
+
+       alignment = (request->flags & _DRM_PAGE_ALIGN)
+           ? PAGE_ALIGN(size) : size;
+       page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+       total = PAGE_SIZE << page_order;
+
+       byte_count = 0;
+       agp_offset = dev->agp->base + request->agp_start;
+
+       DRM_DEBUG("count:      %d\n", count);
+       DRM_DEBUG("order:      %d\n", order);
+       DRM_DEBUG("size:       %d\n", size);
+       DRM_DEBUG("agp_offset: %lx\n", agp_offset);
+       DRM_DEBUG("alignment:  %d\n", alignment);
+       DRM_DEBUG("page_order: %d\n", page_order);
+       DRM_DEBUG("total:      %d\n", total);
+
+       if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+               return -EINVAL;
+       if (dev->queue_count)
+               return -EBUSY;  /* Not while in use */
+
+       /* Make sure buffers are located in AGP memory that we own */
+       valid = 0;
+       list_for_each_entry(agp_entry, &dev->agp->memory, head) {
+               if ((agp_offset >= agp_entry->bound) &&
+                   (agp_offset + total * count <= agp_entry->bound + agp_entry->pages * PAGE_SIZE)) {
+                       valid = 1;
+                       break;
+               }
+       }
+       if (!list_empty(&dev->agp->memory) && !valid) {
+               DRM_DEBUG("zone invalid\n");
+               return -EINVAL;
+       }
+       spin_lock(&dev->count_lock);
+       if (dev->buf_use) {
+               spin_unlock(&dev->count_lock);
+               return -EBUSY;
+       }
+       atomic_inc(&dev->buf_alloc);
+       spin_unlock(&dev->count_lock);
+
+       mutex_lock(&dev->struct_mutex);
+       entry = &dma->bufs[order];
+       if (entry->buf_count) {
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM; /* May only call once for each order */
+       }
+
+       if (count < 0 || count > 4096) {
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -EINVAL;
+       }
+
+       entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+                                  DRM_MEM_BUFS);
+       if (!entry->buflist) {
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+       entry->buf_size = size;
+       entry->page_order = page_order;
+
+       offset = 0;
+
+       while (entry->buf_count < count) {
+               buf = &entry->buflist[entry->buf_count];
+               buf->idx = dma->buf_count + entry->buf_count;
+               buf->total = alignment;
+               buf->order = order;
+               buf->used = 0;
+
+               buf->offset = (dma->byte_count + offset);
+               buf->bus_address = agp_offset + offset;
+               buf->address = (void *)(agp_offset + offset);
+               buf->next = NULL;
+               buf->waiting = 0;
+               buf->pending = 0;
+               init_waitqueue_head(&buf->dma_wait);
+               buf->file_priv = NULL;
+
+               buf->dev_priv_size = dev->driver->dev_priv_size;
+               buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+               if (!buf->dev_private) {
+                       /* Set count correctly so we free the proper amount. */
+                       entry->buf_count = count;
+                       drm_cleanup_buf_error(dev, entry);
+                       mutex_unlock(&dev->struct_mutex);
+                       atomic_dec(&dev->buf_alloc);
+                       return -ENOMEM;
+               }
+               memset(buf->dev_private, 0, buf->dev_priv_size);
+
+               DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
+
+               offset += alignment;
+               entry->buf_count++;
+               byte_count += PAGE_SIZE << page_order;
+       }
+
+       DRM_DEBUG("byte_count: %d\n", byte_count);
+
+       temp_buflist = drm_realloc(dma->buflist,
+                                  dma->buf_count * sizeof(*dma->buflist),
+                                  (dma->buf_count + entry->buf_count)
+                                  * sizeof(*dma->buflist), DRM_MEM_BUFS);
+       if (!temp_buflist) {
+               /* Free the entry because it isn't valid */
+               drm_cleanup_buf_error(dev, entry);
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       dma->buflist = temp_buflist;
+
+       for (i = 0; i < entry->buf_count; i++) {
+               dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+       }
+
+       dma->buf_count += entry->buf_count;
+       dma->seg_count += entry->seg_count;
+       dma->page_count += byte_count >> PAGE_SHIFT;
+       dma->byte_count += byte_count;
+
+       DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
+       DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
+
+       mutex_unlock(&dev->struct_mutex);
+
+       request->count = entry->buf_count;
+       request->size = size;
+
+       dma->flags = _DRM_DMA_USE_AGP;
+
+       atomic_dec(&dev->buf_alloc);
+       return 0;
+}
+EXPORT_SYMBOL(drm_addbufs_agp);
+#endif                         /* __OS_HAS_AGP */
+
+int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int count;
+       int order;
+       int size;
+       int total;
+       int page_order;
+       struct drm_buf_entry *entry;
+       drm_dma_handle_t *dmah;
+       struct drm_buf *buf;
+       int alignment;
+       unsigned long offset;
+       int i;
+       int byte_count;
+       int page_count;
+       unsigned long *temp_pagelist;
+       struct drm_buf **temp_buflist;
+
+       if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
+               return -EINVAL;
+
+       if (!dma)
+               return -EINVAL;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       count = request->count;
+       order = drm_order(request->size);
+       size = 1 << order;
+
+       DRM_DEBUG("count=%d, size=%d (%d), order=%d, queue_count=%d\n",
+                 request->count, request->size, size, order, dev->queue_count);
+
+       if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+               return -EINVAL;
+       if (dev->queue_count)
+               return -EBUSY;  /* Not while in use */
+
+       alignment = (request->flags & _DRM_PAGE_ALIGN)
+           ? PAGE_ALIGN(size) : size;
+       page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+       total = PAGE_SIZE << page_order;
+
+       spin_lock(&dev->count_lock);
+       if (dev->buf_use) {
+               spin_unlock(&dev->count_lock);
+               return -EBUSY;
+       }
+       atomic_inc(&dev->buf_alloc);
+       spin_unlock(&dev->count_lock);
+
+       mutex_lock(&dev->struct_mutex);
+       entry = &dma->bufs[order];
+       if (entry->buf_count) {
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM; /* May only call once for each order */
+       }
+
+       if (count < 0 || count > 4096) {
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -EINVAL;
+       }
+
+       entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+                                  DRM_MEM_BUFS);
+       if (!entry->buflist) {
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+       entry->seglist = drm_alloc(count * sizeof(*entry->seglist),
+                                  DRM_MEM_SEGS);
+       if (!entry->seglist) {
+               drm_free(entry->buflist,
+                        count * sizeof(*entry->buflist), DRM_MEM_BUFS);
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       memset(entry->seglist, 0, count * sizeof(*entry->seglist));
+
+       /* Keep the original pagelist until we know all the allocations
+        * have succeeded
+        */
+       temp_pagelist = drm_alloc((dma->page_count + (count << page_order))
+                                 * sizeof(*dma->pagelist), DRM_MEM_PAGES);
+       if (!temp_pagelist) {
+               drm_free(entry->buflist,
+                        count * sizeof(*entry->buflist), DRM_MEM_BUFS);
+               drm_free(entry->seglist,
+                        count * sizeof(*entry->seglist), DRM_MEM_SEGS);
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       memcpy(temp_pagelist,
+              dma->pagelist, dma->page_count * sizeof(*dma->pagelist));
+       DRM_DEBUG("pagelist: %d entries\n",
+                 dma->page_count + (count << page_order));
+
+       entry->buf_size = size;
+       entry->page_order = page_order;
+       byte_count = 0;
+       page_count = 0;
+
+       while (entry->buf_count < count) {
+
+               dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful);
+
+               if (!dmah) {
+                       /* Set count correctly so we free the proper amount. */
+                       entry->buf_count = count;
+                       entry->seg_count = count;
+                       drm_cleanup_buf_error(dev, entry);
+                       drm_free(temp_pagelist,
+                                (dma->page_count + (count << page_order))
+                                * sizeof(*dma->pagelist), DRM_MEM_PAGES);
+                       mutex_unlock(&dev->struct_mutex);
+                       atomic_dec(&dev->buf_alloc);
+                       return -ENOMEM;
+               }
+               entry->seglist[entry->seg_count++] = dmah;
+               for (i = 0; i < (1 << page_order); i++) {
+                       DRM_DEBUG("page %d @ 0x%08lx\n",
+                                 dma->page_count + page_count,
+                                 (unsigned long)dmah->vaddr + PAGE_SIZE * i);
+                       temp_pagelist[dma->page_count + page_count++]
+                               = (unsigned long)dmah->vaddr + PAGE_SIZE * i;
+               }
+               for (offset = 0;
+                    offset + size <= total && entry->buf_count < count;
+                    offset += alignment, ++entry->buf_count) {
+                       buf = &entry->buflist[entry->buf_count];
+                       buf->idx = dma->buf_count + entry->buf_count;
+                       buf->total = alignment;
+                       buf->order = order;
+                       buf->used = 0;
+                       buf->offset = (dma->byte_count + byte_count + offset);
+                       buf->address = (void *)(dmah->vaddr + offset);
+                       buf->bus_address = dmah->busaddr + offset;
+                       buf->next = NULL;
+                       buf->waiting = 0;
+                       buf->pending = 0;
+                       init_waitqueue_head(&buf->dma_wait);
+                       buf->file_priv = NULL;
+
+                       buf->dev_priv_size = dev->driver->dev_priv_size;
+                       buf->dev_private = drm_alloc(buf->dev_priv_size,
+                                                    DRM_MEM_BUFS);
+                       if (!buf->dev_private) {
+                               /* Set count correctly so we free the proper amount. */
+                               entry->buf_count = count;
+                               entry->seg_count = count;
+                               drm_cleanup_buf_error(dev, entry);
+                               drm_free(temp_pagelist,
+                                        (dma->page_count +
+                                         (count << page_order))
+                                        * sizeof(*dma->pagelist),
+                                        DRM_MEM_PAGES);
+                               mutex_unlock(&dev->struct_mutex);
+                               atomic_dec(&dev->buf_alloc);
+                               return -ENOMEM;
+                       }
+                       memset(buf->dev_private, 0, buf->dev_priv_size);
+
+                       DRM_DEBUG("buffer %d @ %p\n",
+                                 entry->buf_count, buf->address);
+               }
+               byte_count += PAGE_SIZE << page_order;
+       }
+
+       temp_buflist = drm_realloc(dma->buflist,
+                                  dma->buf_count * sizeof(*dma->buflist),
+                                  (dma->buf_count + entry->buf_count)
+                                  * sizeof(*dma->buflist), DRM_MEM_BUFS);
+       if (!temp_buflist) {
+               /* Free the entry because it isn't valid */
+               drm_cleanup_buf_error(dev, entry);
+               drm_free(temp_pagelist,
+                        (dma->page_count + (count << page_order))
+                        * sizeof(*dma->pagelist), DRM_MEM_PAGES);
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       dma->buflist = temp_buflist;
+
+       for (i = 0; i < entry->buf_count; i++) {
+               dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+       }
+
+       /* No allocations failed, so now we can replace the orginal pagelist
+        * with the new one.
+        */
+       if (dma->page_count) {
+               drm_free(dma->pagelist,
+                        dma->page_count * sizeof(*dma->pagelist),
+                        DRM_MEM_PAGES);
+       }
+       dma->pagelist = temp_pagelist;
+
+       dma->buf_count += entry->buf_count;
+       dma->seg_count += entry->seg_count;
+       dma->page_count += entry->seg_count << page_order;
+       dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
+
+       mutex_unlock(&dev->struct_mutex);
+
+       request->count = entry->buf_count;
+       request->size = size;
+
+       if (request->flags & _DRM_PCI_BUFFER_RO)
+               dma->flags = _DRM_DMA_USE_PCI_RO;
+
+       atomic_dec(&dev->buf_alloc);
+       return 0;
+
+}
+EXPORT_SYMBOL(drm_addbufs_pci);
+
+static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request)
+{
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf_entry *entry;
+       struct drm_buf *buf;
+       unsigned long offset;
+       unsigned long agp_offset;
+       int count;
+       int order;
+       int size;
+       int alignment;
+       int page_order;
+       int total;
+       int byte_count;
+       int i;
+       struct drm_buf **temp_buflist;
+
+       if (!drm_core_check_feature(dev, DRIVER_SG))
+               return -EINVAL;
+
+       if (!dma)
+               return -EINVAL;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       count = request->count;
+       order = drm_order(request->size);
+       size = 1 << order;
+
+       alignment = (request->flags & _DRM_PAGE_ALIGN)
+           ? PAGE_ALIGN(size) : size;
+       page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+       total = PAGE_SIZE << page_order;
+
+       byte_count = 0;
+       agp_offset = request->agp_start;
+
+       DRM_DEBUG("count:      %d\n", count);
+       DRM_DEBUG("order:      %d\n", order);
+       DRM_DEBUG("size:       %d\n", size);
+       DRM_DEBUG("agp_offset: %lu\n", agp_offset);
+       DRM_DEBUG("alignment:  %d\n", alignment);
+       DRM_DEBUG("page_order: %d\n", page_order);
+       DRM_DEBUG("total:      %d\n", total);
+
+       if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+               return -EINVAL;
+       if (dev->queue_count)
+               return -EBUSY;  /* Not while in use */
+
+       spin_lock(&dev->count_lock);
+       if (dev->buf_use) {
+               spin_unlock(&dev->count_lock);
+               return -EBUSY;
+       }
+       atomic_inc(&dev->buf_alloc);
+       spin_unlock(&dev->count_lock);
+
+       mutex_lock(&dev->struct_mutex);
+       entry = &dma->bufs[order];
+       if (entry->buf_count) {
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM; /* May only call once for each order */
+       }
+
+       if (count < 0 || count > 4096) {
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -EINVAL;
+       }
+
+       entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+                                  DRM_MEM_BUFS);
+       if (!entry->buflist) {
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+       entry->buf_size = size;
+       entry->page_order = page_order;
+
+       offset = 0;
+
+       while (entry->buf_count < count) {
+               buf = &entry->buflist[entry->buf_count];
+               buf->idx = dma->buf_count + entry->buf_count;
+               buf->total = alignment;
+               buf->order = order;
+               buf->used = 0;
+
+               buf->offset = (dma->byte_count + offset);
+               buf->bus_address = agp_offset + offset;
+               buf->address = (void *)(agp_offset + offset
+                                       + (unsigned long)dev->sg->virtual);
+               buf->next = NULL;
+               buf->waiting = 0;
+               buf->pending = 0;
+               init_waitqueue_head(&buf->dma_wait);
+               buf->file_priv = NULL;
+
+               buf->dev_priv_size = dev->driver->dev_priv_size;
+               buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+               if (!buf->dev_private) {
+                       /* Set count correctly so we free the proper amount. */
+                       entry->buf_count = count;
+                       drm_cleanup_buf_error(dev, entry);
+                       mutex_unlock(&dev->struct_mutex);
+                       atomic_dec(&dev->buf_alloc);
+                       return -ENOMEM;
+               }
+
+               memset(buf->dev_private, 0, buf->dev_priv_size);
+
+               DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
+
+               offset += alignment;
+               entry->buf_count++;
+               byte_count += PAGE_SIZE << page_order;
+       }
+
+       DRM_DEBUG("byte_count: %d\n", byte_count);
+
+       temp_buflist = drm_realloc(dma->buflist,
+                                  dma->buf_count * sizeof(*dma->buflist),
+                                  (dma->buf_count + entry->buf_count)
+                                  * sizeof(*dma->buflist), DRM_MEM_BUFS);
+       if (!temp_buflist) {
+               /* Free the entry because it isn't valid */
+               drm_cleanup_buf_error(dev, entry);
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       dma->buflist = temp_buflist;
+
+       for (i = 0; i < entry->buf_count; i++) {
+               dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+       }
+
+       dma->buf_count += entry->buf_count;
+       dma->seg_count += entry->seg_count;
+       dma->page_count += byte_count >> PAGE_SHIFT;
+       dma->byte_count += byte_count;
+
+       DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
+       DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
+
+       mutex_unlock(&dev->struct_mutex);
+
+       request->count = entry->buf_count;
+       request->size = size;
+
+       dma->flags = _DRM_DMA_USE_SG;
+
+       atomic_dec(&dev->buf_alloc);
+       return 0;
+}
+
+static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request)
+{
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf_entry *entry;
+       struct drm_buf *buf;
+       unsigned long offset;
+       unsigned long agp_offset;
+       int count;
+       int order;
+       int size;
+       int alignment;
+       int page_order;
+       int total;
+       int byte_count;
+       int i;
+       struct drm_buf **temp_buflist;
+
+       if (!drm_core_check_feature(dev, DRIVER_FB_DMA))
+               return -EINVAL;
+
+       if (!dma)
+               return -EINVAL;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       count = request->count;
+       order = drm_order(request->size);
+       size = 1 << order;
+
+       alignment = (request->flags & _DRM_PAGE_ALIGN)
+           ? PAGE_ALIGN(size) : size;
+       page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0;
+       total = PAGE_SIZE << page_order;
+
+       byte_count = 0;
+       agp_offset = request->agp_start;
+
+       DRM_DEBUG("count:      %d\n", count);
+       DRM_DEBUG("order:      %d\n", order);
+       DRM_DEBUG("size:       %d\n", size);
+       DRM_DEBUG("agp_offset: %lu\n", agp_offset);
+       DRM_DEBUG("alignment:  %d\n", alignment);
+       DRM_DEBUG("page_order: %d\n", page_order);
+       DRM_DEBUG("total:      %d\n", total);
+
+       if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+               return -EINVAL;
+       if (dev->queue_count)
+               return -EBUSY;  /* Not while in use */
+
+       spin_lock(&dev->count_lock);
+       if (dev->buf_use) {
+               spin_unlock(&dev->count_lock);
+               return -EBUSY;
+       }
+       atomic_inc(&dev->buf_alloc);
+       spin_unlock(&dev->count_lock);
+
+       mutex_lock(&dev->struct_mutex);
+       entry = &dma->bufs[order];
+       if (entry->buf_count) {
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM; /* May only call once for each order */
+       }
+
+       if (count < 0 || count > 4096) {
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -EINVAL;
+       }
+
+       entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
+                                  DRM_MEM_BUFS);
+       if (!entry->buflist) {
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       memset(entry->buflist, 0, count * sizeof(*entry->buflist));
+
+       entry->buf_size = size;
+       entry->page_order = page_order;
+
+       offset = 0;
+
+       while (entry->buf_count < count) {
+               buf = &entry->buflist[entry->buf_count];
+               buf->idx = dma->buf_count + entry->buf_count;
+               buf->total = alignment;
+               buf->order = order;
+               buf->used = 0;
+
+               buf->offset = (dma->byte_count + offset);
+               buf->bus_address = agp_offset + offset;
+               buf->address = (void *)(agp_offset + offset);
+               buf->next = NULL;
+               buf->waiting = 0;
+               buf->pending = 0;
+               init_waitqueue_head(&buf->dma_wait);
+               buf->file_priv = NULL;
+
+               buf->dev_priv_size = dev->driver->dev_priv_size;
+               buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS);
+               if (!buf->dev_private) {
+                       /* Set count correctly so we free the proper amount. */
+                       entry->buf_count = count;
+                       drm_cleanup_buf_error(dev, entry);
+                       mutex_unlock(&dev->struct_mutex);
+                       atomic_dec(&dev->buf_alloc);
+                       return -ENOMEM;
+               }
+               memset(buf->dev_private, 0, buf->dev_priv_size);
+
+               DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address);
+
+               offset += alignment;
+               entry->buf_count++;
+               byte_count += PAGE_SIZE << page_order;
+       }
+
+       DRM_DEBUG("byte_count: %d\n", byte_count);
+
+       temp_buflist = drm_realloc(dma->buflist,
+                                  dma->buf_count * sizeof(*dma->buflist),
+                                  (dma->buf_count + entry->buf_count)
+                                  * sizeof(*dma->buflist), DRM_MEM_BUFS);
+       if (!temp_buflist) {
+               /* Free the entry because it isn't valid */
+               drm_cleanup_buf_error(dev, entry);
+               mutex_unlock(&dev->struct_mutex);
+               atomic_dec(&dev->buf_alloc);
+               return -ENOMEM;
+       }
+       dma->buflist = temp_buflist;
+
+       for (i = 0; i < entry->buf_count; i++) {
+               dma->buflist[i + dma->buf_count] = &entry->buflist[i];
+       }
+
+       dma->buf_count += entry->buf_count;
+       dma->seg_count += entry->seg_count;
+       dma->page_count += byte_count >> PAGE_SHIFT;
+       dma->byte_count += byte_count;
+
+       DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
+       DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count);
+
+       mutex_unlock(&dev->struct_mutex);
+
+       request->count = entry->buf_count;
+       request->size = size;
+
+       dma->flags = _DRM_DMA_USE_FB;
+
+       atomic_dec(&dev->buf_alloc);
+       return 0;
+}
+
+
+/**
+ * Add buffers for DMA transfers (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a struct drm_buf_desc request.
+ * \return zero on success or a negative number on failure.
+ *
+ * According with the memory type specified in drm_buf_desc::flags and the
+ * build options, it dispatches the call either to addbufs_agp(),
+ * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
+ * PCI memory respectively.
+ */
+int drm_addbufs(struct drm_device *dev, void *data,
+               struct drm_file *file_priv)
+{
+       struct drm_buf_desc *request = data;
+       int ret;
+
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+               return -EINVAL;
+
+#if __OS_HAS_AGP
+       if (request->flags & _DRM_AGP_BUFFER)
+               ret = drm_addbufs_agp(dev, request);
+       else
+#endif
+       if (request->flags & _DRM_SG_BUFFER)
+               ret = drm_addbufs_sg(dev, request);
+       else if (request->flags & _DRM_FB_BUFFER)
+               ret = drm_addbufs_fb(dev, request);
+       else
+               ret = drm_addbufs_pci(dev, request);
+
+       return ret;
+}
+
+/**
+ * Get information about the buffer mappings.
+ *
+ * This was originally mean for debugging purposes, or by a sophisticated
+ * client library to determine how best to use the available buffers (e.g.,
+ * large buffers can be used for image transfer).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_info structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Increments drm_device::buf_use while holding the drm_device::count_lock
+ * lock, preventing of allocating more buffers after this call. Information
+ * about each requested buffer is then copied into user space.
+ */
+int drm_infobufs(struct drm_device *dev, void *data,
+                struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf_info *request = data;
+       int i;
+       int count;
+
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+               return -EINVAL;
+
+       if (!dma)
+               return -EINVAL;
+
+       spin_lock(&dev->count_lock);
+       if (atomic_read(&dev->buf_alloc)) {
+               spin_unlock(&dev->count_lock);
+               return -EBUSY;
+       }
+       ++dev->buf_use;         /* Can't allocate more after this call */
+       spin_unlock(&dev->count_lock);
+
+       for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
+               if (dma->bufs[i].buf_count)
+                       ++count;
+       }
+
+       DRM_DEBUG("count = %d\n", count);
+
+       if (request->count >= count) {
+               for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
+                       if (dma->bufs[i].buf_count) {
+                               struct drm_buf_desc __user *to =
+                                   &request->list[count];
+                               struct drm_buf_entry *from = &dma->bufs[i];
+                               struct drm_freelist *list = &dma->bufs[i].freelist;
+                               if (copy_to_user(&to->count,
+                                                &from->buf_count,
+                                                sizeof(from->buf_count)) ||
+                                   copy_to_user(&to->size,
+                                                &from->buf_size,
+                                                sizeof(from->buf_size)) ||
+                                   copy_to_user(&to->low_mark,
+                                                &list->low_mark,
+                                                sizeof(list->low_mark)) ||
+                                   copy_to_user(&to->high_mark,
+                                                &list->high_mark,
+                                                sizeof(list->high_mark)))
+                                       return -EFAULT;
+
+                               DRM_DEBUG("%d %d %d %d %d\n",
+                                         i,
+                                         dma->bufs[i].buf_count,
+                                         dma->bufs[i].buf_size,
+                                         dma->bufs[i].freelist.low_mark,
+                                         dma->bufs[i].freelist.high_mark);
+                               ++count;
+                       }
+               }
+       }
+       request->count = count;
+
+       return 0;
+}
+
+/**
+ * Specifies a low and high water mark for buffer allocation
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg a pointer to a drm_buf_desc structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies that the size order is bounded between the admissible orders and
+ * updates the respective drm_device_dma::bufs entry low and high water mark.
+ *
+ * \note This ioctl is deprecated and mostly never used.
+ */
+int drm_markbufs(struct drm_device *dev, void *data,
+                struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf_desc *request = data;
+       int order;
+       struct drm_buf_entry *entry;
+
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+               return -EINVAL;
+
+       if (!dma)
+               return -EINVAL;
+
+       DRM_DEBUG("%d, %d, %d\n",
+                 request->size, request->low_mark, request->high_mark);
+       order = drm_order(request->size);
+       if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER)
+               return -EINVAL;
+       entry = &dma->bufs[order];
+
+       if (request->low_mark < 0 || request->low_mark > entry->buf_count)
+               return -EINVAL;
+       if (request->high_mark < 0 || request->high_mark > entry->buf_count)
+               return -EINVAL;
+
+       entry->freelist.low_mark = request->low_mark;
+       entry->freelist.high_mark = request->high_mark;
+
+       return 0;
+}
+
+/**
+ * Unreserve the buffers in list, previously reserved using drmDMA.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_free structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls free_buffer() for each used buffer.
+ * This function is primarily used for debugging.
+ */
+int drm_freebufs(struct drm_device *dev, void *data,
+                struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf_free *request = data;
+       int i;
+       int idx;
+       struct drm_buf *buf;
+
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+               return -EINVAL;
+
+       if (!dma)
+               return -EINVAL;
+
+       DRM_DEBUG("%d\n", request->count);
+       for (i = 0; i < request->count; i++) {
+               if (copy_from_user(&idx, &request->list[i], sizeof(idx)))
+                       return -EFAULT;
+               if (idx < 0 || idx >= dma->buf_count) {
+                       DRM_ERROR("Index %d (of %d max)\n",
+                                 idx, dma->buf_count - 1);
+                       return -EINVAL;
+               }
+               buf = dma->buflist[idx];
+               if (buf->file_priv != file_priv) {
+                       DRM_ERROR("Process %d freeing buffer not owned\n",
+                                 task_pid_nr(current));
+                       return -EINVAL;
+               }
+               drm_free_buffer(dev, buf);
+       }
+
+       return 0;
+}
+
+/**
+ * Maps all of the DMA buffers into client-virtual space (ioctl).
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information
+ * about each buffer into user space. For PCI buffers, it calls do_mmap() with
+ * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
+ * drm_mmap_dma().
+ */
+int drm_mapbufs(struct drm_device *dev, void *data,
+               struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int retcode = 0;
+       const int zero = 0;
+       unsigned long virtual;
+       unsigned long address;
+       struct drm_buf_map *request = data;
+       int i;
+
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+               return -EINVAL;
+
+       if (!dma)
+               return -EINVAL;
+
+       spin_lock(&dev->count_lock);
+       if (atomic_read(&dev->buf_alloc)) {
+               spin_unlock(&dev->count_lock);
+               return -EBUSY;
+       }
+       dev->buf_use++;         /* Can't allocate more after this call */
+       spin_unlock(&dev->count_lock);
+
+       if (request->count >= dma->buf_count) {
+               if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP))
+                   || (drm_core_check_feature(dev, DRIVER_SG)
+                       && (dma->flags & _DRM_DMA_USE_SG))
+                   || (drm_core_check_feature(dev, DRIVER_FB_DMA)
+                       && (dma->flags & _DRM_DMA_USE_FB))) {
+                       struct drm_map *map = dev->agp_buffer_map;
+                       unsigned long token = dev->agp_buffer_token;
+
+                       if (!map) {
+                               retcode = -EINVAL;
+                               goto done;
+                       }
+                       down_write(&current->mm->mmap_sem);
+                       virtual = do_mmap(file_priv->filp, 0, map->size,
+                                         PROT_READ | PROT_WRITE,
+                                         MAP_SHARED,
+                                         token);
+                       up_write(&current->mm->mmap_sem);
+               } else {
+                       down_write(&current->mm->mmap_sem);
+                       virtual = do_mmap(file_priv->filp, 0, dma->byte_count,
+                                         PROT_READ | PROT_WRITE,
+                                         MAP_SHARED, 0);
+                       up_write(&current->mm->mmap_sem);
+               }
+               if (virtual > -1024UL) {
+                       /* Real error */
+                       retcode = (signed long)virtual;
+                       goto done;
+               }
+               request->virtual = (void __user *)virtual;
+
+               for (i = 0; i < dma->buf_count; i++) {
+                       if (copy_to_user(&request->list[i].idx,
+                                        &dma->buflist[i]->idx,
+                                        sizeof(request->list[0].idx))) {
+                               retcode = -EFAULT;
+                               goto done;
+                       }
+                       if (copy_to_user(&request->list[i].total,
+                                        &dma->buflist[i]->total,
+                                        sizeof(request->list[0].total))) {
+                               retcode = -EFAULT;
+                               goto done;
+                       }
+                       if (copy_to_user(&request->list[i].used,
+                                        &zero, sizeof(zero))) {
+                               retcode = -EFAULT;
+                               goto done;
+                       }
+                       address = virtual + dma->buflist[i]->offset;    /* *** */
+                       if (copy_to_user(&request->list[i].address,
+                                        &address, sizeof(address))) {
+                               retcode = -EFAULT;
+                               goto done;
+                       }
+               }
+       }
+      done:
+       request->count = dma->buf_count;
+       DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode);
+
+       return retcode;
+}
+
+/**
+ * Compute size order.  Returns the exponent of the smaller power of two which
+ * is greater or equal to given number.
+ *
+ * \param size size.
+ * \return order.
+ *
+ * \todo Can be made faster.
+ */
+int drm_order(unsigned long size)
+{
+       int order;
+       unsigned long tmp;
+
+       for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
+
+       if (size & (size - 1))
+               ++order;
+
+       return order;
+}
+EXPORT_SYMBOL(drm_order);
diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c
new file mode 100644 (file)
index 0000000..d505f69
--- /dev/null
@@ -0,0 +1,471 @@
+/**
+ * \file drm_context.c
+ * IOCTLs for generic contexts
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * ChangeLog:
+ *  2001-11-16 Torsten Duwe <duwe@caldera.de>
+ *             added context constructor/destructor hooks,
+ *             needed by SiS driver's memory management.
+ */
+
+#include "drmP.h"
+
+/******************************************************************/
+/** \name Context bitmap support */
+/*@{*/
+
+/**
+ * Free a handle from the context bitmap.
+ *
+ * \param dev DRM device.
+ * \param ctx_handle context handle.
+ *
+ * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
+ * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
+ * lock.
+ */
+void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
+{
+       mutex_lock(&dev->struct_mutex);
+       idr_remove(&dev->ctx_idr, ctx_handle);
+       mutex_unlock(&dev->struct_mutex);
+}
+
+/**
+ * Context bitmap allocation.
+ *
+ * \param dev DRM device.
+ * \return (non-negative) context handle on success or a negative number on failure.
+ *
+ * Allocate a new idr from drm_device::ctx_idr while holding the
+ * drm_device::struct_mutex lock.
+ */
+static int drm_ctxbitmap_next(struct drm_device * dev)
+{
+       int new_id;
+       int ret;
+
+again:
+       if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
+               DRM_ERROR("Out of memory expanding drawable idr\n");
+               return -ENOMEM;
+       }
+       mutex_lock(&dev->struct_mutex);
+       ret = idr_get_new_above(&dev->ctx_idr, NULL,
+                               DRM_RESERVED_CONTEXTS, &new_id);
+       if (ret == -EAGAIN) {
+               mutex_unlock(&dev->struct_mutex);
+               goto again;
+       }
+       mutex_unlock(&dev->struct_mutex);
+       return new_id;
+}
+
+/**
+ * Context bitmap initialization.
+ *
+ * \param dev DRM device.
+ *
+ * Initialise the drm_device::ctx_idr
+ */
+int drm_ctxbitmap_init(struct drm_device * dev)
+{
+       idr_init(&dev->ctx_idr);
+       return 0;
+}
+
+/**
+ * Context bitmap cleanup.
+ *
+ * \param dev DRM device.
+ *
+ * Free all idr members using drm_ctx_sarea_free helper function
+ * while holding the drm_device::struct_mutex lock.
+ */
+void drm_ctxbitmap_cleanup(struct drm_device * dev)
+{
+       mutex_lock(&dev->struct_mutex);
+       idr_remove_all(&dev->ctx_idr);
+       mutex_unlock(&dev->struct_mutex);
+}
+
+/*@}*/
+
+/******************************************************************/
+/** \name Per Context SAREA Support */
+/*@{*/
+
+/**
+ * Get per-context SAREA.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_priv_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Gets the map from drm_device::ctx_idr with the handle specified and
+ * returns its handle.
+ */
+int drm_getsareactx(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
+{
+       struct drm_ctx_priv_map *request = data;
+       struct drm_map *map;
+       struct drm_map_list *_entry;
+
+       mutex_lock(&dev->struct_mutex);
+
+       map = idr_find(&dev->ctx_idr, request->ctx_id);
+       if (!map) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
+       }
+
+       mutex_unlock(&dev->struct_mutex);
+
+       request->handle = NULL;
+       list_for_each_entry(_entry, &dev->maplist, head) {
+               if (_entry->map == map) {
+                       request->handle =
+                           (void *)(unsigned long)_entry->user_token;
+                       break;
+               }
+       }
+       if (request->handle == NULL)
+               return -EINVAL;
+
+       return 0;
+}
+
+/**
+ * Set per-context SAREA.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_priv_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches the mapping specified in \p arg and update the entry in
+ * drm_device::ctx_idr with it.
+ */
+int drm_setsareactx(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
+{
+       struct drm_ctx_priv_map *request = data;
+       struct drm_map *map = NULL;
+       struct drm_map_list *r_list = NULL;
+
+       mutex_lock(&dev->struct_mutex);
+       list_for_each_entry(r_list, &dev->maplist, head) {
+               if (r_list->map
+                   && r_list->user_token == (unsigned long) request->handle)
+                       goto found;
+       }
+      bad:
+       mutex_unlock(&dev->struct_mutex);
+       return -EINVAL;
+
+      found:
+       map = r_list->map;
+       if (!map)
+               goto bad;
+
+       if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id)))
+               goto bad;
+
+       mutex_unlock(&dev->struct_mutex);
+
+       return 0;
+}
+
+/*@}*/
+
+/******************************************************************/
+/** \name The actual DRM context handling routines */
+/*@{*/
+
+/**
+ * Switch context.
+ *
+ * \param dev DRM device.
+ * \param old old context handle.
+ * \param new new context handle.
+ * \return zero on success or a negative number on failure.
+ *
+ * Attempt to set drm_device::context_flag.
+ */
+static int drm_context_switch(struct drm_device * dev, int old, int new)
+{
+       if (test_and_set_bit(0, &dev->context_flag)) {
+               DRM_ERROR("Reentering -- FIXME\n");
+               return -EBUSY;
+       }
+
+       DRM_DEBUG("Context switch from %d to %d\n", old, new);
+
+       if (new == dev->last_context) {
+               clear_bit(0, &dev->context_flag);
+               return 0;
+       }
+
+       return 0;
+}
+
+/**
+ * Complete context switch.
+ *
+ * \param dev DRM device.
+ * \param new new context handle.
+ * \return zero on success or a negative number on failure.
+ *
+ * Updates drm_device::last_context and drm_device::last_switch. Verifies the
+ * hardware lock is held, clears the drm_device::context_flag and wakes up
+ * drm_device::context_wait.
+ */
+static int drm_context_switch_complete(struct drm_device * dev, int new)
+{
+       dev->last_context = new;        /* PRE/POST: This is the _only_ writer. */
+       dev->last_switch = jiffies;
+
+       if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+               DRM_ERROR("Lock isn't held after context switch\n");
+       }
+
+       /* If a context switch is ever initiated
+          when the kernel holds the lock, release
+          that lock here. */
+       clear_bit(0, &dev->context_flag);
+       wake_up(&dev->context_wait);
+
+       return 0;
+}
+
+/**
+ * Reserve contexts.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_res structure.
+ * \return zero on success or a negative number on failure.
+ */
+int drm_resctx(struct drm_device *dev, void *data,
+              struct drm_file *file_priv)
+{
+       struct drm_ctx_res *res = data;
+       struct drm_ctx ctx;
+       int i;
+
+       if (res->count >= DRM_RESERVED_CONTEXTS) {
+               memset(&ctx, 0, sizeof(ctx));
+               for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
+                       ctx.handle = i;
+                       if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx)))
+                               return -EFAULT;
+               }
+       }
+       res->count = DRM_RESERVED_CONTEXTS;
+
+       return 0;
+}
+
+/**
+ * Add context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Get a new handle for the context and copy to userspace.
+ */
+int drm_addctx(struct drm_device *dev, void *data,
+              struct drm_file *file_priv)
+{
+       struct drm_ctx_list *ctx_entry;
+       struct drm_ctx *ctx = data;
+
+       ctx->handle = drm_ctxbitmap_next(dev);
+       if (ctx->handle == DRM_KERNEL_CONTEXT) {
+               /* Skip kernel's context and get a new one. */
+               ctx->handle = drm_ctxbitmap_next(dev);
+       }
+       DRM_DEBUG("%d\n", ctx->handle);
+       if (ctx->handle == -1) {
+               DRM_DEBUG("Not enough free contexts.\n");
+               /* Should this return -EBUSY instead? */
+               return -ENOMEM;
+       }
+
+       if (ctx->handle != DRM_KERNEL_CONTEXT) {
+               if (dev->driver->context_ctor)
+                       if (!dev->driver->context_ctor(dev, ctx->handle)) {
+                               DRM_DEBUG("Running out of ctxs or memory.\n");
+                               return -ENOMEM;
+                       }
+       }
+
+       ctx_entry = drm_alloc(sizeof(*ctx_entry), DRM_MEM_CTXLIST);
+       if (!ctx_entry) {
+               DRM_DEBUG("out of memory\n");
+               return -ENOMEM;
+       }
+
+       INIT_LIST_HEAD(&ctx_entry->head);
+       ctx_entry->handle = ctx->handle;
+       ctx_entry->tag = file_priv;
+
+       mutex_lock(&dev->ctxlist_mutex);
+       list_add(&ctx_entry->head, &dev->ctxlist);
+       ++dev->ctx_count;
+       mutex_unlock(&dev->ctxlist_mutex);
+
+       return 0;
+}
+
+int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       /* This does nothing */
+       return 0;
+}
+
+/**
+ * Get context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ */
+int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_ctx *ctx = data;
+
+       /* This is 0, because we don't handle any context flags */
+       ctx->flags = 0;
+
+       return 0;
+}
+
+/**
+ * Switch context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls context_switch().
+ */
+int drm_switchctx(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
+{
+       struct drm_ctx *ctx = data;
+
+       DRM_DEBUG("%d\n", ctx->handle);
+       return drm_context_switch(dev, dev->last_context, ctx->handle);
+}
+
+/**
+ * New context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls context_switch_complete().
+ */
+int drm_newctx(struct drm_device *dev, void *data,
+              struct drm_file *file_priv)
+{
+       struct drm_ctx *ctx = data;
+
+       DRM_DEBUG("%d\n", ctx->handle);
+       drm_context_switch_complete(dev, ctx->handle);
+
+       return 0;
+}
+
+/**
+ * Remove context.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * If not the special kernel context, calls ctxbitmap_free() to free the specified context.
+ */
+int drm_rmctx(struct drm_device *dev, void *data,
+             struct drm_file *file_priv)
+{
+       struct drm_ctx *ctx = data;
+
+       DRM_DEBUG("%d\n", ctx->handle);
+       if (ctx->handle == DRM_KERNEL_CONTEXT + 1) {
+               file_priv->remove_auth_on_close = 1;
+       }
+       if (ctx->handle != DRM_KERNEL_CONTEXT) {
+               if (dev->driver->context_dtor)
+                       dev->driver->context_dtor(dev, ctx->handle);
+               drm_ctxbitmap_free(dev, ctx->handle);
+       }
+
+       mutex_lock(&dev->ctxlist_mutex);
+       if (!list_empty(&dev->ctxlist)) {
+               struct drm_ctx_list *pos, *n;
+
+               list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
+                       if (pos->handle == ctx->handle) {
+                               list_del(&pos->head);
+                               drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
+                               --dev->ctx_count;
+                       }
+               }
+       }
+       mutex_unlock(&dev->ctxlist_mutex);
+
+       return 0;
+}
+
+/*@}*/
diff --git a/drivers/gpu/drm/drm_dma.c b/drivers/gpu/drm/drm_dma.c
new file mode 100644 (file)
index 0000000..7a8e2fb
--- /dev/null
@@ -0,0 +1,180 @@
+/**
+ * \file drm_dma.c
+ * DMA IOCTL and function support
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+
+/**
+ * Initialize the DMA data.
+ *
+ * \param dev DRM device.
+ * \return zero on success or a negative value on failure.
+ *
+ * Allocate and initialize a drm_device_dma structure.
+ */
+int drm_dma_setup(struct drm_device *dev)
+{
+       int i;
+
+       dev->dma = drm_alloc(sizeof(*dev->dma), DRM_MEM_DRIVER);
+       if (!dev->dma)
+               return -ENOMEM;
+
+       memset(dev->dma, 0, sizeof(*dev->dma));
+
+       for (i = 0; i <= DRM_MAX_ORDER; i++)
+               memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
+
+       return 0;
+}
+
+/**
+ * Cleanup the DMA resources.
+ *
+ * \param dev DRM device.
+ *
+ * Free all pages associated with DMA buffers, the buffers and pages lists, and
+ * finally the drm_device::dma structure itself.
+ */
+void drm_dma_takedown(struct drm_device *dev)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int i, j;
+
+       if (!dma)
+               return;
+
+       /* Clear dma buffers */
+       for (i = 0; i <= DRM_MAX_ORDER; i++) {
+               if (dma->bufs[i].seg_count) {
+                       DRM_DEBUG("order %d: buf_count = %d,"
+                                 " seg_count = %d\n",
+                                 i,
+                                 dma->bufs[i].buf_count,
+                                 dma->bufs[i].seg_count);
+                       for (j = 0; j < dma->bufs[i].seg_count; j++) {
+                               if (dma->bufs[i].seglist[j]) {
+                                       drm_pci_free(dev, dma->bufs[i].seglist[j]);
+                               }
+                       }
+                       drm_free(dma->bufs[i].seglist,
+                                dma->bufs[i].seg_count
+                                * sizeof(*dma->bufs[0].seglist), DRM_MEM_SEGS);
+               }
+               if (dma->bufs[i].buf_count) {
+                       for (j = 0; j < dma->bufs[i].buf_count; j++) {
+                               if (dma->bufs[i].buflist[j].dev_private) {
+                                       drm_free(dma->bufs[i].buflist[j].
+                                                dev_private,
+                                                dma->bufs[i].buflist[j].
+                                                dev_priv_size, DRM_MEM_BUFS);
+                               }
+                       }
+                       drm_free(dma->bufs[i].buflist,
+                                dma->bufs[i].buf_count *
+                                sizeof(*dma->bufs[0].buflist), DRM_MEM_BUFS);
+               }
+       }
+
+       if (dma->buflist) {
+               drm_free(dma->buflist,
+                        dma->buf_count * sizeof(*dma->buflist), DRM_MEM_BUFS);
+       }
+
+       if (dma->pagelist) {
+               drm_free(dma->pagelist,
+                        dma->page_count * sizeof(*dma->pagelist),
+                        DRM_MEM_PAGES);
+       }
+       drm_free(dev->dma, sizeof(*dev->dma), DRM_MEM_DRIVER);
+       dev->dma = NULL;
+}
+
+/**
+ * Free a buffer.
+ *
+ * \param dev DRM device.
+ * \param buf buffer to free.
+ *
+ * Resets the fields of \p buf.
+ */
+void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf)
+{
+       if (!buf)
+               return;
+
+       buf->waiting = 0;
+       buf->pending = 0;
+       buf->file_priv = NULL;
+       buf->used = 0;
+
+       if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)
+           && waitqueue_active(&buf->dma_wait)) {
+               wake_up_interruptible(&buf->dma_wait);
+       }
+}
+
+/**
+ * Reclaim the buffers.
+ *
+ * \param file_priv DRM file private.
+ *
+ * Frees each buffer associated with \p file_priv not already on the hardware.
+ */
+void drm_core_reclaim_buffers(struct drm_device *dev,
+                             struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int i;
+
+       if (!dma)
+               return;
+       for (i = 0; i < dma->buf_count; i++) {
+               if (dma->buflist[i]->file_priv == file_priv) {
+                       switch (dma->buflist[i]->list) {
+                       case DRM_LIST_NONE:
+                               drm_free_buffer(dev, dma->buflist[i]);
+                               break;
+                       case DRM_LIST_WAIT:
+                               dma->buflist[i]->list = DRM_LIST_RECLAIM;
+                               break;
+                       default:
+                               /* Buffer already on hardware. */
+                               break;
+                       }
+               }
+       }
+}
+
+EXPORT_SYMBOL(drm_core_reclaim_buffers);
diff --git a/drivers/gpu/drm/drm_drawable.c b/drivers/gpu/drm/drm_drawable.c
new file mode 100644 (file)
index 0000000..1839c57
--- /dev/null
@@ -0,0 +1,192 @@
+/**
+ * \file drm_drawable.c
+ * IOCTLs for drawables
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ * \author Michel Dänzer <michel@tungstengraphics.com>
+ */
+
+/*
+ * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, North Dakota.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+
+/**
+ * Allocate drawable ID and memory to store information about it.
+ */
+int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       unsigned long irqflags;
+       struct drm_draw *draw = data;
+       int new_id = 0;
+       int ret;
+
+again:
+       if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) {
+               DRM_ERROR("Out of memory expanding drawable idr\n");
+               return -ENOMEM;
+       }
+
+       spin_lock_irqsave(&dev->drw_lock, irqflags);
+       ret = idr_get_new_above(&dev->drw_idr, NULL, 1, &new_id);
+       if (ret == -EAGAIN) {
+               spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+               goto again;
+       }
+
+       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+       draw->handle = new_id;
+
+       DRM_DEBUG("%d\n", draw->handle);
+
+       return 0;
+}
+
+/**
+ * Free drawable ID and memory to store information about it.
+ */
+int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_draw *draw = data;
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+       drm_free(drm_get_drawable_info(dev, draw->handle),
+                sizeof(struct drm_drawable_info), DRM_MEM_BUFS);
+
+       idr_remove(&dev->drw_idr, draw->handle);
+
+       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+       DRM_DEBUG("%d\n", draw->handle);
+       return 0;
+}
+
+int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_update_draw *update = data;
+       unsigned long irqflags;
+       struct drm_clip_rect *rects;
+       struct drm_drawable_info *info;
+       int err;
+
+       info = idr_find(&dev->drw_idr, update->handle);
+       if (!info) {
+               info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS);
+               if (!info)
+                       return -ENOMEM;
+               if (IS_ERR(idr_replace(&dev->drw_idr, info, update->handle))) {
+                       DRM_ERROR("No such drawable %d\n", update->handle);
+                       drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+                       return -EINVAL;
+               }
+       }
+
+       switch (update->type) {
+       case DRM_DRAWABLE_CLIPRECTS:
+               if (update->num != info->num_rects) {
+                       rects = drm_alloc(update->num * sizeof(struct drm_clip_rect),
+                                        DRM_MEM_BUFS);
+               } else
+                       rects = info->rects;
+
+               if (update->num && !rects) {
+                       DRM_ERROR("Failed to allocate cliprect memory\n");
+                       err = -ENOMEM;
+                       goto error;
+               }
+
+               if (update->num && DRM_COPY_FROM_USER(rects,
+                                                    (struct drm_clip_rect __user *)
+                                                    (unsigned long)update->data,
+                                                    update->num *
+                                                    sizeof(*rects))) {
+                       DRM_ERROR("Failed to copy cliprects from userspace\n");
+                       err = -EFAULT;
+                       goto error;
+               }
+
+               spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+               if (rects != info->rects) {
+                       drm_free(info->rects, info->num_rects *
+                                sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
+               }
+
+               info->rects = rects;
+               info->num_rects = update->num;
+
+               spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+               DRM_DEBUG("Updated %d cliprects for drawable %d\n",
+                         info->num_rects, update->handle);
+               break;
+       default:
+               DRM_ERROR("Invalid update type %d\n", update->type);
+               return -EINVAL;
+       }
+
+       return 0;
+
+error:
+       if (rects != info->rects)
+               drm_free(rects, update->num * sizeof(struct drm_clip_rect),
+                        DRM_MEM_BUFS);
+
+       return err;
+}
+
+/**
+ * Caller must hold the drawable spinlock!
+ */
+struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id)
+{
+       return idr_find(&dev->drw_idr, id);
+}
+EXPORT_SYMBOL(drm_get_drawable_info);
+
+static int drm_drawable_free(int idr, void *p, void *data)
+{
+       struct drm_drawable_info *info = p;
+
+       if (info) {
+               drm_free(info->rects, info->num_rects *
+                        sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
+               drm_free(info, sizeof(*info), DRM_MEM_BUFS);
+       }
+
+       return 0;
+}
+
+void drm_drawable_free_all(struct drm_device *dev)
+{
+       idr_for_each(&dev->drw_idr, drm_drawable_free, NULL);
+       idr_remove_all(&dev->drw_idr);
+}
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
new file mode 100644 (file)
index 0000000..5641387
--- /dev/null
@@ -0,0 +1,540 @@
+/**
+ * \file drm_drv.c
+ * Generic driver template
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ *
+ * To use this template, you must at least define the following (samples
+ * given for the MGA driver):
+ *
+ * \code
+ * #define DRIVER_AUTHOR       "VA Linux Systems, Inc."
+ *
+ * #define DRIVER_NAME         "mga"
+ * #define DRIVER_DESC         "Matrox G200/G400"
+ * #define DRIVER_DATE         "20001127"
+ *
+ * #define drm_x               mga_##x
+ * \endcode
+ */
+
+/*
+ * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_core.h"
+
+static int drm_version(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
+
+/** Ioctl table */
+static struct drm_ioctl_desc drm_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH),
+       /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
+       DRM_IOCTL_DEF(DRM_IOCTL_DMA, NULL, DRM_AUTH),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+#if __OS_HAS_AGP
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+#endif
+
+       DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
+
+       DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+};
+
+#define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
+
+/**
+ * Take down the DRM device.
+ *
+ * \param dev DRM device structure.
+ *
+ * Frees every resource in \p dev.
+ *
+ * \sa drm_device
+ */
+int drm_lastclose(struct drm_device * dev)
+{
+       struct drm_magic_entry *pt, *next;
+       struct drm_map_list *r_list, *list_t;
+       struct drm_vma_entry *vma, *vma_temp;
+       int i;
+
+       DRM_DEBUG("\n");
+
+       if (dev->driver->lastclose)
+               dev->driver->lastclose(dev);
+       DRM_DEBUG("driver lastclose completed\n");
+
+       if (dev->unique) {
+               drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
+               dev->unique = NULL;
+               dev->unique_len = 0;
+       }
+
+       if (dev->irq_enabled)
+               drm_irq_uninstall(dev);
+
+       mutex_lock(&dev->struct_mutex);
+
+       /* Free drawable information memory */
+       drm_drawable_free_all(dev);
+       del_timer(&dev->timer);
+
+       /* Clear pid list */
+       if (dev->magicfree.next) {
+               list_for_each_entry_safe(pt, next, &dev->magicfree, head) {
+                       list_del(&pt->head);
+                       drm_ht_remove_item(&dev->magiclist, &pt->hash_item);
+                       drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC);
+               }
+               drm_ht_remove(&dev->magiclist);
+       }
+
+       /* Clear AGP information */
+       if (drm_core_has_AGP(dev) && dev->agp) {
+               struct drm_agp_mem *entry, *tempe;
+
+               /* Remove AGP resources, but leave dev->agp
+                  intact until drv_cleanup is called. */
+               list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
+                       if (entry->bound)
+                               drm_unbind_agp(entry->memory);
+                       drm_free_agp(entry->memory, entry->pages);
+                       drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
+               }
+               INIT_LIST_HEAD(&dev->agp->memory);
+
+               if (dev->agp->acquired)
+                       drm_agp_release(dev);
+
+               dev->agp->acquired = 0;
+               dev->agp->enabled = 0;
+       }
+       if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
+               drm_sg_cleanup(dev->sg);
+               dev->sg = NULL;
+       }
+
+       /* Clear vma list (only built for debugging) */
+       list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
+               list_del(&vma->head);
+               drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);
+       }
+
+       list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {
+               if (!(r_list->map->flags & _DRM_DRIVER)) {
+                       drm_rmmap_locked(dev, r_list->map);
+                       r_list = NULL;
+               }
+       }
+
+       if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {
+               for (i = 0; i < dev->queue_count; i++) {
+                       if (dev->queuelist[i]) {
+                               drm_free(dev->queuelist[i],
+                                        sizeof(*dev->queuelist[0]),
+                                        DRM_MEM_QUEUES);
+                               dev->queuelist[i] = NULL;
+                       }
+               }
+               drm_free(dev->queuelist,
+                        dev->queue_slots * sizeof(*dev->queuelist),
+                        DRM_MEM_QUEUES);
+               dev->queuelist = NULL;
+       }
+       dev->queue_count = 0;
+
+       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+               drm_dma_takedown(dev);
+
+       if (dev->lock.hw_lock) {
+               dev->sigdata.lock = dev->lock.hw_lock = NULL;   /* SHM removed */
+               dev->lock.file_priv = NULL;
+               wake_up_interruptible(&dev->lock.lock_queue);
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       DRM_DEBUG("lastclose completed\n");
+       return 0;
+}
+
+/**
+ * Module initialization. Called via init_module at module load time, or via
+ * linux/init/main.c (this is not currently supported).
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Initializes an array of drm_device structures, and attempts to
+ * initialize all available devices, using consecutive minors, registering the
+ * stubs and initializing the AGP device.
+ *
+ * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
+ * after the initialization for driver customization.
+ */
+int drm_init(struct drm_driver *driver)
+{
+       struct pci_dev *pdev = NULL;
+       struct pci_device_id *pid;
+       int i;
+
+       DRM_DEBUG("\n");
+
+       for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
+               pid = (struct pci_device_id *)&driver->pci_driver.id_table[i];
+
+               pdev = NULL;
+               /* pass back in pdev to account for multiple identical cards */
+               while ((pdev =
+                       pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
+                                      pid->subdevice, pdev)) != NULL) {
+                       /* stealth mode requires a manual probe */
+                       pci_dev_get(pdev);
+                       drm_get_dev(pdev, pid, driver);
+               }
+       }
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_init);
+
+/**
+ * Called via cleanup_module() at module unload time.
+ *
+ * Cleans up all DRM device, calling drm_lastclose().
+ *
+ * \sa drm_init
+ */
+static void drm_cleanup(struct drm_device * dev)
+{
+       DRM_DEBUG("\n");
+
+       if (!dev) {
+               DRM_ERROR("cleanup called no dev\n");
+               return;
+       }
+
+       drm_lastclose(dev);
+
+       if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
+           dev->agp && dev->agp->agp_mtrr >= 0) {
+               int retval;
+               retval = mtrr_del(dev->agp->agp_mtrr,
+                                 dev->agp->agp_info.aper_base,
+                                 dev->agp->agp_info.aper_size * 1024 * 1024);
+               DRM_DEBUG("mtrr_del=%d\n", retval);
+       }
+
+       if (drm_core_has_AGP(dev) && dev->agp) {
+               drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
+               dev->agp = NULL;
+       }
+
+       if (dev->driver->unload)
+               dev->driver->unload(dev);
+
+       drm_ht_remove(&dev->map_hash);
+       drm_ctxbitmap_cleanup(dev);
+
+       drm_put_minor(&dev->primary);
+       if (drm_put_dev(dev))
+               DRM_ERROR("Cannot unload module\n");
+}
+
+int drm_minors_cleanup(int id, void *ptr, void *data)
+{
+       struct drm_minor *minor = ptr;
+       struct drm_device *dev;
+       struct drm_driver *driver = data;
+
+       dev = minor->dev;
+       if (minor->dev->driver != driver)
+               return 0;
+
+       if (minor->type != DRM_MINOR_LEGACY)
+               return 0;
+
+       if (dev)
+               pci_dev_put(dev->pdev);
+       drm_cleanup(dev);
+       return 1;
+}
+
+void drm_exit(struct drm_driver *driver)
+{
+       DRM_DEBUG("\n");
+
+       idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver);
+
+       DRM_INFO("Module unloaded\n");
+}
+
+EXPORT_SYMBOL(drm_exit);
+
+/** File operations structure */
+static const struct file_operations drm_stub_fops = {
+       .owner = THIS_MODULE,
+       .open = drm_stub_open
+};
+
+static int __init drm_core_init(void)
+{
+       int ret = -ENOMEM;
+
+       idr_init(&drm_minors_idr);
+
+       if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
+               goto err_p1;
+
+       drm_class = drm_sysfs_create(THIS_MODULE, "drm");
+       if (IS_ERR(drm_class)) {
+               printk(KERN_ERR "DRM: Error creating drm class.\n");
+               ret = PTR_ERR(drm_class);
+               goto err_p2;
+       }
+
+       drm_proc_root = proc_mkdir("dri", NULL);
+       if (!drm_proc_root) {
+               DRM_ERROR("Cannot create /proc/dri\n");
+               ret = -1;
+               goto err_p3;
+       }
+
+       drm_mem_init();
+
+       DRM_INFO("Initialized %s %d.%d.%d %s\n",
+                CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
+       return 0;
+err_p3:
+       drm_sysfs_destroy();
+err_p2:
+       unregister_chrdev(DRM_MAJOR, "drm");
+
+       idr_destroy(&drm_minors_idr);
+err_p1:
+       return ret;
+}
+
+static void __exit drm_core_exit(void)
+{
+       remove_proc_entry("dri", NULL);
+       drm_sysfs_destroy();
+
+       unregister_chrdev(DRM_MAJOR, "drm");
+
+       idr_destroy(&drm_minors_idr);
+}
+
+module_init(drm_core_init);
+module_exit(drm_core_exit);
+
+/**
+ * Get version information
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_version structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Fills in the version information in \p arg.
+ */
+static int drm_version(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       struct drm_version *version = data;
+       int len;
+
+       version->version_major = dev->driver->major;
+       version->version_minor = dev->driver->minor;
+       version->version_patchlevel = dev->driver->patchlevel;
+       DRM_COPY(version->name, dev->driver->name);
+       DRM_COPY(version->date, dev->driver->date);
+       DRM_COPY(version->desc, dev->driver->desc);
+
+       return 0;
+}
+
+/**
+ * Called whenever a process performs an ioctl on /dev/drm.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ *
+ * Looks up the ioctl function in the ::ioctls table, checking for root
+ * previleges if so required, and dispatches to the respective function.
+ */
+int drm_ioctl(struct inode *inode, struct file *filp,
+             unsigned int cmd, unsigned long arg)
+{
+       struct drm_file *file_priv = filp->private_data;
+       struct drm_device *dev = file_priv->minor->dev;
+       struct drm_ioctl_desc *ioctl;
+       drm_ioctl_t *func;
+       unsigned int nr = DRM_IOCTL_NR(cmd);
+       int retcode = -EINVAL;
+       char *kdata = NULL;
+
+       atomic_inc(&dev->ioctl_count);
+       atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
+       ++file_priv->ioctl_count;
+
+       DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
+                 task_pid_nr(current), cmd, nr,
+                 (long)old_encode_dev(file_priv->minor->device),
+                 file_priv->authenticated);
+
+       if ((nr >= DRM_CORE_IOCTL_COUNT) &&
+           ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
+               goto err_i1;
+       if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
+           (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
+               ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+       else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
+               ioctl = &drm_ioctls[nr];
+               cmd = ioctl->cmd;
+       } else
+               goto err_i1;
+
+       /* Do not trust userspace, use our own definition */
+       func = ioctl->func;
+       /* is there a local override? */
+       if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl)
+               func = dev->driver->dma_ioctl;
+
+       if (!func) {
+               DRM_DEBUG("no function\n");
+               retcode = -EINVAL;
+       } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
+                  ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
+                  ((ioctl->flags & DRM_MASTER) && !file_priv->master)) {
+               retcode = -EACCES;
+       } else {
+               if (cmd & (IOC_IN | IOC_OUT)) {
+                       kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
+                       if (!kdata) {
+                               retcode = -ENOMEM;
+                               goto err_i1;
+                       }
+               }
+
+               if (cmd & IOC_IN) {
+                       if (copy_from_user(kdata, (void __user *)arg,
+                                          _IOC_SIZE(cmd)) != 0) {
+                               retcode = -EFAULT;
+                               goto err_i1;
+                       }
+               }
+               retcode = func(dev, kdata, file_priv);
+
+               if ((retcode == 0) && (cmd & IOC_OUT)) {
+                       if (copy_to_user((void __user *)arg, kdata,
+                                        _IOC_SIZE(cmd)) != 0)
+                               retcode = -EFAULT;
+               }
+       }
+
+      err_i1:
+       if (kdata)
+               kfree(kdata);
+       atomic_dec(&dev->ioctl_count);
+       if (retcode)
+               DRM_DEBUG("ret = %x\n", retcode);
+       return retcode;
+}
+
+EXPORT_SYMBOL(drm_ioctl);
+
+drm_local_map_t *drm_getsarea(struct drm_device *dev)
+{
+       struct drm_map_list *entry;
+
+       list_for_each_entry(entry, &dev->maplist, head) {
+               if (entry->map && entry->map->type == _DRM_SHM &&
+                   (entry->map->flags & _DRM_CONTAINS_LOCK)) {
+                       return entry->map;
+               }
+       }
+       return NULL;
+}
+EXPORT_SYMBOL(drm_getsarea);
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
new file mode 100644 (file)
index 0000000..d2e6da8
--- /dev/null
@@ -0,0 +1,466 @@
+/**
+ * \file drm_fops.c
+ * File operations for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Daryll Strauss <daryll@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_sarea.h"
+#include <linux/poll.h>
+
+static int drm_open_helper(struct inode *inode, struct file *filp,
+                          struct drm_device * dev);
+
+static int drm_setup(struct drm_device * dev)
+{
+       drm_local_map_t *map;
+       int i;
+       int ret;
+       u32 sareapage;
+
+       if (dev->driver->firstopen) {
+               ret = dev->driver->firstopen(dev);
+               if (ret != 0)
+                       return ret;
+       }
+
+       dev->magicfree.next = NULL;
+
+       /* prebuild the SAREA */
+       sareapage = max_t(unsigned, SAREA_MAX, PAGE_SIZE);
+       i = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
+       if (i != 0)
+               return i;
+
+       atomic_set(&dev->ioctl_count, 0);
+       atomic_set(&dev->vma_count, 0);
+       dev->buf_use = 0;
+       atomic_set(&dev->buf_alloc, 0);
+
+       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) {
+               i = drm_dma_setup(dev);
+               if (i < 0)
+                       return i;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(dev->counts); i++)
+               atomic_set(&dev->counts[i], 0);
+
+       drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER);
+       INIT_LIST_HEAD(&dev->magicfree);
+
+       dev->sigdata.lock = NULL;
+       init_waitqueue_head(&dev->lock.lock_queue);
+       dev->queue_count = 0;
+       dev->queue_reserved = 0;
+       dev->queue_slots = 0;
+       dev->queuelist = NULL;
+       dev->irq_enabled = 0;
+       dev->context_flag = 0;
+       dev->interrupt_flag = 0;
+       dev->dma_flag = 0;
+       dev->last_context = 0;
+       dev->last_switch = 0;
+       dev->last_checked = 0;
+       init_waitqueue_head(&dev->context_wait);
+       dev->if_version = 0;
+
+       dev->ctx_start = 0;
+       dev->lck_start = 0;
+
+       dev->buf_async = NULL;
+       init_waitqueue_head(&dev->buf_readers);
+       init_waitqueue_head(&dev->buf_writers);
+
+       DRM_DEBUG("\n");
+
+       /*
+        * The kernel's context could be created here, but is now created
+        * in drm_dma_enqueue.  This is more resource-efficient for
+        * hardware that does not do DMA, but may mean that
+        * drm_select_queue fails between the time the interrupt is
+        * initialized and the time the queues are initialized.
+        */
+
+       return 0;
+}
+
+/**
+ * Open file.
+ *
+ * \param inode device inode
+ * \param filp file pointer.
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches the DRM device with the same minor number, calls open_helper(), and
+ * increments the device open count. If the open count was previous at zero,
+ * i.e., it's the first that the device is open, then calls setup().
+ */
+int drm_open(struct inode *inode, struct file *filp)
+{
+       struct drm_device *dev = NULL;
+       int minor_id = iminor(inode);
+       struct drm_minor *minor;
+       int retcode = 0;
+
+       minor = idr_find(&drm_minors_idr, minor_id);
+       if (!minor)
+               return -ENODEV;
+
+       if (!(dev = minor->dev))
+               return -ENODEV;
+
+       retcode = drm_open_helper(inode, filp, dev);
+       if (!retcode) {
+               atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
+               spin_lock(&dev->count_lock);
+               if (!dev->open_count++) {
+                       spin_unlock(&dev->count_lock);
+                       return drm_setup(dev);
+               }
+               spin_unlock(&dev->count_lock);
+       }
+
+       return retcode;
+}
+EXPORT_SYMBOL(drm_open);
+
+/**
+ * File \c open operation.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ *
+ * Puts the dev->fops corresponding to the device minor number into
+ * \p filp, call the \c open method, and restore the file operations.
+ */
+int drm_stub_open(struct inode *inode, struct file *filp)
+{
+       struct drm_device *dev = NULL;
+       struct drm_minor *minor;
+       int minor_id = iminor(inode);
+       int err = -ENODEV;
+       const struct file_operations *old_fops;
+
+       DRM_DEBUG("\n");
+
+       minor = idr_find(&drm_minors_idr, minor_id);
+       if (!minor)
+               return -ENODEV;
+
+       if (!(dev = minor->dev))
+               return -ENODEV;
+
+       old_fops = filp->f_op;
+       filp->f_op = fops_get(&dev->driver->fops);
+       if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
+               fops_put(filp->f_op);
+               filp->f_op = fops_get(old_fops);
+       }
+       fops_put(old_fops);
+
+       return err;
+}
+
+/**
+ * Check whether DRI will run on this CPU.
+ *
+ * \return non-zero if the DRI will run on this CPU, or zero otherwise.
+ */
+static int drm_cpu_valid(void)
+{
+#if defined(__i386__)
+       if (boot_cpu_data.x86 == 3)
+               return 0;       /* No cmpxchg on a 386 */
+#endif
+#if defined(__sparc__) && !defined(__sparc_v9__)
+       return 0;               /* No cmpxchg before v9 sparc. */
+#endif
+       return 1;
+}
+
+/**
+ * Called whenever a process opens /dev/drm.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param dev device.
+ * \return zero on success or a negative number on failure.
+ *
+ * Creates and initializes a drm_file structure for the file private data in \p
+ * filp and add it into the double linked list in \p dev.
+ */
+static int drm_open_helper(struct inode *inode, struct file *filp,
+                          struct drm_device * dev)
+{
+       int minor_id = iminor(inode);
+       struct drm_file *priv;
+       int ret;
+
+       if (filp->f_flags & O_EXCL)
+               return -EBUSY;  /* No exclusive opens */
+       if (!drm_cpu_valid())
+               return -EINVAL;
+
+       DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id);
+
+       priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
+       if (!priv)
+               return -ENOMEM;
+
+       memset(priv, 0, sizeof(*priv));
+       filp->private_data = priv;
+       priv->filp = filp;
+       priv->uid = current->euid;
+       priv->pid = task_pid_nr(current);
+       priv->minor = idr_find(&drm_minors_idr, minor_id);
+       priv->ioctl_count = 0;
+       /* for compatibility root is always authenticated */
+       priv->authenticated = capable(CAP_SYS_ADMIN);
+       priv->lock_count = 0;
+
+       INIT_LIST_HEAD(&priv->lhead);
+
+       if (dev->driver->open) {
+               ret = dev->driver->open(dev, priv);
+               if (ret < 0)
+                       goto out_free;
+       }
+
+       mutex_lock(&dev->struct_mutex);
+       if (list_empty(&dev->filelist))
+               priv->master = 1;
+
+       list_add(&priv->lhead, &dev->filelist);
+       mutex_unlock(&dev->struct_mutex);
+
+#ifdef __alpha__
+       /*
+        * Default the hose
+        */
+       if (!dev->hose) {
+               struct pci_dev *pci_dev;
+               pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
+               if (pci_dev) {
+                       dev->hose = pci_dev->sysdata;
+                       pci_dev_put(pci_dev);
+               }
+               if (!dev->hose) {
+                       struct pci_bus *b = pci_bus_b(pci_root_buses.next);
+                       if (b)
+                               dev->hose = b->sysdata;
+               }
+       }
+#endif
+
+       return 0;
+      out_free:
+       drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
+       filp->private_data = NULL;
+       return ret;
+}
+
+/** No-op. */
+int drm_fasync(int fd, struct file *filp, int on)
+{
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev = priv->minor->dev;
+       int retcode;
+
+       DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
+                 (long)old_encode_dev(priv->minor->device));
+       retcode = fasync_helper(fd, filp, on, &dev->buf_async);
+       if (retcode < 0)
+               return retcode;
+       return 0;
+}
+EXPORT_SYMBOL(drm_fasync);
+
+/**
+ * Release file.
+ *
+ * \param inode device inode
+ * \param file_priv DRM file private.
+ * \return zero on success or a negative number on failure.
+ *
+ * If the hardware lock is held then free it, and take it again for the kernel
+ * context since it's necessary to reclaim buffers. Unlink the file private
+ * data from its list and free it. Decreases the open count and if it reaches
+ * zero calls drm_lastclose().
+ */
+int drm_release(struct inode *inode, struct file *filp)
+{
+       struct drm_file *file_priv = filp->private_data;
+       struct drm_device *dev = file_priv->minor->dev;
+       int retcode = 0;
+
+       lock_kernel();
+
+       DRM_DEBUG("open_count = %d\n", dev->open_count);
+
+       if (dev->driver->preclose)
+               dev->driver->preclose(dev, file_priv);
+
+       /* ========================================================
+        * Begin inline drm_release
+        */
+
+       DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
+                 task_pid_nr(current),
+                 (long)old_encode_dev(file_priv->minor->device),
+                 dev->open_count);
+
+       if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
+               if (drm_i_have_hw_lock(dev, file_priv)) {
+                       dev->driver->reclaim_buffers_locked(dev, file_priv);
+               } else {
+                       unsigned long endtime = jiffies + 3 * DRM_HZ;
+                       int locked = 0;
+
+                       drm_idlelock_take(&dev->lock);
+
+                       /*
+                        * Wait for a while.
+                        */
+
+                       do{
+                               spin_lock_bh(&dev->lock.spinlock);
+                               locked = dev->lock.idle_has_lock;
+                               spin_unlock_bh(&dev->lock.spinlock);
+                               if (locked)
+                                       break;
+                               schedule();
+                       } while (!time_after_eq(jiffies, endtime));
+
+                       if (!locked) {
+                               DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n"
+                                         "\tdriver to use reclaim_buffers_idlelocked() instead.\n"
+                                         "\tI will go on reclaiming the buffers anyway.\n");
+                       }
+
+                       dev->driver->reclaim_buffers_locked(dev, file_priv);
+                       drm_idlelock_release(&dev->lock);
+               }
+       }
+
+       if (dev->driver->reclaim_buffers_idlelocked && dev->lock.hw_lock) {
+
+               drm_idlelock_take(&dev->lock);
+               dev->driver->reclaim_buffers_idlelocked(dev, file_priv);
+               drm_idlelock_release(&dev->lock);
+
+       }
+
+       if (drm_i_have_hw_lock(dev, file_priv)) {
+               DRM_DEBUG("File %p released, freeing lock for context %d\n",
+                         filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+
+               drm_lock_free(&dev->lock,
+                             _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+       }
+
+
+       if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
+           !dev->driver->reclaim_buffers_locked) {
+               dev->driver->reclaim_buffers(dev, file_priv);
+       }
+
+       drm_fasync(-1, filp, 0);
+
+       mutex_lock(&dev->ctxlist_mutex);
+       if (!list_empty(&dev->ctxlist)) {
+               struct drm_ctx_list *pos, *n;
+
+               list_for_each_entry_safe(pos, n, &dev->ctxlist, head) {
+                       if (pos->tag == file_priv &&
+                           pos->handle != DRM_KERNEL_CONTEXT) {
+                               if (dev->driver->context_dtor)
+                                       dev->driver->context_dtor(dev,
+                                                                 pos->handle);
+
+                               drm_ctxbitmap_free(dev, pos->handle);
+
+                               list_del(&pos->head);
+                               drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST);
+                               --dev->ctx_count;
+                       }
+               }
+       }
+       mutex_unlock(&dev->ctxlist_mutex);
+
+       mutex_lock(&dev->struct_mutex);
+       if (file_priv->remove_auth_on_close == 1) {
+               struct drm_file *temp;
+
+               list_for_each_entry(temp, &dev->filelist, lhead)
+                       temp->authenticated = 0;
+       }
+       list_del(&file_priv->lhead);
+       mutex_unlock(&dev->struct_mutex);
+
+       if (dev->driver->postclose)
+               dev->driver->postclose(dev, file_priv);
+       drm_free(file_priv, sizeof(*file_priv), DRM_MEM_FILES);
+
+       /* ========================================================
+        * End inline drm_release
+        */
+
+       atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);
+       spin_lock(&dev->count_lock);
+       if (!--dev->open_count) {
+               if (atomic_read(&dev->ioctl_count) || dev->blocked) {
+                       DRM_ERROR("Device busy: %d %d\n",
+                                 atomic_read(&dev->ioctl_count), dev->blocked);
+                       spin_unlock(&dev->count_lock);
+                       unlock_kernel();
+                       return -EBUSY;
+               }
+               spin_unlock(&dev->count_lock);
+               unlock_kernel();
+               return drm_lastclose(dev);
+       }
+       spin_unlock(&dev->count_lock);
+
+       unlock_kernel();
+
+       return retcode;
+}
+EXPORT_SYMBOL(drm_release);
+
+/** No-op. */
+unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
+{
+       return 0;
+}
+EXPORT_SYMBOL(drm_poll);
diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c
new file mode 100644 (file)
index 0000000..3316067
--- /dev/null
@@ -0,0 +1,202 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+/*
+ * Simple open hash tab implementation.
+ *
+ * Authors:
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "drmP.h"
+#include "drm_hashtab.h"
+#include <linux/hash.h>
+
+int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
+{
+       unsigned int i;
+
+       ht->size = 1 << order;
+       ht->order = order;
+       ht->fill = 0;
+       ht->table = NULL;
+       ht->use_vmalloc = ((ht->size * sizeof(*ht->table)) > PAGE_SIZE);
+       if (!ht->use_vmalloc) {
+               ht->table = drm_calloc(ht->size, sizeof(*ht->table),
+                                      DRM_MEM_HASHTAB);
+       }
+       if (!ht->table) {
+               ht->use_vmalloc = 1;
+               ht->table = vmalloc(ht->size*sizeof(*ht->table));
+       }
+       if (!ht->table) {
+               DRM_ERROR("Out of memory for hash table\n");
+               return -ENOMEM;
+       }
+       for (i=0; i< ht->size; ++i) {
+               INIT_HLIST_HEAD(&ht->table[i]);
+       }
+       return 0;
+}
+
+void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key)
+{
+       struct drm_hash_item *entry;
+       struct hlist_head *h_list;
+       struct hlist_node *list;
+       unsigned int hashed_key;
+       int count = 0;
+
+       hashed_key = hash_long(key, ht->order);
+       DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
+       h_list = &ht->table[hashed_key];
+       hlist_for_each(list, h_list) {
+               entry = hlist_entry(list, struct drm_hash_item, head);
+               DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
+       }
+}
+
+static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht,
+                                         unsigned long key)
+{
+       struct drm_hash_item *entry;
+       struct hlist_head *h_list;
+       struct hlist_node *list;
+       unsigned int hashed_key;
+
+       hashed_key = hash_long(key, ht->order);
+       h_list = &ht->table[hashed_key];
+       hlist_for_each(list, h_list) {
+               entry = hlist_entry(list, struct drm_hash_item, head);
+               if (entry->key == key)
+                       return list;
+               if (entry->key > key)
+                       break;
+       }
+       return NULL;
+}
+
+
+int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item)
+{
+       struct drm_hash_item *entry;
+       struct hlist_head *h_list;
+       struct hlist_node *list, *parent;
+       unsigned int hashed_key;
+       unsigned long key = item->key;
+
+       hashed_key = hash_long(key, ht->order);
+       h_list = &ht->table[hashed_key];
+       parent = NULL;
+       hlist_for_each(list, h_list) {
+               entry = hlist_entry(list, struct drm_hash_item, head);
+               if (entry->key == key)
+                       return -EINVAL;
+               if (entry->key > key)
+                       break;
+               parent = list;
+       }
+       if (parent) {
+               hlist_add_after(parent, &item->head);
+       } else {
+               hlist_add_head(&item->head, h_list);
+       }
+       return 0;
+}
+
+/*
+ * Just insert an item and return any "bits" bit key that hasn't been
+ * used before.
+ */
+int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
+                             unsigned long seed, int bits, int shift,
+                             unsigned long add)
+{
+       int ret;
+       unsigned long mask = (1 << bits) - 1;
+       unsigned long first, unshifted_key;
+
+       unshifted_key = hash_long(seed, bits);
+       first = unshifted_key;
+       do {
+               item->key = (unshifted_key << shift) + add;
+               ret = drm_ht_insert_item(ht, item);
+               if (ret)
+                       unshifted_key = (unshifted_key + 1) & mask;
+       } while(ret && (unshifted_key != first));
+
+       if (ret) {
+               DRM_ERROR("Available key bit space exhausted\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key,
+                    struct drm_hash_item **item)
+{
+       struct hlist_node *list;
+
+       list = drm_ht_find_key(ht, key);
+       if (!list)
+               return -EINVAL;
+
+       *item = hlist_entry(list, struct drm_hash_item, head);
+       return 0;
+}
+
+int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
+{
+       struct hlist_node *list;
+
+       list = drm_ht_find_key(ht, key);
+       if (list) {
+               hlist_del_init(list);
+               ht->fill--;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
+{
+       hlist_del_init(&item->head);
+       ht->fill--;
+       return 0;
+}
+
+void drm_ht_remove(struct drm_open_hash *ht)
+{
+       if (ht->table) {
+               if (ht->use_vmalloc)
+                       vfree(ht->table);
+               else
+                       drm_free(ht->table, ht->size * sizeof(*ht->table),
+                                DRM_MEM_HASHTAB);
+               ht->table = NULL;
+       }
+}
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
new file mode 100644 (file)
index 0000000..90f5a8d
--- /dev/null
@@ -0,0 +1,1073 @@
+/**
+ * \file drm_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the DRM.
+ *
+ * \author Paul Mackerras <paulus@samba.org>
+ *
+ * Copyright (C) Paul Mackerras 2005.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <linux/compat.h>
+
+#include "drmP.h"
+#include "drm_core.h"
+
+#define DRM_IOCTL_VERSION32            DRM_IOWR(0x00, drm_version32_t)
+#define DRM_IOCTL_GET_UNIQUE32         DRM_IOWR(0x01, drm_unique32_t)
+#define DRM_IOCTL_GET_MAP32            DRM_IOWR(0x04, drm_map32_t)
+#define DRM_IOCTL_GET_CLIENT32         DRM_IOWR(0x05, drm_client32_t)
+#define DRM_IOCTL_GET_STATS32          DRM_IOR( 0x06, drm_stats32_t)
+
+#define DRM_IOCTL_SET_UNIQUE32         DRM_IOW( 0x10, drm_unique32_t)
+#define DRM_IOCTL_ADD_MAP32            DRM_IOWR(0x15, drm_map32_t)
+#define DRM_IOCTL_ADD_BUFS32           DRM_IOWR(0x16, drm_buf_desc32_t)
+#define DRM_IOCTL_MARK_BUFS32          DRM_IOW( 0x17, drm_buf_desc32_t)
+#define DRM_IOCTL_INFO_BUFS32          DRM_IOWR(0x18, drm_buf_info32_t)
+#define DRM_IOCTL_MAP_BUFS32           DRM_IOWR(0x19, drm_buf_map32_t)
+#define DRM_IOCTL_FREE_BUFS32          DRM_IOW( 0x1a, drm_buf_free32_t)
+
+#define DRM_IOCTL_RM_MAP32             DRM_IOW( 0x1b, drm_map32_t)
+
+#define DRM_IOCTL_SET_SAREA_CTX32      DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
+#define DRM_IOCTL_GET_SAREA_CTX32      DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
+
+#define DRM_IOCTL_RES_CTX32            DRM_IOWR(0x26, drm_ctx_res32_t)
+#define DRM_IOCTL_DMA32                        DRM_IOWR(0x29, drm_dma32_t)
+
+#define DRM_IOCTL_AGP_ENABLE32         DRM_IOW( 0x32, drm_agp_mode32_t)
+#define DRM_IOCTL_AGP_INFO32           DRM_IOR( 0x33, drm_agp_info32_t)
+#define DRM_IOCTL_AGP_ALLOC32          DRM_IOWR(0x34, drm_agp_buffer32_t)
+#define DRM_IOCTL_AGP_FREE32           DRM_IOW( 0x35, drm_agp_buffer32_t)
+#define DRM_IOCTL_AGP_BIND32           DRM_IOW( 0x36, drm_agp_binding32_t)
+#define DRM_IOCTL_AGP_UNBIND32         DRM_IOW( 0x37, drm_agp_binding32_t)
+
+#define DRM_IOCTL_SG_ALLOC32           DRM_IOW( 0x38, drm_scatter_gather32_t)
+#define DRM_IOCTL_SG_FREE32            DRM_IOW( 0x39, drm_scatter_gather32_t)
+
+#define DRM_IOCTL_WAIT_VBLANK32                DRM_IOWR(0x3a, drm_wait_vblank32_t)
+
+typedef struct drm_version_32 {
+       int version_major;        /**< Major version */
+       int version_minor;        /**< Minor version */
+       int version_patchlevel;    /**< Patch level */
+       u32 name_len;             /**< Length of name buffer */
+       u32 name;                 /**< Name of driver */
+       u32 date_len;             /**< Length of date buffer */
+       u32 date;                 /**< User-space buffer to hold date */
+       u32 desc_len;             /**< Length of desc buffer */
+       u32 desc;                 /**< User-space buffer to hold desc */
+} drm_version32_t;
+
+static int compat_drm_version(struct file *file, unsigned int cmd,
+                             unsigned long arg)
+{
+       drm_version32_t v32;
+       struct drm_version __user *version;
+       int err;
+
+       if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
+               return -EFAULT;
+
+       version = compat_alloc_user_space(sizeof(*version));
+       if (!access_ok(VERIFY_WRITE, version, sizeof(*version)))
+               return -EFAULT;
+       if (__put_user(v32.name_len, &version->name_len)
+           || __put_user((void __user *)(unsigned long)v32.name,
+                         &version->name)
+           || __put_user(v32.date_len, &version->date_len)
+           || __put_user((void __user *)(unsigned long)v32.date,
+                         &version->date)
+           || __put_user(v32.desc_len, &version->desc_len)
+           || __put_user((void __user *)(unsigned long)v32.desc,
+                         &version->desc))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_VERSION, (unsigned long)version);
+       if (err)
+               return err;
+
+       if (__get_user(v32.version_major, &version->version_major)
+           || __get_user(v32.version_minor, &version->version_minor)
+           || __get_user(v32.version_patchlevel, &version->version_patchlevel)
+           || __get_user(v32.name_len, &version->name_len)
+           || __get_user(v32.date_len, &version->date_len)
+           || __get_user(v32.desc_len, &version->desc_len))
+               return -EFAULT;
+
+       if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
+               return -EFAULT;
+       return 0;
+}
+
+typedef struct drm_unique32 {
+       u32 unique_len; /**< Length of unique */
+       u32 unique;     /**< Unique name for driver instantiation */
+} drm_unique32_t;
+
+static int compat_drm_getunique(struct file *file, unsigned int cmd,
+                               unsigned long arg)
+{
+       drm_unique32_t uq32;
+       struct drm_unique __user *u;
+       int err;
+
+       if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
+               return -EFAULT;
+
+       u = compat_alloc_user_space(sizeof(*u));
+       if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
+               return -EFAULT;
+       if (__put_user(uq32.unique_len, &u->unique_len)
+           || __put_user((void __user *)(unsigned long)uq32.unique,
+                         &u->unique))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
+       if (err)
+               return err;
+
+       if (__get_user(uq32.unique_len, &u->unique_len))
+               return -EFAULT;
+       if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
+               return -EFAULT;
+       return 0;
+}
+
+static int compat_drm_setunique(struct file *file, unsigned int cmd,
+                               unsigned long arg)
+{
+       drm_unique32_t uq32;
+       struct drm_unique __user *u;
+
+       if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
+               return -EFAULT;
+
+       u = compat_alloc_user_space(sizeof(*u));
+       if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
+               return -EFAULT;
+       if (__put_user(uq32.unique_len, &u->unique_len)
+           || __put_user((void __user *)(unsigned long)uq32.unique,
+                         &u->unique))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
+}
+
+typedef struct drm_map32 {
+       u32 offset;             /**< Requested physical address (0 for SAREA)*/
+       u32 size;               /**< Requested physical size (bytes) */
+       enum drm_map_type type; /**< Type of memory to map */
+       enum drm_map_flags flags;       /**< Flags */
+       u32 handle;             /**< User-space: "Handle" to pass to mmap() */
+       int mtrr;               /**< MTRR slot used */
+} drm_map32_t;
+
+static int compat_drm_getmap(struct file *file, unsigned int cmd,
+                            unsigned long arg)
+{
+       drm_map32_t __user *argp = (void __user *)arg;
+       drm_map32_t m32;
+       struct drm_map __user *map;
+       int idx, err;
+       void *handle;
+
+       if (get_user(idx, &argp->offset))
+               return -EFAULT;
+
+       map = compat_alloc_user_space(sizeof(*map));
+       if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
+               return -EFAULT;
+       if (__put_user(idx, &map->offset))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_GET_MAP, (unsigned long)map);
+       if (err)
+               return err;
+
+       if (__get_user(m32.offset, &map->offset)
+           || __get_user(m32.size, &map->size)
+           || __get_user(m32.type, &map->type)
+           || __get_user(m32.flags, &map->flags)
+           || __get_user(handle, &map->handle)
+           || __get_user(m32.mtrr, &map->mtrr))
+               return -EFAULT;
+
+       m32.handle = (unsigned long)handle;
+       if (copy_to_user(argp, &m32, sizeof(m32)))
+               return -EFAULT;
+       return 0;
+
+}
+
+static int compat_drm_addmap(struct file *file, unsigned int cmd,
+                            unsigned long arg)
+{
+       drm_map32_t __user *argp = (void __user *)arg;
+       drm_map32_t m32;
+       struct drm_map __user *map;
+       int err;
+       void *handle;
+
+       if (copy_from_user(&m32, argp, sizeof(m32)))
+               return -EFAULT;
+
+       map = compat_alloc_user_space(sizeof(*map));
+       if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
+               return -EFAULT;
+       if (__put_user(m32.offset, &map->offset)
+           || __put_user(m32.size, &map->size)
+           || __put_user(m32.type, &map->type)
+           || __put_user(m32.flags, &map->flags))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_ADD_MAP, (unsigned long)map);
+       if (err)
+               return err;
+
+       if (__get_user(m32.offset, &map->offset)
+           || __get_user(m32.mtrr, &map->mtrr)
+           || __get_user(handle, &map->handle))
+               return -EFAULT;
+
+       m32.handle = (unsigned long)handle;
+       if (m32.handle != (unsigned long)handle && printk_ratelimit())
+               printk(KERN_ERR "compat_drm_addmap truncated handle"
+                      " %p for type %d offset %x\n",
+                      handle, m32.type, m32.offset);
+
+       if (copy_to_user(argp, &m32, sizeof(m32)))
+               return -EFAULT;
+
+       return 0;
+}
+
+static int compat_drm_rmmap(struct file *file, unsigned int cmd,
+                           unsigned long arg)
+{
+       drm_map32_t __user *argp = (void __user *)arg;
+       struct drm_map __user *map;
+       u32 handle;
+
+       if (get_user(handle, &argp->handle))
+               return -EFAULT;
+
+       map = compat_alloc_user_space(sizeof(*map));
+       if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
+               return -EFAULT;
+       if (__put_user((void *)(unsigned long)handle, &map->handle))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_RM_MAP, (unsigned long)map);
+}
+
+typedef struct drm_client32 {
+       int idx;        /**< Which client desired? */
+       int auth;       /**< Is client authenticated? */
+       u32 pid;        /**< Process ID */
+       u32 uid;        /**< User ID */
+       u32 magic;      /**< Magic */
+       u32 iocs;       /**< Ioctl count */
+} drm_client32_t;
+
+static int compat_drm_getclient(struct file *file, unsigned int cmd,
+                               unsigned long arg)
+{
+       drm_client32_t c32;
+       drm_client32_t __user *argp = (void __user *)arg;
+       struct drm_client __user *client;
+       int idx, err;
+
+       if (get_user(idx, &argp->idx))
+               return -EFAULT;
+
+       client = compat_alloc_user_space(sizeof(*client));
+       if (!access_ok(VERIFY_WRITE, client, sizeof(*client)))
+               return -EFAULT;
+       if (__put_user(idx, &client->idx))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_GET_CLIENT, (unsigned long)client);
+       if (err)
+               return err;
+
+       if (__get_user(c32.auth, &client->auth)
+           || __get_user(c32.pid, &client->pid)
+           || __get_user(c32.uid, &client->uid)
+           || __get_user(c32.magic, &client->magic)
+           || __get_user(c32.iocs, &client->iocs))
+               return -EFAULT;
+
+       if (copy_to_user(argp, &c32, sizeof(c32)))
+               return -EFAULT;
+       return 0;
+}
+
+typedef struct drm_stats32 {
+       u32 count;
+       struct {
+               u32 value;
+               enum drm_stat_type type;
+       } data[15];
+} drm_stats32_t;
+
+static int compat_drm_getstats(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       drm_stats32_t s32;
+       drm_stats32_t __user *argp = (void __user *)arg;
+       struct drm_stats __user *stats;
+       int i, err;
+
+       stats = compat_alloc_user_space(sizeof(*stats));
+       if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_GET_STATS, (unsigned long)stats);
+       if (err)
+               return err;
+
+       if (__get_user(s32.count, &stats->count))
+               return -EFAULT;
+       for (i = 0; i < 15; ++i)
+               if (__get_user(s32.data[i].value, &stats->data[i].value)
+                   || __get_user(s32.data[i].type, &stats->data[i].type))
+                       return -EFAULT;
+
+       if (copy_to_user(argp, &s32, sizeof(s32)))
+               return -EFAULT;
+       return 0;
+}
+
+typedef struct drm_buf_desc32 {
+       int count;               /**< Number of buffers of this size */
+       int size;                /**< Size in bytes */
+       int low_mark;            /**< Low water mark */
+       int high_mark;           /**< High water mark */
+       int flags;
+       u32 agp_start;           /**< Start address in the AGP aperture */
+} drm_buf_desc32_t;
+
+static int compat_drm_addbufs(struct file *file, unsigned int cmd,
+                             unsigned long arg)
+{
+       drm_buf_desc32_t __user *argp = (void __user *)arg;
+       struct drm_buf_desc __user *buf;
+       int err;
+       unsigned long agp_start;
+
+       buf = compat_alloc_user_space(sizeof(*buf));
+       if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf))
+           || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)))
+               return -EFAULT;
+
+       if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start))
+           || __get_user(agp_start, &argp->agp_start)
+           || __put_user(agp_start, &buf->agp_start))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
+       if (err)
+               return err;
+
+       if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start))
+           || __get_user(agp_start, &buf->agp_start)
+           || __put_user(agp_start, &argp->agp_start))
+               return -EFAULT;
+
+       return 0;
+}
+
+static int compat_drm_markbufs(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       drm_buf_desc32_t b32;
+       drm_buf_desc32_t __user *argp = (void __user *)arg;
+       struct drm_buf_desc __user *buf;
+
+       if (copy_from_user(&b32, argp, sizeof(b32)))
+               return -EFAULT;
+
+       buf = compat_alloc_user_space(sizeof(*buf));
+       if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)))
+               return -EFAULT;
+
+       if (__put_user(b32.size, &buf->size)
+           || __put_user(b32.low_mark, &buf->low_mark)
+           || __put_user(b32.high_mark, &buf->high_mark))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
+}
+
+typedef struct drm_buf_info32 {
+       int count;              /**< Entries in list */
+       u32 list;
+} drm_buf_info32_t;
+
+static int compat_drm_infobufs(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       drm_buf_info32_t req32;
+       drm_buf_info32_t __user *argp = (void __user *)arg;
+       drm_buf_desc32_t __user *to;
+       struct drm_buf_info __user *request;
+       struct drm_buf_desc __user *list;
+       size_t nbytes;
+       int i, err;
+       int count, actual;
+
+       if (copy_from_user(&req32, argp, sizeof(req32)))
+               return -EFAULT;
+
+       count = req32.count;
+       to = (drm_buf_desc32_t __user *) (unsigned long)req32.list;
+       if (count < 0)
+               count = 0;
+       if (count > 0
+           && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
+               return -EFAULT;
+
+       nbytes = sizeof(*request) + count * sizeof(struct drm_buf_desc);
+       request = compat_alloc_user_space(nbytes);
+       if (!access_ok(VERIFY_WRITE, request, nbytes))
+               return -EFAULT;
+       list = (struct drm_buf_desc *) (request + 1);
+
+       if (__put_user(count, &request->count)
+           || __put_user(list, &request->list))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_INFO_BUFS, (unsigned long)request);
+       if (err)
+               return err;
+
+       if (__get_user(actual, &request->count))
+               return -EFAULT;
+       if (count >= actual)
+               for (i = 0; i < actual; ++i)
+                       if (__copy_in_user(&to[i], &list[i],
+                                          offsetof(struct drm_buf_desc, flags)))
+                               return -EFAULT;
+
+       if (__put_user(actual, &argp->count))
+               return -EFAULT;
+
+       return 0;
+}
+
+typedef struct drm_buf_pub32 {
+       int idx;                /**< Index into the master buffer list */
+       int total;              /**< Buffer size */
+       int used;               /**< Amount of buffer in use (for DMA) */
+       u32 address;            /**< Address of buffer */
+} drm_buf_pub32_t;
+
+typedef struct drm_buf_map32 {
+       int count;              /**< Length of the buffer list */
+       u32 virtual;            /**< Mmap'd area in user-virtual */
+       u32 list;               /**< Buffer information */
+} drm_buf_map32_t;
+
+static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
+                             unsigned long arg)
+{
+       drm_buf_map32_t __user *argp = (void __user *)arg;
+       drm_buf_map32_t req32;
+       drm_buf_pub32_t __user *list32;
+       struct drm_buf_map __user *request;
+       struct drm_buf_pub __user *list;
+       int i, err;
+       int count, actual;
+       size_t nbytes;
+       void __user *addr;
+
+       if (copy_from_user(&req32, argp, sizeof(req32)))
+               return -EFAULT;
+       count = req32.count;
+       list32 = (void __user *)(unsigned long)req32.list;
+
+       if (count < 0)
+               return -EINVAL;
+       nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub);
+       request = compat_alloc_user_space(nbytes);
+       if (!access_ok(VERIFY_WRITE, request, nbytes))
+               return -EFAULT;
+       list = (struct drm_buf_pub *) (request + 1);
+
+       if (__put_user(count, &request->count)
+           || __put_user(list, &request->list))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_MAP_BUFS, (unsigned long)request);
+       if (err)
+               return err;
+
+       if (__get_user(actual, &request->count))
+               return -EFAULT;
+       if (count >= actual)
+               for (i = 0; i < actual; ++i)
+                       if (__copy_in_user(&list32[i], &list[i],
+                                          offsetof(struct drm_buf_pub, address))
+                           || __get_user(addr, &list[i].address)
+                           || __put_user((unsigned long)addr,
+                                         &list32[i].address))
+                               return -EFAULT;
+
+       if (__put_user(actual, &argp->count)
+           || __get_user(addr, &request->virtual)
+           || __put_user((unsigned long)addr, &argp->virtual))
+               return -EFAULT;
+
+       return 0;
+}
+
+typedef struct drm_buf_free32 {
+       int count;
+       u32 list;
+} drm_buf_free32_t;
+
+static int compat_drm_freebufs(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       drm_buf_free32_t req32;
+       struct drm_buf_free __user *request;
+       drm_buf_free32_t __user *argp = (void __user *)arg;
+
+       if (copy_from_user(&req32, argp, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
+               return -EFAULT;
+       if (__put_user(req32.count, &request->count)
+           || __put_user((int __user *)(unsigned long)req32.list,
+                         &request->list))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_FREE_BUFS, (unsigned long)request);
+}
+
+typedef struct drm_ctx_priv_map32 {
+       unsigned int ctx_id;     /**< Context requesting private mapping */
+       u32 handle;             /**< Handle of map */
+} drm_ctx_priv_map32_t;
+
+static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
+                                 unsigned long arg)
+{
+       drm_ctx_priv_map32_t req32;
+       struct drm_ctx_priv_map __user *request;
+       drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
+
+       if (copy_from_user(&req32, argp, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
+               return -EFAULT;
+       if (__put_user(req32.ctx_id, &request->ctx_id)
+           || __put_user((void *)(unsigned long)req32.handle,
+                         &request->handle))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
+}
+
+static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
+                                 unsigned long arg)
+{
+       struct drm_ctx_priv_map __user *request;
+       drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
+       int err;
+       unsigned int ctx_id;
+       void *handle;
+
+       if (!access_ok(VERIFY_WRITE, argp, sizeof(*argp))
+           || __get_user(ctx_id, &argp->ctx_id))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
+               return -EFAULT;
+       if (__put_user(ctx_id, &request->ctx_id))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
+       if (err)
+               return err;
+
+       if (__get_user(handle, &request->handle)
+           || __put_user((unsigned long)handle, &argp->handle))
+               return -EFAULT;
+
+       return 0;
+}
+
+typedef struct drm_ctx_res32 {
+       int count;
+       u32 contexts;
+} drm_ctx_res32_t;
+
+static int compat_drm_resctx(struct file *file, unsigned int cmd,
+                            unsigned long arg)
+{
+       drm_ctx_res32_t __user *argp = (void __user *)arg;
+       drm_ctx_res32_t res32;
+       struct drm_ctx_res __user *res;
+       int err;
+
+       if (copy_from_user(&res32, argp, sizeof(res32)))
+               return -EFAULT;
+
+       res = compat_alloc_user_space(sizeof(*res));
+       if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
+               return -EFAULT;
+       if (__put_user(res32.count, &res->count)
+           || __put_user((struct drm_ctx __user *) (unsigned long)res32.contexts,
+                         &res->contexts))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_RES_CTX, (unsigned long)res);
+       if (err)
+               return err;
+
+       if (__get_user(res32.count, &res->count)
+           || __put_user(res32.count, &argp->count))
+               return -EFAULT;
+
+       return 0;
+}
+
+typedef struct drm_dma32 {
+       int context;              /**< Context handle */
+       int send_count;           /**< Number of buffers to send */
+       u32 send_indices;         /**< List of handles to buffers */
+       u32 send_sizes;           /**< Lengths of data to send */
+       enum drm_dma_flags flags;                 /**< Flags */
+       int request_count;        /**< Number of buffers requested */
+       int request_size;         /**< Desired size for buffers */
+       u32 request_indices;      /**< Buffer information */
+       u32 request_sizes;
+       int granted_count;        /**< Number of buffers granted */
+} drm_dma32_t;
+
+static int compat_drm_dma(struct file *file, unsigned int cmd,
+                         unsigned long arg)
+{
+       drm_dma32_t d32;
+       drm_dma32_t __user *argp = (void __user *)arg;
+       struct drm_dma __user *d;
+       int err;
+
+       if (copy_from_user(&d32, argp, sizeof(d32)))
+               return -EFAULT;
+
+       d = compat_alloc_user_space(sizeof(*d));
+       if (!access_ok(VERIFY_WRITE, d, sizeof(*d)))
+               return -EFAULT;
+
+       if (__put_user(d32.context, &d->context)
+           || __put_user(d32.send_count, &d->send_count)
+           || __put_user((int __user *)(unsigned long)d32.send_indices,
+                         &d->send_indices)
+           || __put_user((int __user *)(unsigned long)d32.send_sizes,
+                         &d->send_sizes)
+           || __put_user(d32.flags, &d->flags)
+           || __put_user(d32.request_count, &d->request_count)
+           || __put_user((int __user *)(unsigned long)d32.request_indices,
+                         &d->request_indices)
+           || __put_user((int __user *)(unsigned long)d32.request_sizes,
+                         &d->request_sizes))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_DMA, (unsigned long)d);
+       if (err)
+               return err;
+
+       if (__get_user(d32.request_size, &d->request_size)
+           || __get_user(d32.granted_count, &d->granted_count)
+           || __put_user(d32.request_size, &argp->request_size)
+           || __put_user(d32.granted_count, &argp->granted_count))
+               return -EFAULT;
+
+       return 0;
+}
+
+#if __OS_HAS_AGP
+typedef struct drm_agp_mode32 {
+       u32 mode;       /**< AGP mode */
+} drm_agp_mode32_t;
+
+static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
+                                unsigned long arg)
+{
+       drm_agp_mode32_t __user *argp = (void __user *)arg;
+       drm_agp_mode32_t m32;
+       struct drm_agp_mode __user *mode;
+
+       if (get_user(m32.mode, &argp->mode))
+               return -EFAULT;
+
+       mode = compat_alloc_user_space(sizeof(*mode));
+       if (put_user(m32.mode, &mode->mode))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
+}
+
+typedef struct drm_agp_info32 {
+       int agp_version_major;
+       int agp_version_minor;
+       u32 mode;
+       u32 aperture_base;      /* physical address */
+       u32 aperture_size;      /* bytes */
+       u32 memory_allowed;     /* bytes */
+       u32 memory_used;
+
+       /* PCI information */
+       unsigned short id_vendor;
+       unsigned short id_device;
+} drm_agp_info32_t;
+
+static int compat_drm_agp_info(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       drm_agp_info32_t __user *argp = (void __user *)arg;
+       drm_agp_info32_t i32;
+       struct drm_agp_info __user *info;
+       int err;
+
+       info = compat_alloc_user_space(sizeof(*info));
+       if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_AGP_INFO, (unsigned long)info);
+       if (err)
+               return err;
+
+       if (__get_user(i32.agp_version_major, &info->agp_version_major)
+           || __get_user(i32.agp_version_minor, &info->agp_version_minor)
+           || __get_user(i32.mode, &info->mode)
+           || __get_user(i32.aperture_base, &info->aperture_base)
+           || __get_user(i32.aperture_size, &info->aperture_size)
+           || __get_user(i32.memory_allowed, &info->memory_allowed)
+           || __get_user(i32.memory_used, &info->memory_used)
+           || __get_user(i32.id_vendor, &info->id_vendor)
+           || __get_user(i32.id_device, &info->id_device))
+               return -EFAULT;
+
+       if (copy_to_user(argp, &i32, sizeof(i32)))
+               return -EFAULT;
+
+       return 0;
+}
+
+typedef struct drm_agp_buffer32 {
+       u32 size;       /**< In bytes -- will round to page boundary */
+       u32 handle;     /**< Used for binding / unbinding */
+       u32 type;       /**< Type of memory to allocate */
+       u32 physical;   /**< Physical used by i810 */
+} drm_agp_buffer32_t;
+
+static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
+                               unsigned long arg)
+{
+       drm_agp_buffer32_t __user *argp = (void __user *)arg;
+       drm_agp_buffer32_t req32;
+       struct drm_agp_buffer __user *request;
+       int err;
+
+       if (copy_from_user(&req32, argp, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user(req32.size, &request->size)
+           || __put_user(req32.type, &request->type))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
+       if (err)
+               return err;
+
+       if (__get_user(req32.handle, &request->handle)
+           || __get_user(req32.physical, &request->physical)
+           || copy_to_user(argp, &req32, sizeof(req32))) {
+               drm_ioctl(file->f_path.dentry->d_inode, file,
+                         DRM_IOCTL_AGP_FREE, (unsigned long)request);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+static int compat_drm_agp_free(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       drm_agp_buffer32_t __user *argp = (void __user *)arg;
+       struct drm_agp_buffer __user *request;
+       u32 handle;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || get_user(handle, &argp->handle)
+           || __put_user(handle, &request->handle))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_AGP_FREE, (unsigned long)request);
+}
+
+typedef struct drm_agp_binding32 {
+       u32 handle;     /**< From drm_agp_buffer */
+       u32 offset;     /**< In bytes -- will round to page boundary */
+} drm_agp_binding32_t;
+
+static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       drm_agp_binding32_t __user *argp = (void __user *)arg;
+       drm_agp_binding32_t req32;
+       struct drm_agp_binding __user *request;
+
+       if (copy_from_user(&req32, argp, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user(req32.handle, &request->handle)
+           || __put_user(req32.offset, &request->offset))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_AGP_BIND, (unsigned long)request);
+}
+
+static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
+                                unsigned long arg)
+{
+       drm_agp_binding32_t __user *argp = (void __user *)arg;
+       struct drm_agp_binding __user *request;
+       u32 handle;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || get_user(handle, &argp->handle)
+           || __put_user(handle, &request->handle))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
+}
+#endif                         /* __OS_HAS_AGP */
+
+typedef struct drm_scatter_gather32 {
+       u32 size;       /**< In bytes -- will round to page boundary */
+       u32 handle;     /**< Used for mapping / unmapping */
+} drm_scatter_gather32_t;
+
+static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       drm_scatter_gather32_t __user *argp = (void __user *)arg;
+       struct drm_scatter_gather __user *request;
+       int err;
+       unsigned long x;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
+           || __get_user(x, &argp->size)
+           || __put_user(x, &request->size))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_SG_ALLOC, (unsigned long)request);
+       if (err)
+               return err;
+
+       /* XXX not sure about the handle conversion here... */
+       if (__get_user(x, &request->handle)
+           || __put_user(x >> PAGE_SHIFT, &argp->handle))
+               return -EFAULT;
+
+       return 0;
+}
+
+static int compat_drm_sg_free(struct file *file, unsigned int cmd,
+                             unsigned long arg)
+{
+       drm_scatter_gather32_t __user *argp = (void __user *)arg;
+       struct drm_scatter_gather __user *request;
+       unsigned long x;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
+           || __get_user(x, &argp->handle)
+           || __put_user(x << PAGE_SHIFT, &request->handle))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_SG_FREE, (unsigned long)request);
+}
+
+struct drm_wait_vblank_request32 {
+       enum drm_vblank_seq_type type;
+       unsigned int sequence;
+       u32 signal;
+};
+
+struct drm_wait_vblank_reply32 {
+       enum drm_vblank_seq_type type;
+       unsigned int sequence;
+       s32 tval_sec;
+       s32 tval_usec;
+};
+
+typedef union drm_wait_vblank32 {
+       struct drm_wait_vblank_request32 request;
+       struct drm_wait_vblank_reply32 reply;
+} drm_wait_vblank32_t;
+
+static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
+                                 unsigned long arg)
+{
+       drm_wait_vblank32_t __user *argp = (void __user *)arg;
+       drm_wait_vblank32_t req32;
+       union drm_wait_vblank __user *request;
+       int err;
+
+       if (copy_from_user(&req32, argp, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user(req32.request.type, &request->request.type)
+           || __put_user(req32.request.sequence, &request->request.sequence)
+           || __put_user(req32.request.signal, &request->request.signal))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
+       if (err)
+               return err;
+
+       if (__get_user(req32.reply.type, &request->reply.type)
+           || __get_user(req32.reply.sequence, &request->reply.sequence)
+           || __get_user(req32.reply.tval_sec, &request->reply.tval_sec)
+           || __get_user(req32.reply.tval_usec, &request->reply.tval_usec))
+               return -EFAULT;
+
+       if (copy_to_user(argp, &req32, sizeof(req32)))
+               return -EFAULT;
+
+       return 0;
+}
+
+drm_ioctl_compat_t *drm_compat_ioctls[] = {
+       [DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version,
+       [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique,
+       [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap,
+       [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT32)] = compat_drm_getclient,
+       [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS32)] = compat_drm_getstats,
+       [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE32)] = compat_drm_setunique,
+       [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP32)] = compat_drm_addmap,
+       [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS32)] = compat_drm_addbufs,
+       [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS32)] = compat_drm_markbufs,
+       [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS32)] = compat_drm_infobufs,
+       [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS32)] = compat_drm_mapbufs,
+       [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS32)] = compat_drm_freebufs,
+       [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP32)] = compat_drm_rmmap,
+       [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX32)] = compat_drm_setsareactx,
+       [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX32)] = compat_drm_getsareactx,
+       [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX32)] = compat_drm_resctx,
+       [DRM_IOCTL_NR(DRM_IOCTL_DMA32)] = compat_drm_dma,
+#if __OS_HAS_AGP
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE32)] = compat_drm_agp_enable,
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO32)] = compat_drm_agp_info,
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC32)] = compat_drm_agp_alloc,
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE32)] = compat_drm_agp_free,
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND32)] = compat_drm_agp_bind,
+       [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND32)] = compat_drm_agp_unbind,
+#endif
+       [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc,
+       [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free,
+       [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/drm.
+ *
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       unsigned int nr = DRM_IOCTL_NR(cmd);
+       drm_ioctl_compat_t *fn;
+       int ret;
+
+       /* Assume that ioctls without an explicit compat routine will just
+        * work.  This may not always be a good assumption, but it's better
+        * than always failing.
+        */
+       if (nr >= ARRAY_SIZE(drm_compat_ioctls))
+               return drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+
+       fn = drm_compat_ioctls[nr];
+
+       lock_kernel();          /* XXX for now */
+       if (fn != NULL)
+               ret = (*fn) (filp, cmd, arg);
+       else
+               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
+       unlock_kernel();
+
+       return ret;
+}
+
+EXPORT_SYMBOL(drm_compat_ioctl);
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
new file mode 100644 (file)
index 0000000..16829fb
--- /dev/null
@@ -0,0 +1,352 @@
+/**
+ * \file drm_ioctl.c
+ * IOCTL processing for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Fri Jan  8 09:01:26 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm_core.h"
+
+#include "linux/pci.h"
+
+/**
+ * Get the bus id.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_unique structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Copies the bus id from drm_device::unique into user space.
+ */
+int drm_getunique(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
+{
+       struct drm_unique *u = data;
+
+       if (u->unique_len >= dev->unique_len) {
+               if (copy_to_user(u->unique, dev->unique, dev->unique_len))
+                       return -EFAULT;
+       }
+       u->unique_len = dev->unique_len;
+
+       return 0;
+}
+
+/**
+ * Set the bus id.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_unique structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Copies the bus id from userspace into drm_device::unique, and verifies that
+ * it matches the device this DRM is attached to (EINVAL otherwise).  Deprecated
+ * in interface version 1.1 and will return EBUSY when setversion has requested
+ * version 1.1 or greater.
+ */
+int drm_setunique(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
+{
+       struct drm_unique *u = data;
+       int domain, bus, slot, func, ret;
+
+       if (dev->unique_len || dev->unique)
+               return -EBUSY;
+
+       if (!u->unique_len || u->unique_len > 1024)
+               return -EINVAL;
+
+       dev->unique_len = u->unique_len;
+       dev->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER);
+       if (!dev->unique)
+               return -ENOMEM;
+       if (copy_from_user(dev->unique, u->unique, dev->unique_len))
+               return -EFAULT;
+
+       dev->unique[dev->unique_len] = '\0';
+
+       dev->devname =
+           drm_alloc(strlen(dev->driver->pci_driver.name) +
+                     strlen(dev->unique) + 2, DRM_MEM_DRIVER);
+       if (!dev->devname)
+               return -ENOMEM;
+
+       sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
+               dev->unique);
+
+       /* Return error if the busid submitted doesn't match the device's actual
+        * busid.
+        */
+       ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
+       if (ret != 3)
+               return -EINVAL;
+       domain = bus >> 8;
+       bus &= 0xff;
+
+       if ((domain != drm_get_pci_domain(dev)) ||
+           (bus != dev->pdev->bus->number) ||
+           (slot != PCI_SLOT(dev->pdev->devfn)) ||
+           (func != PCI_FUNC(dev->pdev->devfn)))
+               return -EINVAL;
+
+       return 0;
+}
+
+static int drm_set_busid(struct drm_device * dev)
+{
+       int len;
+
+       if (dev->unique != NULL)
+               return 0;
+
+       dev->unique_len = 40;
+       dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER);
+       if (dev->unique == NULL)
+               return -ENOMEM;
+
+       len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
+                      drm_get_pci_domain(dev), dev->pdev->bus->number,
+                      PCI_SLOT(dev->pdev->devfn),
+                      PCI_FUNC(dev->pdev->devfn));
+
+       if (len > dev->unique_len)
+               DRM_ERROR("Unique buffer overflowed\n");
+
+       dev->devname =
+           drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len +
+                     2, DRM_MEM_DRIVER);
+       if (dev->devname == NULL)
+               return -ENOMEM;
+
+       sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
+               dev->unique);
+
+       return 0;
+}
+
+/**
+ * Get a mapping information.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_map structure.
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches for the mapping with the specified offset and copies its information
+ * into userspace
+ */
+int drm_getmap(struct drm_device *dev, void *data,
+              struct drm_file *file_priv)
+{
+       struct drm_map *map = data;
+       struct drm_map_list *r_list = NULL;
+       struct list_head *list;
+       int idx;
+       int i;
+
+       idx = map->offset;
+
+       mutex_lock(&dev->struct_mutex);
+       if (idx < 0) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
+       }
+
+       i = 0;
+       list_for_each(list, &dev->maplist) {
+               if (i == idx) {
+                       r_list = list_entry(list, struct drm_map_list, head);
+                       break;
+               }
+               i++;
+       }
+       if (!r_list || !r_list->map) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
+       }
+
+       map->offset = r_list->map->offset;
+       map->size = r_list->map->size;
+       map->type = r_list->map->type;
+       map->flags = r_list->map->flags;
+       map->handle = (void *)(unsigned long) r_list->user_token;
+       map->mtrr = r_list->map->mtrr;
+       mutex_unlock(&dev->struct_mutex);
+
+       return 0;
+}
+
+/**
+ * Get client information.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_client structure.
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches for the client with the specified index and copies its information
+ * into userspace
+ */
+int drm_getclient(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
+{
+       struct drm_client *client = data;
+       struct drm_file *pt;
+       int idx;
+       int i;
+
+       idx = client->idx;
+       mutex_lock(&dev->struct_mutex);
+
+       i = 0;
+       list_for_each_entry(pt, &dev->filelist, lhead) {
+               if (i++ >= idx) {
+                       client->auth = pt->authenticated;
+                       client->pid = pt->pid;
+                       client->uid = pt->uid;
+                       client->magic = pt->magic;
+                       client->iocs = pt->ioctl_count;
+                       mutex_unlock(&dev->struct_mutex);
+
+                       return 0;
+               }
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       return -EINVAL;
+}
+
+/**
+ * Get statistics information.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_stats structure.
+ *
+ * \return zero on success or a negative number on failure.
+ */
+int drm_getstats(struct drm_device *dev, void *data,
+                struct drm_file *file_priv)
+{
+       struct drm_stats *stats = data;
+       int i;
+
+       memset(stats, 0, sizeof(*stats));
+
+       mutex_lock(&dev->struct_mutex);
+
+       for (i = 0; i < dev->counters; i++) {
+               if (dev->types[i] == _DRM_STAT_LOCK)
+                       stats->data[i].value =
+                           (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0);
+               else
+                       stats->data[i].value = atomic_read(&dev->counts[i]);
+               stats->data[i].type = dev->types[i];
+       }
+
+       stats->count = dev->counters;
+
+       mutex_unlock(&dev->struct_mutex);
+
+       return 0;
+}
+
+/**
+ * Setversion ioctl.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_lock structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Sets the requested interface version
+ */
+int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_set_version *sv = data;
+       int if_version, retcode = 0;
+
+       if (sv->drm_di_major != -1) {
+               if (sv->drm_di_major != DRM_IF_MAJOR ||
+                   sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) {
+                       retcode = -EINVAL;
+                       goto done;
+               }
+               if_version = DRM_IF_VERSION(sv->drm_di_major,
+                                           sv->drm_di_minor);
+               dev->if_version = max(if_version, dev->if_version);
+               if (sv->drm_di_minor >= 1) {
+                       /*
+                        * Version 1.1 includes tying of DRM to specific device
+                        */
+                       drm_set_busid(dev);
+               }
+       }
+
+       if (sv->drm_dd_major != -1) {
+               if (sv->drm_dd_major != dev->driver->major ||
+                   sv->drm_dd_minor < 0 || sv->drm_dd_minor >
+                   dev->driver->minor) {
+                       retcode = -EINVAL;
+                       goto done;
+               }
+
+               if (dev->driver->set_version)
+                       dev->driver->set_version(dev, sv);
+       }
+
+done:
+       sv->drm_di_major = DRM_IF_MAJOR;
+       sv->drm_di_minor = DRM_IF_MINOR;
+       sv->drm_dd_major = dev->driver->major;
+       sv->drm_dd_minor = dev->driver->minor;
+
+       return retcode;
+}
+
+/** No-op ioctl. */
+int drm_noop(struct drm_device *dev, void *data,
+            struct drm_file *file_priv)
+{
+       DRM_DEBUG("\n");
+       return 0;
+}
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
new file mode 100644 (file)
index 0000000..089c015
--- /dev/null
@@ -0,0 +1,462 @@
+/**
+ * \file drm_irq.c
+ * IRQ support
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+
+#include <linux/interrupt.h>   /* For task queue support */
+
+/**
+ * Get interrupt from bus id.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_irq_busid structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Finds the PCI device with the specified bus id and gets its IRQ number.
+ * This IOCTL is deprecated, and will now return EINVAL for any busid not equal
+ * to that of the device that this DRM instance attached to.
+ */
+int drm_irq_by_busid(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
+{
+       struct drm_irq_busid *p = data;
+
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+               return -EINVAL;
+
+       if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
+           (p->busnum & 0xff) != dev->pdev->bus->number ||
+           p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
+               return -EINVAL;
+
+       p->irq = dev->irq;
+
+       DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
+                 p->irq);
+
+       return 0;
+}
+
+/**
+ * Install IRQ handler.
+ *
+ * \param dev DRM device.
+ * \param irq IRQ number.
+ *
+ * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
+ * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
+ * before and after the installation.
+ */
+static int drm_irq_install(struct drm_device * dev)
+{
+       int ret;
+       unsigned long sh_flags = 0;
+
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+               return -EINVAL;
+
+       if (dev->irq == 0)
+               return -EINVAL;
+
+       mutex_lock(&dev->struct_mutex);
+
+       /* Driver must have been initialized */
+       if (!dev->dev_private) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
+       }
+
+       if (dev->irq_enabled) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EBUSY;
+       }
+       dev->irq_enabled = 1;
+       mutex_unlock(&dev->struct_mutex);
+
+       DRM_DEBUG("irq=%d\n", dev->irq);
+
+       if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
+               init_waitqueue_head(&dev->vbl_queue);
+
+               spin_lock_init(&dev->vbl_lock);
+
+               INIT_LIST_HEAD(&dev->vbl_sigs);
+               INIT_LIST_HEAD(&dev->vbl_sigs2);
+
+               dev->vbl_pending = 0;
+       }
+
+       /* Before installing handler */
+       dev->driver->irq_preinstall(dev);
+
+       /* Install handler */
+       if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
+               sh_flags = IRQF_SHARED;
+
+       ret = request_irq(dev->irq, dev->driver->irq_handler,
+                         sh_flags, dev->devname, dev);
+       if (ret < 0) {
+               mutex_lock(&dev->struct_mutex);
+               dev->irq_enabled = 0;
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
+
+       /* After installing handler */
+       dev->driver->irq_postinstall(dev);
+
+       return 0;
+}
+
+/**
+ * Uninstall the IRQ handler.
+ *
+ * \param dev DRM device.
+ *
+ * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq.
+ */
+int drm_irq_uninstall(struct drm_device * dev)
+{
+       int irq_enabled;
+
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+               return -EINVAL;
+
+       mutex_lock(&dev->struct_mutex);
+       irq_enabled = dev->irq_enabled;
+       dev->irq_enabled = 0;
+       mutex_unlock(&dev->struct_mutex);
+
+       if (!irq_enabled)
+               return -EINVAL;
+
+       DRM_DEBUG("irq=%d\n", dev->irq);
+
+       dev->driver->irq_uninstall(dev);
+
+       free_irq(dev->irq, dev);
+
+       dev->locked_tasklet_func = NULL;
+
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_irq_uninstall);
+
+/**
+ * IRQ control ioctl.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_control structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls irq_install() or irq_uninstall() according to \p arg.
+ */
+int drm_control(struct drm_device *dev, void *data,
+               struct drm_file *file_priv)
+{
+       struct drm_control *ctl = data;
+
+       /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
+
+
+       switch (ctl->func) {
+       case DRM_INST_HANDLER:
+               if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+                       return 0;
+               if (dev->if_version < DRM_IF_VERSION(1, 2) &&
+                   ctl->irq != dev->irq)
+                       return -EINVAL;
+               return drm_irq_install(dev);
+       case DRM_UNINST_HANDLER:
+               if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+                       return 0;
+               return drm_irq_uninstall(dev);
+       default:
+               return -EINVAL;
+       }
+}
+
+/**
+ * Wait for VBLANK.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param data user argument, pointing to a drm_wait_vblank structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the IRQ is installed.
+ *
+ * If a signal is requested checks if this task has already scheduled the same signal
+ * for the same vblank sequence number - nothing to be done in
+ * that case. If the number of tasks waiting for the interrupt exceeds 100 the
+ * function fails. Otherwise adds a new entry to drm_device::vbl_sigs for this
+ * task.
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
+int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       union drm_wait_vblank *vblwait = data;
+       struct timeval now;
+       int ret = 0;
+       unsigned int flags, seq;
+
+       if ((!dev->irq) || (!dev->irq_enabled))
+               return -EINVAL;
+
+       if (vblwait->request.type &
+           ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
+               DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
+                         vblwait->request.type,
+                         (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
+               return -EINVAL;
+       }
+
+       flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
+
+       if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
+                                   DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
+               return -EINVAL;
+
+       seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
+                         : &dev->vbl_received);
+
+       switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
+       case _DRM_VBLANK_RELATIVE:
+               vblwait->request.sequence += seq;
+               vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
+       case _DRM_VBLANK_ABSOLUTE:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if ((flags & _DRM_VBLANK_NEXTONMISS) &&
+           (seq - vblwait->request.sequence) <= (1<<23)) {
+               vblwait->request.sequence = seq + 1;
+       }
+
+       if (flags & _DRM_VBLANK_SIGNAL) {
+               unsigned long irqflags;
+               struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
+                                     ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+               struct drm_vbl_sig *vbl_sig;
+
+               spin_lock_irqsave(&dev->vbl_lock, irqflags);
+
+               /* Check if this task has already scheduled the same signal
+                * for the same vblank sequence number; nothing to be done in
+                * that case
+                */
+               list_for_each_entry(vbl_sig, vbl_sigs, head) {
+                       if (vbl_sig->sequence == vblwait->request.sequence
+                           && vbl_sig->info.si_signo ==
+                           vblwait->request.signal
+                           && vbl_sig->task == current) {
+                               spin_unlock_irqrestore(&dev->vbl_lock,
+                                                      irqflags);
+                               vblwait->reply.sequence = seq;
+                               goto done;
+                       }
+               }
+
+               if (dev->vbl_pending >= 100) {
+                       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+                       return -EBUSY;
+               }
+
+               dev->vbl_pending++;
+
+               spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+               if (!
+                   (vbl_sig =
+                    drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
+                       return -ENOMEM;
+               }
+
+               memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
+
+               vbl_sig->sequence = vblwait->request.sequence;
+               vbl_sig->info.si_signo = vblwait->request.signal;
+               vbl_sig->task = current;
+
+               spin_lock_irqsave(&dev->vbl_lock, irqflags);
+
+               list_add_tail(&vbl_sig->head, vbl_sigs);
+
+               spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
+               vblwait->reply.sequence = seq;
+       } else {
+               if (flags & _DRM_VBLANK_SECONDARY) {
+                       if (dev->driver->vblank_wait2)
+                               ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
+               } else if (dev->driver->vblank_wait)
+                       ret =
+                           dev->driver->vblank_wait(dev,
+                                                    &vblwait->request.sequence);
+
+               do_gettimeofday(&now);
+               vblwait->reply.tval_sec = now.tv_sec;
+               vblwait->reply.tval_usec = now.tv_usec;
+       }
+
+      done:
+       return ret;
+}
+
+/**
+ * Send the VBLANK signals.
+ *
+ * \param dev DRM device.
+ *
+ * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
+void drm_vbl_send_signals(struct drm_device * dev)
+{
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&dev->vbl_lock, flags);
+
+       for (i = 0; i < 2; i++) {
+               struct drm_vbl_sig *vbl_sig, *tmp;
+               struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
+               unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
+                                                  &dev->vbl_received);
+
+               list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
+                       if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
+                               vbl_sig->info.si_code = vbl_seq;
+                               send_sig_info(vbl_sig->info.si_signo,
+                                             &vbl_sig->info, vbl_sig->task);
+
+                               list_del(&vbl_sig->head);
+
+                               drm_free(vbl_sig, sizeof(*vbl_sig),
+                                        DRM_MEM_DRIVER);
+
+                               dev->vbl_pending--;
+                       }
+               }
+       }
+
+       spin_unlock_irqrestore(&dev->vbl_lock, flags);
+}
+
+EXPORT_SYMBOL(drm_vbl_send_signals);
+
+/**
+ * Tasklet wrapper function.
+ *
+ * \param data DRM device in disguise.
+ *
+ * Attempts to grab the HW lock and calls the driver callback on success. On
+ * failure, leave the lock marked as contended so the callback can be called
+ * from drm_unlock().
+ */
+static void drm_locked_tasklet_func(unsigned long data)
+{
+       struct drm_device *dev = (struct drm_device *)data;
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev->tasklet_lock, irqflags);
+
+       if (!dev->locked_tasklet_func ||
+           !drm_lock_take(&dev->lock,
+                          DRM_KERNEL_CONTEXT)) {
+               spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+               return;
+       }
+
+       dev->lock.lock_time = jiffies;
+       atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
+
+       dev->locked_tasklet_func(dev);
+
+       drm_lock_free(&dev->lock,
+                     DRM_KERNEL_CONTEXT);
+
+       dev->locked_tasklet_func = NULL;
+
+       spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+}
+
+/**
+ * Schedule a tasklet to call back a driver hook with the HW lock held.
+ *
+ * \param dev DRM device.
+ * \param func Driver callback.
+ *
+ * This is intended for triggering actions that require the HW lock from an
+ * interrupt handler. The lock will be grabbed ASAP after the interrupt handler
+ * completes. Note that the callback may be called from interrupt or process
+ * context, it must not make any assumptions about this. Also, the HW lock will
+ * be held with the kernel context or any client context.
+ */
+void drm_locked_tasklet(struct drm_device *dev, void (*func)(struct drm_device *))
+{
+       unsigned long irqflags;
+       static DECLARE_TASKLET(drm_tasklet, drm_locked_tasklet_func, 0);
+
+       if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ) ||
+           test_bit(TASKLET_STATE_SCHED, &drm_tasklet.state))
+               return;
+
+       spin_lock_irqsave(&dev->tasklet_lock, irqflags);
+
+       if (dev->locked_tasklet_func) {
+               spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+               return;
+       }
+
+       dev->locked_tasklet_func = func;
+
+       spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+
+       drm_tasklet.data = (unsigned long)dev;
+
+       tasklet_hi_schedule(&drm_tasklet);
+}
+EXPORT_SYMBOL(drm_locked_tasklet);
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c
new file mode 100644 (file)
index 0000000..0998723
--- /dev/null
@@ -0,0 +1,391 @@
+/**
+ * \file drm_lock.c
+ * IOCTLs for locking
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+
+static int drm_notifier(void *priv);
+
+/**
+ * Lock ioctl.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_lock structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Add the current task to the lock wait queue, and attempt to take to lock.
+ */
+int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       DECLARE_WAITQUEUE(entry, current);
+       struct drm_lock *lock = data;
+       int ret = 0;
+
+       ++file_priv->lock_count;
+
+       if (lock->context == DRM_KERNEL_CONTEXT) {
+               DRM_ERROR("Process %d using kernel context %d\n",
+                         task_pid_nr(current), lock->context);
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
+                 lock->context, task_pid_nr(current),
+                 dev->lock.hw_lock->lock, lock->flags);
+
+       if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
+               if (lock->context < 0)
+                       return -EINVAL;
+
+       add_wait_queue(&dev->lock.lock_queue, &entry);
+       spin_lock_bh(&dev->lock.spinlock);
+       dev->lock.user_waiters++;
+       spin_unlock_bh(&dev->lock.spinlock);
+       for (;;) {
+               __set_current_state(TASK_INTERRUPTIBLE);
+               if (!dev->lock.hw_lock) {
+                       /* Device has been unregistered */
+                       ret = -EINTR;
+                       break;
+               }
+               if (drm_lock_take(&dev->lock, lock->context)) {
+                       dev->lock.file_priv = file_priv;
+                       dev->lock.lock_time = jiffies;
+                       atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
+                       break;  /* Got lock */
+               }
+
+               /* Contention */
+               schedule();
+               if (signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       break;
+               }
+       }
+       spin_lock_bh(&dev->lock.spinlock);
+       dev->lock.user_waiters--;
+       spin_unlock_bh(&dev->lock.spinlock);
+       __set_current_state(TASK_RUNNING);
+       remove_wait_queue(&dev->lock.lock_queue, &entry);
+
+       DRM_DEBUG("%d %s\n", lock->context,
+                 ret ? "interrupted" : "has lock");
+       if (ret) return ret;
+
+       sigemptyset(&dev->sigmask);
+       sigaddset(&dev->sigmask, SIGSTOP);
+       sigaddset(&dev->sigmask, SIGTSTP);
+       sigaddset(&dev->sigmask, SIGTTIN);
+       sigaddset(&dev->sigmask, SIGTTOU);
+       dev->sigdata.context = lock->context;
+       dev->sigdata.lock = dev->lock.hw_lock;
+       block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
+
+       if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY))
+               dev->driver->dma_ready(dev);
+
+       if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT))
+       {
+               if (dev->driver->dma_quiescent(dev)) {
+                       DRM_DEBUG("%d waiting for DMA quiescent\n",
+                                 lock->context);
+                       return -EBUSY;
+               }
+       }
+
+       if (dev->driver->kernel_context_switch &&
+           dev->last_context != lock->context) {
+               dev->driver->kernel_context_switch(dev, dev->last_context,
+                                                  lock->context);
+       }
+
+       return 0;
+}
+
+/**
+ * Unlock ioctl.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_lock structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Transfer and free the lock.
+ */
+int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_lock *lock = data;
+       unsigned long irqflags;
+
+       if (lock->context == DRM_KERNEL_CONTEXT) {
+               DRM_ERROR("Process %d using kernel context %d\n",
+                         task_pid_nr(current), lock->context);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&dev->tasklet_lock, irqflags);
+
+       if (dev->locked_tasklet_func) {
+               dev->locked_tasklet_func(dev);
+
+               dev->locked_tasklet_func = NULL;
+       }
+
+       spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
+
+       atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);
+
+       /* kernel_context_switch isn't used by any of the x86 drm
+        * modules but is required by the Sparc driver.
+        */
+       if (dev->driver->kernel_context_switch_unlock)
+               dev->driver->kernel_context_switch_unlock(dev);
+       else {
+               if (drm_lock_free(&dev->lock,lock->context)) {
+                       /* FIXME: Should really bail out here. */
+               }
+       }
+
+       unblock_all_signals();
+       return 0;
+}
+
+/**
+ * Take the heavyweight lock.
+ *
+ * \param lock lock pointer.
+ * \param context locking context.
+ * \return one if the lock is held, or zero otherwise.
+ *
+ * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction.
+ */
+int drm_lock_take(struct drm_lock_data *lock_data,
+                 unsigned int context)
+{
+       unsigned int old, new, prev;
+       volatile unsigned int *lock = &lock_data->hw_lock->lock;
+
+       spin_lock_bh(&lock_data->spinlock);
+       do {
+               old = *lock;
+               if (old & _DRM_LOCK_HELD)
+                       new = old | _DRM_LOCK_CONT;
+               else {
+                       new = context | _DRM_LOCK_HELD |
+                               ((lock_data->user_waiters + lock_data->kernel_waiters > 1) ?
+                                _DRM_LOCK_CONT : 0);
+               }
+               prev = cmpxchg(lock, old, new);
+       } while (prev != old);
+       spin_unlock_bh(&lock_data->spinlock);
+
+       if (_DRM_LOCKING_CONTEXT(old) == context) {
+               if (old & _DRM_LOCK_HELD) {
+                       if (context != DRM_KERNEL_CONTEXT) {
+                               DRM_ERROR("%d holds heavyweight lock\n",
+                                         context);
+                       }
+                       return 0;
+               }
+       }
+
+       if ((_DRM_LOCKING_CONTEXT(new)) == context && (new & _DRM_LOCK_HELD)) {
+               /* Have lock */
+               return 1;
+       }
+       return 0;
+}
+
+/**
+ * This takes a lock forcibly and hands it to context. Should ONLY be used
+ * inside *_unlock to give lock to kernel before calling *_dma_schedule.
+ *
+ * \param dev DRM device.
+ * \param lock lock pointer.
+ * \param context locking context.
+ * \return always one.
+ *
+ * Resets the lock file pointer.
+ * Marks the lock as held by the given context, via the \p cmpxchg instruction.
+ */
+static int drm_lock_transfer(struct drm_lock_data *lock_data,
+                            unsigned int context)
+{
+       unsigned int old, new, prev;
+       volatile unsigned int *lock = &lock_data->hw_lock->lock;
+
+       lock_data->file_priv = NULL;
+       do {
+               old = *lock;
+               new = context | _DRM_LOCK_HELD;
+               prev = cmpxchg(lock, old, new);
+       } while (prev != old);
+       return 1;
+}
+
+/**
+ * Free lock.
+ *
+ * \param dev DRM device.
+ * \param lock lock.
+ * \param context context.
+ *
+ * Resets the lock file pointer.
+ * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
+ * waiting on the lock queue.
+ */
+int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
+{
+       unsigned int old, new, prev;
+       volatile unsigned int *lock = &lock_data->hw_lock->lock;
+
+       spin_lock_bh(&lock_data->spinlock);
+       if (lock_data->kernel_waiters != 0) {
+               drm_lock_transfer(lock_data, 0);
+               lock_data->idle_has_lock = 1;
+               spin_unlock_bh(&lock_data->spinlock);
+               return 1;
+       }
+       spin_unlock_bh(&lock_data->spinlock);
+
+       do {
+               old = *lock;
+               new = _DRM_LOCKING_CONTEXT(old);
+               prev = cmpxchg(lock, old, new);
+       } while (prev != old);
+
+       if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) {
+               DRM_ERROR("%d freed heavyweight lock held by %d\n",
+                         context, _DRM_LOCKING_CONTEXT(old));
+               return 1;
+       }
+       wake_up_interruptible(&lock_data->lock_queue);
+       return 0;
+}
+
+/**
+ * If we get here, it means that the process has called DRM_IOCTL_LOCK
+ * without calling DRM_IOCTL_UNLOCK.
+ *
+ * If the lock is not held, then let the signal proceed as usual.  If the lock
+ * is held, then set the contended flag and keep the signal blocked.
+ *
+ * \param priv pointer to a drm_sigdata structure.
+ * \return one if the signal should be delivered normally, or zero if the
+ * signal should be blocked.
+ */
+static int drm_notifier(void *priv)
+{
+       struct drm_sigdata *s = (struct drm_sigdata *) priv;
+       unsigned int old, new, prev;
+
+       /* Allow signal delivery if lock isn't held */
+       if (!s->lock || !_DRM_LOCK_IS_HELD(s->lock->lock)
+           || _DRM_LOCKING_CONTEXT(s->lock->lock) != s->context)
+               return 1;
+
+       /* Otherwise, set flag to force call to
+          drmUnlock */
+       do {
+               old = s->lock->lock;
+               new = old | _DRM_LOCK_CONT;
+               prev = cmpxchg(&s->lock->lock, old, new);
+       } while (prev != old);
+       return 0;
+}
+
+/**
+ * This function returns immediately and takes the hw lock
+ * with the kernel context if it is free, otherwise it gets the highest priority when and if
+ * it is eventually released.
+ *
+ * This guarantees that the kernel will _eventually_ have the lock _unless_ it is held
+ * by a blocked process. (In the latter case an explicit wait for the hardware lock would cause
+ * a deadlock, which is why the "idlelock" was invented).
+ *
+ * This should be sufficient to wait for GPU idle without
+ * having to worry about starvation.
+ */
+
+void drm_idlelock_take(struct drm_lock_data *lock_data)
+{
+       int ret = 0;
+
+       spin_lock_bh(&lock_data->spinlock);
+       lock_data->kernel_waiters++;
+       if (!lock_data->idle_has_lock) {
+
+               spin_unlock_bh(&lock_data->spinlock);
+               ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT);
+               spin_lock_bh(&lock_data->spinlock);
+
+               if (ret == 1)
+                       lock_data->idle_has_lock = 1;
+       }
+       spin_unlock_bh(&lock_data->spinlock);
+}
+EXPORT_SYMBOL(drm_idlelock_take);
+
+void drm_idlelock_release(struct drm_lock_data *lock_data)
+{
+       unsigned int old, prev;
+       volatile unsigned int *lock = &lock_data->hw_lock->lock;
+
+       spin_lock_bh(&lock_data->spinlock);
+       if (--lock_data->kernel_waiters == 0) {
+               if (lock_data->idle_has_lock) {
+                       do {
+                               old = *lock;
+                               prev = cmpxchg(lock, old, DRM_KERNEL_CONTEXT);
+                       } while (prev != old);
+                       wake_up_interruptible(&lock_data->lock_queue);
+                       lock_data->idle_has_lock = 0;
+               }
+       }
+       spin_unlock_bh(&lock_data->spinlock);
+}
+EXPORT_SYMBOL(drm_idlelock_release);
+
+
+int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv)
+{
+       return (file_priv->lock_count && dev->lock.hw_lock &&
+               _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
+               dev->lock.file_priv == file_priv);
+}
+
+EXPORT_SYMBOL(drm_i_have_hw_lock);
diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c
new file mode 100644 (file)
index 0000000..845081b
--- /dev/null
@@ -0,0 +1,181 @@
+/**
+ * \file drm_memory.c
+ * Memory management wrappers for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Thu Feb  4 14:00:34 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/highmem.h>
+#include "drmP.h"
+
+#ifdef DEBUG_MEMORY
+#include "drm_memory_debug.h"
+#else
+
+/** No-op. */
+void drm_mem_init(void)
+{
+}
+
+/**
+ * Called when "/proc/dri/%dev%/mem" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param len requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ *
+ * No-op.
+ */
+int drm_mem_info(char *buf, char **start, off_t offset,
+                int len, int *eof, void *data)
+{
+       return 0;
+}
+
+/** Wrapper around kmalloc() and kfree() */
+void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
+{
+       void *pt;
+
+       if (!(pt = kmalloc(size, GFP_KERNEL)))
+               return NULL;
+       if (oldpt && oldsize) {
+               memcpy(pt, oldpt, oldsize);
+               kfree(oldpt);
+       }
+       return pt;
+}
+
+#if __OS_HAS_AGP
+static void *agp_remap(unsigned long offset, unsigned long size,
+                      struct drm_device * dev)
+{
+       unsigned long *phys_addr_map, i, num_pages =
+           PAGE_ALIGN(size) / PAGE_SIZE;
+       struct drm_agp_mem *agpmem;
+       struct page **page_map;
+       void *addr;
+
+       size = PAGE_ALIGN(size);
+
+#ifdef __alpha__
+       offset -= dev->hose->mem_space->start;
+#endif
+
+       list_for_each_entry(agpmem, &dev->agp->memory, head)
+               if (agpmem->bound <= offset
+                   && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
+                   (offset + size))
+                       break;
+       if (!agpmem)
+               return NULL;
+
+       /*
+        * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
+        * the CPU do not get remapped by the GART.  We fix this by using the kernel's
+        * page-table instead (that's probably faster anyhow...).
+        */
+       /* note: use vmalloc() because num_pages could be large... */
+       page_map = vmalloc(num_pages * sizeof(struct page *));
+       if (!page_map)
+               return NULL;
+
+       phys_addr_map =
+           agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
+       for (i = 0; i < num_pages; ++i)
+               page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
+       addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
+       vfree(page_map);
+
+       return addr;
+}
+
+/** Wrapper around agp_allocate_memory() */
+DRM_AGP_MEM *drm_alloc_agp(struct drm_device * dev, int pages, u32 type)
+{
+       return drm_agp_allocate_memory(dev->agp->bridge, pages, type);
+}
+
+/** Wrapper around agp_free_memory() */
+int drm_free_agp(DRM_AGP_MEM * handle, int pages)
+{
+       return drm_agp_free_memory(handle) ? 0 : -EINVAL;
+}
+
+/** Wrapper around agp_bind_memory() */
+int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start)
+{
+       return drm_agp_bind_memory(handle, start);
+}
+
+/** Wrapper around agp_unbind_memory() */
+int drm_unbind_agp(DRM_AGP_MEM * handle)
+{
+       return drm_agp_unbind_memory(handle);
+}
+
+#else  /*  __OS_HAS_AGP  */
+static inline void *agp_remap(unsigned long offset, unsigned long size,
+                             struct drm_device * dev)
+{
+       return NULL;
+}
+
+#endif                         /* agp */
+
+#endif                         /* debug_memory */
+
+void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
+{
+       if (drm_core_has_AGP(dev) &&
+           dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
+               map->handle = agp_remap(map->offset, map->size, dev);
+       else
+               map->handle = ioremap(map->offset, map->size);
+}
+EXPORT_SYMBOL(drm_core_ioremap);
+
+void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
+{
+       if (!map->handle || !map->size)
+               return;
+
+       if (drm_core_has_AGP(dev) &&
+           dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
+               vunmap(map->handle);
+       else
+               iounmap(map->handle);
+}
+EXPORT_SYMBOL(drm_core_ioremapfree);
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
new file mode 100644 (file)
index 0000000..dcff9e9
--- /dev/null
@@ -0,0 +1,295 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+
+/*
+ * Generic simple memory manager implementation. Intended to be used as a base
+ * class implementation for more advanced memory managers.
+ *
+ * Note that the algorithm used is quite simple and there might be substantial
+ * performance gains if a smarter free list is implemented. Currently it is just an
+ * unordered stack of free regions. This could easily be improved if an RB-tree
+ * is used instead. At least if we expect heavy fragmentation.
+ *
+ * Aligned allocations can also see improvement.
+ *
+ * Authors:
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "drmP.h"
+#include <linux/slab.h>
+
+unsigned long drm_mm_tail_space(struct drm_mm *mm)
+{
+       struct list_head *tail_node;
+       struct drm_mm_node *entry;
+
+       tail_node = mm->ml_entry.prev;
+       entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
+       if (!entry->free)
+               return 0;
+
+       return entry->size;
+}
+
+int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size)
+{
+       struct list_head *tail_node;
+       struct drm_mm_node *entry;
+
+       tail_node = mm->ml_entry.prev;
+       entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
+       if (!entry->free)
+               return -ENOMEM;
+
+       if (entry->size <= size)
+               return -ENOMEM;
+
+       entry->size -= size;
+       return 0;
+}
+
+
+static int drm_mm_create_tail_node(struct drm_mm *mm,
+                           unsigned long start,
+                           unsigned long size)
+{
+       struct drm_mm_node *child;
+
+       child = (struct drm_mm_node *)
+               drm_alloc(sizeof(*child), DRM_MEM_MM);
+       if (!child)
+               return -ENOMEM;
+
+       child->free = 1;
+       child->size = size;
+       child->start = start;
+       child->mm = mm;
+
+       list_add_tail(&child->ml_entry, &mm->ml_entry);
+       list_add_tail(&child->fl_entry, &mm->fl_entry);
+
+       return 0;
+}
+
+
+int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size)
+{
+       struct list_head *tail_node;
+       struct drm_mm_node *entry;
+
+       tail_node = mm->ml_entry.prev;
+       entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
+       if (!entry->free) {
+               return drm_mm_create_tail_node(mm, entry->start + entry->size, size);
+       }
+       entry->size += size;
+       return 0;
+}
+
+static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
+                                           unsigned long size)
+{
+       struct drm_mm_node *child;
+
+       child = (struct drm_mm_node *)
+               drm_alloc(sizeof(*child), DRM_MEM_MM);
+       if (!child)
+               return NULL;
+
+       INIT_LIST_HEAD(&child->fl_entry);
+
+       child->free = 0;
+       child->size = size;
+       child->start = parent->start;
+       child->mm = parent->mm;
+
+       list_add_tail(&child->ml_entry, &parent->ml_entry);
+       INIT_LIST_HEAD(&child->fl_entry);
+
+       parent->size -= size;
+       parent->start += size;
+       return child;
+}
+
+
+
+struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
+                               unsigned long size, unsigned alignment)
+{
+
+       struct drm_mm_node *align_splitoff = NULL;
+       struct drm_mm_node *child;
+       unsigned tmp = 0;
+
+       if (alignment)
+               tmp = parent->start % alignment;
+
+       if (tmp) {
+               align_splitoff = drm_mm_split_at_start(parent, alignment - tmp);
+               if (!align_splitoff)
+                       return NULL;
+       }
+
+       if (parent->size == size) {
+               list_del_init(&parent->fl_entry);
+               parent->free = 0;
+               return parent;
+       } else {
+               child = drm_mm_split_at_start(parent, size);
+       }
+
+       if (align_splitoff)
+               drm_mm_put_block(align_splitoff);
+
+       return child;
+}
+
+/*
+ * Put a block. Merge with the previous and / or next block if they are free.
+ * Otherwise add to the free stack.
+ */
+
+void drm_mm_put_block(struct drm_mm_node * cur)
+{
+
+       struct drm_mm *mm = cur->mm;
+       struct list_head *cur_head = &cur->ml_entry;
+       struct list_head *root_head = &mm->ml_entry;
+       struct drm_mm_node *prev_node = NULL;
+       struct drm_mm_node *next_node;
+
+       int merged = 0;
+
+       if (cur_head->prev != root_head) {
+               prev_node = list_entry(cur_head->prev, struct drm_mm_node, ml_entry);
+               if (prev_node->free) {
+                       prev_node->size += cur->size;
+                       merged = 1;
+               }
+       }
+       if (cur_head->next != root_head) {
+               next_node = list_entry(cur_head->next, struct drm_mm_node, ml_entry);
+               if (next_node->free) {
+                       if (merged) {
+                               prev_node->size += next_node->size;
+                               list_del(&next_node->ml_entry);
+                               list_del(&next_node->fl_entry);
+                               drm_free(next_node, sizeof(*next_node),
+                                        DRM_MEM_MM);
+                       } else {
+                               next_node->size += cur->size;
+                               next_node->start = cur->start;
+                               merged = 1;
+                       }
+               }
+       }
+       if (!merged) {
+               cur->free = 1;
+               list_add(&cur->fl_entry, &mm->fl_entry);
+       } else {
+               list_del(&cur->ml_entry);
+               drm_free(cur, sizeof(*cur), DRM_MEM_MM);
+       }
+}
+
+struct drm_mm_node *drm_mm_search_free(const struct drm_mm * mm,
+                                 unsigned long size,
+                                 unsigned alignment, int best_match)
+{
+       struct list_head *list;
+       const struct list_head *free_stack = &mm->fl_entry;
+       struct drm_mm_node *entry;
+       struct drm_mm_node *best;
+       unsigned long best_size;
+       unsigned wasted;
+
+       best = NULL;
+       best_size = ~0UL;
+
+       list_for_each(list, free_stack) {
+               entry = list_entry(list, struct drm_mm_node, fl_entry);
+               wasted = 0;
+
+               if (entry->size < size)
+                       continue;
+
+               if (alignment) {
+                       register unsigned tmp = entry->start % alignment;
+                       if (tmp)
+                               wasted += alignment - tmp;
+               }
+
+
+               if (entry->size >= size + wasted) {
+                       if (!best_match)
+                               return entry;
+                       if (size < best_size) {
+                               best = entry;
+                               best_size = entry->size;
+                       }
+               }
+       }
+
+       return best;
+}
+
+int drm_mm_clean(struct drm_mm * mm)
+{
+       struct list_head *head = &mm->ml_entry;
+
+       return (head->next->next == head);
+}
+
+int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
+{
+       INIT_LIST_HEAD(&mm->ml_entry);
+       INIT_LIST_HEAD(&mm->fl_entry);
+
+       return drm_mm_create_tail_node(mm, start, size);
+}
+
+
+void drm_mm_takedown(struct drm_mm * mm)
+{
+       struct list_head *bnode = mm->fl_entry.next;
+       struct drm_mm_node *entry;
+
+       entry = list_entry(bnode, struct drm_mm_node, fl_entry);
+
+       if (entry->ml_entry.next != &mm->ml_entry ||
+           entry->fl_entry.next != &mm->fl_entry) {
+               DRM_ERROR("Memory manager not clean. Delaying takedown\n");
+               return;
+       }
+
+       list_del(&entry->fl_entry);
+       list_del(&entry->ml_entry);
+
+       drm_free(entry, sizeof(*entry), DRM_MEM_MM);
+}
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
new file mode 100644 (file)
index 0000000..b55d5bc
--- /dev/null
@@ -0,0 +1,183 @@
+/* drm_pci.h -- PCI DMA memory management wrappers for DRM -*- linux-c -*- */
+/**
+ * \file drm_pci.c
+ * \brief Functions and ioctls to manage PCI memory
+ *
+ * \warning These interfaces aren't stable yet.
+ *
+ * \todo Implement the remaining ioctl's for the PCI pools.
+ * \todo The wrappers here are so thin that they would be better off inlined..
+ *
+ * \author José Fonseca <jrfonseca@tungstengraphics.com>
+ * \author Leif Delgass <ldelgass@retinalburn.net>
+ */
+
+/*
+ * Copyright 2003 José Fonseca.
+ * Copyright 2003 Leif Delgass.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include "drmP.h"
+
+/**********************************************************************/
+/** \name PCI memory */
+/*@{*/
+
+/**
+ * \brief Allocate a PCI consistent memory block, for DMA.
+ */
+drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align,
+                               dma_addr_t maxaddr)
+{
+       drm_dma_handle_t *dmah;
+#if 1
+       unsigned long addr;
+       size_t sz;
+#endif
+#ifdef DRM_DEBUG_MEMORY
+       int area = DRM_MEM_DMA;
+
+       spin_lock(&drm_mem_lock);
+       if ((drm_ram_used >> PAGE_SHIFT)
+           > (DRM_RAM_PERCENT * drm_ram_available) / 100) {
+               spin_unlock(&drm_mem_lock);
+               return 0;
+       }
+       spin_unlock(&drm_mem_lock);
+#endif
+
+       /* pci_alloc_consistent only guarantees alignment to the smallest
+        * PAGE_SIZE order which is greater than or equal to the requested size.
+        * Return NULL here for now to make sure nobody tries for larger alignment
+        */
+       if (align > size)
+               return NULL;
+
+       if (pci_set_dma_mask(dev->pdev, maxaddr) != 0) {
+               DRM_ERROR("Setting pci dma mask failed\n");
+               return NULL;
+       }
+
+       dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL);
+       if (!dmah)
+               return NULL;
+
+       dmah->size = size;
+       dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP);
+
+#ifdef DRM_DEBUG_MEMORY
+       if (dmah->vaddr == NULL) {
+               spin_lock(&drm_mem_lock);
+               ++drm_mem_stats[area].fail_count;
+               spin_unlock(&drm_mem_lock);
+               kfree(dmah);
+               return NULL;
+       }
+
+       spin_lock(&drm_mem_lock);
+       ++drm_mem_stats[area].succeed_count;
+       drm_mem_stats[area].bytes_allocated += size;
+       drm_ram_used += size;
+       spin_unlock(&drm_mem_lock);
+#else
+       if (dmah->vaddr == NULL) {
+               kfree(dmah);
+               return NULL;
+       }
+#endif
+
+       memset(dmah->vaddr, 0, size);
+
+       /* XXX - Is virt_to_page() legal for consistent mem? */
+       /* Reserve */
+       for (addr = (unsigned long)dmah->vaddr, sz = size;
+            sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+               SetPageReserved(virt_to_page(addr));
+       }
+
+       return dmah;
+}
+
+EXPORT_SYMBOL(drm_pci_alloc);
+
+/**
+ * \brief Free a PCI consistent memory block without freeing its descriptor.
+ *
+ * This function is for internal use in the Linux-specific DRM core code.
+ */
+void __drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
+{
+#if 1
+       unsigned long addr;
+       size_t sz;
+#endif
+#ifdef DRM_DEBUG_MEMORY
+       int area = DRM_MEM_DMA;
+       int alloc_count;
+       int free_count;
+#endif
+
+       if (!dmah->vaddr) {
+#ifdef DRM_DEBUG_MEMORY
+               DRM_MEM_ERROR(area, "Attempt to free address 0\n");
+#endif
+       } else {
+               /* XXX - Is virt_to_page() legal for consistent mem? */
+               /* Unreserve */
+               for (addr = (unsigned long)dmah->vaddr, sz = dmah->size;
+                    sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
+                       ClearPageReserved(virt_to_page(addr));
+               }
+               dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
+                                 dmah->busaddr);
+       }
+
+#ifdef DRM_DEBUG_MEMORY
+       spin_lock(&drm_mem_lock);
+       free_count = ++drm_mem_stats[area].free_count;
+       alloc_count = drm_mem_stats[area].succeed_count;
+       drm_mem_stats[area].bytes_freed += size;
+       drm_ram_used -= size;
+       spin_unlock(&drm_mem_lock);
+       if (free_count > alloc_count) {
+               DRM_MEM_ERROR(area,
+                             "Excess frees: %d frees, %d allocs\n",
+                             free_count, alloc_count);
+       }
+#endif
+
+}
+
+/**
+ * \brief Free a PCI consistent memory block
+ */
+void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
+{
+       __drm_pci_free(dev, dmah);
+       kfree(dmah);
+}
+
+EXPORT_SYMBOL(drm_pci_free);
+
+/*@}*/
diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c
new file mode 100644 (file)
index 0000000..93b1e04
--- /dev/null
@@ -0,0 +1,557 @@
+/**
+ * \file drm_proc.c
+ * /proc support for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ *
+ * \par Acknowledgements:
+ *    Matthew J Sottek <matthew.j.sottek@intel.com> sent in a patch to fix
+ *    the problem with the proc files not outputting all their information.
+ */
+
+/*
+ * Created: Mon Jan 11 09:48:47 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+
+static int drm_name_info(char *buf, char **start, off_t offset,
+                        int request, int *eof, void *data);
+static int drm_vm_info(char *buf, char **start, off_t offset,
+                      int request, int *eof, void *data);
+static int drm_clients_info(char *buf, char **start, off_t offset,
+                           int request, int *eof, void *data);
+static int drm_queues_info(char *buf, char **start, off_t offset,
+                          int request, int *eof, void *data);
+static int drm_bufs_info(char *buf, char **start, off_t offset,
+                        int request, int *eof, void *data);
+#if DRM_DEBUG_CODE
+static int drm_vma_info(char *buf, char **start, off_t offset,
+                       int request, int *eof, void *data);
+#endif
+
+/**
+ * Proc file list.
+ */
+static struct drm_proc_list {
+       const char *name;       /**< file name */
+       int (*f) (char *, char **, off_t, int, int *, void *);          /**< proc callback*/
+} drm_proc_list[] = {
+       {"name", drm_name_info},
+       {"mem", drm_mem_info},
+       {"vm", drm_vm_info},
+       {"clients", drm_clients_info},
+       {"queues", drm_queues_info},
+       {"bufs", drm_bufs_info},
+#if DRM_DEBUG_CODE
+       {"vma", drm_vma_info},
+#endif
+};
+
+#define DRM_PROC_ENTRIES ARRAY_SIZE(drm_proc_list)
+
+/**
+ * Initialize the DRI proc filesystem for a device.
+ *
+ * \param dev DRM device.
+ * \param minor device minor number.
+ * \param root DRI proc dir entry.
+ * \param dev_root resulting DRI device proc dir entry.
+ * \return root entry pointer on success, or NULL on failure.
+ *
+ * Create the DRI proc root entry "/proc/dri", the device proc root entry
+ * "/proc/dri/%minor%/", and each entry in proc_list as
+ * "/proc/dri/%minor%/%name%".
+ */
+int drm_proc_init(struct drm_minor *minor, int minor_id,
+                 struct proc_dir_entry *root)
+{
+       struct proc_dir_entry *ent;
+       int i, j;
+       char name[64];
+
+       sprintf(name, "%d", minor_id);
+       minor->dev_root = proc_mkdir(name, root);
+       if (!minor->dev_root) {
+               DRM_ERROR("Cannot create /proc/dri/%s\n", name);
+               return -1;
+       }
+
+       for (i = 0; i < DRM_PROC_ENTRIES; i++) {
+               ent = create_proc_entry(drm_proc_list[i].name,
+                                       S_IFREG | S_IRUGO, minor->dev_root);
+               if (!ent) {
+                       DRM_ERROR("Cannot create /proc/dri/%s/%s\n",
+                                 name, drm_proc_list[i].name);
+                       for (j = 0; j < i; j++)
+                               remove_proc_entry(drm_proc_list[i].name,
+                                                 minor->dev_root);
+                       remove_proc_entry(name, root);
+                       minor->dev_root = NULL;
+                       return -1;
+               }
+               ent->read_proc = drm_proc_list[i].f;
+               ent->data = minor;
+       }
+
+       return 0;
+}
+
+/**
+ * Cleanup the proc filesystem resources.
+ *
+ * \param minor device minor number.
+ * \param root DRI proc dir entry.
+ * \param dev_root DRI device proc dir entry.
+ * \return always zero.
+ *
+ * Remove all proc entries created by proc_init().
+ */
+int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root)
+{
+       int i;
+       char name[64];
+
+       if (!root || !minor->dev_root)
+               return 0;
+
+       for (i = 0; i < DRM_PROC_ENTRIES; i++)
+               remove_proc_entry(drm_proc_list[i].name, minor->dev_root);
+       sprintf(name, "%d", minor->index);
+       remove_proc_entry(name, root);
+
+       return 0;
+}
+
+/**
+ * Called when "/proc/dri/.../name" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ *
+ * Prints the device name together with the bus id if available.
+ */
+static int drm_name_info(char *buf, char **start, off_t offset, int request,
+                        int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int len = 0;
+
+       if (offset > DRM_PROC_LIMIT) {
+               *eof = 1;
+               return 0;
+       }
+
+       *start = &buf[offset];
+       *eof = 0;
+
+       if (dev->unique) {
+               DRM_PROC_PRINT("%s %s %s\n",
+                              dev->driver->pci_driver.name,
+                              pci_name(dev->pdev), dev->unique);
+       } else {
+               DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name,
+                              pci_name(dev->pdev));
+       }
+
+       if (len > request + offset)
+               return request;
+       *eof = 1;
+       return len - offset;
+}
+
+/**
+ * Called when "/proc/dri/.../vm" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ *
+ * Prints information about all mappings in drm_device::maplist.
+ */
+static int drm__vm_info(char *buf, char **start, off_t offset, int request,
+                       int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int len = 0;
+       struct drm_map *map;
+       struct drm_map_list *r_list;
+
+       /* Hardcoded from _DRM_FRAME_BUFFER,
+          _DRM_REGISTERS, _DRM_SHM, _DRM_AGP, and
+          _DRM_SCATTER_GATHER and _DRM_CONSISTENT */
+       const char *types[] = { "FB", "REG", "SHM", "AGP", "SG", "PCI" };
+       const char *type;
+       int i;
+
+       if (offset > DRM_PROC_LIMIT) {
+               *eof = 1;
+               return 0;
+       }
+
+       *start = &buf[offset];
+       *eof = 0;
+
+       DRM_PROC_PRINT("slot     offset       size type flags    "
+                      "address mtrr\n\n");
+       i = 0;
+       list_for_each_entry(r_list, &dev->maplist, head) {
+               map = r_list->map;
+               if (!map)
+                       continue;
+               if (map->type < 0 || map->type > 5)
+                       type = "??";
+               else
+                       type = types[map->type];
+               DRM_PROC_PRINT("%4d 0x%08lx 0x%08lx %4.4s  0x%02x 0x%08lx ",
+                              i,
+                              map->offset,
+                              map->size, type, map->flags,
+                              (unsigned long) r_list->user_token);
+               if (map->mtrr < 0) {
+                       DRM_PROC_PRINT("none\n");
+               } else {
+                       DRM_PROC_PRINT("%4d\n", map->mtrr);
+               }
+               i++;
+       }
+
+       if (len > request + offset)
+               return request;
+       *eof = 1;
+       return len - offset;
+}
+
+/**
+ * Simply calls _vm_info() while holding the drm_device::struct_mutex lock.
+ */
+static int drm_vm_info(char *buf, char **start, off_t offset, int request,
+                      int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm__vm_info(buf, start, offset, request, eof, data);
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+
+/**
+ * Called when "/proc/dri/.../queues" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
+static int drm__queues_info(char *buf, char **start, off_t offset,
+                           int request, int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int len = 0;
+       int i;
+       struct drm_queue *q;
+
+       if (offset > DRM_PROC_LIMIT) {
+               *eof = 1;
+               return 0;
+       }
+
+       *start = &buf[offset];
+       *eof = 0;
+
+       DRM_PROC_PRINT("  ctx/flags   use   fin"
+                      "   blk/rw/rwf  wait    flushed     queued"
+                      "      locks\n\n");
+       for (i = 0; i < dev->queue_count; i++) {
+               q = dev->queuelist[i];
+               atomic_inc(&q->use_count);
+               DRM_PROC_PRINT_RET(atomic_dec(&q->use_count),
+                                  "%5d/0x%03x %5d %5d"
+                                  " %5d/%c%c/%c%c%c %5Zd\n",
+                                  i,
+                                  q->flags,
+                                  atomic_read(&q->use_count),
+                                  atomic_read(&q->finalization),
+                                  atomic_read(&q->block_count),
+                                  atomic_read(&q->block_read) ? 'r' : '-',
+                                  atomic_read(&q->block_write) ? 'w' : '-',
+                                  waitqueue_active(&q->read_queue) ? 'r' : '-',
+                                  waitqueue_active(&q->
+                                                   write_queue) ? 'w' : '-',
+                                  waitqueue_active(&q->
+                                                   flush_queue) ? 'f' : '-',
+                                  DRM_BUFCOUNT(&q->waitlist));
+               atomic_dec(&q->use_count);
+       }
+
+       if (len > request + offset)
+               return request;
+       *eof = 1;
+       return len - offset;
+}
+
+/**
+ * Simply calls _queues_info() while holding the drm_device::struct_mutex lock.
+ */
+static int drm_queues_info(char *buf, char **start, off_t offset, int request,
+                          int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm__queues_info(buf, start, offset, request, eof, data);
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+
+/**
+ * Called when "/proc/dri/.../bufs" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
+static int drm__bufs_info(char *buf, char **start, off_t offset, int request,
+                         int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int len = 0;
+       struct drm_device_dma *dma = dev->dma;
+       int i;
+
+       if (!dma || offset > DRM_PROC_LIMIT) {
+               *eof = 1;
+               return 0;
+       }
+
+       *start = &buf[offset];
+       *eof = 0;
+
+       DRM_PROC_PRINT(" o     size count  free  segs pages    kB\n\n");
+       for (i = 0; i <= DRM_MAX_ORDER; i++) {
+               if (dma->bufs[i].buf_count)
+                       DRM_PROC_PRINT("%2d %8d %5d %5d %5d %5d %5ld\n",
+                                      i,
+                                      dma->bufs[i].buf_size,
+                                      dma->bufs[i].buf_count,
+                                      atomic_read(&dma->bufs[i]
+                                                  .freelist.count),
+                                      dma->bufs[i].seg_count,
+                                      dma->bufs[i].seg_count
+                                      * (1 << dma->bufs[i].page_order),
+                                      (dma->bufs[i].seg_count
+                                       * (1 << dma->bufs[i].page_order))
+                                      * PAGE_SIZE / 1024);
+       }
+       DRM_PROC_PRINT("\n");
+       for (i = 0; i < dma->buf_count; i++) {
+               if (i && !(i % 32))
+                       DRM_PROC_PRINT("\n");
+               DRM_PROC_PRINT(" %d", dma->buflist[i]->list);
+       }
+       DRM_PROC_PRINT("\n");
+
+       if (len > request + offset)
+               return request;
+       *eof = 1;
+       return len - offset;
+}
+
+/**
+ * Simply calls _bufs_info() while holding the drm_device::struct_mutex lock.
+ */
+static int drm_bufs_info(char *buf, char **start, off_t offset, int request,
+                        int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm__bufs_info(buf, start, offset, request, eof, data);
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+
+/**
+ * Called when "/proc/dri/.../clients" is read.
+ *
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
+static int drm__clients_info(char *buf, char **start, off_t offset,
+                            int request, int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int len = 0;
+       struct drm_file *priv;
+
+       if (offset > DRM_PROC_LIMIT) {
+               *eof = 1;
+               return 0;
+       }
+
+       *start = &buf[offset];
+       *eof = 0;
+
+       DRM_PROC_PRINT("a dev   pid    uid      magic     ioctls\n\n");
+       list_for_each_entry(priv, &dev->filelist, lhead) {
+               DRM_PROC_PRINT("%c %3d %5d %5d %10u %10lu\n",
+                              priv->authenticated ? 'y' : 'n',
+                              priv->minor->index,
+                              priv->pid,
+                              priv->uid, priv->magic, priv->ioctl_count);
+       }
+
+       if (len > request + offset)
+               return request;
+       *eof = 1;
+       return len - offset;
+}
+
+/**
+ * Simply calls _clients_info() while holding the drm_device::struct_mutex lock.
+ */
+static int drm_clients_info(char *buf, char **start, off_t offset,
+                           int request, int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm__clients_info(buf, start, offset, request, eof, data);
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+
+#if DRM_DEBUG_CODE
+
+static int drm__vma_info(char *buf, char **start, off_t offset, int request,
+                        int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int len = 0;
+       struct drm_vma_entry *pt;
+       struct vm_area_struct *vma;
+#if defined(__i386__)
+       unsigned int pgprot;
+#endif
+
+       if (offset > DRM_PROC_LIMIT) {
+               *eof = 1;
+               return 0;
+       }
+
+       *start = &buf[offset];
+       *eof = 0;
+
+       DRM_PROC_PRINT("vma use count: %d, high_memory = %p, 0x%08lx\n",
+                      atomic_read(&dev->vma_count),
+                      high_memory, virt_to_phys(high_memory));
+       list_for_each_entry(pt, &dev->vmalist, head) {
+               if (!(vma = pt->vma))
+                       continue;
+               DRM_PROC_PRINT("\n%5d 0x%08lx-0x%08lx %c%c%c%c%c%c 0x%08lx000",
+                              pt->pid,
+                              vma->vm_start,
+                              vma->vm_end,
+                              vma->vm_flags & VM_READ ? 'r' : '-',
+                              vma->vm_flags & VM_WRITE ? 'w' : '-',
+                              vma->vm_flags & VM_EXEC ? 'x' : '-',
+                              vma->vm_flags & VM_MAYSHARE ? 's' : 'p',
+                              vma->vm_flags & VM_LOCKED ? 'l' : '-',
+                              vma->vm_flags & VM_IO ? 'i' : '-',
+                              vma->vm_pgoff);
+
+#if defined(__i386__)
+               pgprot = pgprot_val(vma->vm_page_prot);
+               DRM_PROC_PRINT(" %c%c%c%c%c%c%c%c%c",
+                              pgprot & _PAGE_PRESENT ? 'p' : '-',
+                              pgprot & _PAGE_RW ? 'w' : 'r',
+                              pgprot & _PAGE_USER ? 'u' : 's',
+                              pgprot & _PAGE_PWT ? 't' : 'b',
+                              pgprot & _PAGE_PCD ? 'u' : 'c',
+                              pgprot & _PAGE_ACCESSED ? 'a' : '-',
+                              pgprot & _PAGE_DIRTY ? 'd' : '-',
+                              pgprot & _PAGE_PSE ? 'm' : 'k',
+                              pgprot & _PAGE_GLOBAL ? 'g' : 'l');
+#endif
+               DRM_PROC_PRINT("\n");
+       }
+
+       if (len > request + offset)
+               return request;
+       *eof = 1;
+       return len - offset;
+}
+
+static int drm_vma_info(char *buf, char **start, off_t offset, int request,
+                       int *eof, void *data)
+{
+       struct drm_minor *minor = (struct drm_minor *) data;
+       struct drm_device *dev = minor->dev;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm__vma_info(buf, start, offset, request, eof, data);
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+#endif
diff --git a/drivers/gpu/drm/drm_scatter.c b/drivers/gpu/drm/drm_scatter.c
new file mode 100644 (file)
index 0000000..b2b0f3d
--- /dev/null
@@ -0,0 +1,227 @@
+/**
+ * \file drm_scatter.c
+ * IOCTLs to manage scatter/gather memory
+ *
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/vmalloc.h>
+#include "drmP.h"
+
+#define DEBUG_SCATTER 0
+
+static inline void *drm_vmalloc_dma(unsigned long size)
+{
+#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE)
+       return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL | _PAGE_NO_CACHE);
+#else
+       return vmalloc_32(size);
+#endif
+}
+
+void drm_sg_cleanup(struct drm_sg_mem * entry)
+{
+       struct page *page;
+       int i;
+
+       for (i = 0; i < entry->pages; i++) {
+               page = entry->pagelist[i];
+               if (page)
+                       ClearPageReserved(page);
+       }
+
+       vfree(entry->virtual);
+
+       drm_free(entry->busaddr,
+                entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
+       drm_free(entry->pagelist,
+                entry->pages * sizeof(*entry->pagelist), DRM_MEM_PAGES);
+       drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+}
+
+#ifdef _LP64
+# define ScatterHandle(x) (unsigned int)((x >> 32) + (x & ((1L << 32) - 1)))
+#else
+# define ScatterHandle(x) (unsigned int)(x)
+#endif
+
+int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request)
+{
+       struct drm_sg_mem *entry;
+       unsigned long pages, i, j;
+
+       DRM_DEBUG("\n");
+
+       if (!drm_core_check_feature(dev, DRIVER_SG))
+               return -EINVAL;
+
+       if (dev->sg)
+               return -EINVAL;
+
+       entry = drm_alloc(sizeof(*entry), DRM_MEM_SGLISTS);
+       if (!entry)
+               return -ENOMEM;
+
+       memset(entry, 0, sizeof(*entry));
+       pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
+       DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages);
+
+       entry->pages = pages;
+       entry->pagelist = drm_alloc(pages * sizeof(*entry->pagelist),
+                                   DRM_MEM_PAGES);
+       if (!entry->pagelist) {
+               drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+               return -ENOMEM;
+       }
+
+       memset(entry->pagelist, 0, pages * sizeof(*entry->pagelist));
+
+       entry->busaddr = drm_alloc(pages * sizeof(*entry->busaddr),
+                                  DRM_MEM_PAGES);
+       if (!entry->busaddr) {
+               drm_free(entry->pagelist,
+                        entry->pages * sizeof(*entry->pagelist),
+                        DRM_MEM_PAGES);
+               drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+               return -ENOMEM;
+       }
+       memset((void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr));
+
+       entry->virtual = drm_vmalloc_dma(pages << PAGE_SHIFT);
+       if (!entry->virtual) {
+               drm_free(entry->busaddr,
+                        entry->pages * sizeof(*entry->busaddr), DRM_MEM_PAGES);
+               drm_free(entry->pagelist,
+                        entry->pages * sizeof(*entry->pagelist),
+                        DRM_MEM_PAGES);
+               drm_free(entry, sizeof(*entry), DRM_MEM_SGLISTS);
+               return -ENOMEM;
+       }
+
+       /* This also forces the mapping of COW pages, so our page list
+        * will be valid.  Please don't remove it...
+        */
+       memset(entry->virtual, 0, pages << PAGE_SHIFT);
+
+       entry->handle = ScatterHandle((unsigned long)entry->virtual);
+
+       DRM_DEBUG("handle  = %08lx\n", entry->handle);
+       DRM_DEBUG("virtual = %p\n", entry->virtual);
+
+       for (i = (unsigned long)entry->virtual, j = 0; j < pages;
+            i += PAGE_SIZE, j++) {
+               entry->pagelist[j] = vmalloc_to_page((void *)i);
+               if (!entry->pagelist[j])
+                       goto failed;
+               SetPageReserved(entry->pagelist[j]);
+       }
+
+       request->handle = entry->handle;
+
+       dev->sg = entry;
+
+#if DEBUG_SCATTER
+       /* Verify that each page points to its virtual address, and vice
+        * versa.
+        */
+       {
+               int error = 0;
+
+               for (i = 0; i < pages; i++) {
+                       unsigned long *tmp;
+
+                       tmp = page_address(entry->pagelist[i]);
+                       for (j = 0;
+                            j < PAGE_SIZE / sizeof(unsigned long);
+                            j++, tmp++) {
+                               *tmp = 0xcafebabe;
+                       }
+                       tmp = (unsigned long *)((u8 *) entry->virtual +
+                                               (PAGE_SIZE * i));
+                       for (j = 0;
+                            j < PAGE_SIZE / sizeof(unsigned long);
+                            j++, tmp++) {
+                               if (*tmp != 0xcafebabe && error == 0) {
+                                       error = 1;
+                                       DRM_ERROR("Scatter allocation error, "
+                                                 "pagelist does not match "
+                                                 "virtual mapping\n");
+                               }
+                       }
+                       tmp = page_address(entry->pagelist[i]);
+                       for (j = 0;
+                            j < PAGE_SIZE / sizeof(unsigned long);
+                            j++, tmp++) {
+                               *tmp = 0;
+                       }
+               }
+               if (error == 0)
+                       DRM_ERROR("Scatter allocation matches pagelist\n");
+       }
+#endif
+
+       return 0;
+
+      failed:
+       drm_sg_cleanup(entry);
+       return -ENOMEM;
+}
+EXPORT_SYMBOL(drm_sg_alloc);
+
+
+int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       struct drm_scatter_gather *request = data;
+
+       return drm_sg_alloc(dev, request);
+
+}
+
+int drm_sg_free(struct drm_device *dev, void *data,
+               struct drm_file *file_priv)
+{
+       struct drm_scatter_gather *request = data;
+       struct drm_sg_mem *entry;
+
+       if (!drm_core_check_feature(dev, DRIVER_SG))
+               return -EINVAL;
+
+       entry = dev->sg;
+       dev->sg = NULL;
+
+       if (!entry || entry->handle != request->handle)
+               return -EINVAL;
+
+       DRM_DEBUG("virtual  = %p\n", entry->virtual);
+
+       drm_sg_cleanup(entry);
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/drm_sman.c b/drivers/gpu/drm/drm_sman.c
new file mode 100644 (file)
index 0000000..926f146
--- /dev/null
@@ -0,0 +1,353 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck., ND., USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ *
+ **************************************************************************/
+/*
+ * Simple memory manager interface that keeps track on allocate regions on a
+ * per "owner" basis. All regions associated with an "owner" can be released
+ * with a simple call. Typically if the "owner" exists. The owner is any
+ * "unsigned long" identifier. Can typically be a pointer to a file private
+ * struct or a context identifier.
+ *
+ * Authors:
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "drm_sman.h"
+
+struct drm_owner_item {
+       struct drm_hash_item owner_hash;
+       struct list_head sman_list;
+       struct list_head mem_blocks;
+};
+
+void drm_sman_takedown(struct drm_sman * sman)
+{
+       drm_ht_remove(&sman->user_hash_tab);
+       drm_ht_remove(&sman->owner_hash_tab);
+       if (sman->mm)
+               drm_free(sman->mm, sman->num_managers * sizeof(*sman->mm),
+                        DRM_MEM_MM);
+}
+
+EXPORT_SYMBOL(drm_sman_takedown);
+
+int
+drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
+             unsigned int user_order, unsigned int owner_order)
+{
+       int ret = 0;
+
+       sman->mm = (struct drm_sman_mm *) drm_calloc(num_managers, sizeof(*sman->mm),
+                                               DRM_MEM_MM);
+       if (!sman->mm) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       sman->num_managers = num_managers;
+       INIT_LIST_HEAD(&sman->owner_items);
+       ret = drm_ht_create(&sman->owner_hash_tab, owner_order);
+       if (ret)
+               goto out1;
+       ret = drm_ht_create(&sman->user_hash_tab, user_order);
+       if (!ret)
+               goto out;
+
+       drm_ht_remove(&sman->owner_hash_tab);
+out1:
+       drm_free(sman->mm, num_managers * sizeof(*sman->mm), DRM_MEM_MM);
+out:
+       return ret;
+}
+
+EXPORT_SYMBOL(drm_sman_init);
+
+static void *drm_sman_mm_allocate(void *private, unsigned long size,
+                                 unsigned alignment)
+{
+       struct drm_mm *mm = (struct drm_mm *) private;
+       struct drm_mm_node *tmp;
+
+       tmp = drm_mm_search_free(mm, size, alignment, 1);
+       if (!tmp) {
+               return NULL;
+       }
+       tmp = drm_mm_get_block(tmp, size, alignment);
+       return tmp;
+}
+
+static void drm_sman_mm_free(void *private, void *ref)
+{
+       struct drm_mm_node *node = (struct drm_mm_node *) ref;
+
+       drm_mm_put_block(node);
+}
+
+static void drm_sman_mm_destroy(void *private)
+{
+       struct drm_mm *mm = (struct drm_mm *) private;
+       drm_mm_takedown(mm);
+       drm_free(mm, sizeof(*mm), DRM_MEM_MM);
+}
+
+static unsigned long drm_sman_mm_offset(void *private, void *ref)
+{
+       struct drm_mm_node *node = (struct drm_mm_node *) ref;
+       return node->start;
+}
+
+int
+drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
+                  unsigned long start, unsigned long size)
+{
+       struct drm_sman_mm *sman_mm;
+       struct drm_mm *mm;
+       int ret;
+
+       BUG_ON(manager >= sman->num_managers);
+
+       sman_mm = &sman->mm[manager];
+       mm = drm_calloc(1, sizeof(*mm), DRM_MEM_MM);
+       if (!mm) {
+               return -ENOMEM;
+       }
+       sman_mm->private = mm;
+       ret = drm_mm_init(mm, start, size);
+
+       if (ret) {
+               drm_free(mm, sizeof(*mm), DRM_MEM_MM);
+               return ret;
+       }
+
+       sman_mm->allocate = drm_sman_mm_allocate;
+       sman_mm->free = drm_sman_mm_free;
+       sman_mm->destroy = drm_sman_mm_destroy;
+       sman_mm->offset = drm_sman_mm_offset;
+
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_sman_set_range);
+
+int
+drm_sman_set_manager(struct drm_sman * sman, unsigned int manager,
+                    struct drm_sman_mm * allocator)
+{
+       BUG_ON(manager >= sman->num_managers);
+       sman->mm[manager] = *allocator;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_sman_set_manager);
+
+static struct drm_owner_item *drm_sman_get_owner_item(struct drm_sman * sman,
+                                                unsigned long owner)
+{
+       int ret;
+       struct drm_hash_item *owner_hash_item;
+       struct drm_owner_item *owner_item;
+
+       ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item);
+       if (!ret) {
+               return drm_hash_entry(owner_hash_item, struct drm_owner_item,
+                                     owner_hash);
+       }
+
+       owner_item = drm_calloc(1, sizeof(*owner_item), DRM_MEM_MM);
+       if (!owner_item)
+               goto out;
+
+       INIT_LIST_HEAD(&owner_item->mem_blocks);
+       owner_item->owner_hash.key = owner;
+       if (drm_ht_insert_item(&sman->owner_hash_tab, &owner_item->owner_hash))
+               goto out1;
+
+       list_add_tail(&owner_item->sman_list, &sman->owner_items);
+       return owner_item;
+
+out1:
+       drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
+out:
+       return NULL;
+}
+
+struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int manager,
+                                   unsigned long size, unsigned alignment,
+                                   unsigned long owner)
+{
+       void *tmp;
+       struct drm_sman_mm *sman_mm;
+       struct drm_owner_item *owner_item;
+       struct drm_memblock_item *memblock;
+
+       BUG_ON(manager >= sman->num_managers);
+
+       sman_mm = &sman->mm[manager];
+       tmp = sman_mm->allocate(sman_mm->private, size, alignment);
+
+       if (!tmp) {
+               return NULL;
+       }
+
+       memblock = drm_calloc(1, sizeof(*memblock), DRM_MEM_MM);
+
+       if (!memblock)
+               goto out;
+
+       memblock->mm_info = tmp;
+       memblock->mm = sman_mm;
+       memblock->sman = sman;
+
+       if (drm_ht_just_insert_please
+           (&sman->user_hash_tab, &memblock->user_hash,
+            (unsigned long)memblock, 32, 0, 0))
+               goto out1;
+
+       owner_item = drm_sman_get_owner_item(sman, owner);
+       if (!owner_item)
+               goto out2;
+
+       list_add_tail(&memblock->owner_list, &owner_item->mem_blocks);
+
+       return memblock;
+
+out2:
+       drm_ht_remove_item(&sman->user_hash_tab, &memblock->user_hash);
+out1:
+       drm_free(memblock, sizeof(*memblock), DRM_MEM_MM);
+out:
+       sman_mm->free(sman_mm->private, tmp);
+
+       return NULL;
+}
+
+EXPORT_SYMBOL(drm_sman_alloc);
+
+static void drm_sman_free(struct drm_memblock_item *item)
+{
+       struct drm_sman *sman = item->sman;
+
+       list_del(&item->owner_list);
+       drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash);
+       item->mm->free(item->mm->private, item->mm_info);
+       drm_free(item, sizeof(*item), DRM_MEM_MM);
+}
+
+int drm_sman_free_key(struct drm_sman *sman, unsigned int key)
+{
+       struct drm_hash_item *hash_item;
+       struct drm_memblock_item *memblock_item;
+
+       if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item))
+               return -EINVAL;
+
+       memblock_item = drm_hash_entry(hash_item, struct drm_memblock_item,
+                                      user_hash);
+       drm_sman_free(memblock_item);
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_sman_free_key);
+
+static void drm_sman_remove_owner(struct drm_sman *sman,
+                                 struct drm_owner_item *owner_item)
+{
+       list_del(&owner_item->sman_list);
+       drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash);
+       drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM);
+}
+
+int drm_sman_owner_clean(struct drm_sman *sman, unsigned long owner)
+{
+
+       struct drm_hash_item *hash_item;
+       struct drm_owner_item *owner_item;
+
+       if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
+               return -1;
+       }
+
+       owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
+       if (owner_item->mem_blocks.next == &owner_item->mem_blocks) {
+               drm_sman_remove_owner(sman, owner_item);
+               return -1;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL(drm_sman_owner_clean);
+
+static void drm_sman_do_owner_cleanup(struct drm_sman *sman,
+                                     struct drm_owner_item *owner_item)
+{
+       struct drm_memblock_item *entry, *next;
+
+       list_for_each_entry_safe(entry, next, &owner_item->mem_blocks,
+                                owner_list) {
+               drm_sman_free(entry);
+       }
+       drm_sman_remove_owner(sman, owner_item);
+}
+
+void drm_sman_owner_cleanup(struct drm_sman *sman, unsigned long owner)
+{
+
+       struct drm_hash_item *hash_item;
+       struct drm_owner_item *owner_item;
+
+       if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) {
+
+               return;
+       }
+
+       owner_item = drm_hash_entry(hash_item, struct drm_owner_item, owner_hash);
+       drm_sman_do_owner_cleanup(sman, owner_item);
+}
+
+EXPORT_SYMBOL(drm_sman_owner_cleanup);
+
+void drm_sman_cleanup(struct drm_sman *sman)
+{
+       struct drm_owner_item *entry, *next;
+       unsigned int i;
+       struct drm_sman_mm *sman_mm;
+
+       list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) {
+               drm_sman_do_owner_cleanup(sman, entry);
+       }
+       if (sman->mm) {
+               for (i = 0; i < sman->num_managers; ++i) {
+                       sman_mm = &sman->mm[i];
+                       if (sman_mm->private) {
+                               sman_mm->destroy(sman_mm->private);
+                               sman_mm->private = NULL;
+                       }
+               }
+       }
+}
+
+EXPORT_SYMBOL(drm_sman_cleanup);
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
new file mode 100644 (file)
index 0000000..c2f584f
--- /dev/null
@@ -0,0 +1,331 @@
+/**
+ * \file drm_stub.h
+ * Stub support
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ */
+
+/*
+ * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
+ *
+ * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include "drmP.h"
+#include "drm_core.h"
+
+unsigned int drm_debug = 0;    /* 1 to enable debug output */
+EXPORT_SYMBOL(drm_debug);
+
+MODULE_AUTHOR(CORE_AUTHOR);
+MODULE_DESCRIPTION(CORE_DESC);
+MODULE_LICENSE("GPL and additional rights");
+MODULE_PARM_DESC(debug, "Enable debug output");
+
+module_param_named(debug, drm_debug, int, 0600);
+
+struct idr drm_minors_idr;
+
+struct class *drm_class;
+struct proc_dir_entry *drm_proc_root;
+
+static int drm_minor_get_id(struct drm_device *dev, int type)
+{
+       int new_id;
+       int ret;
+       int base = 0, limit = 63;
+
+again:
+       if (idr_pre_get(&drm_minors_idr, GFP_KERNEL) == 0) {
+               DRM_ERROR("Out of memory expanding drawable idr\n");
+               return -ENOMEM;
+       }
+       mutex_lock(&dev->struct_mutex);
+       ret = idr_get_new_above(&drm_minors_idr, NULL,
+                               base, &new_id);
+       mutex_unlock(&dev->struct_mutex);
+       if (ret == -EAGAIN) {
+               goto again;
+       } else if (ret) {
+               return ret;
+       }
+
+       if (new_id >= limit) {
+               idr_remove(&drm_minors_idr, new_id);
+               return -EINVAL;
+       }
+       return new_id;
+}
+
+static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
+                          const struct pci_device_id *ent,
+                          struct drm_driver *driver)
+{
+       int retcode;
+
+       INIT_LIST_HEAD(&dev->filelist);
+       INIT_LIST_HEAD(&dev->ctxlist);
+       INIT_LIST_HEAD(&dev->vmalist);
+       INIT_LIST_HEAD(&dev->maplist);
+
+       spin_lock_init(&dev->count_lock);
+       spin_lock_init(&dev->drw_lock);
+       spin_lock_init(&dev->tasklet_lock);
+       spin_lock_init(&dev->lock.spinlock);
+       init_timer(&dev->timer);
+       mutex_init(&dev->struct_mutex);
+       mutex_init(&dev->ctxlist_mutex);
+
+       idr_init(&dev->drw_idr);
+
+       dev->pdev = pdev;
+       dev->pci_device = pdev->device;
+       dev->pci_vendor = pdev->vendor;
+
+#ifdef __alpha__
+       dev->hose = pdev->sysdata;
+#endif
+       dev->irq = pdev->irq;
+
+       if (drm_ht_create(&dev->map_hash, 12)) {
+               return -ENOMEM;
+       }
+
+       /* the DRM has 6 basic counters */
+       dev->counters = 6;
+       dev->types[0] = _DRM_STAT_LOCK;
+       dev->types[1] = _DRM_STAT_OPENS;
+       dev->types[2] = _DRM_STAT_CLOSES;
+       dev->types[3] = _DRM_STAT_IOCTLS;
+       dev->types[4] = _DRM_STAT_LOCKS;
+       dev->types[5] = _DRM_STAT_UNLOCKS;
+
+       dev->driver = driver;
+
+       if (drm_core_has_AGP(dev)) {
+               if (drm_device_is_agp(dev))
+                       dev->agp = drm_agp_init(dev);
+               if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
+                   && (dev->agp == NULL)) {
+                       DRM_ERROR("Cannot initialize the agpgart module.\n");
+                       retcode = -EINVAL;
+                       goto error_out_unreg;
+               }
+               if (drm_core_has_MTRR(dev)) {
+                       if (dev->agp)
+                               dev->agp->agp_mtrr =
+                                   mtrr_add(dev->agp->agp_info.aper_base,
+                                            dev->agp->agp_info.aper_size *
+                                            1024 * 1024, MTRR_TYPE_WRCOMB, 1);
+               }
+       }
+
+       if (dev->driver->load)
+               if ((retcode = dev->driver->load(dev, ent->driver_data)))
+                       goto error_out_unreg;
+
+       retcode = drm_ctxbitmap_init(dev);
+       if (retcode) {
+               DRM_ERROR("Cannot allocate memory for context bitmap.\n");
+               goto error_out_unreg;
+       }
+
+       return 0;
+
+      error_out_unreg:
+       drm_lastclose(dev);
+       return retcode;
+}
+
+
+/**
+ * Get a secondary minor number.
+ *
+ * \param dev device data structure
+ * \param sec-minor structure to hold the assigned minor
+ * \return negative number on failure.
+ *
+ * Search an empty entry and initialize it to the given parameters, and
+ * create the proc init entry via proc_init(). This routines assigns
+ * minor numbers to secondary heads of multi-headed cards
+ */
+static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
+{
+       struct drm_minor *new_minor;
+       int ret;
+       int minor_id;
+
+       DRM_DEBUG("\n");
+
+       minor_id = drm_minor_get_id(dev, type);
+       if (minor_id < 0)
+               return minor_id;
+
+       new_minor = kzalloc(sizeof(struct drm_minor), GFP_KERNEL);
+       if (!new_minor) {
+               ret = -ENOMEM;
+               goto err_idr;
+       }
+
+       new_minor->type = type;
+       new_minor->device = MKDEV(DRM_MAJOR, minor_id);
+       new_minor->dev = dev;
+       new_minor->index = minor_id;
+
+       idr_replace(&drm_minors_idr, new_minor, minor_id);
+
+       if (type == DRM_MINOR_LEGACY) {
+               ret = drm_proc_init(new_minor, minor_id, drm_proc_root);
+               if (ret) {
+                       DRM_ERROR("DRM: Failed to initialize /proc/dri.\n");
+                       goto err_mem;
+               }
+       } else
+               new_minor->dev_root = NULL;
+
+       ret = drm_sysfs_device_add(new_minor);
+       if (ret) {
+               printk(KERN_ERR
+                      "DRM: Error sysfs_device_add.\n");
+               goto err_g2;
+       }
+       *minor = new_minor;
+
+       DRM_DEBUG("new minor assigned %d\n", minor_id);
+       return 0;
+
+
+err_g2:
+       if (new_minor->type == DRM_MINOR_LEGACY)
+               drm_proc_cleanup(new_minor, drm_proc_root);
+err_mem:
+       kfree(new_minor);
+err_idr:
+       idr_remove(&drm_minors_idr, minor_id);
+       *minor = NULL;
+       return ret;
+}
+
+/**
+ * Register.
+ *
+ * \param pdev - PCI device structure
+ * \param ent entry from the PCI ID table with device type flags
+ * \return zero on success or a negative number on failure.
+ *
+ * Attempt to gets inter module "drm" information. If we are first
+ * then register the character device and inter module information.
+ * Try and register, if we fail to register, backout previous work.
+ */
+int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+               struct drm_driver *driver)
+{
+       struct drm_device *dev;
+       int ret;
+
+       DRM_DEBUG("\n");
+
+       dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
+       if (!dev)
+               return -ENOMEM;
+
+       ret = pci_enable_device(pdev);
+       if (ret)
+               goto err_g1;
+
+       pci_set_master(pdev);
+       if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
+               printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
+               goto err_g2;
+       }
+       if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
+               goto err_g2;
+
+       DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+                driver->name, driver->major, driver->minor, driver->patchlevel,
+                driver->date, dev->primary->index);
+
+       return 0;
+
+err_g2:
+       pci_disable_device(pdev);
+err_g1:
+       drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+       return ret;
+}
+
+/**
+ * Put a device minor number.
+ *
+ * \param dev device data structure
+ * \return always zero
+ *
+ * Cleans up the proc resources. If it is the last minor then release the foreign
+ * "drm" data, otherwise unregisters the "drm" data, frees the dev list and
+ * unregisters the character device.
+ */
+int drm_put_dev(struct drm_device * dev)
+{
+       DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
+
+       if (dev->unique) {
+               drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
+               dev->unique = NULL;
+               dev->unique_len = 0;
+       }
+       if (dev->devname) {
+               drm_free(dev->devname, strlen(dev->devname) + 1,
+                        DRM_MEM_DRIVER);
+               dev->devname = NULL;
+       }
+       drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+       return 0;
+}
+
+/**
+ * Put a secondary minor number.
+ *
+ * \param sec_minor - structure to be released
+ * \return always zero
+ *
+ * Cleans up the proc resources. Not legal for this to be the
+ * last minor released.
+ *
+ */
+int drm_put_minor(struct drm_minor **minor_p)
+{
+       struct drm_minor *minor = *minor_p;
+       DRM_DEBUG("release secondary minor %d\n", minor->index);
+
+       if (minor->type == DRM_MINOR_LEGACY)
+               drm_proc_cleanup(minor, drm_proc_root);
+       drm_sysfs_device_remove(minor);
+
+       idr_remove(&drm_minors_idr, minor->index);
+
+       kfree(minor);
+       *minor_p = NULL;
+       return 0;
+}
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
new file mode 100644 (file)
index 0000000..af211a0
--- /dev/null
@@ -0,0 +1,208 @@
+
+/*
+ * drm_sysfs.c - Modifications to drm_sysfs_class.c to support
+ *               extra sysfs attribute from DRM. Normal drm_sysfs_class
+ *               does not allow adding attributes.
+ *
+ * Copyright (c) 2004 Jon Smirl <jonsmirl@gmail.com>
+ * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
+ * Copyright (c) 2003-2004 IBM Corp.
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/kdev_t.h>
+#include <linux/err.h>
+
+#include "drm_core.h"
+#include "drmP.h"
+
+#define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
+
+/**
+ * drm_sysfs_suspend - DRM class suspend hook
+ * @dev: Linux device to suspend
+ * @state: power state to enter
+ *
+ * Just figures out what the actual struct drm_device associated with
+ * @dev is and calls its suspend hook, if present.
+ */
+static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
+{
+       struct drm_minor *drm_minor = to_drm_minor(dev);
+       struct drm_device *drm_dev = drm_minor->dev;
+
+       if (drm_dev->driver->suspend)
+               return drm_dev->driver->suspend(drm_dev, state);
+
+       return 0;
+}
+
+/**
+ * drm_sysfs_resume - DRM class resume hook
+ * @dev: Linux device to resume
+ *
+ * Just figures out what the actual struct drm_device associated with
+ * @dev is and calls its resume hook, if present.
+ */
+static int drm_sysfs_resume(struct device *dev)
+{
+       struct drm_minor *drm_minor = to_drm_minor(dev);
+       struct drm_device *drm_dev = drm_minor->dev;
+
+       if (drm_dev->driver->resume)
+               return drm_dev->driver->resume(drm_dev);
+
+       return 0;
+}
+
+/* Display the version of drm_core. This doesn't work right in current design */
+static ssize_t version_show(struct class *dev, char *buf)
+{
+       return sprintf(buf, "%s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR,
+                      CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
+}
+
+static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
+
+/**
+ * drm_sysfs_create - create a struct drm_sysfs_class structure
+ * @owner: pointer to the module that is to "own" this struct drm_sysfs_class
+ * @name: pointer to a string for the name of this class.
+ *
+ * This is used to create DRM class pointer that can then be used
+ * in calls to drm_sysfs_device_add().
+ *
+ * Note, the pointer created here is to be destroyed when finished by making a
+ * call to drm_sysfs_destroy().
+ */
+struct class *drm_sysfs_create(struct module *owner, char *name)
+{
+       struct class *class;
+       int err;
+
+       class = class_create(owner, name);
+       if (IS_ERR(class)) {
+               err = PTR_ERR(class);
+               goto err_out;
+       }
+
+       class->suspend = drm_sysfs_suspend;
+       class->resume = drm_sysfs_resume;
+
+       err = class_create_file(class, &class_attr_version);
+       if (err)
+               goto err_out_class;
+
+       return class;
+
+err_out_class:
+       class_destroy(class);
+err_out:
+       return ERR_PTR(err);
+}
+
+/**
+ * drm_sysfs_destroy - destroys DRM class
+ *
+ * Destroy the DRM device class.
+ */
+void drm_sysfs_destroy(void)
+{
+       if ((drm_class == NULL) || (IS_ERR(drm_class)))
+               return;
+       class_remove_file(drm_class, &class_attr_version);
+       class_destroy(drm_class);
+}
+
+static ssize_t show_dri(struct device *device, struct device_attribute *attr,
+                       char *buf)
+{
+       struct drm_minor *drm_minor = to_drm_minor(device);
+       struct drm_device *drm_dev = drm_minor->dev;
+       if (drm_dev->driver->dri_library_name)
+               return drm_dev->driver->dri_library_name(drm_dev, buf);
+       return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name);
+}
+
+static struct device_attribute device_attrs[] = {
+       __ATTR(dri_library_name, S_IRUGO, show_dri, NULL),
+};
+
+/**
+ * drm_sysfs_device_release - do nothing
+ * @dev: Linux device
+ *
+ * Normally, this would free the DRM device associated with @dev, along
+ * with cleaning up any other stuff.  But we do that in the DRM core, so
+ * this function can just return and hope that the core does its job.
+ */
+static void drm_sysfs_device_release(struct device *dev)
+{
+       return;
+}
+
+/**
+ * drm_sysfs_device_add - adds a class device to sysfs for a character driver
+ * @dev: DRM device to be added
+ * @head: DRM head in question
+ *
+ * Add a DRM device to the DRM's device model class.  We use @dev's PCI device
+ * as the parent for the Linux device, and make sure it has a file containing
+ * the driver we're using (for userspace compatibility).
+ */
+int drm_sysfs_device_add(struct drm_minor *minor)
+{
+       int err;
+       int i, j;
+       char *minor_str;
+
+       minor->kdev.parent = &minor->dev->pdev->dev;
+       minor->kdev.class = drm_class;
+       minor->kdev.release = drm_sysfs_device_release;
+       minor->kdev.devt = minor->device;
+       minor_str = "card%d";
+
+       snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index);
+
+       err = device_register(&minor->kdev);
+       if (err) {
+               DRM_ERROR("device add failed: %d\n", err);
+               goto err_out;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
+               err = device_create_file(&minor->kdev, &device_attrs[i]);
+               if (err)
+                       goto err_out_files;
+       }
+
+       return 0;
+
+err_out_files:
+       if (i > 0)
+               for (j = 0; j < i; j++)
+                       device_remove_file(&minor->kdev, &device_attrs[i]);
+       device_unregister(&minor->kdev);
+err_out:
+
+       return err;
+}
+
+/**
+ * drm_sysfs_device_remove - remove DRM device
+ * @dev: DRM device to remove
+ *
+ * This call unregisters and cleans up a class device that was created with a
+ * call to drm_sysfs_device_add()
+ */
+void drm_sysfs_device_remove(struct drm_minor *minor)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
+               device_remove_file(&minor->kdev, &device_attrs[i]);
+       device_unregister(&minor->kdev);
+}
diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
new file mode 100644 (file)
index 0000000..c234c6f
--- /dev/null
@@ -0,0 +1,673 @@
+/**
+ * \file drm_vm.c
+ * Memory mapping for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#if defined(__ia64__)
+#include <linux/efi.h>
+#endif
+
+static void drm_vm_open(struct vm_area_struct *vma);
+static void drm_vm_close(struct vm_area_struct *vma);
+
+static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
+{
+       pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
+
+#if defined(__i386__) || defined(__x86_64__)
+       if (boot_cpu_data.x86 > 3 && map_type != _DRM_AGP) {
+               pgprot_val(tmp) |= _PAGE_PCD;
+               pgprot_val(tmp) &= ~_PAGE_PWT;
+       }
+#elif defined(__powerpc__)
+       pgprot_val(tmp) |= _PAGE_NO_CACHE;
+       if (map_type == _DRM_REGISTERS)
+               pgprot_val(tmp) |= _PAGE_GUARDED;
+#elif defined(__ia64__)
+       if (efi_range_is_wc(vma->vm_start, vma->vm_end -
+                                   vma->vm_start))
+               tmp = pgprot_writecombine(tmp);
+       else
+               tmp = pgprot_noncached(tmp);
+#elif defined(__sparc__)
+       tmp = pgprot_noncached(tmp);
+#endif
+       return tmp;
+}
+
+static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
+{
+       pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
+
+#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE)
+       tmp |= _PAGE_NO_CACHE;
+#endif
+       return tmp;
+}
+
+/**
+ * \c fault method for AGP virtual memory.
+ *
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \return pointer to the page structure.
+ *
+ * Find the right map and if it's AGP memory find the real physical page to
+ * map, get the page, increment the use count and return it.
+ */
+#if __OS_HAS_AGP
+static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->minor->dev;
+       struct drm_map *map = NULL;
+       struct drm_map_list *r_list;
+       struct drm_hash_item *hash;
+
+       /*
+        * Find the right map
+        */
+       if (!drm_core_has_AGP(dev))
+               goto vm_fault_error;
+
+       if (!dev->agp || !dev->agp->cant_use_aperture)
+               goto vm_fault_error;
+
+       if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash))
+               goto vm_fault_error;
+
+       r_list = drm_hash_entry(hash, struct drm_map_list, hash);
+       map = r_list->map;
+
+       if (map && map->type == _DRM_AGP) {
+               /*
+                * Using vm_pgoff as a selector forces us to use this unusual
+                * addressing scheme.
+                */
+               unsigned long offset = (unsigned long)vmf->virtual_address -
+                                                               vma->vm_start;
+               unsigned long baddr = map->offset + offset;
+               struct drm_agp_mem *agpmem;
+               struct page *page;
+
+#ifdef __alpha__
+               /*
+                * Adjust to a bus-relative address
+                */
+               baddr -= dev->hose->mem_space->start;
+#endif
+
+               /*
+                * It's AGP memory - find the real physical page to map
+                */
+               list_for_each_entry(agpmem, &dev->agp->memory, head) {
+                       if (agpmem->bound <= baddr &&
+                           agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
+                               break;
+               }
+
+               if (!agpmem)
+                       goto vm_fault_error;
+
+               /*
+                * Get the page, inc the use count, and return it
+                */
+               offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
+               page = virt_to_page(__va(agpmem->memory->memory[offset]));
+               get_page(page);
+               vmf->page = page;
+
+               DRM_DEBUG
+                   ("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",
+                    baddr, __va(agpmem->memory->memory[offset]), offset,
+                    page_count(page));
+               return 0;
+       }
+vm_fault_error:
+       return VM_FAULT_SIGBUS; /* Disallow mremap */
+}
+#else                          /* __OS_HAS_AGP */
+static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       return VM_FAULT_SIGBUS;
+}
+#endif                         /* __OS_HAS_AGP */
+
+/**
+ * \c nopage method for shared virtual memory.
+ *
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \return pointer to the page structure.
+ *
+ * Get the mapping, find the real physical page to map, get the page, and
+ * return it.
+ */
+static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       struct drm_map *map = (struct drm_map *) vma->vm_private_data;
+       unsigned long offset;
+       unsigned long i;
+       struct page *page;
+
+       if (!map)
+               return VM_FAULT_SIGBUS; /* Nothing allocated */
+
+       offset = (unsigned long)vmf->virtual_address - vma->vm_start;
+       i = (unsigned long)map->handle + offset;
+       page = vmalloc_to_page((void *)i);
+       if (!page)
+               return VM_FAULT_SIGBUS;
+       get_page(page);
+       vmf->page = page;
+
+       DRM_DEBUG("shm_fault 0x%lx\n", offset);
+       return 0;
+}
+
+/**
+ * \c close method for shared virtual memory.
+ *
+ * \param vma virtual memory area.
+ *
+ * Deletes map information if we are the last
+ * person to close a mapping and it's not in the global maplist.
+ */
+static void drm_vm_shm_close(struct vm_area_struct *vma)
+{
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->minor->dev;
+       struct drm_vma_entry *pt, *temp;
+       struct drm_map *map;
+       struct drm_map_list *r_list;
+       int found_maps = 0;
+
+       DRM_DEBUG("0x%08lx,0x%08lx\n",
+                 vma->vm_start, vma->vm_end - vma->vm_start);
+       atomic_dec(&dev->vma_count);
+
+       map = vma->vm_private_data;
+
+       mutex_lock(&dev->struct_mutex);
+       list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
+               if (pt->vma->vm_private_data == map)
+                       found_maps++;
+               if (pt->vma == vma) {
+                       list_del(&pt->head);
+                       drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
+               }
+       }
+
+       /* We were the only map that was found */
+       if (found_maps == 1 && map->flags & _DRM_REMOVABLE) {
+               /* Check to see if we are in the maplist, if we are not, then
+                * we delete this mappings information.
+                */
+               found_maps = 0;
+               list_for_each_entry(r_list, &dev->maplist, head) {
+                       if (r_list->map == map)
+                               found_maps++;
+               }
+
+               if (!found_maps) {
+                       drm_dma_handle_t dmah;
+
+                       switch (map->type) {
+                       case _DRM_REGISTERS:
+                       case _DRM_FRAME_BUFFER:
+                               if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
+                                       int retcode;
+                                       retcode = mtrr_del(map->mtrr,
+                                                          map->offset,
+                                                          map->size);
+                                       DRM_DEBUG("mtrr_del = %d\n", retcode);
+                               }
+                               iounmap(map->handle);
+                               break;
+                       case _DRM_SHM:
+                               vfree(map->handle);
+                               break;
+                       case _DRM_AGP:
+                       case _DRM_SCATTER_GATHER:
+                               break;
+                       case _DRM_CONSISTENT:
+                               dmah.vaddr = map->handle;
+                               dmah.busaddr = map->offset;
+                               dmah.size = map->size;
+                               __drm_pci_free(dev, &dmah);
+                               break;
+                       }
+                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+               }
+       }
+       mutex_unlock(&dev->struct_mutex);
+}
+
+/**
+ * \c fault method for DMA virtual memory.
+ *
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \return pointer to the page structure.
+ *
+ * Determine the page number from the page offset and get it from drm_device_dma::pagelist.
+ */
+static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->minor->dev;
+       struct drm_device_dma *dma = dev->dma;
+       unsigned long offset;
+       unsigned long page_nr;
+       struct page *page;
+
+       if (!dma)
+               return VM_FAULT_SIGBUS; /* Error */
+       if (!dma->pagelist)
+               return VM_FAULT_SIGBUS; /* Nothing allocated */
+
+       offset = (unsigned long)vmf->virtual_address - vma->vm_start;   /* vm_[pg]off[set] should be 0 */
+       page_nr = offset >> PAGE_SHIFT; /* page_nr could just be vmf->pgoff */
+       page = virt_to_page((dma->pagelist[page_nr] + (offset & (~PAGE_MASK))));
+
+       get_page(page);
+       vmf->page = page;
+
+       DRM_DEBUG("dma_fault 0x%lx (page %lu)\n", offset, page_nr);
+       return 0;
+}
+
+/**
+ * \c fault method for scatter-gather virtual memory.
+ *
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \return pointer to the page structure.
+ *
+ * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
+ */
+static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       struct drm_map *map = (struct drm_map *) vma->vm_private_data;
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->minor->dev;
+       struct drm_sg_mem *entry = dev->sg;
+       unsigned long offset;
+       unsigned long map_offset;
+       unsigned long page_offset;
+       struct page *page;
+
+       if (!entry)
+               return VM_FAULT_SIGBUS; /* Error */
+       if (!entry->pagelist)
+               return VM_FAULT_SIGBUS; /* Nothing allocated */
+
+       offset = (unsigned long)vmf->virtual_address - vma->vm_start;
+       map_offset = map->offset - (unsigned long)dev->sg->virtual;
+       page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
+       page = entry->pagelist[page_offset];
+       get_page(page);
+       vmf->page = page;
+
+       return 0;
+}
+
+static int drm_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       return drm_do_vm_fault(vma, vmf);
+}
+
+static int drm_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       return drm_do_vm_shm_fault(vma, vmf);
+}
+
+static int drm_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       return drm_do_vm_dma_fault(vma, vmf);
+}
+
+static int drm_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       return drm_do_vm_sg_fault(vma, vmf);
+}
+
+/** AGP virtual memory operations */
+static struct vm_operations_struct drm_vm_ops = {
+       .fault = drm_vm_fault,
+       .open = drm_vm_open,
+       .close = drm_vm_close,
+};
+
+/** Shared virtual memory operations */
+static struct vm_operations_struct drm_vm_shm_ops = {
+       .fault = drm_vm_shm_fault,
+       .open = drm_vm_open,
+       .close = drm_vm_shm_close,
+};
+
+/** DMA virtual memory operations */
+static struct vm_operations_struct drm_vm_dma_ops = {
+       .fault = drm_vm_dma_fault,
+       .open = drm_vm_open,
+       .close = drm_vm_close,
+};
+
+/** Scatter-gather virtual memory operations */
+static struct vm_operations_struct drm_vm_sg_ops = {
+       .fault = drm_vm_sg_fault,
+       .open = drm_vm_open,
+       .close = drm_vm_close,
+};
+
+/**
+ * \c open method for shared virtual memory.
+ *
+ * \param vma virtual memory area.
+ *
+ * Create a new drm_vma_entry structure as the \p vma private data entry and
+ * add it to drm_device::vmalist.
+ */
+static void drm_vm_open_locked(struct vm_area_struct *vma)
+{
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->minor->dev;
+       struct drm_vma_entry *vma_entry;
+
+       DRM_DEBUG("0x%08lx,0x%08lx\n",
+                 vma->vm_start, vma->vm_end - vma->vm_start);
+       atomic_inc(&dev->vma_count);
+
+       vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
+       if (vma_entry) {
+               vma_entry->vma = vma;
+               vma_entry->pid = current->pid;
+               list_add(&vma_entry->head, &dev->vmalist);
+       }
+}
+
+static void drm_vm_open(struct vm_area_struct *vma)
+{
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->minor->dev;
+
+       mutex_lock(&dev->struct_mutex);
+       drm_vm_open_locked(vma);
+       mutex_unlock(&dev->struct_mutex);
+}
+
+/**
+ * \c close method for all virtual memory types.
+ *
+ * \param vma virtual memory area.
+ *
+ * Search the \p vma private data entry in drm_device::vmalist, unlink it, and
+ * free it.
+ */
+static void drm_vm_close(struct vm_area_struct *vma)
+{
+       struct drm_file *priv = vma->vm_file->private_data;
+       struct drm_device *dev = priv->minor->dev;
+       struct drm_vma_entry *pt, *temp;
+
+       DRM_DEBUG("0x%08lx,0x%08lx\n",
+                 vma->vm_start, vma->vm_end - vma->vm_start);
+       atomic_dec(&dev->vma_count);
+
+       mutex_lock(&dev->struct_mutex);
+       list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
+               if (pt->vma == vma) {
+                       list_del(&pt->head);
+                       drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
+                       break;
+               }
+       }
+       mutex_unlock(&dev->struct_mutex);
+}
+
+/**
+ * mmap DMA memory.
+ *
+ * \param file_priv DRM file private.
+ * \param vma virtual memory area.
+ * \return zero on success or a negative number on failure.
+ *
+ * Sets the virtual memory area operations structure to vm_dma_ops, the file
+ * pointer, and calls vm_open().
+ */
+static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
+{
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev;
+       struct drm_device_dma *dma;
+       unsigned long length = vma->vm_end - vma->vm_start;
+
+       dev = priv->minor->dev;
+       dma = dev->dma;
+       DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
+                 vma->vm_start, vma->vm_end, vma->vm_pgoff);
+
+       /* Length must match exact page count */
+       if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
+               return -EINVAL;
+       }
+
+       if (!capable(CAP_SYS_ADMIN) &&
+           (dma->flags & _DRM_DMA_USE_PCI_RO)) {
+               vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
+#if defined(__i386__) || defined(__x86_64__)
+               pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
+#else
+               /* Ye gads this is ugly.  With more thought
+                  we could move this up higher and use
+                  `protection_map' instead.  */
+               vma->vm_page_prot =
+                   __pgprot(pte_val
+                            (pte_wrprotect
+                             (__pte(pgprot_val(vma->vm_page_prot)))));
+#endif
+       }
+
+       vma->vm_ops = &drm_vm_dma_ops;
+
+       vma->vm_flags |= VM_RESERVED;   /* Don't swap */
+       vma->vm_flags |= VM_DONTEXPAND;
+
+       vma->vm_file = filp;    /* Needed for drm_vm_open() */
+       drm_vm_open_locked(vma);
+       return 0;
+}
+
+unsigned long drm_core_get_map_ofs(struct drm_map * map)
+{
+       return map->offset;
+}
+
+EXPORT_SYMBOL(drm_core_get_map_ofs);
+
+unsigned long drm_core_get_reg_ofs(struct drm_device *dev)
+{
+#ifdef __alpha__
+       return dev->hose->dense_mem_base - dev->hose->mem_space->start;
+#else
+       return 0;
+#endif
+}
+
+EXPORT_SYMBOL(drm_core_get_reg_ofs);
+
+/**
+ * mmap DMA memory.
+ *
+ * \param file_priv DRM file private.
+ * \param vma virtual memory area.
+ * \return zero on success or a negative number on failure.
+ *
+ * If the virtual memory area has no offset associated with it then it's a DMA
+ * area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist,
+ * checks that the restricted flag is not set, sets the virtual memory operations
+ * according to the mapping type and remaps the pages. Finally sets the file
+ * pointer and calls vm_open().
+ */
+static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
+{
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev = priv->minor->dev;
+       struct drm_map *map = NULL;
+       unsigned long offset = 0;
+       struct drm_hash_item *hash;
+
+       DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
+                 vma->vm_start, vma->vm_end, vma->vm_pgoff);
+
+       if (!priv->authenticated)
+               return -EACCES;
+
+       /* We check for "dma". On Apple's UniNorth, it's valid to have
+        * the AGP mapped at physical address 0
+        * --BenH.
+        */
+       if (!vma->vm_pgoff
+#if __OS_HAS_AGP
+           && (!dev->agp
+               || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
+#endif
+           )
+               return drm_mmap_dma(filp, vma);
+
+       if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) {
+               DRM_ERROR("Could not find map\n");
+               return -EINVAL;
+       }
+
+       map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
+       if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
+               return -EPERM;
+
+       /* Check for valid size. */
+       if (map->size < vma->vm_end - vma->vm_start)
+               return -EINVAL;
+
+       if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
+               vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
+#if defined(__i386__) || defined(__x86_64__)
+               pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
+#else
+               /* Ye gads this is ugly.  With more thought
+                  we could move this up higher and use
+                  `protection_map' instead.  */
+               vma->vm_page_prot =
+                   __pgprot(pte_val
+                            (pte_wrprotect
+                             (__pte(pgprot_val(vma->vm_page_prot)))));
+#endif
+       }
+
+       switch (map->type) {
+       case _DRM_AGP:
+               if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
+                       /*
+                        * On some platforms we can't talk to bus dma address from the CPU, so for
+                        * memory of type DRM_AGP, we'll deal with sorting out the real physical
+                        * pages and mappings in fault()
+                        */
+#if defined(__powerpc__)
+                       pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
+#endif
+                       vma->vm_ops = &drm_vm_ops;
+                       break;
+               }
+               /* fall through to _DRM_FRAME_BUFFER... */
+       case _DRM_FRAME_BUFFER:
+       case _DRM_REGISTERS:
+               offset = dev->driver->get_reg_ofs(dev);
+               vma->vm_flags |= VM_IO; /* not in core dump */
+               vma->vm_page_prot = drm_io_prot(map->type, vma);
+               if (io_remap_pfn_range(vma, vma->vm_start,
+                                      (map->offset + offset) >> PAGE_SHIFT,
+                                      vma->vm_end - vma->vm_start,
+                                      vma->vm_page_prot))
+                       return -EAGAIN;
+               DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
+                         " offset = 0x%lx\n",
+                         map->type,
+                         vma->vm_start, vma->vm_end, map->offset + offset);
+               vma->vm_ops = &drm_vm_ops;
+               break;
+       case _DRM_CONSISTENT:
+               /* Consistent memory is really like shared memory. But
+                * it's allocated in a different way, so avoid fault */
+               if (remap_pfn_range(vma, vma->vm_start,
+                   page_to_pfn(virt_to_page(map->handle)),
+                   vma->vm_end - vma->vm_start, vma->vm_page_prot))
+                       return -EAGAIN;
+               vma->vm_page_prot = drm_dma_prot(map->type, vma);
+       /* fall through to _DRM_SHM */
+       case _DRM_SHM:
+               vma->vm_ops = &drm_vm_shm_ops;
+               vma->vm_private_data = (void *)map;
+               /* Don't let this area swap.  Change when
+                  DRM_KERNEL advisory is supported. */
+               vma->vm_flags |= VM_RESERVED;
+               break;
+       case _DRM_SCATTER_GATHER:
+               vma->vm_ops = &drm_vm_sg_ops;
+               vma->vm_private_data = (void *)map;
+               vma->vm_flags |= VM_RESERVED;
+               vma->vm_page_prot = drm_dma_prot(map->type, vma);
+               break;
+       default:
+               return -EINVAL; /* This should never happen. */
+       }
+       vma->vm_flags |= VM_RESERVED;   /* Don't swap */
+       vma->vm_flags |= VM_DONTEXPAND;
+
+       vma->vm_file = filp;    /* Needed for drm_vm_open() */
+       drm_vm_open_locked(vma);
+       return 0;
+}
+
+int drm_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev = priv->minor->dev;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_mmap_locked(filp, vma);
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_mmap);
diff --git a/drivers/gpu/drm/i810/Makefile b/drivers/gpu/drm/i810/Makefile
new file mode 100644 (file)
index 0000000..43844ec
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+i810-y := i810_drv.o i810_dma.o
+
+obj-$(CONFIG_DRM_I810) += i810.o
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
new file mode 100644 (file)
index 0000000..e5de8ea
--- /dev/null
@@ -0,0 +1,1283 @@
+/* i810_dma.c -- DMA support for the i810 -*- linux-c -*-
+ * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
+ *         Jeff Hartmann <jhartmann@valinux.com>
+ *          Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i810_drm.h"
+#include "i810_drv.h"
+#include <linux/interrupt.h>   /* For task queue support */
+#include <linux/delay.h>
+#include <linux/pagemap.h>
+
+#define I810_BUF_FREE          2
+#define I810_BUF_CLIENT                1
+#define I810_BUF_HARDWARE      0
+
+#define I810_BUF_UNMAPPED 0
+#define I810_BUF_MAPPED   1
+
+static struct drm_buf *i810_freelist_get(struct drm_device * dev)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int i;
+       int used;
+
+       /* Linear search might not be the best solution */
+
+       for (i = 0; i < dma->buf_count; i++) {
+               struct drm_buf *buf = dma->buflist[i];
+               drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+               /* In use is already a pointer */
+               used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
+                              I810_BUF_CLIENT);
+               if (used == I810_BUF_FREE) {
+                       return buf;
+               }
+       }
+       return NULL;
+}
+
+/* This should only be called if the buffer is not sent to the hardware
+ * yet, the hardware updates in use for us once its on the ring buffer.
+ */
+
+static int i810_freelist_put(struct drm_device * dev, struct drm_buf * buf)
+{
+       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+       int used;
+
+       /* In use is already a pointer */
+       used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE);
+       if (used != I810_BUF_CLIENT) {
+               DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+{
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev;
+       drm_i810_private_t *dev_priv;
+       struct drm_buf *buf;
+       drm_i810_buf_priv_t *buf_priv;
+
+       lock_kernel();
+       dev = priv->minor->dev;
+       dev_priv = dev->dev_private;
+       buf = dev_priv->mmap_buffer;
+       buf_priv = buf->dev_private;
+
+       vma->vm_flags |= (VM_IO | VM_DONTCOPY);
+       vma->vm_file = filp;
+
+       buf_priv->currently_mapped = I810_BUF_MAPPED;
+       unlock_kernel();
+
+       if (io_remap_pfn_range(vma, vma->vm_start,
+                              vma->vm_pgoff,
+                              vma->vm_end - vma->vm_start, vma->vm_page_prot))
+               return -EAGAIN;
+       return 0;
+}
+
+static const struct file_operations i810_buffer_fops = {
+       .open = drm_open,
+       .release = drm_release,
+       .ioctl = drm_ioctl,
+       .mmap = i810_mmap_buffers,
+       .fasync = drm_fasync,
+};
+
+static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
+{
+       struct drm_device *dev = file_priv->minor->dev;
+       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       const struct file_operations *old_fops;
+       int retcode = 0;
+
+       if (buf_priv->currently_mapped == I810_BUF_MAPPED)
+               return -EINVAL;
+
+       down_write(&current->mm->mmap_sem);
+       old_fops = file_priv->filp->f_op;
+       file_priv->filp->f_op = &i810_buffer_fops;
+       dev_priv->mmap_buffer = buf;
+       buf_priv->virtual = (void *)do_mmap(file_priv->filp, 0, buf->total,
+                                           PROT_READ | PROT_WRITE,
+                                           MAP_SHARED, buf->bus_address);
+       dev_priv->mmap_buffer = NULL;
+       file_priv->filp->f_op = old_fops;
+       if (IS_ERR(buf_priv->virtual)) {
+               /* Real error */
+               DRM_ERROR("mmap error\n");
+               retcode = PTR_ERR(buf_priv->virtual);
+               buf_priv->virtual = NULL;
+       }
+       up_write(&current->mm->mmap_sem);
+
+       return retcode;
+}
+
+static int i810_unmap_buffer(struct drm_buf * buf)
+{
+       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+       int retcode = 0;
+
+       if (buf_priv->currently_mapped != I810_BUF_MAPPED)
+               return -EINVAL;
+
+       down_write(&current->mm->mmap_sem);
+       retcode = do_munmap(current->mm,
+                           (unsigned long)buf_priv->virtual,
+                           (size_t) buf->total);
+       up_write(&current->mm->mmap_sem);
+
+       buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+       buf_priv->virtual = NULL;
+
+       return retcode;
+}
+
+static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d,
+                              struct drm_file *file_priv)
+{
+       struct drm_buf *buf;
+       drm_i810_buf_priv_t *buf_priv;
+       int retcode = 0;
+
+       buf = i810_freelist_get(dev);
+       if (!buf) {
+               retcode = -ENOMEM;
+               DRM_DEBUG("retcode=%d\n", retcode);
+               return retcode;
+       }
+
+       retcode = i810_map_buffer(buf, file_priv);
+       if (retcode) {
+               i810_freelist_put(dev, buf);
+               DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
+               return retcode;
+       }
+       buf->file_priv = file_priv;
+       buf_priv = buf->dev_private;
+       d->granted = 1;
+       d->request_idx = buf->idx;
+       d->request_size = buf->total;
+       d->virtual = buf_priv->virtual;
+
+       return retcode;
+}
+
+static int i810_dma_cleanup(struct drm_device * dev)
+{
+       struct drm_device_dma *dma = dev->dma;
+
+       /* Make sure interrupts are disabled here because the uninstall ioctl
+        * may not have been called from userspace and after dev_private
+        * is freed, it's too late.
+        */
+       if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ) && dev->irq_enabled)
+               drm_irq_uninstall(dev);
+
+       if (dev->dev_private) {
+               int i;
+               drm_i810_private_t *dev_priv =
+                   (drm_i810_private_t *) dev->dev_private;
+
+               if (dev_priv->ring.virtual_start) {
+                       drm_core_ioremapfree(&dev_priv->ring.map, dev);
+               }
+               if (dev_priv->hw_status_page) {
+                       pci_free_consistent(dev->pdev, PAGE_SIZE,
+                                           dev_priv->hw_status_page,
+                                           dev_priv->dma_status_page);
+                       /* Need to rewrite hardware status page */
+                       I810_WRITE(0x02080, 0x1ffff000);
+               }
+               drm_free(dev->dev_private, sizeof(drm_i810_private_t),
+                        DRM_MEM_DRIVER);
+               dev->dev_private = NULL;
+
+               for (i = 0; i < dma->buf_count; i++) {
+                       struct drm_buf *buf = dma->buflist[i];
+                       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+
+                       if (buf_priv->kernel_virtual && buf->total)
+                               drm_core_ioremapfree(&buf_priv->map, dev);
+               }
+       }
+       return 0;
+}
+
+static int i810_wait_ring(struct drm_device * dev, int n)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
+       int iters = 0;
+       unsigned long end;
+       unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+
+       end = jiffies + (HZ * 3);
+       while (ring->space < n) {
+               ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+               ring->space = ring->head - (ring->tail + 8);
+               if (ring->space < 0)
+                       ring->space += ring->Size;
+
+               if (ring->head != last_head) {
+                       end = jiffies + (HZ * 3);
+                       last_head = ring->head;
+               }
+
+               iters++;
+               if (time_before(end, jiffies)) {
+                       DRM_ERROR("space: %d wanted %d\n", ring->space, n);
+                       DRM_ERROR("lockup\n");
+                       goto out_wait_ring;
+               }
+               udelay(1);
+       }
+
+      out_wait_ring:
+       return iters;
+}
+
+static void i810_kernel_lost_context(struct drm_device * dev)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
+
+       ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+       ring->tail = I810_READ(LP_RING + RING_TAIL);
+       ring->space = ring->head - (ring->tail + 8);
+       if (ring->space < 0)
+               ring->space += ring->Size;
+}
+
+static int i810_freelist_init(struct drm_device * dev, drm_i810_private_t * dev_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int my_idx = 24;
+       u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
+       int i;
+
+       if (dma->buf_count > 1019) {
+               /* Not enough space in the status page for the freelist */
+               return -EINVAL;
+       }
+
+       for (i = 0; i < dma->buf_count; i++) {
+               struct drm_buf *buf = dma->buflist[i];
+               drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+
+               buf_priv->in_use = hw_status++;
+               buf_priv->my_use_idx = my_idx;
+               my_idx += 4;
+
+               *buf_priv->in_use = I810_BUF_FREE;
+
+               buf_priv->map.offset = buf->bus_address;
+               buf_priv->map.size = buf->total;
+               buf_priv->map.type = _DRM_AGP;
+               buf_priv->map.flags = 0;
+               buf_priv->map.mtrr = 0;
+
+               drm_core_ioremap(&buf_priv->map, dev);
+               buf_priv->kernel_virtual = buf_priv->map.handle;
+
+       }
+       return 0;
+}
+
+static int i810_dma_initialize(struct drm_device * dev,
+                              drm_i810_private_t * dev_priv,
+                              drm_i810_init_t * init)
+{
+       struct drm_map_list *r_list;
+       memset(dev_priv, 0, sizeof(drm_i810_private_t));
+
+       list_for_each_entry(r_list, &dev->maplist, head) {
+               if (r_list->map &&
+                   r_list->map->type == _DRM_SHM &&
+                   r_list->map->flags & _DRM_CONTAINS_LOCK) {
+                       dev_priv->sarea_map = r_list->map;
+                       break;
+               }
+       }
+       if (!dev_priv->sarea_map) {
+               dev->dev_private = (void *)dev_priv;
+               i810_dma_cleanup(dev);
+               DRM_ERROR("can not find sarea!\n");
+               return -EINVAL;
+       }
+       dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
+       if (!dev_priv->mmio_map) {
+               dev->dev_private = (void *)dev_priv;
+               i810_dma_cleanup(dev);
+               DRM_ERROR("can not find mmio map!\n");
+               return -EINVAL;
+       }
+       dev->agp_buffer_token = init->buffers_offset;
+       dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+       if (!dev->agp_buffer_map) {
+               dev->dev_private = (void *)dev_priv;
+               i810_dma_cleanup(dev);
+               DRM_ERROR("can not find dma buffer map!\n");
+               return -EINVAL;
+       }
+
+       dev_priv->sarea_priv = (drm_i810_sarea_t *)
+           ((u8 *) dev_priv->sarea_map->handle + init->sarea_priv_offset);
+
+       dev_priv->ring.Start = init->ring_start;
+       dev_priv->ring.End = init->ring_end;
+       dev_priv->ring.Size = init->ring_size;
+
+       dev_priv->ring.map.offset = dev->agp->base + init->ring_start;
+       dev_priv->ring.map.size = init->ring_size;
+       dev_priv->ring.map.type = _DRM_AGP;
+       dev_priv->ring.map.flags = 0;
+       dev_priv->ring.map.mtrr = 0;
+
+       drm_core_ioremap(&dev_priv->ring.map, dev);
+
+       if (dev_priv->ring.map.handle == NULL) {
+               dev->dev_private = (void *)dev_priv;
+               i810_dma_cleanup(dev);
+               DRM_ERROR("can not ioremap virtual address for"
+                         " ring buffer\n");
+               return -ENOMEM;
+       }
+
+       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+
+       dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
+       dev_priv->w = init->w;
+       dev_priv->h = init->h;
+       dev_priv->pitch = init->pitch;
+       dev_priv->back_offset = init->back_offset;
+       dev_priv->depth_offset = init->depth_offset;
+       dev_priv->front_offset = init->front_offset;
+
+       dev_priv->overlay_offset = init->overlay_offset;
+       dev_priv->overlay_physical = init->overlay_physical;
+
+       dev_priv->front_di1 = init->front_offset | init->pitch_bits;
+       dev_priv->back_di1 = init->back_offset | init->pitch_bits;
+       dev_priv->zi1 = init->depth_offset | init->pitch_bits;
+
+       /* Program Hardware Status Page */
+       dev_priv->hw_status_page =
+           pci_alloc_consistent(dev->pdev, PAGE_SIZE,
+                                &dev_priv->dma_status_page);
+       if (!dev_priv->hw_status_page) {
+               dev->dev_private = (void *)dev_priv;
+               i810_dma_cleanup(dev);
+               DRM_ERROR("Can not allocate hardware status page\n");
+               return -ENOMEM;
+       }
+       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+       DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+
+       I810_WRITE(0x02080, dev_priv->dma_status_page);
+       DRM_DEBUG("Enabled hardware status page\n");
+
+       /* Now we need to init our freelist */
+       if (i810_freelist_init(dev, dev_priv) != 0) {
+               dev->dev_private = (void *)dev_priv;
+               i810_dma_cleanup(dev);
+               DRM_ERROR("Not enough space in the status page for"
+                         " the freelist\n");
+               return -ENOMEM;
+       }
+       dev->dev_private = (void *)dev_priv;
+
+       return 0;
+}
+
+static int i810_dma_init(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i810_private_t *dev_priv;
+       drm_i810_init_t *init = data;
+       int retcode = 0;
+
+       switch (init->func) {
+       case I810_INIT_DMA_1_4:
+               DRM_INFO("Using v1.4 init.\n");
+               dev_priv = drm_alloc(sizeof(drm_i810_private_t),
+                                    DRM_MEM_DRIVER);
+               if (dev_priv == NULL)
+                       return -ENOMEM;
+               retcode = i810_dma_initialize(dev, dev_priv, init);
+               break;
+
+       case I810_CLEANUP_DMA:
+               DRM_INFO("DMA Cleanup\n");
+               retcode = i810_dma_cleanup(dev);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return retcode;
+}
+
+/* Most efficient way to verify state for the i810 is as it is
+ * emitted.  Non-conformant state is silently dropped.
+ *
+ * Use 'volatile' & local var tmp to force the emitted values to be
+ * identical to the verified ones.
+ */
+static void i810EmitContextVerified(struct drm_device * dev,
+                                   volatile unsigned int *code)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       int i, j = 0;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING(I810_CTX_SETUP_SIZE);
+
+       OUT_RING(GFX_OP_COLOR_FACTOR);
+       OUT_RING(code[I810_CTXREG_CF1]);
+
+       OUT_RING(GFX_OP_STIPPLE);
+       OUT_RING(code[I810_CTXREG_ST1]);
+
+       for (i = 4; i < I810_CTX_SETUP_SIZE; i++) {
+               tmp = code[i];
+
+               if ((tmp & (7 << 29)) == (3 << 29) &&
+                   (tmp & (0x1f << 24)) < (0x1d << 24)) {
+                       OUT_RING(tmp);
+                       j++;
+               } else
+                       printk("constext state dropped!!!\n");
+       }
+
+       if (j & 1)
+               OUT_RING(0);
+
+       ADVANCE_LP_RING();
+}
+
+static void i810EmitTexVerified(struct drm_device * dev, volatile unsigned int *code)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       int i, j = 0;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING(I810_TEX_SETUP_SIZE);
+
+       OUT_RING(GFX_OP_MAP_INFO);
+       OUT_RING(code[I810_TEXREG_MI1]);
+       OUT_RING(code[I810_TEXREG_MI2]);
+       OUT_RING(code[I810_TEXREG_MI3]);
+
+       for (i = 4; i < I810_TEX_SETUP_SIZE; i++) {
+               tmp = code[i];
+
+               if ((tmp & (7 << 29)) == (3 << 29) &&
+                   (tmp & (0x1f << 24)) < (0x1d << 24)) {
+                       OUT_RING(tmp);
+                       j++;
+               } else
+                       printk("texture state dropped!!!\n");
+       }
+
+       if (j & 1)
+               OUT_RING(0);
+
+       ADVANCE_LP_RING();
+}
+
+/* Need to do some additional checking when setting the dest buffer.
+ */
+static void i810EmitDestVerified(struct drm_device * dev,
+                                volatile unsigned int *code)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2);
+
+       tmp = code[I810_DESTREG_DI1];
+       if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
+               OUT_RING(CMD_OP_DESTBUFFER_INFO);
+               OUT_RING(tmp);
+       } else
+               DRM_DEBUG("bad di1 %x (allow %x or %x)\n",
+                         tmp, dev_priv->front_di1, dev_priv->back_di1);
+
+       /* invarient:
+        */
+       OUT_RING(CMD_OP_Z_BUFFER_INFO);
+       OUT_RING(dev_priv->zi1);
+
+       OUT_RING(GFX_OP_DESTBUFFER_VARS);
+       OUT_RING(code[I810_DESTREG_DV1]);
+
+       OUT_RING(GFX_OP_DRAWRECT_INFO);
+       OUT_RING(code[I810_DESTREG_DR1]);
+       OUT_RING(code[I810_DESTREG_DR2]);
+       OUT_RING(code[I810_DESTREG_DR3]);
+       OUT_RING(code[I810_DESTREG_DR4]);
+       OUT_RING(0);
+
+       ADVANCE_LP_RING();
+}
+
+static void i810EmitState(struct drm_device * dev)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned int dirty = sarea_priv->dirty;
+
+       DRM_DEBUG("%x\n", dirty);
+
+       if (dirty & I810_UPLOAD_BUFFERS) {
+               i810EmitDestVerified(dev, sarea_priv->BufferState);
+               sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS;
+       }
+
+       if (dirty & I810_UPLOAD_CTX) {
+               i810EmitContextVerified(dev, sarea_priv->ContextState);
+               sarea_priv->dirty &= ~I810_UPLOAD_CTX;
+       }
+
+       if (dirty & I810_UPLOAD_TEX0) {
+               i810EmitTexVerified(dev, sarea_priv->TexState[0]);
+               sarea_priv->dirty &= ~I810_UPLOAD_TEX0;
+       }
+
+       if (dirty & I810_UPLOAD_TEX1) {
+               i810EmitTexVerified(dev, sarea_priv->TexState[1]);
+               sarea_priv->dirty &= ~I810_UPLOAD_TEX1;
+       }
+}
+
+/* need to verify
+ */
+static void i810_dma_dispatch_clear(struct drm_device * dev, int flags,
+                                   unsigned int clear_color,
+                                   unsigned int clear_zval)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
+       int pitch = dev_priv->pitch;
+       int cpp = 2;
+       int i;
+       RING_LOCALS;
+
+       if (dev_priv->current_page == 1) {
+               unsigned int tmp = flags;
+
+               flags &= ~(I810_FRONT | I810_BACK);
+               if (tmp & I810_FRONT)
+                       flags |= I810_BACK;
+               if (tmp & I810_BACK)
+                       flags |= I810_FRONT;
+       }
+
+       i810_kernel_lost_context(dev);
+
+       if (nbox > I810_NR_SAREA_CLIPRECTS)
+               nbox = I810_NR_SAREA_CLIPRECTS;
+
+       for (i = 0; i < nbox; i++, pbox++) {
+               unsigned int x = pbox->x1;
+               unsigned int y = pbox->y1;
+               unsigned int width = (pbox->x2 - x) * cpp;
+               unsigned int height = pbox->y2 - y;
+               unsigned int start = y * pitch + x * cpp;
+
+               if (pbox->x1 > pbox->x2 ||
+                   pbox->y1 > pbox->y2 ||
+                   pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
+                       continue;
+
+               if (flags & I810_FRONT) {
+                       BEGIN_LP_RING(6);
+                       OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
+                       OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
+                       OUT_RING((height << 16) | width);
+                       OUT_RING(start);
+                       OUT_RING(clear_color);
+                       OUT_RING(0);
+                       ADVANCE_LP_RING();
+               }
+
+               if (flags & I810_BACK) {
+                       BEGIN_LP_RING(6);
+                       OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
+                       OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
+                       OUT_RING((height << 16) | width);
+                       OUT_RING(dev_priv->back_offset + start);
+                       OUT_RING(clear_color);
+                       OUT_RING(0);
+                       ADVANCE_LP_RING();
+               }
+
+               if (flags & I810_DEPTH) {
+                       BEGIN_LP_RING(6);
+                       OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3);
+                       OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch);
+                       OUT_RING((height << 16) | width);
+                       OUT_RING(dev_priv->depth_offset + start);
+                       OUT_RING(clear_zval);
+                       OUT_RING(0);
+                       ADVANCE_LP_RING();
+               }
+       }
+}
+
+static void i810_dma_dispatch_swap(struct drm_device * dev)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
+       int pitch = dev_priv->pitch;
+       int cpp = 2;
+       int i;
+       RING_LOCALS;
+
+       DRM_DEBUG("swapbuffers\n");
+
+       i810_kernel_lost_context(dev);
+
+       if (nbox > I810_NR_SAREA_CLIPRECTS)
+               nbox = I810_NR_SAREA_CLIPRECTS;
+
+       for (i = 0; i < nbox; i++, pbox++) {
+               unsigned int w = pbox->x2 - pbox->x1;
+               unsigned int h = pbox->y2 - pbox->y1;
+               unsigned int dst = pbox->x1 * cpp + pbox->y1 * pitch;
+               unsigned int start = dst;
+
+               if (pbox->x1 > pbox->x2 ||
+                   pbox->y1 > pbox->y2 ||
+                   pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
+                       continue;
+
+               BEGIN_LP_RING(6);
+               OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4);
+               OUT_RING(pitch | (0xCC << 16));
+               OUT_RING((h << 16) | (w * cpp));
+               if (dev_priv->current_page == 0)
+                       OUT_RING(dev_priv->front_offset + start);
+               else
+                       OUT_RING(dev_priv->back_offset + start);
+               OUT_RING(pitch);
+               if (dev_priv->current_page == 0)
+                       OUT_RING(dev_priv->back_offset + start);
+               else
+                       OUT_RING(dev_priv->front_offset + start);
+               ADVANCE_LP_RING();
+       }
+}
+
+static void i810_dma_dispatch_vertex(struct drm_device * dev,
+                                    struct drm_buf * buf, int discard, int used)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       struct drm_clip_rect *box = sarea_priv->boxes;
+       int nbox = sarea_priv->nbox;
+       unsigned long address = (unsigned long)buf->bus_address;
+       unsigned long start = address - dev->agp->base;
+       int i = 0;
+       RING_LOCALS;
+
+       i810_kernel_lost_context(dev);
+
+       if (nbox > I810_NR_SAREA_CLIPRECTS)
+               nbox = I810_NR_SAREA_CLIPRECTS;
+
+       if (used > 4 * 1024)
+               used = 0;
+
+       if (sarea_priv->dirty)
+               i810EmitState(dev);
+
+       if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
+               unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
+
+               *(u32 *) buf_priv->kernel_virtual =
+                   ((GFX_OP_PRIMITIVE | prim | ((used / 4) - 2)));
+
+               if (used & 4) {
+                       *(u32 *) ((char *) buf_priv->kernel_virtual + used) = 0;
+                       used += 4;
+               }
+
+               i810_unmap_buffer(buf);
+       }
+
+       if (used) {
+               do {
+                       if (i < nbox) {
+                               BEGIN_LP_RING(4);
+                               OUT_RING(GFX_OP_SCISSOR | SC_UPDATE_SCISSOR |
+                                        SC_ENABLE);
+                               OUT_RING(GFX_OP_SCISSOR_INFO);
+                               OUT_RING(box[i].x1 | (box[i].y1 << 16));
+                               OUT_RING((box[i].x2 -
+                                         1) | ((box[i].y2 - 1) << 16));
+                               ADVANCE_LP_RING();
+                       }
+
+                       BEGIN_LP_RING(4);
+                       OUT_RING(CMD_OP_BATCH_BUFFER);
+                       OUT_RING(start | BB1_PROTECTED);
+                       OUT_RING(start + used - 4);
+                       OUT_RING(0);
+                       ADVANCE_LP_RING();
+
+               } while (++i < nbox);
+       }
+
+       if (discard) {
+               dev_priv->counter++;
+
+               (void)cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
+                             I810_BUF_HARDWARE);
+
+               BEGIN_LP_RING(8);
+               OUT_RING(CMD_STORE_DWORD_IDX);
+               OUT_RING(20);
+               OUT_RING(dev_priv->counter);
+               OUT_RING(CMD_STORE_DWORD_IDX);
+               OUT_RING(buf_priv->my_use_idx);
+               OUT_RING(I810_BUF_FREE);
+               OUT_RING(CMD_REPORT_HEAD);
+               OUT_RING(0);
+               ADVANCE_LP_RING();
+       }
+}
+
+static void i810_dma_dispatch_flip(struct drm_device * dev)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       int pitch = dev_priv->pitch;
+       RING_LOCALS;
+
+       DRM_DEBUG("page=%d pfCurrentPage=%d\n",
+                 dev_priv->current_page,
+                 dev_priv->sarea_priv->pf_current_page);
+
+       i810_kernel_lost_context(dev);
+
+       BEGIN_LP_RING(2);
+       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2);
+       /* On i815 at least ASYNC is buggy */
+       /* pitch<<5 is from 11.2.8 p158,
+          its the pitch / 8 then left shifted 8,
+          so (pitch >> 3) << 8 */
+       OUT_RING(CMD_OP_FRONTBUFFER_INFO | (pitch << 5) /*| ASYNC_FLIP */ );
+       if (dev_priv->current_page == 0) {
+               OUT_RING(dev_priv->back_offset);
+               dev_priv->current_page = 1;
+       } else {
+               OUT_RING(dev_priv->front_offset);
+               dev_priv->current_page = 0;
+       }
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       BEGIN_LP_RING(2);
+       OUT_RING(CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       /* Increment the frame counter.  The client-side 3D driver must
+        * throttle the framerate by waiting for this value before
+        * performing the swapbuffer ioctl.
+        */
+       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+
+}
+
+static void i810_dma_quiescent(struct drm_device * dev)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       i810_kernel_lost_context(dev);
+
+       BEGIN_LP_RING(4);
+       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+       OUT_RING(CMD_REPORT_HEAD);
+       OUT_RING(0);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       i810_wait_ring(dev, dev_priv->ring.Size - 8);
+}
+
+static int i810_flush_queue(struct drm_device * dev)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       int i, ret = 0;
+       RING_LOCALS;
+
+       i810_kernel_lost_context(dev);
+
+       BEGIN_LP_RING(2);
+       OUT_RING(CMD_REPORT_HEAD);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       i810_wait_ring(dev, dev_priv->ring.Size - 8);
+
+       for (i = 0; i < dma->buf_count; i++) {
+               struct drm_buf *buf = dma->buflist[i];
+               drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+
+               int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE,
+                                  I810_BUF_FREE);
+
+               if (used == I810_BUF_HARDWARE)
+                       DRM_DEBUG("reclaimed from HARDWARE\n");
+               if (used == I810_BUF_CLIENT)
+                       DRM_DEBUG("still on client\n");
+       }
+
+       return ret;
+}
+
+/* Must be called with the lock held */
+static void i810_reclaim_buffers(struct drm_device * dev,
+                                struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int i;
+
+       if (!dma)
+               return;
+       if (!dev->dev_private)
+               return;
+       if (!dma->buflist)
+               return;
+
+       i810_flush_queue(dev);
+
+       for (i = 0; i < dma->buf_count; i++) {
+               struct drm_buf *buf = dma->buflist[i];
+               drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+
+               if (buf->file_priv == file_priv && buf_priv) {
+                       int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT,
+                                          I810_BUF_FREE);
+
+                       if (used == I810_BUF_CLIENT)
+                               DRM_DEBUG("reclaimed from client\n");
+                       if (buf_priv->currently_mapped == I810_BUF_MAPPED)
+                               buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+               }
+       }
+}
+
+static int i810_flush_ioctl(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv)
+{
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       i810_flush_queue(dev);
+       return 0;
+}
+
+static int i810_dma_vertex(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+       u32 *hw_status = dev_priv->hw_status_page;
+       drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+           dev_priv->sarea_priv;
+       drm_i810_vertex_t *vertex = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       DRM_DEBUG("idx %d used %d discard %d\n",
+                 vertex->idx, vertex->used, vertex->discard);
+
+       if (vertex->idx < 0 || vertex->idx > dma->buf_count)
+               return -EINVAL;
+
+       i810_dma_dispatch_vertex(dev,
+                                dma->buflist[vertex->idx],
+                                vertex->discard, vertex->used);
+
+       atomic_add(vertex->used, &dev->counts[_DRM_STAT_SECONDARY]);
+       atomic_inc(&dev->counts[_DRM_STAT_DMA]);
+       sarea_priv->last_enqueue = dev_priv->counter - 1;
+       sarea_priv->last_dispatch = (int)hw_status[5];
+
+       return 0;
+}
+
+static int i810_clear_bufs(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       drm_i810_clear_t *clear = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       /* GH: Someone's doing nasty things... */
+       if (!dev->dev_private) {
+               return -EINVAL;
+       }
+
+       i810_dma_dispatch_clear(dev, clear->flags,
+                               clear->clear_color, clear->clear_depth);
+       return 0;
+}
+
+static int i810_swap_bufs(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       i810_dma_dispatch_swap(dev);
+       return 0;
+}
+
+static int i810_getage(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+       u32 *hw_status = dev_priv->hw_status_page;
+       drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+           dev_priv->sarea_priv;
+
+       sarea_priv->last_dispatch = (int)hw_status[5];
+       return 0;
+}
+
+static int i810_getbuf(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       int retcode = 0;
+       drm_i810_dma_t *d = data;
+       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+       u32 *hw_status = dev_priv->hw_status_page;
+       drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+           dev_priv->sarea_priv;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       d->granted = 0;
+
+       retcode = i810_dma_get_buffer(dev, d, file_priv);
+
+       DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
+                 task_pid_nr(current), retcode, d->granted);
+
+       sarea_priv->last_dispatch = (int)hw_status[5];
+
+       return retcode;
+}
+
+static int i810_copybuf(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       /* Never copy - 2.4.x doesn't need it */
+       return 0;
+}
+
+static int i810_docopy(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       /* Never copy - 2.4.x doesn't need it */
+       return 0;
+}
+
+static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf, int used,
+                                unsigned int last_render)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+       drm_i810_buf_priv_t *buf_priv = buf->dev_private;
+       drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned long address = (unsigned long)buf->bus_address;
+       unsigned long start = address - dev->agp->base;
+       int u;
+       RING_LOCALS;
+
+       i810_kernel_lost_context(dev);
+
+       u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_HARDWARE);
+       if (u != I810_BUF_CLIENT) {
+               DRM_DEBUG("MC found buffer that isn't mine!\n");
+       }
+
+       if (used > 4 * 1024)
+               used = 0;
+
+       sarea_priv->dirty = 0x7f;
+
+       DRM_DEBUG("addr 0x%lx, used 0x%x\n", address, used);
+
+       dev_priv->counter++;
+       DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
+       DRM_DEBUG("start : %lx\n", start);
+       DRM_DEBUG("used : %d\n", used);
+       DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
+
+       if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
+               if (used & 4) {
+                       *(u32 *) ((char *) buf_priv->virtual + used) = 0;
+                       used += 4;
+               }
+
+               i810_unmap_buffer(buf);
+       }
+       BEGIN_LP_RING(4);
+       OUT_RING(CMD_OP_BATCH_BUFFER);
+       OUT_RING(start | BB1_PROTECTED);
+       OUT_RING(start + used - 4);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       BEGIN_LP_RING(8);
+       OUT_RING(CMD_STORE_DWORD_IDX);
+       OUT_RING(buf_priv->my_use_idx);
+       OUT_RING(I810_BUF_FREE);
+       OUT_RING(0);
+
+       OUT_RING(CMD_STORE_DWORD_IDX);
+       OUT_RING(16);
+       OUT_RING(last_render);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+}
+
+static int i810_dma_mc(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+       u32 *hw_status = dev_priv->hw_status_page;
+       drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
+           dev_priv->sarea_priv;
+       drm_i810_mc_t *mc = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (mc->idx >= dma->buf_count || mc->idx < 0)
+               return -EINVAL;
+
+       i810_dma_dispatch_mc(dev, dma->buflist[mc->idx], mc->used,
+                            mc->last_render);
+
+       atomic_add(mc->used, &dev->counts[_DRM_STAT_SECONDARY]);
+       atomic_inc(&dev->counts[_DRM_STAT_DMA]);
+       sarea_priv->last_enqueue = dev_priv->counter - 1;
+       sarea_priv->last_dispatch = (int)hw_status[5];
+
+       return 0;
+}
+
+static int i810_rstatus(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+
+       return (int)(((u32 *) (dev_priv->hw_status_page))[4]);
+}
+
+static int i810_ov0_info(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+       drm_i810_overlay_t *ov = data;
+
+       ov->offset = dev_priv->overlay_offset;
+       ov->physical = dev_priv->overlay_physical;
+
+       return 0;
+}
+
+static int i810_fstatus(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+       return I810_READ(0x30008);
+}
+
+static int i810_ov0_flip(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       //Tell the overlay to update
+       I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000);
+
+       return 0;
+}
+
+/* Not sure why this isn't set all the time:
+ */
+static void i810_do_init_pageflip(struct drm_device * dev)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+       dev_priv->page_flipping = 1;
+       dev_priv->current_page = 0;
+       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+}
+
+static int i810_do_cleanup_pageflip(struct drm_device * dev)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+       if (dev_priv->current_page != 0)
+               i810_dma_dispatch_flip(dev);
+
+       dev_priv->page_flipping = 0;
+       return 0;
+}
+
+static int i810_flip_bufs(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       drm_i810_private_t *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (!dev_priv->page_flipping)
+               i810_do_init_pageflip(dev);
+
+       i810_dma_dispatch_flip(dev);
+       return 0;
+}
+
+int i810_driver_load(struct drm_device *dev, unsigned long flags)
+{
+       /* i810 has 4 more counters */
+       dev->counters += 4;
+       dev->types[6] = _DRM_STAT_IRQ;
+       dev->types[7] = _DRM_STAT_PRIMARY;
+       dev->types[8] = _DRM_STAT_SECONDARY;
+       dev->types[9] = _DRM_STAT_DMA;
+
+       return 0;
+}
+
+void i810_driver_lastclose(struct drm_device * dev)
+{
+       i810_dma_cleanup(dev);
+}
+
+void i810_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
+{
+       if (dev->dev_private) {
+               drm_i810_private_t *dev_priv = dev->dev_private;
+               if (dev_priv->page_flipping) {
+                       i810_do_cleanup_pageflip(dev);
+               }
+       }
+}
+
+void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
+                                       struct drm_file *file_priv)
+{
+       i810_reclaim_buffers(dev, file_priv);
+}
+
+int i810_driver_dma_quiescent(struct drm_device * dev)
+{
+       i810_dma_quiescent(dev);
+       return 0;
+}
+
+struct drm_ioctl_desc i810_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH)
+};
+
+int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev   The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i810 is AGP.
+ */
+int i810_driver_device_is_agp(struct drm_device * dev)
+{
+       return 1;
+}
diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c
new file mode 100644 (file)
index 0000000..fabb9a8
--- /dev/null
@@ -0,0 +1,97 @@
+/* i810_drv.c -- I810 driver -*- linux-c -*-
+ * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Jeff Hartmann <jhartmann@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i810_drm.h"
+#include "i810_drv.h"
+
+#include "drm_pciids.h"
+
+static struct pci_device_id pciidlist[] = {
+       i810_PCI_IDS
+};
+
+static struct drm_driver driver = {
+       .driver_features =
+           DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
+           DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
+       .dev_priv_size = sizeof(drm_i810_buf_priv_t),
+       .load = i810_driver_load,
+       .lastclose = i810_driver_lastclose,
+       .preclose = i810_driver_preclose,
+       .device_is_agp = i810_driver_device_is_agp,
+       .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked,
+       .dma_quiescent = i810_driver_dma_quiescent,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .ioctls = i810_ioctls,
+       .fops = {
+                .owner = THIS_MODULE,
+                .open = drm_open,
+                .release = drm_release,
+                .ioctl = drm_ioctl,
+                .mmap = drm_mmap,
+                .poll = drm_poll,
+                .fasync = drm_fasync,
+       },
+
+       .pci_driver = {
+                .name = DRIVER_NAME,
+                .id_table = pciidlist,
+       },
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int __init i810_init(void)
+{
+       driver.num_ioctls = i810_max_ioctl;
+       return drm_init(&driver);
+}
+
+static void __exit i810_exit(void)
+{
+       drm_exit(&driver);
+}
+
+module_init(i810_init);
+module_exit(i810_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/i810/i810_drv.h b/drivers/gpu/drm/i810/i810_drv.h
new file mode 100644 (file)
index 0000000..0118849
--- /dev/null
@@ -0,0 +1,242 @@
+/* i810_drv.h -- Private header for the Matrox g200/g400 driver -*- linux-c -*-
+ * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
+ *         Jeff Hartmann <jhartmann@valinux.com>
+ *
+ */
+
+#ifndef _I810_DRV_H_
+#define _I810_DRV_H_
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR          "VA Linux Systems Inc."
+
+#define DRIVER_NAME            "i810"
+#define DRIVER_DESC            "Intel i810"
+#define DRIVER_DATE            "20030605"
+
+/* Interface history
+ *
+ * 1.1   - XFree86 4.1
+ * 1.2   - XvMC interfaces
+ *       - XFree86 4.2
+ * 1.2.1 - Disable copying code (leave stub ioctls for backwards compatibility)
+ *       - Remove requirement for interrupt (leave stubs again)
+ * 1.3   - Add page flipping.
+ * 1.4   - fix DRM interface
+ */
+#define DRIVER_MAJOR           1
+#define DRIVER_MINOR           4
+#define DRIVER_PATCHLEVEL      0
+
+typedef struct drm_i810_buf_priv {
+       u32 *in_use;
+       int my_use_idx;
+       int currently_mapped;
+       void *virtual;
+       void *kernel_virtual;
+       drm_local_map_t map;
+} drm_i810_buf_priv_t;
+
+typedef struct _drm_i810_ring_buffer {
+       int tail_mask;
+       unsigned long Start;
+       unsigned long End;
+       unsigned long Size;
+       u8 *virtual_start;
+       int head;
+       int tail;
+       int space;
+       drm_local_map_t map;
+} drm_i810_ring_buffer_t;
+
+typedef struct drm_i810_private {
+       struct drm_map *sarea_map;
+       struct drm_map *mmio_map;
+
+       drm_i810_sarea_t *sarea_priv;
+       drm_i810_ring_buffer_t ring;
+
+       void *hw_status_page;
+       unsigned long counter;
+
+       dma_addr_t dma_status_page;
+
+       struct drm_buf *mmap_buffer;
+
+       u32 front_di1, back_di1, zi1;
+
+       int back_offset;
+       int depth_offset;
+       int overlay_offset;
+       int overlay_physical;
+       int w, h;
+       int pitch;
+       int back_pitch;
+       int depth_pitch;
+
+       int do_boxes;
+       int dma_used;
+
+       int current_page;
+       int page_flipping;
+
+       wait_queue_head_t irq_queue;
+       atomic_t irq_received;
+       atomic_t irq_emitted;
+
+       int front_offset;
+} drm_i810_private_t;
+
+                               /* i810_dma.c */
+extern int i810_driver_dma_quiescent(struct drm_device * dev);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
+                                              struct drm_file *file_priv);
+extern int i810_driver_load(struct drm_device *, unsigned long flags);
+extern void i810_driver_lastclose(struct drm_device * dev);
+extern void i810_driver_preclose(struct drm_device * dev,
+                                struct drm_file *file_priv);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
+                                              struct drm_file *file_priv);
+extern int i810_driver_device_is_agp(struct drm_device * dev);
+
+extern struct drm_ioctl_desc i810_ioctls[];
+extern int i810_max_ioctl;
+
+#define I810_BASE(reg)         ((unsigned long) \
+                               dev_priv->mmio_map->handle)
+#define I810_ADDR(reg)         (I810_BASE(reg) + reg)
+#define I810_DEREF(reg)                *(__volatile__ int *)I810_ADDR(reg)
+#define I810_READ(reg)         I810_DEREF(reg)
+#define I810_WRITE(reg,val)    do { I810_DEREF(reg) = val; } while (0)
+#define I810_DEREF16(reg)      *(__volatile__ u16 *)I810_ADDR(reg)
+#define I810_READ16(reg)       I810_DEREF16(reg)
+#define I810_WRITE16(reg,val)  do { I810_DEREF16(reg) = val; } while (0)
+
+#define I810_VERBOSE 0
+#define RING_LOCALS    unsigned int outring, ringmask; \
+                        volatile char *virt;
+
+#define BEGIN_LP_RING(n) do {                                          \
+       if (I810_VERBOSE)                                               \
+               DRM_DEBUG("BEGIN_LP_RING(%d)\n", n);                    \
+       if (dev_priv->ring.space < n*4)                                 \
+               i810_wait_ring(dev, n*4);                               \
+       dev_priv->ring.space -= n*4;                                    \
+       outring = dev_priv->ring.tail;                                  \
+       ringmask = dev_priv->ring.tail_mask;                            \
+       virt = dev_priv->ring.virtual_start;                            \
+} while (0)
+
+#define ADVANCE_LP_RING() do {                                 \
+       if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n");       \
+       dev_priv->ring.tail = outring;                          \
+       I810_WRITE(LP_RING + RING_TAIL, outring);               \
+} while(0)
+
+#define OUT_RING(n) do {                                               \
+       if (I810_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));      \
+       *(volatile unsigned int *)(virt + outring) = n;                 \
+       outring += 4;                                                   \
+       outring &= ringmask;                                            \
+} while (0)
+
+#define GFX_OP_USER_INTERRUPT          ((0<<29)|(2<<23))
+#define GFX_OP_BREAKPOINT_INTERRUPT    ((0<<29)|(1<<23))
+#define CMD_REPORT_HEAD                        (7<<23)
+#define CMD_STORE_DWORD_IDX            ((0x21<<23) | 0x1)
+#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
+
+#define INST_PARSER_CLIENT   0x00000000
+#define INST_OP_FLUSH        0x02000000
+#define INST_FLUSH_MAP_CACHE 0x00000001
+
+#define BB1_START_ADDR_MASK   (~0x7)
+#define BB1_PROTECTED         (1<<0)
+#define BB1_UNPROTECTED       (0<<0)
+#define BB2_END_ADDR_MASK     (~0x7)
+
+#define I810REG_HWSTAM         0x02098
+#define I810REG_INT_IDENTITY_R 0x020a4
+#define I810REG_INT_MASK_R     0x020a8
+#define I810REG_INT_ENABLE_R   0x020a0
+
+#define LP_RING                        0x2030
+#define HP_RING                        0x2040
+#define RING_TAIL              0x00
+#define TAIL_ADDR              0x000FFFF8
+#define RING_HEAD              0x04
+#define HEAD_WRAP_COUNT                0xFFE00000
+#define HEAD_WRAP_ONE          0x00200000
+#define HEAD_ADDR              0x001FFFFC
+#define RING_START             0x08
+#define START_ADDR             0x00FFFFF8
+#define RING_LEN               0x0C
+#define RING_NR_PAGES          0x000FF000
+#define RING_REPORT_MASK       0x00000006
+#define RING_REPORT_64K                0x00000002
+#define RING_REPORT_128K       0x00000004
+#define RING_NO_REPORT         0x00000000
+#define RING_VALID_MASK                0x00000001
+#define RING_VALID             0x00000001
+#define RING_INVALID           0x00000000
+
+#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define SC_UPDATE_SCISSOR       (0x1<<1)
+#define SC_ENABLE_MASK          (0x1<<0)
+#define SC_ENABLE               (0x1<<0)
+
+#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
+#define SCI_YMIN_MASK      (0xffff<<16)
+#define SCI_XMIN_MASK      (0xffff<<0)
+#define SCI_YMAX_MASK      (0xffff<<16)
+#define SCI_XMAX_MASK      (0xffff<<0)
+
+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x2)
+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+#define GFX_OP_PRIMITIVE         ((0x3<<29)|(0x1f<<24))
+
+#define CMD_OP_Z_BUFFER_INFO     ((0x0<<29)|(0x16<<23))
+#define CMD_OP_DESTBUFFER_INFO   ((0x0<<29)|(0x15<<23))
+#define CMD_OP_FRONTBUFFER_INFO  ((0x0<<29)|(0x14<<23))
+#define CMD_OP_WAIT_FOR_EVENT    ((0x0<<29)|(0x03<<23))
+
+#define BR00_BITBLT_CLIENT   0x40000000
+#define BR00_OP_COLOR_BLT    0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR13_SOLID_PATTERN   0x80000000
+
+#define WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+#define WAIT_FOR_PLANE_A_FLIP      (1<<2)
+#define WAIT_FOR_VBLANK (1<<3)
+
+#endif
diff --git a/drivers/gpu/drm/i830/Makefile b/drivers/gpu/drm/i830/Makefile
new file mode 100644 (file)
index 0000000..c642ee0
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+i830-y := i830_drv.o i830_dma.o i830_irq.o
+
+obj-$(CONFIG_DRM_I830) += i830.o
diff --git a/drivers/gpu/drm/i830/i830_dma.c b/drivers/gpu/drm/i830/i830_dma.c
new file mode 100644 (file)
index 0000000..a86ab30
--- /dev/null
@@ -0,0 +1,1553 @@
+/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
+ * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
+ *         Jeff Hartmann <jhartmann@valinux.com>
+ *         Keith Whitwell <keith@tungstengraphics.com>
+ *         Abraham vd Merwe <abraham@2d3d.co.za>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i830_drm.h"
+#include "i830_drv.h"
+#include <linux/interrupt.h>   /* For task queue support */
+#include <linux/pagemap.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+#define I830_BUF_FREE          2
+#define I830_BUF_CLIENT                1
+#define I830_BUF_HARDWARE      0
+
+#define I830_BUF_UNMAPPED 0
+#define I830_BUF_MAPPED   1
+
+static struct drm_buf *i830_freelist_get(struct drm_device * dev)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int i;
+       int used;
+
+       /* Linear search might not be the best solution */
+
+       for (i = 0; i < dma->buf_count; i++) {
+               struct drm_buf *buf = dma->buflist[i];
+               drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+               /* In use is already a pointer */
+               used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
+                              I830_BUF_CLIENT);
+               if (used == I830_BUF_FREE) {
+                       return buf;
+               }
+       }
+       return NULL;
+}
+
+/* This should only be called if the buffer is not sent to the hardware
+ * yet, the hardware updates in use for us once its on the ring buffer.
+ */
+
+static int i830_freelist_put(struct drm_device * dev, struct drm_buf * buf)
+{
+       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+       int used;
+
+       /* In use is already a pointer */
+       used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE);
+       if (used != I830_BUF_CLIENT) {
+               DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
+{
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev;
+       drm_i830_private_t *dev_priv;
+       struct drm_buf *buf;
+       drm_i830_buf_priv_t *buf_priv;
+
+       lock_kernel();
+       dev = priv->minor->dev;
+       dev_priv = dev->dev_private;
+       buf = dev_priv->mmap_buffer;
+       buf_priv = buf->dev_private;
+
+       vma->vm_flags |= (VM_IO | VM_DONTCOPY);
+       vma->vm_file = filp;
+
+       buf_priv->currently_mapped = I830_BUF_MAPPED;
+       unlock_kernel();
+
+       if (io_remap_pfn_range(vma, vma->vm_start,
+                              vma->vm_pgoff,
+                              vma->vm_end - vma->vm_start, vma->vm_page_prot))
+               return -EAGAIN;
+       return 0;
+}
+
+static const struct file_operations i830_buffer_fops = {
+       .open = drm_open,
+       .release = drm_release,
+       .ioctl = drm_ioctl,
+       .mmap = i830_mmap_buffers,
+       .fasync = drm_fasync,
+};
+
+static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
+{
+       struct drm_device *dev = file_priv->minor->dev;
+       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       const struct file_operations *old_fops;
+       unsigned long virtual;
+       int retcode = 0;
+
+       if (buf_priv->currently_mapped == I830_BUF_MAPPED)
+               return -EINVAL;
+
+       down_write(&current->mm->mmap_sem);
+       old_fops = file_priv->filp->f_op;
+       file_priv->filp->f_op = &i830_buffer_fops;
+       dev_priv->mmap_buffer = buf;
+       virtual = do_mmap(file_priv->filp, 0, buf->total, PROT_READ | PROT_WRITE,
+                         MAP_SHARED, buf->bus_address);
+       dev_priv->mmap_buffer = NULL;
+       file_priv->filp->f_op = old_fops;
+       if (IS_ERR((void *)virtual)) {  /* ugh */
+               /* Real error */
+               DRM_ERROR("mmap error\n");
+               retcode = PTR_ERR((void *)virtual);
+               buf_priv->virtual = NULL;
+       } else {
+               buf_priv->virtual = (void __user *)virtual;
+       }
+       up_write(&current->mm->mmap_sem);
+
+       return retcode;
+}
+
+static int i830_unmap_buffer(struct drm_buf * buf)
+{
+       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+       int retcode = 0;
+
+       if (buf_priv->currently_mapped != I830_BUF_MAPPED)
+               return -EINVAL;
+
+       down_write(&current->mm->mmap_sem);
+       retcode = do_munmap(current->mm,
+                           (unsigned long)buf_priv->virtual,
+                           (size_t) buf->total);
+       up_write(&current->mm->mmap_sem);
+
+       buf_priv->currently_mapped = I830_BUF_UNMAPPED;
+       buf_priv->virtual = NULL;
+
+       return retcode;
+}
+
+static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d,
+                              struct drm_file *file_priv)
+{
+       struct drm_buf *buf;
+       drm_i830_buf_priv_t *buf_priv;
+       int retcode = 0;
+
+       buf = i830_freelist_get(dev);
+       if (!buf) {
+               retcode = -ENOMEM;
+               DRM_DEBUG("retcode=%d\n", retcode);
+               return retcode;
+       }
+
+       retcode = i830_map_buffer(buf, file_priv);
+       if (retcode) {
+               i830_freelist_put(dev, buf);
+               DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
+               return retcode;
+       }
+       buf->file_priv = file_priv;
+       buf_priv = buf->dev_private;
+       d->granted = 1;
+       d->request_idx = buf->idx;
+       d->request_size = buf->total;
+       d->virtual = buf_priv->virtual;
+
+       return retcode;
+}
+
+static int i830_dma_cleanup(struct drm_device * dev)
+{
+       struct drm_device_dma *dma = dev->dma;
+
+       /* Make sure interrupts are disabled here because the uninstall ioctl
+        * may not have been called from userspace and after dev_private
+        * is freed, it's too late.
+        */
+       if (dev->irq_enabled)
+               drm_irq_uninstall(dev);
+
+       if (dev->dev_private) {
+               int i;
+               drm_i830_private_t *dev_priv =
+                   (drm_i830_private_t *) dev->dev_private;
+
+               if (dev_priv->ring.virtual_start) {
+                       drm_core_ioremapfree(&dev_priv->ring.map, dev);
+               }
+               if (dev_priv->hw_status_page) {
+                       pci_free_consistent(dev->pdev, PAGE_SIZE,
+                                           dev_priv->hw_status_page,
+                                           dev_priv->dma_status_page);
+                       /* Need to rewrite hardware status page */
+                       I830_WRITE(0x02080, 0x1ffff000);
+               }
+
+               drm_free(dev->dev_private, sizeof(drm_i830_private_t),
+                        DRM_MEM_DRIVER);
+               dev->dev_private = NULL;
+
+               for (i = 0; i < dma->buf_count; i++) {
+                       struct drm_buf *buf = dma->buflist[i];
+                       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+                       if (buf_priv->kernel_virtual && buf->total)
+                               drm_core_ioremapfree(&buf_priv->map, dev);
+               }
+       }
+       return 0;
+}
+
+int i830_wait_ring(struct drm_device * dev, int n, const char *caller)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
+       int iters = 0;
+       unsigned long end;
+       unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+
+       end = jiffies + (HZ * 3);
+       while (ring->space < n) {
+               ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+               ring->space = ring->head - (ring->tail + 8);
+               if (ring->space < 0)
+                       ring->space += ring->Size;
+
+               if (ring->head != last_head) {
+                       end = jiffies + (HZ * 3);
+                       last_head = ring->head;
+               }
+
+               iters++;
+               if (time_before(end, jiffies)) {
+                       DRM_ERROR("space: %d wanted %d\n", ring->space, n);
+                       DRM_ERROR("lockup\n");
+                       goto out_wait_ring;
+               }
+               udelay(1);
+               dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
+       }
+
+      out_wait_ring:
+       return iters;
+}
+
+static void i830_kernel_lost_context(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
+
+       ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+       ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
+       ring->space = ring->head - (ring->tail + 8);
+       if (ring->space < 0)
+               ring->space += ring->Size;
+
+       if (ring->head == ring->tail)
+               dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
+}
+
+static int i830_freelist_init(struct drm_device * dev, drm_i830_private_t * dev_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int my_idx = 36;
+       u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
+       int i;
+
+       if (dma->buf_count > 1019) {
+               /* Not enough space in the status page for the freelist */
+               return -EINVAL;
+       }
+
+       for (i = 0; i < dma->buf_count; i++) {
+               struct drm_buf *buf = dma->buflist[i];
+               drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+
+               buf_priv->in_use = hw_status++;
+               buf_priv->my_use_idx = my_idx;
+               my_idx += 4;
+
+               *buf_priv->in_use = I830_BUF_FREE;
+
+               buf_priv->map.offset = buf->bus_address;
+               buf_priv->map.size = buf->total;
+               buf_priv->map.type = _DRM_AGP;
+               buf_priv->map.flags = 0;
+               buf_priv->map.mtrr = 0;
+
+               drm_core_ioremap(&buf_priv->map, dev);
+               buf_priv->kernel_virtual = buf_priv->map.handle;
+       }
+       return 0;
+}
+
+static int i830_dma_initialize(struct drm_device * dev,
+                              drm_i830_private_t * dev_priv,
+                              drm_i830_init_t * init)
+{
+       struct drm_map_list *r_list;
+
+       memset(dev_priv, 0, sizeof(drm_i830_private_t));
+
+       list_for_each_entry(r_list, &dev->maplist, head) {
+               if (r_list->map &&
+                   r_list->map->type == _DRM_SHM &&
+                   r_list->map->flags & _DRM_CONTAINS_LOCK) {
+                       dev_priv->sarea_map = r_list->map;
+                       break;
+               }
+       }
+
+       if (!dev_priv->sarea_map) {
+               dev->dev_private = (void *)dev_priv;
+               i830_dma_cleanup(dev);
+               DRM_ERROR("can not find sarea!\n");
+               return -EINVAL;
+       }
+       dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
+       if (!dev_priv->mmio_map) {
+               dev->dev_private = (void *)dev_priv;
+               i830_dma_cleanup(dev);
+               DRM_ERROR("can not find mmio map!\n");
+               return -EINVAL;
+       }
+       dev->agp_buffer_token = init->buffers_offset;
+       dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+       if (!dev->agp_buffer_map) {
+               dev->dev_private = (void *)dev_priv;
+               i830_dma_cleanup(dev);
+               DRM_ERROR("can not find dma buffer map!\n");
+               return -EINVAL;
+       }
+
+       dev_priv->sarea_priv = (drm_i830_sarea_t *)
+           ((u8 *) dev_priv->sarea_map->handle + init->sarea_priv_offset);
+
+       dev_priv->ring.Start = init->ring_start;
+       dev_priv->ring.End = init->ring_end;
+       dev_priv->ring.Size = init->ring_size;
+
+       dev_priv->ring.map.offset = dev->agp->base + init->ring_start;
+       dev_priv->ring.map.size = init->ring_size;
+       dev_priv->ring.map.type = _DRM_AGP;
+       dev_priv->ring.map.flags = 0;
+       dev_priv->ring.map.mtrr = 0;
+
+       drm_core_ioremap(&dev_priv->ring.map, dev);
+
+       if (dev_priv->ring.map.handle == NULL) {
+               dev->dev_private = (void *)dev_priv;
+               i830_dma_cleanup(dev);
+               DRM_ERROR("can not ioremap virtual address for"
+                         " ring buffer\n");
+               return -ENOMEM;
+       }
+
+       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+
+       dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
+       dev_priv->w = init->w;
+       dev_priv->h = init->h;
+       dev_priv->pitch = init->pitch;
+       dev_priv->back_offset = init->back_offset;
+       dev_priv->depth_offset = init->depth_offset;
+       dev_priv->front_offset = init->front_offset;
+
+       dev_priv->front_di1 = init->front_offset | init->pitch_bits;
+       dev_priv->back_di1 = init->back_offset | init->pitch_bits;
+       dev_priv->zi1 = init->depth_offset | init->pitch_bits;
+
+       DRM_DEBUG("front_di1 %x\n", dev_priv->front_di1);
+       DRM_DEBUG("back_offset %x\n", dev_priv->back_offset);
+       DRM_DEBUG("back_di1 %x\n", dev_priv->back_di1);
+       DRM_DEBUG("pitch_bits %x\n", init->pitch_bits);
+
+       dev_priv->cpp = init->cpp;
+       /* We are using separate values as placeholders for mechanisms for
+        * private backbuffer/depthbuffer usage.
+        */
+
+       dev_priv->back_pitch = init->back_pitch;
+       dev_priv->depth_pitch = init->depth_pitch;
+       dev_priv->do_boxes = 0;
+       dev_priv->use_mi_batchbuffer_start = 0;
+
+       /* Program Hardware Status Page */
+       dev_priv->hw_status_page =
+           pci_alloc_consistent(dev->pdev, PAGE_SIZE,
+                                &dev_priv->dma_status_page);
+       if (!dev_priv->hw_status_page) {
+               dev->dev_private = (void *)dev_priv;
+               i830_dma_cleanup(dev);
+               DRM_ERROR("Can not allocate hardware status page\n");
+               return -ENOMEM;
+       }
+       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+       DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+
+       I830_WRITE(0x02080, dev_priv->dma_status_page);
+       DRM_DEBUG("Enabled hardware status page\n");
+
+       /* Now we need to init our freelist */
+       if (i830_freelist_init(dev, dev_priv) != 0) {
+               dev->dev_private = (void *)dev_priv;
+               i830_dma_cleanup(dev);
+               DRM_ERROR("Not enough space in the status page for"
+                         " the freelist\n");
+               return -ENOMEM;
+       }
+       dev->dev_private = (void *)dev_priv;
+
+       return 0;
+}
+
+static int i830_dma_init(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i830_private_t *dev_priv;
+       drm_i830_init_t *init = data;
+       int retcode = 0;
+
+       switch (init->func) {
+       case I830_INIT_DMA:
+               dev_priv = drm_alloc(sizeof(drm_i830_private_t),
+                                    DRM_MEM_DRIVER);
+               if (dev_priv == NULL)
+                       return -ENOMEM;
+               retcode = i830_dma_initialize(dev, dev_priv, init);
+               break;
+       case I830_CLEANUP_DMA:
+               retcode = i830_dma_cleanup(dev);
+               break;
+       default:
+               retcode = -EINVAL;
+               break;
+       }
+
+       return retcode;
+}
+
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define ST1_ENABLE               (1<<16)
+#define ST1_MASK                 (0xffff)
+
+/* Most efficient way to verify state for the i830 is as it is
+ * emitted.  Non-conformant state is silently dropped.
+ */
+static void i830EmitContextVerified(struct drm_device * dev, unsigned int *code)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       int i, j = 0;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING(I830_CTX_SETUP_SIZE + 4);
+
+       for (i = 0; i < I830_CTXREG_BLENDCOLR0; i++) {
+               tmp = code[i];
+               if ((tmp & (7 << 29)) == CMD_3D &&
+                   (tmp & (0x1f << 24)) < (0x1d << 24)) {
+                       OUT_RING(tmp);
+                       j++;
+               } else {
+                       DRM_ERROR("Skipping %d\n", i);
+               }
+       }
+
+       OUT_RING(STATE3D_CONST_BLEND_COLOR_CMD);
+       OUT_RING(code[I830_CTXREG_BLENDCOLR]);
+       j += 2;
+
+       for (i = I830_CTXREG_VF; i < I830_CTXREG_MCSB0; i++) {
+               tmp = code[i];
+               if ((tmp & (7 << 29)) == CMD_3D &&
+                   (tmp & (0x1f << 24)) < (0x1d << 24)) {
+                       OUT_RING(tmp);
+                       j++;
+               } else {
+                       DRM_ERROR("Skipping %d\n", i);
+               }
+       }
+
+       OUT_RING(STATE3D_MAP_COORD_SETBIND_CMD);
+       OUT_RING(code[I830_CTXREG_MCSB1]);
+       j += 2;
+
+       if (j & 1)
+               OUT_RING(0);
+
+       ADVANCE_LP_RING();
+}
+
+static void i830EmitTexVerified(struct drm_device * dev, unsigned int *code)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       int i, j = 0;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO ||
+           (code[I830_TEXREG_MI0] & ~(0xf * LOAD_TEXTURE_MAP0)) ==
+           (STATE3D_LOAD_STATE_IMMEDIATE_2 | 4)) {
+
+               BEGIN_LP_RING(I830_TEX_SETUP_SIZE);
+
+               OUT_RING(code[I830_TEXREG_MI0]);        /* TM0LI */
+               OUT_RING(code[I830_TEXREG_MI1]);        /* TM0S0 */
+               OUT_RING(code[I830_TEXREG_MI2]);        /* TM0S1 */
+               OUT_RING(code[I830_TEXREG_MI3]);        /* TM0S2 */
+               OUT_RING(code[I830_TEXREG_MI4]);        /* TM0S3 */
+               OUT_RING(code[I830_TEXREG_MI5]);        /* TM0S4 */
+
+               for (i = 6; i < I830_TEX_SETUP_SIZE; i++) {
+                       tmp = code[i];
+                       OUT_RING(tmp);
+                       j++;
+               }
+
+               if (j & 1)
+                       OUT_RING(0);
+
+               ADVANCE_LP_RING();
+       } else
+               printk("rejected packet %x\n", code[0]);
+}
+
+static void i830EmitTexBlendVerified(struct drm_device * dev,
+                                    unsigned int *code, unsigned int num)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       int i, j = 0;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       if (!num)
+               return;
+
+       BEGIN_LP_RING(num + 1);
+
+       for (i = 0; i < num; i++) {
+               tmp = code[i];
+               OUT_RING(tmp);
+               j++;
+       }
+
+       if (j & 1)
+               OUT_RING(0);
+
+       ADVANCE_LP_RING();
+}
+
+static void i830EmitTexPalette(struct drm_device * dev,
+                              unsigned int *palette, int number, int is_shared)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       int i;
+       RING_LOCALS;
+
+       return;
+
+       BEGIN_LP_RING(258);
+
+       if (is_shared == 1) {
+               OUT_RING(CMD_OP_MAP_PALETTE_LOAD |
+                        MAP_PALETTE_NUM(0) | MAP_PALETTE_BOTH);
+       } else {
+               OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
+       }
+       for (i = 0; i < 256; i++) {
+               OUT_RING(palette[i]);
+       }
+       OUT_RING(0);
+       /* KW:  WHERE IS THE ADVANCE_LP_RING?  This is effectively a noop!
+        */
+}
+
+/* Need to do some additional checking when setting the dest buffer.
+ */
+static void i830EmitDestVerified(struct drm_device * dev, unsigned int *code)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       unsigned int tmp;
+       RING_LOCALS;
+
+       BEGIN_LP_RING(I830_DEST_SETUP_SIZE + 10);
+
+       tmp = code[I830_DESTREG_CBUFADDR];
+       if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
+               if (((int)outring) & 8) {
+                       OUT_RING(0);
+                       OUT_RING(0);
+               }
+
+               OUT_RING(CMD_OP_DESTBUFFER_INFO);
+               OUT_RING(BUF_3D_ID_COLOR_BACK |
+                        BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
+                        BUF_3D_USE_FENCE);
+               OUT_RING(tmp);
+               OUT_RING(0);
+
+               OUT_RING(CMD_OP_DESTBUFFER_INFO);
+               OUT_RING(BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE |
+                        BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
+               OUT_RING(dev_priv->zi1);
+               OUT_RING(0);
+       } else {
+               DRM_ERROR("bad di1 %x (allow %x or %x)\n",
+                         tmp, dev_priv->front_di1, dev_priv->back_di1);
+       }
+
+       /* invarient:
+        */
+
+       OUT_RING(GFX_OP_DESTBUFFER_VARS);
+       OUT_RING(code[I830_DESTREG_DV1]);
+
+       OUT_RING(GFX_OP_DRAWRECT_INFO);
+       OUT_RING(code[I830_DESTREG_DR1]);
+       OUT_RING(code[I830_DESTREG_DR2]);
+       OUT_RING(code[I830_DESTREG_DR3]);
+       OUT_RING(code[I830_DESTREG_DR4]);
+
+       /* Need to verify this */
+       tmp = code[I830_DESTREG_SENABLE];
+       if ((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
+               OUT_RING(tmp);
+       } else {
+               DRM_ERROR("bad scissor enable\n");
+               OUT_RING(0);
+       }
+
+       OUT_RING(GFX_OP_SCISSOR_RECT);
+       OUT_RING(code[I830_DESTREG_SR1]);
+       OUT_RING(code[I830_DESTREG_SR2]);
+       OUT_RING(0);
+
+       ADVANCE_LP_RING();
+}
+
+static void i830EmitStippleVerified(struct drm_device * dev, unsigned int *code)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       BEGIN_LP_RING(2);
+       OUT_RING(GFX_OP_STIPPLE);
+       OUT_RING(code[1]);
+       ADVANCE_LP_RING();
+}
+
+static void i830EmitState(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned int dirty = sarea_priv->dirty;
+
+       DRM_DEBUG("%s %x\n", __func__, dirty);
+
+       if (dirty & I830_UPLOAD_BUFFERS) {
+               i830EmitDestVerified(dev, sarea_priv->BufferState);
+               sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS;
+       }
+
+       if (dirty & I830_UPLOAD_CTX) {
+               i830EmitContextVerified(dev, sarea_priv->ContextState);
+               sarea_priv->dirty &= ~I830_UPLOAD_CTX;
+       }
+
+       if (dirty & I830_UPLOAD_TEX0) {
+               i830EmitTexVerified(dev, sarea_priv->TexState[0]);
+               sarea_priv->dirty &= ~I830_UPLOAD_TEX0;
+       }
+
+       if (dirty & I830_UPLOAD_TEX1) {
+               i830EmitTexVerified(dev, sarea_priv->TexState[1]);
+               sarea_priv->dirty &= ~I830_UPLOAD_TEX1;
+       }
+
+       if (dirty & I830_UPLOAD_TEXBLEND0) {
+               i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[0],
+                                        sarea_priv->TexBlendStateWordsUsed[0]);
+               sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0;
+       }
+
+       if (dirty & I830_UPLOAD_TEXBLEND1) {
+               i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[1],
+                                        sarea_priv->TexBlendStateWordsUsed[1]);
+               sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1;
+       }
+
+       if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) {
+               i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1);
+       } else {
+               if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
+                       i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0);
+                       sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0);
+               }
+               if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
+                       i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0);
+                       sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1);
+               }
+
+               /* 1.3:
+                */
+#if 0
+               if (dirty & I830_UPLOAD_TEX_PALETTE_N(2)) {
+                       i830EmitTexPalette(dev, sarea_priv->Palette2[0], 0, 0);
+                       sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
+               }
+               if (dirty & I830_UPLOAD_TEX_PALETTE_N(3)) {
+                       i830EmitTexPalette(dev, sarea_priv->Palette2[1], 1, 0);
+                       sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
+               }
+#endif
+       }
+
+       /* 1.3:
+        */
+       if (dirty & I830_UPLOAD_STIPPLE) {
+               i830EmitStippleVerified(dev, sarea_priv->StippleState);
+               sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE;
+       }
+
+       if (dirty & I830_UPLOAD_TEX2) {
+               i830EmitTexVerified(dev, sarea_priv->TexState2);
+               sarea_priv->dirty &= ~I830_UPLOAD_TEX2;
+       }
+
+       if (dirty & I830_UPLOAD_TEX3) {
+               i830EmitTexVerified(dev, sarea_priv->TexState3);
+               sarea_priv->dirty &= ~I830_UPLOAD_TEX3;
+       }
+
+       if (dirty & I830_UPLOAD_TEXBLEND2) {
+               i830EmitTexBlendVerified(dev,
+                                        sarea_priv->TexBlendState2,
+                                        sarea_priv->TexBlendStateWordsUsed2);
+
+               sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2;
+       }
+
+       if (dirty & I830_UPLOAD_TEXBLEND3) {
+               i830EmitTexBlendVerified(dev,
+                                        sarea_priv->TexBlendState3,
+                                        sarea_priv->TexBlendStateWordsUsed3);
+               sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3;
+       }
+}
+
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void i830_fill_box(struct drm_device * dev,
+                         int x, int y, int w, int h, int r, int g, int b)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       u32 color;
+       unsigned int BR13, CMD;
+       RING_LOCALS;
+
+       BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1 << 24);
+       CMD = XY_COLOR_BLT_CMD;
+       x += dev_priv->sarea_priv->boxes[0].x1;
+       y += dev_priv->sarea_priv->boxes[0].y1;
+
+       if (dev_priv->cpp == 4) {
+               BR13 |= (1 << 25);
+               CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
+               color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+       } else {
+               color = (((r & 0xf8) << 8) |
+                        ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
+       }
+
+       BEGIN_LP_RING(6);
+       OUT_RING(CMD);
+       OUT_RING(BR13);
+       OUT_RING((y << 16) | x);
+       OUT_RING(((y + h) << 16) | (x + w));
+
+       if (dev_priv->current_page == 1) {
+               OUT_RING(dev_priv->front_offset);
+       } else {
+               OUT_RING(dev_priv->back_offset);
+       }
+
+       OUT_RING(color);
+       ADVANCE_LP_RING();
+}
+
+static void i830_cp_performance_boxes(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+
+       /* Purple box for page flipping
+        */
+       if (dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP)
+               i830_fill_box(dev, 4, 4, 8, 8, 255, 0, 255);
+
+       /* Red box if we have to wait for idle at any point
+        */
+       if (dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT)
+               i830_fill_box(dev, 16, 4, 8, 8, 255, 0, 0);
+
+       /* Blue box: lost context?
+        */
+       if (dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT)
+               i830_fill_box(dev, 28, 4, 8, 8, 0, 0, 255);
+
+       /* Yellow box for texture swaps
+        */
+       if (dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD)
+               i830_fill_box(dev, 40, 4, 8, 8, 255, 255, 0);
+
+       /* Green box if hardware never idles (as far as we can tell)
+        */
+       if (!(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY))
+               i830_fill_box(dev, 64, 4, 8, 8, 0, 255, 0);
+
+       /* Draw bars indicating number of buffers allocated
+        * (not a great measure, easily confused)
+        */
+       if (dev_priv->dma_used) {
+               int bar = dev_priv->dma_used / 10240;
+               if (bar > 100)
+                       bar = 100;
+               if (bar < 1)
+                       bar = 1;
+               i830_fill_box(dev, 4, 16, bar, 4, 196, 128, 128);
+               dev_priv->dma_used = 0;
+       }
+
+       dev_priv->sarea_priv->perf_boxes = 0;
+}
+
+static void i830_dma_dispatch_clear(struct drm_device * dev, int flags,
+                                   unsigned int clear_color,
+                                   unsigned int clear_zval,
+                                   unsigned int clear_depthmask)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
+       int pitch = dev_priv->pitch;
+       int cpp = dev_priv->cpp;
+       int i;
+       unsigned int BR13, CMD, D_CMD;
+       RING_LOCALS;
+
+       if (dev_priv->current_page == 1) {
+               unsigned int tmp = flags;
+
+               flags &= ~(I830_FRONT | I830_BACK);
+               if (tmp & I830_FRONT)
+                       flags |= I830_BACK;
+               if (tmp & I830_BACK)
+                       flags |= I830_FRONT;
+       }
+
+       i830_kernel_lost_context(dev);
+
+       switch (cpp) {
+       case 2:
+               BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
+               D_CMD = CMD = XY_COLOR_BLT_CMD;
+               break;
+       case 4:
+               BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24) | (1 << 25);
+               CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
+                      XY_COLOR_BLT_WRITE_RGB);
+               D_CMD = XY_COLOR_BLT_CMD;
+               if (clear_depthmask & 0x00ffffff)
+                       D_CMD |= XY_COLOR_BLT_WRITE_RGB;
+               if (clear_depthmask & 0xff000000)
+                       D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
+               break;
+       default:
+               BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
+               D_CMD = CMD = XY_COLOR_BLT_CMD;
+               break;
+       }
+
+       if (nbox > I830_NR_SAREA_CLIPRECTS)
+               nbox = I830_NR_SAREA_CLIPRECTS;
+
+       for (i = 0; i < nbox; i++, pbox++) {
+               if (pbox->x1 > pbox->x2 ||
+                   pbox->y1 > pbox->y2 ||
+                   pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
+                       continue;
+
+               if (flags & I830_FRONT) {
+                       DRM_DEBUG("clear front\n");
+                       BEGIN_LP_RING(6);
+                       OUT_RING(CMD);
+                       OUT_RING(BR13);
+                       OUT_RING((pbox->y1 << 16) | pbox->x1);
+                       OUT_RING((pbox->y2 << 16) | pbox->x2);
+                       OUT_RING(dev_priv->front_offset);
+                       OUT_RING(clear_color);
+                       ADVANCE_LP_RING();
+               }
+
+               if (flags & I830_BACK) {
+                       DRM_DEBUG("clear back\n");
+                       BEGIN_LP_RING(6);
+                       OUT_RING(CMD);
+                       OUT_RING(BR13);
+                       OUT_RING((pbox->y1 << 16) | pbox->x1);
+                       OUT_RING((pbox->y2 << 16) | pbox->x2);
+                       OUT_RING(dev_priv->back_offset);
+                       OUT_RING(clear_color);
+                       ADVANCE_LP_RING();
+               }
+
+               if (flags & I830_DEPTH) {
+                       DRM_DEBUG("clear depth\n");
+                       BEGIN_LP_RING(6);
+                       OUT_RING(D_CMD);
+                       OUT_RING(BR13);
+                       OUT_RING((pbox->y1 << 16) | pbox->x1);
+                       OUT_RING((pbox->y2 << 16) | pbox->x2);
+                       OUT_RING(dev_priv->depth_offset);
+                       OUT_RING(clear_zval);
+                       ADVANCE_LP_RING();
+               }
+       }
+}
+
+static void i830_dma_dispatch_swap(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
+       int pitch = dev_priv->pitch;
+       int cpp = dev_priv->cpp;
+       int i;
+       unsigned int CMD, BR13;
+       RING_LOCALS;
+
+       DRM_DEBUG("swapbuffers\n");
+
+       i830_kernel_lost_context(dev);
+
+       if (dev_priv->do_boxes)
+               i830_cp_performance_boxes(dev);
+
+       switch (cpp) {
+       case 2:
+               BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
+               CMD = XY_SRC_COPY_BLT_CMD;
+               break;
+       case 4:
+               BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
+               CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+                      XY_SRC_COPY_BLT_WRITE_RGB);
+               break;
+       default:
+               BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
+               CMD = XY_SRC_COPY_BLT_CMD;
+               break;
+       }
+
+       if (nbox > I830_NR_SAREA_CLIPRECTS)
+               nbox = I830_NR_SAREA_CLIPRECTS;
+
+       for (i = 0; i < nbox; i++, pbox++) {
+               if (pbox->x1 > pbox->x2 ||
+                   pbox->y1 > pbox->y2 ||
+                   pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
+                       continue;
+
+               DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
+                         pbox->x1, pbox->y1, pbox->x2, pbox->y2);
+
+               BEGIN_LP_RING(8);
+               OUT_RING(CMD);
+               OUT_RING(BR13);
+               OUT_RING((pbox->y1 << 16) | pbox->x1);
+               OUT_RING((pbox->y2 << 16) | pbox->x2);
+
+               if (dev_priv->current_page == 0)
+                       OUT_RING(dev_priv->front_offset);
+               else
+                       OUT_RING(dev_priv->back_offset);
+
+               OUT_RING((pbox->y1 << 16) | pbox->x1);
+               OUT_RING(BR13 & 0xffff);
+
+               if (dev_priv->current_page == 0)
+                       OUT_RING(dev_priv->back_offset);
+               else
+                       OUT_RING(dev_priv->front_offset);
+
+               ADVANCE_LP_RING();
+       }
+}
+
+static void i830_dma_dispatch_flip(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+                 __func__,
+                 dev_priv->current_page,
+                 dev_priv->sarea_priv->pf_current_page);
+
+       i830_kernel_lost_context(dev);
+
+       if (dev_priv->do_boxes) {
+               dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP;
+               i830_cp_performance_boxes(dev);
+       }
+
+       BEGIN_LP_RING(2);
+       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       BEGIN_LP_RING(6);
+       OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
+       OUT_RING(0);
+       if (dev_priv->current_page == 0) {
+               OUT_RING(dev_priv->back_offset);
+               dev_priv->current_page = 1;
+       } else {
+               OUT_RING(dev_priv->front_offset);
+               dev_priv->current_page = 0;
+       }
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       BEGIN_LP_RING(2);
+       OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+}
+
+static void i830_dma_dispatch_vertex(struct drm_device * dev,
+                                    struct drm_buf * buf, int discard, int used)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+       drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       struct drm_clip_rect *box = sarea_priv->boxes;
+       int nbox = sarea_priv->nbox;
+       unsigned long address = (unsigned long)buf->bus_address;
+       unsigned long start = address - dev->agp->base;
+       int i = 0, u;
+       RING_LOCALS;
+
+       i830_kernel_lost_context(dev);
+
+       if (nbox > I830_NR_SAREA_CLIPRECTS)
+               nbox = I830_NR_SAREA_CLIPRECTS;
+
+       if (discard) {
+               u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
+                           I830_BUF_HARDWARE);
+               if (u != I830_BUF_CLIENT) {
+                       DRM_DEBUG("xxxx 2\n");
+               }
+       }
+
+       if (used > 4 * 1023)
+               used = 0;
+
+       if (sarea_priv->dirty)
+               i830EmitState(dev);
+
+       DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
+                 address, used, nbox);
+
+       dev_priv->counter++;
+       DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
+       DRM_DEBUG("i830_dma_dispatch\n");
+       DRM_DEBUG("start : %lx\n", start);
+       DRM_DEBUG("used : %d\n", used);
+       DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
+
+       if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
+               u32 *vp = buf_priv->kernel_virtual;
+
+               vp[0] = (GFX_OP_PRIMITIVE |
+                        sarea_priv->vertex_prim | ((used / 4) - 2));
+
+               if (dev_priv->use_mi_batchbuffer_start) {
+                       vp[used / 4] = MI_BATCH_BUFFER_END;
+                       used += 4;
+               }
+
+               if (used & 4) {
+                       vp[used / 4] = 0;
+                       used += 4;
+               }
+
+               i830_unmap_buffer(buf);
+       }
+
+       if (used) {
+               do {
+                       if (i < nbox) {
+                               BEGIN_LP_RING(6);
+                               OUT_RING(GFX_OP_DRAWRECT_INFO);
+                               OUT_RING(sarea_priv->
+                                        BufferState[I830_DESTREG_DR1]);
+                               OUT_RING(box[i].x1 | (box[i].y1 << 16));
+                               OUT_RING(box[i].x2 | (box[i].y2 << 16));
+                               OUT_RING(sarea_priv->
+                                        BufferState[I830_DESTREG_DR4]);
+                               OUT_RING(0);
+                               ADVANCE_LP_RING();
+                       }
+
+                       if (dev_priv->use_mi_batchbuffer_start) {
+                               BEGIN_LP_RING(2);
+                               OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+                               OUT_RING(start | MI_BATCH_NON_SECURE);
+                               ADVANCE_LP_RING();
+                       } else {
+                               BEGIN_LP_RING(4);
+                               OUT_RING(MI_BATCH_BUFFER);
+                               OUT_RING(start | MI_BATCH_NON_SECURE);
+                               OUT_RING(start + used - 4);
+                               OUT_RING(0);
+                               ADVANCE_LP_RING();
+                       }
+
+               } while (++i < nbox);
+       }
+
+       if (discard) {
+               dev_priv->counter++;
+
+               (void)cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
+                             I830_BUF_HARDWARE);
+
+               BEGIN_LP_RING(8);
+               OUT_RING(CMD_STORE_DWORD_IDX);
+               OUT_RING(20);
+               OUT_RING(dev_priv->counter);
+               OUT_RING(CMD_STORE_DWORD_IDX);
+               OUT_RING(buf_priv->my_use_idx);
+               OUT_RING(I830_BUF_FREE);
+               OUT_RING(CMD_REPORT_HEAD);
+               OUT_RING(0);
+               ADVANCE_LP_RING();
+       }
+}
+
+static void i830_dma_quiescent(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       i830_kernel_lost_context(dev);
+
+       BEGIN_LP_RING(4);
+       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+       OUT_RING(CMD_REPORT_HEAD);
+       OUT_RING(0);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
+}
+
+static int i830_flush_queue(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       int i, ret = 0;
+       RING_LOCALS;
+
+       i830_kernel_lost_context(dev);
+
+       BEGIN_LP_RING(2);
+       OUT_RING(CMD_REPORT_HEAD);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
+
+       for (i = 0; i < dma->buf_count; i++) {
+               struct drm_buf *buf = dma->buflist[i];
+               drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+
+               int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,
+                                  I830_BUF_FREE);
+
+               if (used == I830_BUF_HARDWARE)
+                       DRM_DEBUG("reclaimed from HARDWARE\n");
+               if (used == I830_BUF_CLIENT)
+                       DRM_DEBUG("still on client\n");
+       }
+
+       return ret;
+}
+
+/* Must be called with the lock held */
+static void i830_reclaim_buffers(struct drm_device * dev, struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int i;
+
+       if (!dma)
+               return;
+       if (!dev->dev_private)
+               return;
+       if (!dma->buflist)
+               return;
+
+       i830_flush_queue(dev);
+
+       for (i = 0; i < dma->buf_count; i++) {
+               struct drm_buf *buf = dma->buflist[i];
+               drm_i830_buf_priv_t *buf_priv = buf->dev_private;
+
+               if (buf->file_priv == file_priv && buf_priv) {
+                       int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
+                                          I830_BUF_FREE);
+
+                       if (used == I830_BUF_CLIENT)
+                               DRM_DEBUG("reclaimed from client\n");
+                       if (buf_priv->currently_mapped == I830_BUF_MAPPED)
+                               buf_priv->currently_mapped = I830_BUF_UNMAPPED;
+               }
+       }
+}
+
+static int i830_flush_ioctl(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv)
+{
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       i830_flush_queue(dev);
+       return 0;
+}
+
+static int i830_dma_vertex(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+       u32 *hw_status = dev_priv->hw_status_page;
+       drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
+           dev_priv->sarea_priv;
+       drm_i830_vertex_t *vertex = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n",
+                 vertex->idx, vertex->used, vertex->discard);
+
+       if (vertex->idx < 0 || vertex->idx > dma->buf_count)
+               return -EINVAL;
+
+       i830_dma_dispatch_vertex(dev,
+                                dma->buflist[vertex->idx],
+                                vertex->discard, vertex->used);
+
+       sarea_priv->last_enqueue = dev_priv->counter - 1;
+       sarea_priv->last_dispatch = (int)hw_status[5];
+
+       return 0;
+}
+
+static int i830_clear_bufs(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       drm_i830_clear_t *clear = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       /* GH: Someone's doing nasty things... */
+       if (!dev->dev_private) {
+               return -EINVAL;
+       }
+
+       i830_dma_dispatch_clear(dev, clear->flags,
+                               clear->clear_color,
+                               clear->clear_depth, clear->clear_depthmask);
+       return 0;
+}
+
+static int i830_swap_bufs(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       DRM_DEBUG("i830_swap_bufs\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       i830_dma_dispatch_swap(dev);
+       return 0;
+}
+
+/* Not sure why this isn't set all the time:
+ */
+static void i830_do_init_pageflip(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("%s\n", __func__);
+       dev_priv->page_flipping = 1;
+       dev_priv->current_page = 0;
+       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+}
+
+static int i830_do_cleanup_pageflip(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("%s\n", __func__);
+       if (dev_priv->current_page != 0)
+               i830_dma_dispatch_flip(dev);
+
+       dev_priv->page_flipping = 0;
+       return 0;
+}
+
+static int i830_flip_bufs(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("%s\n", __func__);
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (!dev_priv->page_flipping)
+               i830_do_init_pageflip(dev);
+
+       i830_dma_dispatch_flip(dev);
+       return 0;
+}
+
+static int i830_getage(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+       u32 *hw_status = dev_priv->hw_status_page;
+       drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
+           dev_priv->sarea_priv;
+
+       sarea_priv->last_dispatch = (int)hw_status[5];
+       return 0;
+}
+
+static int i830_getbuf(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       int retcode = 0;
+       drm_i830_dma_t *d = data;
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+       u32 *hw_status = dev_priv->hw_status_page;
+       drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
+           dev_priv->sarea_priv;
+
+       DRM_DEBUG("getbuf\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       d->granted = 0;
+
+       retcode = i830_dma_get_buffer(dev, d, file_priv);
+
+       DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
+                 task_pid_nr(current), retcode, d->granted);
+
+       sarea_priv->last_dispatch = (int)hw_status[5];
+
+       return retcode;
+}
+
+static int i830_copybuf(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       /* Never copy - 2.4.x doesn't need it */
+       return 0;
+}
+
+static int i830_docopy(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       return 0;
+}
+
+static int i830_getparam(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_getparam_t *param = data;
+       int value;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __func__);
+               return -EINVAL;
+       }
+
+       switch (param->param) {
+       case I830_PARAM_IRQ_ACTIVE:
+               value = dev->irq_enabled;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (copy_to_user(param->value, &value, sizeof(int))) {
+               DRM_ERROR("copy_to_user\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+static int i830_setparam(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_setparam_t *param = data;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __func__);
+               return -EINVAL;
+       }
+
+       switch (param->param) {
+       case I830_SETPARAM_USE_MI_BATCHBUFFER_START:
+               dev_priv->use_mi_batchbuffer_start = param->value;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int i830_driver_load(struct drm_device *dev, unsigned long flags)
+{
+       /* i830 has 4 more counters */
+       dev->counters += 4;
+       dev->types[6] = _DRM_STAT_IRQ;
+       dev->types[7] = _DRM_STAT_PRIMARY;
+       dev->types[8] = _DRM_STAT_SECONDARY;
+       dev->types[9] = _DRM_STAT_DMA;
+
+       return 0;
+}
+
+void i830_driver_lastclose(struct drm_device * dev)
+{
+       i830_dma_cleanup(dev);
+}
+
+void i830_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
+{
+       if (dev->dev_private) {
+               drm_i830_private_t *dev_priv = dev->dev_private;
+               if (dev_priv->page_flipping) {
+                       i830_do_cleanup_pageflip(dev);
+               }
+       }
+}
+
+void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct drm_file *file_priv)
+{
+       i830_reclaim_buffers(dev, file_priv);
+}
+
+int i830_driver_dma_quiescent(struct drm_device * dev)
+{
+       i830_dma_quiescent(dev);
+       return 0;
+}
+
+struct drm_ioctl_desc i830_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH)
+};
+
+int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev   The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i8xx is AGP.
+ */
+int i830_driver_device_is_agp(struct drm_device * dev)
+{
+       return 1;
+}
diff --git a/drivers/gpu/drm/i830/i830_drv.c b/drivers/gpu/drm/i830/i830_drv.c
new file mode 100644 (file)
index 0000000..389597e
--- /dev/null
@@ -0,0 +1,108 @@
+/* i830_drv.c -- I810 driver -*- linux-c -*-
+ * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Jeff Hartmann <jhartmann@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Abraham vd Merwe <abraham@2d3d.co.za>
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i830_drm.h"
+#include "i830_drv.h"
+
+#include "drm_pciids.h"
+
+static struct pci_device_id pciidlist[] = {
+       i830_PCI_IDS
+};
+
+static struct drm_driver driver = {
+       .driver_features =
+           DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
+           DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
+#if USE_IRQS
+       .driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ,
+#endif
+       .dev_priv_size = sizeof(drm_i830_buf_priv_t),
+       .load = i830_driver_load,
+       .lastclose = i830_driver_lastclose,
+       .preclose = i830_driver_preclose,
+       .device_is_agp = i830_driver_device_is_agp,
+       .reclaim_buffers_locked = i830_driver_reclaim_buffers_locked,
+       .dma_quiescent = i830_driver_dma_quiescent,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+#if USE_IRQS
+       .irq_preinstall = i830_driver_irq_preinstall,
+       .irq_postinstall = i830_driver_irq_postinstall,
+       .irq_uninstall = i830_driver_irq_uninstall,
+       .irq_handler = i830_driver_irq_handler,
+#endif
+       .ioctls = i830_ioctls,
+       .fops = {
+                .owner = THIS_MODULE,
+                .open = drm_open,
+                .release = drm_release,
+                .ioctl = drm_ioctl,
+                .mmap = drm_mmap,
+                .poll = drm_poll,
+                .fasync = drm_fasync,
+       },
+
+       .pci_driver = {
+                .name = DRIVER_NAME,
+                .id_table = pciidlist,
+       },
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int __init i830_init(void)
+{
+       driver.num_ioctls = i830_max_ioctl;
+       return drm_init(&driver);
+}
+
+static void __exit i830_exit(void)
+{
+       drm_exit(&driver);
+}
+
+module_init(i830_init);
+module_exit(i830_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/i830/i830_drv.h b/drivers/gpu/drm/i830/i830_drv.h
new file mode 100644 (file)
index 0000000..b5bf8cc
--- /dev/null
@@ -0,0 +1,292 @@
+/* i830_drv.h -- Private header for the I830 driver -*- linux-c -*-
+ * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
+ *         Jeff Hartmann <jhartmann@valinux.com>
+ *
+ */
+
+#ifndef _I830_DRV_H_
+#define _I830_DRV_H_
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR          "VA Linux Systems Inc."
+
+#define DRIVER_NAME            "i830"
+#define DRIVER_DESC            "Intel 830M"
+#define DRIVER_DATE            "20021108"
+
+/* Interface history:
+ *
+ * 1.1: Original.
+ * 1.2: ?
+ * 1.3: New irq emit/wait ioctls.
+ *      New pageflip ioctl.
+ *      New getparam ioctl.
+ *      State for texunits 3&4 in sarea.
+ *      New (alternative) layout for texture state.
+ */
+#define DRIVER_MAJOR           1
+#define DRIVER_MINOR           3
+#define DRIVER_PATCHLEVEL      2
+
+/* Driver will work either way: IRQ's save cpu time when waiting for
+ * the card, but are subject to subtle interactions between bios,
+ * hardware and the driver.
+ */
+/* XXX: Add vblank support? */
+#define USE_IRQS 0
+
+typedef struct drm_i830_buf_priv {
+       u32 *in_use;
+       int my_use_idx;
+       int currently_mapped;
+       void __user *virtual;
+       void *kernel_virtual;
+       drm_local_map_t map;
+} drm_i830_buf_priv_t;
+
+typedef struct _drm_i830_ring_buffer {
+       int tail_mask;
+       unsigned long Start;
+       unsigned long End;
+       unsigned long Size;
+       u8 *virtual_start;
+       int head;
+       int tail;
+       int space;
+       drm_local_map_t map;
+} drm_i830_ring_buffer_t;
+
+typedef struct drm_i830_private {
+       struct drm_map *sarea_map;
+       struct drm_map *mmio_map;
+
+       drm_i830_sarea_t *sarea_priv;
+       drm_i830_ring_buffer_t ring;
+
+       void *hw_status_page;
+       unsigned long counter;
+
+       dma_addr_t dma_status_page;
+
+       struct drm_buf *mmap_buffer;
+
+       u32 front_di1, back_di1, zi1;
+
+       int back_offset;
+       int depth_offset;
+       int front_offset;
+       int w, h;
+       int pitch;
+       int back_pitch;
+       int depth_pitch;
+       unsigned int cpp;
+
+       int do_boxes;
+       int dma_used;
+
+       int current_page;
+       int page_flipping;
+
+       wait_queue_head_t irq_queue;
+       atomic_t irq_received;
+       atomic_t irq_emitted;
+
+       int use_mi_batchbuffer_start;
+
+} drm_i830_private_t;
+
+extern struct drm_ioctl_desc i830_ioctls[];
+extern int i830_max_ioctl;
+
+/* i830_irq.c */
+extern int i830_irq_emit(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int i830_irq_wait(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+
+extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
+extern void i830_driver_irq_preinstall(struct drm_device * dev);
+extern void i830_driver_irq_postinstall(struct drm_device * dev);
+extern void i830_driver_irq_uninstall(struct drm_device * dev);
+extern int i830_driver_load(struct drm_device *, unsigned long flags);
+extern void i830_driver_preclose(struct drm_device * dev,
+                                struct drm_file *file_priv);
+extern void i830_driver_lastclose(struct drm_device * dev);
+extern void i830_driver_reclaim_buffers_locked(struct drm_device * dev,
+                                              struct drm_file *file_priv);
+extern int i830_driver_dma_quiescent(struct drm_device * dev);
+extern int i830_driver_device_is_agp(struct drm_device * dev);
+
+#define I830_READ(reg)          DRM_READ32(dev_priv->mmio_map, reg)
+#define I830_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, reg, val)
+#define I830_READ16(reg)        DRM_READ16(dev_priv->mmio_map, reg)
+#define I830_WRITE16(reg,val)   DRM_WRITE16(dev_priv->mmio_map, reg, val)
+
+#define I830_VERBOSE 0
+
+#define RING_LOCALS    unsigned int outring, ringmask, outcount; \
+                        volatile char *virt;
+
+#define BEGIN_LP_RING(n) do {                          \
+       if (I830_VERBOSE)                               \
+               printk("BEGIN_LP_RING(%d)\n", (n));     \
+       if (dev_priv->ring.space < n*4)                 \
+               i830_wait_ring(dev, n*4, __func__);             \
+       outcount = 0;                                   \
+       outring = dev_priv->ring.tail;                  \
+       ringmask = dev_priv->ring.tail_mask;            \
+       virt = dev_priv->ring.virtual_start;            \
+} while (0)
+
+#define OUT_RING(n) do {                                       \
+       if (I830_VERBOSE) printk("   OUT_RING %x\n", (int)(n)); \
+       *(volatile unsigned int *)(virt + outring) = n;         \
+        outcount++;                                            \
+       outring += 4;                                           \
+       outring &= ringmask;                                    \
+} while (0)
+
+#define ADVANCE_LP_RING() do {                                         \
+       if (I830_VERBOSE) printk("ADVANCE_LP_RING %x\n", outring);      \
+       dev_priv->ring.tail = outring;                                  \
+       dev_priv->ring.space -= outcount * 4;                           \
+       I830_WRITE(LP_RING + RING_TAIL, outring);                       \
+} while(0)
+
+extern int i830_wait_ring(struct drm_device * dev, int n, const char *caller);
+
+#define GFX_OP_USER_INTERRUPT          ((0<<29)|(2<<23))
+#define GFX_OP_BREAKPOINT_INTERRUPT    ((0<<29)|(1<<23))
+#define CMD_REPORT_HEAD                        (7<<23)
+#define CMD_STORE_DWORD_IDX            ((0x21<<23) | 0x1)
+#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
+
+#define STATE3D_LOAD_STATE_IMMEDIATE_2      ((0x3<<29)|(0x1d<<24)|(0x03<<16))
+#define LOAD_TEXTURE_MAP0                   (1<<11)
+
+#define INST_PARSER_CLIENT   0x00000000
+#define INST_OP_FLUSH        0x02000000
+#define INST_FLUSH_MAP_CACHE 0x00000001
+
+#define BB1_START_ADDR_MASK   (~0x7)
+#define BB1_PROTECTED         (1<<0)
+#define BB1_UNPROTECTED       (0<<0)
+#define BB2_END_ADDR_MASK     (~0x7)
+
+#define I830REG_HWSTAM         0x02098
+#define I830REG_INT_IDENTITY_R 0x020a4
+#define I830REG_INT_MASK_R     0x020a8
+#define I830REG_INT_ENABLE_R   0x020a0
+
+#define I830_IRQ_RESERVED ((1<<13)|(3<<2))
+
+#define LP_RING                        0x2030
+#define HP_RING                        0x2040
+#define RING_TAIL              0x00
+#define TAIL_ADDR              0x001FFFF8
+#define RING_HEAD              0x04
+#define HEAD_WRAP_COUNT                0xFFE00000
+#define HEAD_WRAP_ONE          0x00200000
+#define HEAD_ADDR              0x001FFFFC
+#define RING_START             0x08
+#define START_ADDR             0x0xFFFFF000
+#define RING_LEN               0x0C
+#define RING_NR_PAGES          0x001FF000
+#define RING_REPORT_MASK       0x00000006
+#define RING_REPORT_64K                0x00000002
+#define RING_REPORT_128K       0x00000004
+#define RING_NO_REPORT         0x00000000
+#define RING_VALID_MASK                0x00000001
+#define RING_VALID             0x00000001
+#define RING_INVALID           0x00000000
+
+#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define SC_UPDATE_SCISSOR       (0x1<<1)
+#define SC_ENABLE_MASK          (0x1<<0)
+#define SC_ENABLE               (0x1<<0)
+
+#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
+#define SCI_YMIN_MASK      (0xffff<<16)
+#define SCI_XMIN_MASK      (0xffff<<0)
+#define SCI_YMAX_MASK      (0xffff<<16)
+#define SCI_XMAX_MASK      (0xffff<<0)
+
+#define GFX_OP_SCISSOR_ENABLE   ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define GFX_OP_SCISSOR_RECT     ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+#define GFX_OP_PRIMITIVE         ((0x3<<29)|(0x1f<<24))
+
+#define CMD_OP_DESTBUFFER_INFO  ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+
+#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
+#define ASYNC_FLIP                (1<<22)
+
+#define CMD_3D                          (0x3<<29)
+#define STATE3D_CONST_BLEND_COLOR_CMD   (CMD_3D|(0x1d<<24)|(0x88<<16))
+#define STATE3D_MAP_COORD_SETBIND_CMD   (CMD_3D|(0x1d<<24)|(0x02<<16))
+
+#define BR00_BITBLT_CLIENT   0x40000000
+#define BR00_OP_COLOR_BLT    0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR13_SOLID_PATTERN   0x80000000
+
+#define BUF_3D_ID_COLOR_BACK    (0x3<<24)
+#define BUF_3D_ID_DEPTH         (0x7<<24)
+#define BUF_3D_USE_FENCE        (1<<23)
+#define BUF_3D_PITCH(x)         (((x)/4)<<2)
+
+#define CMD_OP_MAP_PALETTE_LOAD        ((3<<29)|(0x1d<<24)|(0x82<<16)|255)
+#define MAP_PALETTE_NUM(x)     ((x<<8) & (1<<8))
+#define MAP_PALETTE_BOTH       (1<<11)
+
+#define XY_COLOR_BLT_CMD               ((2<<29)|(0x50<<22)|0x4)
+#define XY_COLOR_BLT_WRITE_ALPHA       (1<<21)
+#define XY_COLOR_BLT_WRITE_RGB         (1<<20)
+
+#define XY_SRC_COPY_BLT_CMD             ((2<<29)|(0x53<<22)|6)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA     (1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB       (1<<20)
+
+#define MI_BATCH_BUFFER                ((0x30<<23)|1)
+#define MI_BATCH_BUFFER_START  (0x31<<23)
+#define MI_BATCH_BUFFER_END    (0xA<<23)
+#define MI_BATCH_NON_SECURE    (1)
+
+#define MI_WAIT_FOR_EVENT       ((0x3<<23))
+#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
+#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+
+#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
+
+#endif
diff --git a/drivers/gpu/drm/i830/i830_irq.c b/drivers/gpu/drm/i830/i830_irq.c
new file mode 100644 (file)
index 0000000..91ec2bb
--- /dev/null
@@ -0,0 +1,186 @@
+/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
+ *
+ * Copyright 2002 Tungsten Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i830_drm.h"
+#include "i830_drv.h"
+#include <linux/interrupt.h>   /* For task queue support */
+#include <linux/delay.h>
+
+irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+       u16 temp;
+
+       temp = I830_READ16(I830REG_INT_IDENTITY_R);
+       DRM_DEBUG("%x\n", temp);
+
+       if (!(temp & 2))
+               return IRQ_NONE;
+
+       I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
+
+       atomic_inc(&dev_priv->irq_received);
+       wake_up_interruptible(&dev_priv->irq_queue);
+
+       return IRQ_HANDLED;
+}
+
+static int i830_emit_irq(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       DRM_DEBUG("%s\n", __func__);
+
+       atomic_inc(&dev_priv->irq_emitted);
+
+       BEGIN_LP_RING(2);
+       OUT_RING(0);
+       OUT_RING(GFX_OP_USER_INTERRUPT);
+       ADVANCE_LP_RING();
+
+       return atomic_read(&dev_priv->irq_emitted);
+}
+
+static int i830_wait_irq(struct drm_device * dev, int irq_nr)
+{
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+       DECLARE_WAITQUEUE(entry, current);
+       unsigned long end = jiffies + HZ * 3;
+       int ret = 0;
+
+       DRM_DEBUG("%s\n", __func__);
+
+       if (atomic_read(&dev_priv->irq_received) >= irq_nr)
+               return 0;
+
+       dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
+
+       add_wait_queue(&dev_priv->irq_queue, &entry);
+
+       for (;;) {
+               __set_current_state(TASK_INTERRUPTIBLE);
+               if (atomic_read(&dev_priv->irq_received) >= irq_nr)
+                       break;
+               if ((signed)(end - jiffies) <= 0) {
+                       DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n",
+                                 I830_READ16(I830REG_INT_IDENTITY_R),
+                                 I830_READ16(I830REG_INT_MASK_R),
+                                 I830_READ16(I830REG_INT_ENABLE_R),
+                                 I830_READ16(I830REG_HWSTAM));
+
+                       ret = -EBUSY;   /* Lockup?  Missed irq? */
+                       break;
+               }
+               schedule_timeout(HZ * 3);
+               if (signal_pending(current)) {
+                       ret = -EINTR;
+                       break;
+               }
+       }
+
+       __set_current_state(TASK_RUNNING);
+       remove_wait_queue(&dev_priv->irq_queue, &entry);
+       return ret;
+}
+
+/* Needs the lock as it touches the ring.
+ */
+int i830_irq_emit(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_irq_emit_t *emit = data;
+       int result;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __func__);
+               return -EINVAL;
+       }
+
+       result = i830_emit_irq(dev);
+
+       if (copy_to_user(emit->irq_seq, &result, sizeof(int))) {
+               DRM_ERROR("copy_to_user\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/* Doesn't need the hardware lock.
+ */
+int i830_irq_wait(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
+{
+       drm_i830_private_t *dev_priv = dev->dev_private;
+       drm_i830_irq_wait_t *irqwait = data;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __func__);
+               return -EINVAL;
+       }
+
+       return i830_wait_irq(dev, irqwait->irq_seq);
+}
+
+/* drm_dma.h hooks
+*/
+void i830_driver_irq_preinstall(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+
+       I830_WRITE16(I830REG_HWSTAM, 0xffff);
+       I830_WRITE16(I830REG_INT_MASK_R, 0x0);
+       I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
+       atomic_set(&dev_priv->irq_received, 0);
+       atomic_set(&dev_priv->irq_emitted, 0);
+       init_waitqueue_head(&dev_priv->irq_queue);
+}
+
+void i830_driver_irq_postinstall(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+
+       I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
+}
+
+void i830_driver_irq_uninstall(struct drm_device * dev)
+{
+       drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
+       if (!dev_priv)
+               return;
+
+       I830_WRITE16(I830REG_INT_MASK_R, 0xffff);
+       I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
+}
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
new file mode 100644 (file)
index 0000000..a9e6046
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
+
+i915-$(CONFIG_COMPAT)   += i915_ioc32.o
+
+obj-$(CONFIG_DRM_I915)  += i915.o
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
new file mode 100644 (file)
index 0000000..8897434
--- /dev/null
@@ -0,0 +1,858 @@
+/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
+ */
+/*
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/* Really want an OS-independent resettable timer.  Would like to have
+ * this loop run for (eg) 3 sec, but have the timer reset every time
+ * the head pointer changes, so that EBUSY only happens if the ring
+ * actually stalls for (eg) 3 seconds.
+ */
+int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+       u32 last_head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+       int i;
+
+       for (i = 0; i < 10000; i++) {
+               ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+               ring->space = ring->head - (ring->tail + 8);
+               if (ring->space < 0)
+                       ring->space += ring->Size;
+               if (ring->space >= n)
+                       return 0;
+
+               dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+
+               if (ring->head != last_head)
+                       i = 0;
+
+               last_head = ring->head;
+       }
+
+       return -EBUSY;
+}
+
+void i915_kernel_lost_context(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
+
+       ring->head = I915_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
+       ring->tail = I915_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
+       ring->space = ring->head - (ring->tail + 8);
+       if (ring->space < 0)
+               ring->space += ring->Size;
+
+       if (ring->head == ring->tail)
+               dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
+}
+
+static int i915_dma_cleanup(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       /* Make sure interrupts are disabled here because the uninstall ioctl
+        * may not have been called from userspace and after dev_private
+        * is freed, it's too late.
+        */
+       if (dev->irq)
+               drm_irq_uninstall(dev);
+
+       if (dev_priv->ring.virtual_start) {
+               drm_core_ioremapfree(&dev_priv->ring.map, dev);
+               dev_priv->ring.virtual_start = 0;
+               dev_priv->ring.map.handle = 0;
+               dev_priv->ring.map.size = 0;
+       }
+
+       if (dev_priv->status_page_dmah) {
+               drm_pci_free(dev, dev_priv->status_page_dmah);
+               dev_priv->status_page_dmah = NULL;
+               /* Need to rewrite hardware status page */
+               I915_WRITE(0x02080, 0x1ffff000);
+       }
+
+       if (dev_priv->status_gfx_addr) {
+               dev_priv->status_gfx_addr = 0;
+               drm_core_ioremapfree(&dev_priv->hws_map, dev);
+               I915_WRITE(0x2080, 0x1ffff000);
+       }
+
+       return 0;
+}
+
+static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+
+       dev_priv->sarea = drm_getsarea(dev);
+       if (!dev_priv->sarea) {
+               DRM_ERROR("can not find sarea!\n");
+               i915_dma_cleanup(dev);
+               return -EINVAL;
+       }
+
+       dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
+       if (!dev_priv->mmio_map) {
+               i915_dma_cleanup(dev);
+               DRM_ERROR("can not find mmio map!\n");
+               return -EINVAL;
+       }
+
+       dev_priv->sarea_priv = (drm_i915_sarea_t *)
+           ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset);
+
+       dev_priv->ring.Start = init->ring_start;
+       dev_priv->ring.End = init->ring_end;
+       dev_priv->ring.Size = init->ring_size;
+       dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
+
+       dev_priv->ring.map.offset = init->ring_start;
+       dev_priv->ring.map.size = init->ring_size;
+       dev_priv->ring.map.type = 0;
+       dev_priv->ring.map.flags = 0;
+       dev_priv->ring.map.mtrr = 0;
+
+       drm_core_ioremap(&dev_priv->ring.map, dev);
+
+       if (dev_priv->ring.map.handle == NULL) {
+               i915_dma_cleanup(dev);
+               DRM_ERROR("can not ioremap virtual address for"
+                         " ring buffer\n");
+               return -ENOMEM;
+       }
+
+       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+
+       dev_priv->cpp = init->cpp;
+       dev_priv->back_offset = init->back_offset;
+       dev_priv->front_offset = init->front_offset;
+       dev_priv->current_page = 0;
+       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+
+       /* We are using separate values as placeholders for mechanisms for
+        * private backbuffer/depthbuffer usage.
+        */
+       dev_priv->use_mi_batchbuffer_start = 0;
+       if (IS_I965G(dev)) /* 965 doesn't support older method */
+               dev_priv->use_mi_batchbuffer_start = 1;
+
+       /* Allow hardware batchbuffers unless told otherwise.
+        */
+       dev_priv->allow_batchbuffer = 1;
+
+       /* Program Hardware Status Page */
+       if (!I915_NEED_GFX_HWS(dev)) {
+               dev_priv->status_page_dmah =
+                       drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
+
+               if (!dev_priv->status_page_dmah) {
+                       i915_dma_cleanup(dev);
+                       DRM_ERROR("Can not allocate hardware status page\n");
+                       return -ENOMEM;
+               }
+               dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+               dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+
+               memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+               I915_WRITE(0x02080, dev_priv->dma_status_page);
+       }
+       DRM_DEBUG("Enabled hardware status page\n");
+       return 0;
+}
+
+static int i915_dma_resume(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+       DRM_DEBUG("%s\n", __func__);
+
+       if (!dev_priv->sarea) {
+               DRM_ERROR("can not find sarea!\n");
+               return -EINVAL;
+       }
+
+       if (!dev_priv->mmio_map) {
+               DRM_ERROR("can not find mmio map!\n");
+               return -EINVAL;
+       }
+
+       if (dev_priv->ring.map.handle == NULL) {
+               DRM_ERROR("can not ioremap virtual address for"
+                         " ring buffer\n");
+               return -ENOMEM;
+       }
+
+       /* Program Hardware Status Page */
+       if (!dev_priv->hw_status_page) {
+               DRM_ERROR("Can not find hardware status page\n");
+               return -EINVAL;
+       }
+       DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
+
+       if (dev_priv->status_gfx_addr != 0)
+               I915_WRITE(0x02080, dev_priv->status_gfx_addr);
+       else
+               I915_WRITE(0x02080, dev_priv->dma_status_page);
+       DRM_DEBUG("Enabled hardware status page\n");
+
+       return 0;
+}
+
+static int i915_dma_init(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i915_init_t *init = data;
+       int retcode = 0;
+
+       switch (init->func) {
+       case I915_INIT_DMA:
+               retcode = i915_initialize(dev, init);
+               break;
+       case I915_CLEANUP_DMA:
+               retcode = i915_dma_cleanup(dev);
+               break;
+       case I915_RESUME_DMA:
+               retcode = i915_dma_resume(dev);
+               break;
+       default:
+               retcode = -EINVAL;
+               break;
+       }
+
+       return retcode;
+}
+
+/* Implement basically the same security restrictions as hardware does
+ * for MI_BATCH_NON_SECURE.  These can be made stricter at any time.
+ *
+ * Most of the calculations below involve calculating the size of a
+ * particular instruction.  It's important to get the size right as
+ * that tells us where the next instruction to check is.  Any illegal
+ * instruction detected will be given a size of zero, which is a
+ * signal to abort the rest of the buffer.
+ */
+static int do_validate_cmd(int cmd)
+{
+       switch (((cmd >> 29) & 0x7)) {
+       case 0x0:
+               switch ((cmd >> 23) & 0x3f) {
+               case 0x0:
+                       return 1;       /* MI_NOOP */
+               case 0x4:
+                       return 1;       /* MI_FLUSH */
+               default:
+                       return 0;       /* disallow everything else */
+               }
+               break;
+       case 0x1:
+               return 0;       /* reserved */
+       case 0x2:
+               return (cmd & 0xff) + 2;        /* 2d commands */
+       case 0x3:
+               if (((cmd >> 24) & 0x1f) <= 0x18)
+                       return 1;
+
+               switch ((cmd >> 24) & 0x1f) {
+               case 0x1c:
+                       return 1;
+               case 0x1d:
+                       switch ((cmd >> 16) & 0xff) {
+                       case 0x3:
+                               return (cmd & 0x1f) + 2;
+                       case 0x4:
+                               return (cmd & 0xf) + 2;
+                       default:
+                               return (cmd & 0xffff) + 2;
+                       }
+               case 0x1e:
+                       if (cmd & (1 << 23))
+                               return (cmd & 0xffff) + 1;
+                       else
+                               return 1;
+               case 0x1f:
+                       if ((cmd & (1 << 23)) == 0)     /* inline vertices */
+                               return (cmd & 0x1ffff) + 2;
+                       else if (cmd & (1 << 17))       /* indirect random */
+                               if ((cmd & 0xffff) == 0)
+                                       return 0;       /* unknown length, too hard */
+                               else
+                                       return (((cmd & 0xffff) + 1) / 2) + 1;
+                       else
+                               return 2;       /* indirect sequential */
+               default:
+                       return 0;
+               }
+       default:
+               return 0;
+       }
+
+       return 0;
+}
+
+static int validate_cmd(int cmd)
+{
+       int ret = do_validate_cmd(cmd);
+
+/*     printk("validate_cmd( %x ): %d\n", cmd, ret); */
+
+       return ret;
+}
+
+static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       int i;
+       RING_LOCALS;
+
+       if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
+               return -EINVAL;
+
+       BEGIN_LP_RING((dwords+1)&~1);
+
+       for (i = 0; i < dwords;) {
+               int cmd, sz;
+
+               if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
+                       return -EINVAL;
+
+               if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
+                       return -EINVAL;
+
+               OUT_RING(cmd);
+
+               while (++i, --sz) {
+                       if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
+                                                        sizeof(cmd))) {
+                               return -EINVAL;
+                       }
+                       OUT_RING(cmd);
+               }
+       }
+
+       if (dwords & 1)
+               OUT_RING(0);
+
+       ADVANCE_LP_RING();
+
+       return 0;
+}
+
+static int i915_emit_box(struct drm_device * dev,
+                        struct drm_clip_rect __user * boxes,
+                        int i, int DR1, int DR4)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_clip_rect box;
+       RING_LOCALS;
+
+       if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
+               return -EFAULT;
+       }
+
+       if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
+               DRM_ERROR("Bad box %d,%d..%d,%d\n",
+                         box.x1, box.y1, box.x2, box.y2);
+               return -EINVAL;
+       }
+
+       if (IS_I965G(dev)) {
+               BEGIN_LP_RING(4);
+               OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
+               OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
+               OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
+               OUT_RING(DR4);
+               ADVANCE_LP_RING();
+       } else {
+               BEGIN_LP_RING(6);
+               OUT_RING(GFX_OP_DRAWRECT_INFO);
+               OUT_RING(DR1);
+               OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
+               OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
+               OUT_RING(DR4);
+               OUT_RING(0);
+               ADVANCE_LP_RING();
+       }
+
+       return 0;
+}
+
+/* XXX: Emitting the counter should really be moved to part of the IRQ
+ * emit. For now, do it in both places:
+ */
+
+static void i915_emit_breadcrumb(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
+
+       if (dev_priv->counter > 0x7FFFFFFFUL)
+               dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
+
+       BEGIN_LP_RING(4);
+       OUT_RING(CMD_STORE_DWORD_IDX);
+       OUT_RING(20);
+       OUT_RING(dev_priv->counter);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+}
+
+static int i915_dispatch_cmdbuffer(struct drm_device * dev,
+                                  drm_i915_cmdbuffer_t * cmd)
+{
+       int nbox = cmd->num_cliprects;
+       int i = 0, count, ret;
+
+       if (cmd->sz & 0x3) {
+               DRM_ERROR("alignment");
+               return -EINVAL;
+       }
+
+       i915_kernel_lost_context(dev);
+
+       count = nbox ? nbox : 1;
+
+       for (i = 0; i < count; i++) {
+               if (i < nbox) {
+                       ret = i915_emit_box(dev, cmd->cliprects, i,
+                                           cmd->DR1, cmd->DR4);
+                       if (ret)
+                               return ret;
+               }
+
+               ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
+               if (ret)
+                       return ret;
+       }
+
+       i915_emit_breadcrumb(dev);
+       return 0;
+}
+
+static int i915_dispatch_batchbuffer(struct drm_device * dev,
+                                    drm_i915_batchbuffer_t * batch)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_clip_rect __user *boxes = batch->cliprects;
+       int nbox = batch->num_cliprects;
+       int i = 0, count;
+       RING_LOCALS;
+
+       if ((batch->start | batch->used) & 0x7) {
+               DRM_ERROR("alignment");
+               return -EINVAL;
+       }
+
+       i915_kernel_lost_context(dev);
+
+       count = nbox ? nbox : 1;
+
+       for (i = 0; i < count; i++) {
+               if (i < nbox) {
+                       int ret = i915_emit_box(dev, boxes, i,
+                                               batch->DR1, batch->DR4);
+                       if (ret)
+                               return ret;
+               }
+
+               if (dev_priv->use_mi_batchbuffer_start) {
+                       BEGIN_LP_RING(2);
+                       if (IS_I965G(dev)) {
+                               OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
+                               OUT_RING(batch->start);
+                       } else {
+                               OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+                               OUT_RING(batch->start | MI_BATCH_NON_SECURE);
+                       }
+                       ADVANCE_LP_RING();
+               } else {
+                       BEGIN_LP_RING(4);
+                       OUT_RING(MI_BATCH_BUFFER);
+                       OUT_RING(batch->start | MI_BATCH_NON_SECURE);
+                       OUT_RING(batch->start + batch->used - 4);
+                       OUT_RING(0);
+                       ADVANCE_LP_RING();
+               }
+       }
+
+       i915_emit_breadcrumb(dev);
+
+       return 0;
+}
+
+static int i915_dispatch_flip(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
+                 __FUNCTION__,
+                 dev_priv->current_page,
+                 dev_priv->sarea_priv->pf_current_page);
+
+       i915_kernel_lost_context(dev);
+
+       BEGIN_LP_RING(2);
+       OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       BEGIN_LP_RING(6);
+       OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
+       OUT_RING(0);
+       if (dev_priv->current_page == 0) {
+               OUT_RING(dev_priv->back_offset);
+               dev_priv->current_page = 1;
+       } else {
+               OUT_RING(dev_priv->front_offset);
+               dev_priv->current_page = 0;
+       }
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       BEGIN_LP_RING(2);
+       OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+
+       BEGIN_LP_RING(4);
+       OUT_RING(CMD_STORE_DWORD_IDX);
+       OUT_RING(20);
+       OUT_RING(dev_priv->counter);
+       OUT_RING(0);
+       ADVANCE_LP_RING();
+
+       dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+       return 0;
+}
+
+static int i915_quiescent(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+
+       i915_kernel_lost_context(dev);
+       return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
+}
+
+static int i915_flush_ioctl(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv)
+{
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       return i915_quiescent(dev);
+}
+
+static int i915_batchbuffer(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u32 *hw_status = dev_priv->hw_status_page;
+       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+           dev_priv->sarea_priv;
+       drm_i915_batchbuffer_t *batch = data;
+       int ret;
+
+       if (!dev_priv->allow_batchbuffer) {
+               DRM_ERROR("Batchbuffer ioctl disabled\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n",
+                 batch->start, batch->used, batch->num_cliprects);
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
+                                                      batch->num_cliprects *
+                                                      sizeof(struct drm_clip_rect)))
+               return -EFAULT;
+
+       ret = i915_dispatch_batchbuffer(dev, batch);
+
+       sarea_priv->last_dispatch = (int)hw_status[5];
+       return ret;
+}
+
+static int i915_cmdbuffer(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u32 *hw_status = dev_priv->hw_status_page;
+       drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
+           dev_priv->sarea_priv;
+       drm_i915_cmdbuffer_t *cmdbuf = data;
+       int ret;
+
+       DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
+                 cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (cmdbuf->num_cliprects &&
+           DRM_VERIFYAREA_READ(cmdbuf->cliprects,
+                               cmdbuf->num_cliprects *
+                               sizeof(struct drm_clip_rect))) {
+               DRM_ERROR("Fault accessing cliprects\n");
+               return -EFAULT;
+       }
+
+       ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
+       if (ret) {
+               DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
+               return ret;
+       }
+
+       sarea_priv->last_dispatch = (int)hw_status[5];
+       return 0;
+}
+
+static int i915_flip_bufs(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       DRM_DEBUG("%s\n", __FUNCTION__);
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       return i915_dispatch_flip(dev);
+}
+
+static int i915_getparam(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_getparam_t *param = data;
+       int value;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       switch (param->param) {
+       case I915_PARAM_IRQ_ACTIVE:
+               value = dev->irq ? 1 : 0;
+               break;
+       case I915_PARAM_ALLOW_BATCHBUFFER:
+               value = dev_priv->allow_batchbuffer ? 1 : 0;
+               break;
+       case I915_PARAM_LAST_DISPATCH:
+               value = READ_BREADCRUMB(dev_priv);
+               break;
+       default:
+               DRM_ERROR("Unknown parameter %d\n", param->param);
+               return -EINVAL;
+       }
+
+       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
+               DRM_ERROR("DRM_COPY_TO_USER failed\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+static int i915_setparam(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_setparam_t *param = data;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       switch (param->param) {
+       case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
+               if (!IS_I965G(dev))
+                       dev_priv->use_mi_batchbuffer_start = param->value;
+               break;
+       case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
+               dev_priv->tex_lru_log_granularity = param->value;
+               break;
+       case I915_SETPARAM_ALLOW_BATCHBUFFER:
+               dev_priv->allow_batchbuffer = param->value;
+               break;
+       default:
+               DRM_ERROR("unknown parameter %d\n", param->param);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int i915_set_status_page(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_hws_addr_t *hws = data;
+
+       if (!I915_NEED_GFX_HWS(dev))
+               return -EINVAL;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr);
+
+       dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
+
+       dev_priv->hws_map.offset = dev->agp->base + hws->addr;
+       dev_priv->hws_map.size = 4*1024;
+       dev_priv->hws_map.type = 0;
+       dev_priv->hws_map.flags = 0;
+       dev_priv->hws_map.mtrr = 0;
+
+       drm_core_ioremap(&dev_priv->hws_map, dev);
+       if (dev_priv->hws_map.handle == NULL) {
+               i915_dma_cleanup(dev);
+               dev_priv->status_gfx_addr = 0;
+               DRM_ERROR("can not ioremap virtual address for"
+                               " G33 hw status page\n");
+               return -ENOMEM;
+       }
+       dev_priv->hw_status_page = dev_priv->hws_map.handle;
+
+       memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+       I915_WRITE(0x02080, dev_priv->status_gfx_addr);
+       DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
+                       dev_priv->status_gfx_addr);
+       DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
+       return 0;
+}
+
+int i915_driver_load(struct drm_device *dev, unsigned long flags)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned long base, size;
+       int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
+
+       /* i915 has 4 more counters */
+       dev->counters += 4;
+       dev->types[6] = _DRM_STAT_IRQ;
+       dev->types[7] = _DRM_STAT_PRIMARY;
+       dev->types[8] = _DRM_STAT_SECONDARY;
+       dev->types[9] = _DRM_STAT_DMA;
+
+       dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       memset(dev_priv, 0, sizeof(drm_i915_private_t));
+
+       dev->dev_private = (void *)dev_priv;
+
+       /* Add register map (needed for suspend/resume) */
+       base = drm_get_resource_start(dev, mmio_bar);
+       size = drm_get_resource_len(dev, mmio_bar);
+
+       ret = drm_addmap(dev, base, size, _DRM_REGISTERS,
+                        _DRM_KERNEL | _DRM_DRIVER,
+                        &dev_priv->mmio_map);
+       return ret;
+}
+
+int i915_driver_unload(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (dev_priv->mmio_map)
+               drm_rmmap(dev, dev_priv->mmio_map);
+
+       drm_free(dev->dev_private, sizeof(drm_i915_private_t),
+                DRM_MEM_DRIVER);
+
+       return 0;
+}
+
+void i915_driver_lastclose(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+
+       if (!dev_priv)
+               return;
+
+       if (dev_priv->agp_heap)
+               i915_mem_takedown(&(dev_priv->agp_heap));
+
+       i915_dma_cleanup(dev);
+}
+
+void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       i915_mem_release(dev, file_priv, dev_priv->agp_heap);
+}
+
+struct drm_ioctl_desc i915_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP,  i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
+       DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ),
+       DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH ),
+       DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH),
+};
+
+int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * All Intel graphics chipsets are treated as AGP, even if they are really
+ * PCI-e.
+ *
+ * \param dev   The device to be tested.
+ *
+ * \returns
+ * A value of 1 is always retured to indictate every i9x5 is AGP.
+ */
+int i915_driver_device_is_agp(struct drm_device * dev)
+{
+       return 1;
+}
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
new file mode 100644 (file)
index 0000000..93aed1c
--- /dev/null
@@ -0,0 +1,605 @@
+/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
+ */
+/*
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#include "drm_pciids.h"
+
+static struct pci_device_id pciidlist[] = {
+       i915_PCI_IDS
+};
+
+enum pipe {
+    PIPE_A = 0,
+    PIPE_B,
+};
+
+static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (pipe == PIPE_A)
+               return (I915_READ(DPLL_A) & DPLL_VCO_ENABLE);
+       else
+               return (I915_READ(DPLL_B) & DPLL_VCO_ENABLE);
+}
+
+static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+       u32 *array;
+       int i;
+
+       if (!i915_pipe_enabled(dev, pipe))
+               return;
+
+       if (pipe == PIPE_A)
+               array = dev_priv->save_palette_a;
+       else
+               array = dev_priv->save_palette_b;
+
+       for(i = 0; i < 256; i++)
+               array[i] = I915_READ(reg + (i << 2));
+}
+
+static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+       u32 *array;
+       int i;
+
+       if (!i915_pipe_enabled(dev, pipe))
+               return;
+
+       if (pipe == PIPE_A)
+               array = dev_priv->save_palette_a;
+       else
+               array = dev_priv->save_palette_b;
+
+       for(i = 0; i < 256; i++)
+               I915_WRITE(reg + (i << 2), array[i]);
+}
+
+static u8 i915_read_indexed(u16 index_port, u16 data_port, u8 reg)
+{
+       outb(reg, index_port);
+       return inb(data_port);
+}
+
+static u8 i915_read_ar(u16 st01, u8 reg, u16 palette_enable)
+{
+       inb(st01);
+       outb(palette_enable | reg, VGA_AR_INDEX);
+       return inb(VGA_AR_DATA_READ);
+}
+
+static void i915_write_ar(u8 st01, u8 reg, u8 val, u16 palette_enable)
+{
+       inb(st01);
+       outb(palette_enable | reg, VGA_AR_INDEX);
+       outb(val, VGA_AR_DATA_WRITE);
+}
+
+static void i915_write_indexed(u16 index_port, u16 data_port, u8 reg, u8 val)
+{
+       outb(reg, index_port);
+       outb(val, data_port);
+}
+
+static void i915_save_vga(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int i;
+       u16 cr_index, cr_data, st01;
+
+       /* VGA color palette registers */
+       dev_priv->saveDACMASK = inb(VGA_DACMASK);
+       /* DACCRX automatically increments during read */
+       outb(0, VGA_DACRX);
+       /* Read 3 bytes of color data from each index */
+       for (i = 0; i < 256 * 3; i++)
+               dev_priv->saveDACDATA[i] = inb(VGA_DACDATA);
+
+       /* MSR bits */
+       dev_priv->saveMSR = inb(VGA_MSR_READ);
+       if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
+               cr_index = VGA_CR_INDEX_CGA;
+               cr_data = VGA_CR_DATA_CGA;
+               st01 = VGA_ST01_CGA;
+       } else {
+               cr_index = VGA_CR_INDEX_MDA;
+               cr_data = VGA_CR_DATA_MDA;
+               st01 = VGA_ST01_MDA;
+       }
+
+       /* CRT controller regs */
+       i915_write_indexed(cr_index, cr_data, 0x11,
+                          i915_read_indexed(cr_index, cr_data, 0x11) &
+                          (~0x80));
+       for (i = 0; i <= 0x24; i++)
+               dev_priv->saveCR[i] =
+                       i915_read_indexed(cr_index, cr_data, i);
+       /* Make sure we don't turn off CR group 0 writes */
+       dev_priv->saveCR[0x11] &= ~0x80;
+
+       /* Attribute controller registers */
+       inb(st01);
+       dev_priv->saveAR_INDEX = inb(VGA_AR_INDEX);
+       for (i = 0; i <= 0x14; i++)
+               dev_priv->saveAR[i] = i915_read_ar(st01, i, 0);
+       inb(st01);
+       outb(dev_priv->saveAR_INDEX, VGA_AR_INDEX);
+       inb(st01);
+
+       /* Graphics controller registers */
+       for (i = 0; i < 9; i++)
+               dev_priv->saveGR[i] =
+                       i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, i);
+
+       dev_priv->saveGR[0x10] =
+               i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x10);
+       dev_priv->saveGR[0x11] =
+               i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x11);
+       dev_priv->saveGR[0x18] =
+               i915_read_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x18);
+
+       /* Sequencer registers */
+       for (i = 0; i < 8; i++)
+               dev_priv->saveSR[i] =
+                       i915_read_indexed(VGA_SR_INDEX, VGA_SR_DATA, i);
+}
+
+static void i915_restore_vga(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int i;
+       u16 cr_index, cr_data, st01;
+
+       /* MSR bits */
+       outb(dev_priv->saveMSR, VGA_MSR_WRITE);
+       if (dev_priv->saveMSR & VGA_MSR_CGA_MODE) {
+               cr_index = VGA_CR_INDEX_CGA;
+               cr_data = VGA_CR_DATA_CGA;
+               st01 = VGA_ST01_CGA;
+       } else {
+               cr_index = VGA_CR_INDEX_MDA;
+               cr_data = VGA_CR_DATA_MDA;
+               st01 = VGA_ST01_MDA;
+       }
+
+       /* Sequencer registers, don't write SR07 */
+       for (i = 0; i < 7; i++)
+               i915_write_indexed(VGA_SR_INDEX, VGA_SR_DATA, i,
+                                  dev_priv->saveSR[i]);
+
+       /* CRT controller regs */
+       /* Enable CR group 0 writes */
+       i915_write_indexed(cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
+       for (i = 0; i <= 0x24; i++)
+               i915_write_indexed(cr_index, cr_data, i, dev_priv->saveCR[i]);
+
+       /* Graphics controller regs */
+       for (i = 0; i < 9; i++)
+               i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, i,
+                                  dev_priv->saveGR[i]);
+
+       i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x10,
+                          dev_priv->saveGR[0x10]);
+       i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x11,
+                          dev_priv->saveGR[0x11]);
+       i915_write_indexed(VGA_GR_INDEX, VGA_GR_DATA, 0x18,
+                          dev_priv->saveGR[0x18]);
+
+       /* Attribute controller registers */
+       inb(st01);
+       for (i = 0; i <= 0x14; i++)
+               i915_write_ar(st01, i, dev_priv->saveAR[i], 0);
+       inb(st01); /* switch back to index mode */
+       outb(dev_priv->saveAR_INDEX | 0x20, VGA_AR_INDEX);
+       inb(st01);
+
+       /* VGA color palette registers */
+       outb(dev_priv->saveDACMASK, VGA_DACMASK);
+       /* DACCRX automatically increments during read */
+       outb(0, VGA_DACWX);
+       /* Read 3 bytes of color data from each index */
+       for (i = 0; i < 256 * 3; i++)
+               outb(dev_priv->saveDACDATA[i], VGA_DACDATA);
+
+}
+
+static int i915_suspend(struct drm_device *dev, pm_message_t state)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int i;
+
+       if (!dev || !dev_priv) {
+               printk(KERN_ERR "dev: %p, dev_priv: %p\n", dev, dev_priv);
+               printk(KERN_ERR "DRM not initialized, aborting suspend.\n");
+               return -ENODEV;
+       }
+
+       if (state.event == PM_EVENT_PRETHAW)
+               return 0;
+
+       pci_save_state(dev->pdev);
+       pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
+
+       /* Display arbitration control */
+       dev_priv->saveDSPARB = I915_READ(DSPARB);
+
+       /* Pipe & plane A info */
+       dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
+       dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
+       dev_priv->saveFPA0 = I915_READ(FPA0);
+       dev_priv->saveFPA1 = I915_READ(FPA1);
+       dev_priv->saveDPLL_A = I915_READ(DPLL_A);
+       if (IS_I965G(dev))
+               dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
+       dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
+       dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
+       dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
+       dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
+       dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
+       dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
+       dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+
+       dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
+       dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
+       dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
+       dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
+       dev_priv->saveDSPABASE = I915_READ(DSPABASE);
+       if (IS_I965G(dev)) {
+               dev_priv->saveDSPASURF = I915_READ(DSPASURF);
+               dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
+       }
+       i915_save_palette(dev, PIPE_A);
+       dev_priv->savePIPEASTAT = I915_READ(I915REG_PIPEASTAT);
+
+       /* Pipe & plane B info */
+       dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
+       dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
+       dev_priv->saveFPB0 = I915_READ(FPB0);
+       dev_priv->saveFPB1 = I915_READ(FPB1);
+       dev_priv->saveDPLL_B = I915_READ(DPLL_B);
+       if (IS_I965G(dev))
+               dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
+       dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
+       dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
+       dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
+       dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
+       dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
+       dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
+       dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+
+       dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
+       dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
+       dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
+       dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
+       dev_priv->saveDSPBBASE = I915_READ(DSPBBASE);
+       if (IS_I965GM(dev) || IS_IGD_GM(dev)) {
+               dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
+               dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
+       }
+       i915_save_palette(dev, PIPE_B);
+       dev_priv->savePIPEBSTAT = I915_READ(I915REG_PIPEBSTAT);
+
+       /* CRT state */
+       dev_priv->saveADPA = I915_READ(ADPA);
+
+       /* LVDS state */
+       dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL);
+       dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS);
+       dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
+       if (IS_I965G(dev))
+               dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
+       if (IS_MOBILE(dev) && !IS_I830(dev))
+               dev_priv->saveLVDS = I915_READ(LVDS);
+       if (!IS_I830(dev) && !IS_845G(dev))
+               dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
+       dev_priv->saveLVDSPP_ON = I915_READ(LVDSPP_ON);
+       dev_priv->saveLVDSPP_OFF = I915_READ(LVDSPP_OFF);
+       dev_priv->savePP_CYCLE = I915_READ(PP_CYCLE);
+
+       /* FIXME: save TV & SDVO state */
+
+       /* FBC state */
+       dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
+       dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
+       dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
+       dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
+
+       /* Interrupt state */
+       dev_priv->saveIIR = I915_READ(I915REG_INT_IDENTITY_R);
+       dev_priv->saveIER = I915_READ(I915REG_INT_ENABLE_R);
+       dev_priv->saveIMR = I915_READ(I915REG_INT_MASK_R);
+
+       /* VGA state */
+       dev_priv->saveVCLK_DIVISOR_VGA0 = I915_READ(VCLK_DIVISOR_VGA0);
+       dev_priv->saveVCLK_DIVISOR_VGA1 = I915_READ(VCLK_DIVISOR_VGA1);
+       dev_priv->saveVCLK_POST_DIV = I915_READ(VCLK_POST_DIV);
+       dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
+
+       /* Clock gating state */
+       dev_priv->saveD_STATE = I915_READ(D_STATE);
+       dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D);
+
+       /* Cache mode state */
+       dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
+
+       /* Memory Arbitration state */
+       dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE);
+
+       /* Scratch space */
+       for (i = 0; i < 16; i++) {
+               dev_priv->saveSWF0[i] = I915_READ(SWF0 + (i << 2));
+               dev_priv->saveSWF1[i] = I915_READ(SWF10 + (i << 2));
+       }
+       for (i = 0; i < 3; i++)
+               dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
+
+       i915_save_vga(dev);
+
+       if (state.event == PM_EVENT_SUSPEND) {
+               /* Shut down the device */
+               pci_disable_device(dev->pdev);
+               pci_set_power_state(dev->pdev, PCI_D3hot);
+       }
+
+       return 0;
+}
+
+static int i915_resume(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int i;
+
+       pci_set_power_state(dev->pdev, PCI_D0);
+       pci_restore_state(dev->pdev);
+       if (pci_enable_device(dev->pdev))
+               return -1;
+       pci_set_master(dev->pdev);
+
+       pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
+
+       I915_WRITE(DSPARB, dev_priv->saveDSPARB);
+
+       /* Pipe & plane A info */
+       /* Prime the clock */
+       if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
+               I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
+                          ~DPLL_VCO_ENABLE);
+               udelay(150);
+       }
+       I915_WRITE(FPA0, dev_priv->saveFPA0);
+       I915_WRITE(FPA1, dev_priv->saveFPA1);
+       /* Actually enable it */
+       I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
+       udelay(150);
+       if (IS_I965G(dev))
+               I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
+       udelay(150);
+
+       /* Restore mode */
+       I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
+       I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
+       I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
+       I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
+       I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
+       I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
+       I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
+
+       /* Restore plane info */
+       I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
+       I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
+       I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
+       I915_WRITE(DSPABASE, dev_priv->saveDSPABASE);
+       I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
+       if (IS_I965G(dev)) {
+               I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
+               I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
+       }
+
+       I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
+
+       i915_restore_palette(dev, PIPE_A);
+       /* Enable the plane */
+       I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
+       I915_WRITE(DSPABASE, I915_READ(DSPABASE));
+
+       /* Pipe & plane B info */
+       if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
+               I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
+                          ~DPLL_VCO_ENABLE);
+               udelay(150);
+       }
+       I915_WRITE(FPB0, dev_priv->saveFPB0);
+       I915_WRITE(FPB1, dev_priv->saveFPB1);
+       /* Actually enable it */
+       I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
+       udelay(150);
+       if (IS_I965G(dev))
+               I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
+       udelay(150);
+
+       /* Restore mode */
+       I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
+       I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
+       I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
+       I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
+       I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
+       I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
+       I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
+
+       /* Restore plane info */
+       I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
+       I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
+       I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
+       I915_WRITE(DSPBBASE, dev_priv->saveDSPBBASE);
+       I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
+       if (IS_I965G(dev)) {
+               I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
+               I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
+       }
+
+       I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
+
+       i915_restore_palette(dev, PIPE_B);
+       /* Enable the plane */
+       I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
+       I915_WRITE(DSPBBASE, I915_READ(DSPBBASE));
+
+       /* CRT state */
+       I915_WRITE(ADPA, dev_priv->saveADPA);
+
+       /* LVDS state */
+       if (IS_I965G(dev))
+               I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
+       if (IS_MOBILE(dev) && !IS_I830(dev))
+               I915_WRITE(LVDS, dev_priv->saveLVDS);
+       if (!IS_I830(dev) && !IS_845G(dev))
+               I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
+
+       I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
+       I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
+       I915_WRITE(LVDSPP_ON, dev_priv->saveLVDSPP_ON);
+       I915_WRITE(LVDSPP_OFF, dev_priv->saveLVDSPP_OFF);
+       I915_WRITE(PP_CYCLE, dev_priv->savePP_CYCLE);
+       I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
+
+       /* FIXME: restore TV & SDVO state */
+
+       /* FBC info */
+       I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
+       I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
+       I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
+       I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
+
+       /* VGA state */
+       I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
+       I915_WRITE(VCLK_DIVISOR_VGA0, dev_priv->saveVCLK_DIVISOR_VGA0);
+       I915_WRITE(VCLK_DIVISOR_VGA1, dev_priv->saveVCLK_DIVISOR_VGA1);
+       I915_WRITE(VCLK_POST_DIV, dev_priv->saveVCLK_POST_DIV);
+       udelay(150);
+
+       /* Clock gating state */
+       I915_WRITE (D_STATE, dev_priv->saveD_STATE);
+       I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
+
+       /* Cache mode state */
+       I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
+
+       /* Memory arbitration state */
+       I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000);
+
+       for (i = 0; i < 16; i++) {
+               I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF0[i]);
+               I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
+       }
+       for (i = 0; i < 3; i++)
+               I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
+
+       i915_restore_vga(dev);
+
+       return 0;
+}
+
+static struct drm_driver driver = {
+       /* don't use mtrr's here, the Xserver or user space app should
+        * deal with them for intel hardware.
+        */
+       .driver_features =
+           DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
+           DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
+           DRIVER_IRQ_VBL2,
+       .load = i915_driver_load,
+       .unload = i915_driver_unload,
+       .lastclose = i915_driver_lastclose,
+       .preclose = i915_driver_preclose,
+       .suspend = i915_suspend,
+       .resume = i915_resume,
+       .device_is_agp = i915_driver_device_is_agp,
+       .vblank_wait = i915_driver_vblank_wait,
+       .vblank_wait2 = i915_driver_vblank_wait2,
+       .irq_preinstall = i915_driver_irq_preinstall,
+       .irq_postinstall = i915_driver_irq_postinstall,
+       .irq_uninstall = i915_driver_irq_uninstall,
+       .irq_handler = i915_driver_irq_handler,
+       .reclaim_buffers = drm_core_reclaim_buffers,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .ioctls = i915_ioctls,
+       .fops = {
+                .owner = THIS_MODULE,
+                .open = drm_open,
+                .release = drm_release,
+                .ioctl = drm_ioctl,
+                .mmap = drm_mmap,
+                .poll = drm_poll,
+                .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+                .compat_ioctl = i915_compat_ioctl,
+#endif
+       },
+
+       .pci_driver = {
+                .name = DRIVER_NAME,
+                .id_table = pciidlist,
+       },
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int __init i915_init(void)
+{
+       driver.num_ioctls = i915_max_ioctl;
+       return drm_init(&driver);
+}
+
+static void __exit i915_exit(void)
+{
+       drm_exit(&driver);
+}
+
+module_init(i915_init);
+module_exit(i915_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
new file mode 100644 (file)
index 0000000..d7326d9
--- /dev/null
@@ -0,0 +1,1142 @@
+/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
+ */
+/*
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _I915_DRV_H_
+#define _I915_DRV_H_
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR          "Tungsten Graphics, Inc."
+
+#define DRIVER_NAME            "i915"
+#define DRIVER_DESC            "Intel Graphics"
+#define DRIVER_DATE            "20060119"
+
+/* Interface history:
+ *
+ * 1.1: Original.
+ * 1.2: Add Power Management
+ * 1.3: Add vblank support
+ * 1.4: Fix cmdbuffer path, add heap destroy
+ * 1.5: Add vblank pipe configuration
+ * 1.6: - New ioctl for scheduling buffer swaps on vertical blank
+ *      - Support vertical blank on secondary display pipe
+ */
+#define DRIVER_MAJOR           1
+#define DRIVER_MINOR           6
+#define DRIVER_PATCHLEVEL      0
+
+typedef struct _drm_i915_ring_buffer {
+       int tail_mask;
+       unsigned long Start;
+       unsigned long End;
+       unsigned long Size;
+       u8 *virtual_start;
+       int head;
+       int tail;
+       int space;
+       drm_local_map_t map;
+} drm_i915_ring_buffer_t;
+
+struct mem_block {
+       struct mem_block *next;
+       struct mem_block *prev;
+       int start;
+       int size;
+       struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */
+};
+
+typedef struct _drm_i915_vbl_swap {
+       struct list_head head;
+       drm_drawable_t drw_id;
+       unsigned int pipe;
+       unsigned int sequence;
+} drm_i915_vbl_swap_t;
+
+typedef struct drm_i915_private {
+       drm_local_map_t *sarea;
+       drm_local_map_t *mmio_map;
+
+       drm_i915_sarea_t *sarea_priv;
+       drm_i915_ring_buffer_t ring;
+
+       drm_dma_handle_t *status_page_dmah;
+       void *hw_status_page;
+       dma_addr_t dma_status_page;
+       unsigned long counter;
+       unsigned int status_gfx_addr;
+       drm_local_map_t hws_map;
+
+       unsigned int cpp;
+       int back_offset;
+       int front_offset;
+       int current_page;
+       int page_flipping;
+       int use_mi_batchbuffer_start;
+
+       wait_queue_head_t irq_queue;
+       atomic_t irq_received;
+       atomic_t irq_emitted;
+
+       int tex_lru_log_granularity;
+       int allow_batchbuffer;
+       struct mem_block *agp_heap;
+       unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
+       int vblank_pipe;
+
+       spinlock_t swaps_lock;
+       drm_i915_vbl_swap_t vbl_swaps;
+       unsigned int swaps_pending;
+
+       /* Register state */
+       u8 saveLBB;
+       u32 saveDSPACNTR;
+       u32 saveDSPBCNTR;
+       u32 saveDSPARB;
+       u32 savePIPEACONF;
+       u32 savePIPEBCONF;
+       u32 savePIPEASRC;
+       u32 savePIPEBSRC;
+       u32 saveFPA0;
+       u32 saveFPA1;
+       u32 saveDPLL_A;
+       u32 saveDPLL_A_MD;
+       u32 saveHTOTAL_A;
+       u32 saveHBLANK_A;
+       u32 saveHSYNC_A;
+       u32 saveVTOTAL_A;
+       u32 saveVBLANK_A;
+       u32 saveVSYNC_A;
+       u32 saveBCLRPAT_A;
+       u32 savePIPEASTAT;
+       u32 saveDSPASTRIDE;
+       u32 saveDSPASIZE;
+       u32 saveDSPAPOS;
+       u32 saveDSPABASE;
+       u32 saveDSPASURF;
+       u32 saveDSPATILEOFF;
+       u32 savePFIT_PGM_RATIOS;
+       u32 saveBLC_PWM_CTL;
+       u32 saveBLC_PWM_CTL2;
+       u32 saveFPB0;
+       u32 saveFPB1;
+       u32 saveDPLL_B;
+       u32 saveDPLL_B_MD;
+       u32 saveHTOTAL_B;
+       u32 saveHBLANK_B;
+       u32 saveHSYNC_B;
+       u32 saveVTOTAL_B;
+       u32 saveVBLANK_B;
+       u32 saveVSYNC_B;
+       u32 saveBCLRPAT_B;
+       u32 savePIPEBSTAT;
+       u32 saveDSPBSTRIDE;
+       u32 saveDSPBSIZE;
+       u32 saveDSPBPOS;
+       u32 saveDSPBBASE;
+       u32 saveDSPBSURF;
+       u32 saveDSPBTILEOFF;
+       u32 saveVCLK_DIVISOR_VGA0;
+       u32 saveVCLK_DIVISOR_VGA1;
+       u32 saveVCLK_POST_DIV;
+       u32 saveVGACNTRL;
+       u32 saveADPA;
+       u32 saveLVDS;
+       u32 saveLVDSPP_ON;
+       u32 saveLVDSPP_OFF;
+       u32 saveDVOA;
+       u32 saveDVOB;
+       u32 saveDVOC;
+       u32 savePP_ON;
+       u32 savePP_OFF;
+       u32 savePP_CONTROL;
+       u32 savePP_CYCLE;
+       u32 savePFIT_CONTROL;
+       u32 save_palette_a[256];
+       u32 save_palette_b[256];
+       u32 saveFBC_CFB_BASE;
+       u32 saveFBC_LL_BASE;
+       u32 saveFBC_CONTROL;
+       u32 saveFBC_CONTROL2;
+       u32 saveIER;
+       u32 saveIIR;
+       u32 saveIMR;
+       u32 saveCACHE_MODE_0;
+       u32 saveD_STATE;
+       u32 saveDSPCLK_GATE_D;
+       u32 saveMI_ARB_STATE;
+       u32 saveSWF0[16];
+       u32 saveSWF1[16];
+       u32 saveSWF2[3];
+       u8 saveMSR;
+       u8 saveSR[8];
+       u8 saveGR[25];
+       u8 saveAR_INDEX;
+       u8 saveAR[21];
+       u8 saveDACMASK;
+       u8 saveDACDATA[256*3]; /* 256 3-byte colors */
+       u8 saveCR[37];
+} drm_i915_private_t;
+
+extern struct drm_ioctl_desc i915_ioctls[];
+extern int i915_max_ioctl;
+
+                               /* i915_dma.c */
+extern void i915_kernel_lost_context(struct drm_device * dev);
+extern int i915_driver_load(struct drm_device *, unsigned long flags);
+extern int i915_driver_unload(struct drm_device *);
+extern void i915_driver_lastclose(struct drm_device * dev);
+extern void i915_driver_preclose(struct drm_device *dev,
+                                struct drm_file *file_priv);
+extern int i915_driver_device_is_agp(struct drm_device * dev);
+extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
+                             unsigned long arg);
+
+/* i915_irq.c */
+extern int i915_irq_emit(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int i915_irq_wait(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+
+extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
+extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
+extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
+extern void i915_driver_irq_preinstall(struct drm_device * dev);
+extern void i915_driver_irq_postinstall(struct drm_device * dev);
+extern void i915_driver_irq_uninstall(struct drm_device * dev);
+extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
+extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
+extern int i915_vblank_swap(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv);
+
+/* i915_mem.c */
+extern int i915_mem_alloc(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv);
+extern int i915_mem_free(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int i915_mem_init_heap(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv);
+extern int i915_mem_destroy_heap(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+extern void i915_mem_takedown(struct mem_block **heap);
+extern void i915_mem_release(struct drm_device * dev,
+                            struct drm_file *file_priv, struct mem_block *heap);
+
+#define I915_READ(reg)          DRM_READ32(dev_priv->mmio_map, (reg))
+#define I915_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
+#define I915_READ16(reg)       DRM_READ16(dev_priv->mmio_map, (reg))
+#define I915_WRITE16(reg,val)  DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
+
+#define I915_VERBOSE 0
+
+#define RING_LOCALS    unsigned int outring, ringmask, outcount; \
+                        volatile char *virt;
+
+#define BEGIN_LP_RING(n) do {                          \
+       if (I915_VERBOSE)                               \
+               DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n));  \
+       if (dev_priv->ring.space < (n)*4)               \
+               i915_wait_ring(dev, (n)*4, __func__);           \
+       outcount = 0;                                   \
+       outring = dev_priv->ring.tail;                  \
+       ringmask = dev_priv->ring.tail_mask;            \
+       virt = dev_priv->ring.virtual_start;            \
+} while (0)
+
+#define OUT_RING(n) do {                                       \
+       if (I915_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));      \
+       *(volatile unsigned int *)(virt + outring) = (n);       \
+        outcount++;                                            \
+       outring += 4;                                           \
+       outring &= ringmask;                                    \
+} while (0)
+
+#define ADVANCE_LP_RING() do {                                         \
+       if (I915_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING %x\n", outring);   \
+       dev_priv->ring.tail = outring;                                  \
+       dev_priv->ring.space -= outcount * 4;                           \
+       I915_WRITE(LP_RING + RING_TAIL, outring);                       \
+} while(0)
+
+extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
+
+/* Extended config space */
+#define LBB 0xf4
+
+/* VGA stuff */
+
+#define VGA_ST01_MDA 0x3ba
+#define VGA_ST01_CGA 0x3da
+
+#define VGA_MSR_WRITE 0x3c2
+#define VGA_MSR_READ 0x3cc
+#define   VGA_MSR_MEM_EN (1<<1)
+#define   VGA_MSR_CGA_MODE (1<<0)
+
+#define VGA_SR_INDEX 0x3c4
+#define VGA_SR_DATA 0x3c5
+
+#define VGA_AR_INDEX 0x3c0
+#define   VGA_AR_VID_EN (1<<5)
+#define VGA_AR_DATA_WRITE 0x3c0
+#define VGA_AR_DATA_READ 0x3c1
+
+#define VGA_GR_INDEX 0x3ce
+#define VGA_GR_DATA 0x3cf
+/* GR05 */
+#define   VGA_GR_MEM_READ_MODE_SHIFT 3
+#define     VGA_GR_MEM_READ_MODE_PLANE 1
+/* GR06 */
+#define   VGA_GR_MEM_MODE_MASK 0xc
+#define   VGA_GR_MEM_MODE_SHIFT 2
+#define   VGA_GR_MEM_A0000_AFFFF 0
+#define   VGA_GR_MEM_A0000_BFFFF 1
+#define   VGA_GR_MEM_B0000_B7FFF 2
+#define   VGA_GR_MEM_B0000_BFFFF 3
+
+#define VGA_DACMASK 0x3c6
+#define VGA_DACRX 0x3c7
+#define VGA_DACWX 0x3c8
+#define VGA_DACDATA 0x3c9
+
+#define VGA_CR_INDEX_MDA 0x3b4
+#define VGA_CR_DATA_MDA 0x3b5
+#define VGA_CR_INDEX_CGA 0x3d4
+#define VGA_CR_DATA_CGA 0x3d5
+
+#define GFX_OP_USER_INTERRUPT          ((0<<29)|(2<<23))
+#define GFX_OP_BREAKPOINT_INTERRUPT    ((0<<29)|(1<<23))
+#define CMD_REPORT_HEAD                        (7<<23)
+#define CMD_STORE_DWORD_IDX            ((0x21<<23) | 0x1)
+#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
+
+#define INST_PARSER_CLIENT   0x00000000
+#define INST_OP_FLUSH        0x02000000
+#define INST_FLUSH_MAP_CACHE 0x00000001
+
+#define BB1_START_ADDR_MASK   (~0x7)
+#define BB1_PROTECTED         (1<<0)
+#define BB1_UNPROTECTED       (0<<0)
+#define BB2_END_ADDR_MASK     (~0x7)
+
+/* Framebuffer compression */
+#define FBC_CFB_BASE           0x03200 /* 4k page aligned */
+#define FBC_LL_BASE            0x03204 /* 4k page aligned */
+#define FBC_CONTROL            0x03208
+#define   FBC_CTL_EN           (1<<31)
+#define   FBC_CTL_PERIODIC     (1<<30)
+#define   FBC_CTL_INTERVAL_SHIFT (16)
+#define   FBC_CTL_UNCOMPRESSIBLE (1<<14)
+#define   FBC_CTL_STRIDE_SHIFT (5)
+#define   FBC_CTL_FENCENO      (1<<0)
+#define FBC_COMMAND            0x0320c
+#define   FBC_CMD_COMPRESS     (1<<0)
+#define FBC_STATUS             0x03210
+#define   FBC_STAT_COMPRESSING (1<<31)
+#define   FBC_STAT_COMPRESSED  (1<<30)
+#define   FBC_STAT_MODIFIED    (1<<29)
+#define   FBC_STAT_CURRENT_LINE        (1<<0)
+#define FBC_CONTROL2           0x03214
+#define   FBC_CTL_FENCE_DBL    (0<<4)
+#define   FBC_CTL_IDLE_IMM     (0<<2)
+#define   FBC_CTL_IDLE_FULL    (1<<2)
+#define   FBC_CTL_IDLE_LINE    (2<<2)
+#define   FBC_CTL_IDLE_DEBUG   (3<<2)
+#define   FBC_CTL_CPU_FENCE    (1<<1)
+#define   FBC_CTL_PLANEA       (0<<0)
+#define   FBC_CTL_PLANEB       (1<<0)
+#define FBC_FENCE_OFF          0x0321b
+
+#define FBC_LL_SIZE            (1536)
+#define FBC_LL_PAD             (32)
+
+/* Interrupt bits:
+ */
+#define USER_INT_FLAG    (1<<1)
+#define VSYNC_PIPEB_FLAG (1<<5)
+#define VSYNC_PIPEA_FLAG (1<<7)
+#define HWB_OOM_FLAG     (1<<13) /* binner out of memory */
+
+#define I915REG_HWSTAM         0x02098
+#define I915REG_INT_IDENTITY_R 0x020a4
+#define I915REG_INT_MASK_R     0x020a8
+#define I915REG_INT_ENABLE_R   0x020a0
+
+#define I915REG_PIPEASTAT      0x70024
+#define I915REG_PIPEBSTAT      0x71024
+
+#define I915_VBLANK_INTERRUPT_ENABLE   (1UL<<17)
+#define I915_VBLANK_CLEAR              (1UL<<1)
+
+#define SRX_INDEX              0x3c4
+#define SRX_DATA               0x3c5
+#define SR01                   1
+#define SR01_SCREEN_OFF                (1<<5)
+
+#define PPCR                   0x61204
+#define PPCR_ON                        (1<<0)
+
+#define DVOB                   0x61140
+#define DVOB_ON                        (1<<31)
+#define DVOC                   0x61160
+#define DVOC_ON                        (1<<31)
+#define LVDS                   0x61180
+#define LVDS_ON                        (1<<31)
+
+#define ADPA                   0x61100
+#define ADPA_DPMS_MASK         (~(3<<10))
+#define ADPA_DPMS_ON           (0<<10)
+#define ADPA_DPMS_SUSPEND      (1<<10)
+#define ADPA_DPMS_STANDBY      (2<<10)
+#define ADPA_DPMS_OFF          (3<<10)
+
+#define NOPID                   0x2094
+#define LP_RING                        0x2030
+#define HP_RING                        0x2040
+/* The binner has its own ring buffer:
+ */
+#define HWB_RING               0x2400
+
+#define RING_TAIL              0x00
+#define TAIL_ADDR              0x001FFFF8
+#define RING_HEAD              0x04
+#define HEAD_WRAP_COUNT                0xFFE00000
+#define HEAD_WRAP_ONE          0x00200000
+#define HEAD_ADDR              0x001FFFFC
+#define RING_START             0x08
+#define START_ADDR             0x0xFFFFF000
+#define RING_LEN               0x0C
+#define RING_NR_PAGES          0x001FF000
+#define RING_REPORT_MASK       0x00000006
+#define RING_REPORT_64K                0x00000002
+#define RING_REPORT_128K       0x00000004
+#define RING_NO_REPORT         0x00000000
+#define RING_VALID_MASK                0x00000001
+#define RING_VALID             0x00000001
+#define RING_INVALID           0x00000000
+
+/* Instruction parser error reg:
+ */
+#define IPEIR                  0x2088
+
+/* Scratch pad debug 0 reg:
+ */
+#define SCPD0                  0x209c
+
+/* Error status reg:
+ */
+#define ESR                    0x20b8
+
+/* Secondary DMA fetch address debug reg:
+ */
+#define DMA_FADD_S             0x20d4
+
+/* Memory Interface Arbitration State
+ */
+#define MI_ARB_STATE           0x20e4
+
+/* Cache mode 0 reg.
+ *  - Manipulating render cache behaviour is central
+ *    to the concept of zone rendering, tuning this reg can help avoid
+ *    unnecessary render cache reads and even writes (for z/stencil)
+ *    at beginning and end of scene.
+ *
+ * - To change a bit, write to this reg with a mask bit set and the
+ * bit of interest either set or cleared.  EG: (BIT<<16) | BIT to set.
+ */
+#define Cache_Mode_0           0x2120
+#define CACHE_MODE_0           0x2120
+#define CM0_MASK_SHIFT          16
+#define CM0_IZ_OPT_DISABLE      (1<<6)
+#define CM0_ZR_OPT_DISABLE      (1<<5)
+#define CM0_DEPTH_EVICT_DISABLE (1<<4)
+#define CM0_COLOR_EVICT_DISABLE (1<<3)
+#define CM0_DEPTH_WRITE_DISABLE (1<<1)
+#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
+
+
+/* Graphics flush control.  A CPU write flushes the GWB of all writes.
+ * The data is discarded.
+ */
+#define GFX_FLSH_CNTL          0x2170
+
+/* Binner control.  Defines the location of the bin pointer list:
+ */
+#define BINCTL                 0x2420
+#define BC_MASK                        (1 << 9)
+
+/* Binned scene info.
+ */
+#define BINSCENE               0x2428
+#define BS_OP_LOAD             (1 << 8)
+#define BS_MASK                        (1 << 22)
+
+/* Bin command parser debug reg:
+ */
+#define BCPD                   0x2480
+
+/* Bin memory control debug reg:
+ */
+#define BMCD                   0x2484
+
+/* Bin data cache debug reg:
+ */
+#define BDCD                   0x2488
+
+/* Binner pointer cache debug reg:
+ */
+#define BPCD                   0x248c
+
+/* Binner scratch pad debug reg:
+ */
+#define BINSKPD                        0x24f0
+
+/* HWB scratch pad debug reg:
+ */
+#define HWBSKPD                        0x24f4
+
+/* Binner memory pool reg:
+ */
+#define BMP_BUFFER             0x2430
+#define BMP_PAGE_SIZE_4K       (0 << 10)
+#define BMP_BUFFER_SIZE_SHIFT  1
+#define BMP_ENABLE             (1 << 0)
+
+/* Get/put memory from the binner memory pool:
+ */
+#define BMP_GET                        0x2438
+#define BMP_PUT                        0x2440
+#define BMP_OFFSET_SHIFT       5
+
+/* 3D state packets:
+ */
+#define GFX_OP_RASTER_RULES    ((0x3<<29)|(0x7<<24))
+
+#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define SC_UPDATE_SCISSOR       (0x1<<1)
+#define SC_ENABLE_MASK          (0x1<<0)
+#define SC_ENABLE               (0x1<<0)
+
+#define GFX_OP_LOAD_INDIRECT   ((0x3<<29)|(0x1d<<24)|(0x7<<16))
+
+#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
+#define SCI_YMIN_MASK      (0xffff<<16)
+#define SCI_XMIN_MASK      (0xffff<<0)
+#define SCI_YMAX_MASK      (0xffff<<16)
+#define SCI_XMAX_MASK      (0xffff<<0)
+
+#define GFX_OP_SCISSOR_ENABLE   ((0x3<<29)|(0x1c<<24)|(0x10<<19))
+#define GFX_OP_SCISSOR_RECT     ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
+#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
+#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
+#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
+#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
+#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
+
+#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2)
+
+#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
+#define XY_SRC_COPY_BLT_CMD            ((2<<29)|(0x53<<22)|6)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA    (1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB      (1<<20)
+#define XY_SRC_COPY_BLT_SRC_TILED      (1<<15)
+#define XY_SRC_COPY_BLT_DST_TILED      (1<<11)
+
+#define MI_BATCH_BUFFER                ((0x30<<23)|1)
+#define MI_BATCH_BUFFER_START  (0x31<<23)
+#define MI_BATCH_BUFFER_END    (0xA<<23)
+#define MI_BATCH_NON_SECURE    (1)
+#define MI_BATCH_NON_SECURE_I965 (1<<8)
+
+#define MI_WAIT_FOR_EVENT       ((0x3<<23))
+#define MI_WAIT_FOR_PLANE_B_FLIP      (1<<6)
+#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
+#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
+
+#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
+
+#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
+#define ASYNC_FLIP                (1<<22)
+#define DISPLAY_PLANE_A           (0<<20)
+#define DISPLAY_PLANE_B           (1<<20)
+
+/* Display regs */
+#define DSPACNTR                0x70180
+#define DSPBCNTR                0x71180
+#define DISPPLANE_SEL_PIPE_MASK                 (1<<24)
+
+/* Define the region of interest for the binner:
+ */
+#define CMD_OP_BIN_CONTROL      ((0x3<<29)|(0x1d<<24)|(0x84<<16)|4)
+
+#define CMD_OP_DESTBUFFER_INFO  ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+
+#define CMD_MI_FLUSH         (0x04 << 23)
+#define MI_NO_WRITE_FLUSH    (1 << 2)
+#define MI_READ_FLUSH        (1 << 0)
+#define MI_EXE_FLUSH         (1 << 1)
+#define MI_END_SCENE         (1 << 4) /* flush binner and incr scene count */
+#define MI_SCENE_COUNT       (1 << 3) /* just increment scene count */
+
+#define BREADCRUMB_BITS 31
+#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
+
+#define READ_BREADCRUMB(dev_priv)  (((volatile u32*)(dev_priv->hw_status_page))[5])
+#define READ_HWSP(dev_priv, reg)  (((volatile u32*)(dev_priv->hw_status_page))[reg])
+
+#define BLC_PWM_CTL            0x61254
+#define BACKLIGHT_MODULATION_FREQ_SHIFT                (17)
+
+#define BLC_PWM_CTL2           0x61250
+/**
+ * This is the most significant 15 bits of the number of backlight cycles in a
+ * complete cycle of the modulated backlight control.
+ *
+ * The actual value is this field multiplied by two.
+ */
+#define BACKLIGHT_MODULATION_FREQ_MASK         (0x7fff << 17)
+#define BLM_LEGACY_MODE                                (1 << 16)
+/**
+ * This is the number of cycles out of the backlight modulation cycle for which
+ * the backlight is on.
+ *
+ * This field must be no greater than the number of cycles in the complete
+ * backlight modulation cycle.
+ */
+#define BACKLIGHT_DUTY_CYCLE_SHIFT             (0)
+#define BACKLIGHT_DUTY_CYCLE_MASK              (0xffff)
+
+#define I915_GCFGC                     0xf0
+#define I915_LOW_FREQUENCY_ENABLE              (1 << 7)
+#define I915_DISPLAY_CLOCK_190_200_MHZ         (0 << 4)
+#define I915_DISPLAY_CLOCK_333_MHZ             (4 << 4)
+#define I915_DISPLAY_CLOCK_MASK                        (7 << 4)
+
+#define I855_HPLLCC                    0xc0
+#define I855_CLOCK_CONTROL_MASK                        (3 << 0)
+#define I855_CLOCK_133_200                     (0 << 0)
+#define I855_CLOCK_100_200                     (1 << 0)
+#define I855_CLOCK_100_133                     (2 << 0)
+#define I855_CLOCK_166_250                     (3 << 0)
+
+/* p317, 319
+ */
+#define VCLK2_VCO_M        0x6008 /* treat as 16 bit? (includes msbs) */
+#define VCLK2_VCO_N        0x600a
+#define VCLK2_VCO_DIV_SEL  0x6012
+
+#define VCLK_DIVISOR_VGA0   0x6000
+#define VCLK_DIVISOR_VGA1   0x6004
+#define VCLK_POST_DIV      0x6010
+/** Selects a post divisor of 4 instead of 2. */
+# define VGA1_PD_P2_DIV_4      (1 << 15)
+/** Overrides the p2 post divisor field */
+# define VGA1_PD_P1_DIV_2      (1 << 13)
+# define VGA1_PD_P1_SHIFT      8
+/** P1 value is 2 greater than this field */
+# define VGA1_PD_P1_MASK       (0x1f << 8)
+/** Selects a post divisor of 4 instead of 2. */
+# define VGA0_PD_P2_DIV_4      (1 << 7)
+/** Overrides the p2 post divisor field */
+# define VGA0_PD_P1_DIV_2      (1 << 5)
+# define VGA0_PD_P1_SHIFT      0
+/** P1 value is 2 greater than this field */
+# define VGA0_PD_P1_MASK       (0x1f << 0)
+
+/* PCI D state control register */
+#define D_STATE                0x6104
+#define DSPCLK_GATE_D  0x6200
+
+/* I830 CRTC registers */
+#define HTOTAL_A       0x60000
+#define HBLANK_A       0x60004
+#define HSYNC_A                0x60008
+#define VTOTAL_A       0x6000c
+#define VBLANK_A       0x60010
+#define VSYNC_A                0x60014
+#define PIPEASRC       0x6001c
+#define BCLRPAT_A      0x60020
+#define VSYNCSHIFT_A   0x60028
+
+#define HTOTAL_B       0x61000
+#define HBLANK_B       0x61004
+#define HSYNC_B                0x61008
+#define VTOTAL_B       0x6100c
+#define VBLANK_B       0x61010
+#define VSYNC_B                0x61014
+#define PIPEBSRC       0x6101c
+#define BCLRPAT_B      0x61020
+#define VSYNCSHIFT_B   0x61028
+
+#define PP_STATUS      0x61200
+# define PP_ON                                 (1 << 31)
+/**
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+# define PP_READY                              (1 << 30)
+# define PP_SEQUENCE_NONE                      (0 << 28)
+# define PP_SEQUENCE_ON                                (1 << 28)
+# define PP_SEQUENCE_OFF                       (2 << 28)
+# define PP_SEQUENCE_MASK                      0x30000000
+#define PP_CONTROL     0x61204
+# define POWER_TARGET_ON                       (1 << 0)
+
+#define LVDSPP_ON       0x61208
+#define LVDSPP_OFF      0x6120c
+#define PP_CYCLE        0x61210
+
+#define PFIT_CONTROL   0x61230
+# define PFIT_ENABLE                           (1 << 31)
+# define PFIT_PIPE_MASK                                (3 << 29)
+# define PFIT_PIPE_SHIFT                       29
+# define VERT_INTERP_DISABLE                   (0 << 10)
+# define VERT_INTERP_BILINEAR                  (1 << 10)
+# define VERT_INTERP_MASK                      (3 << 10)
+# define VERT_AUTO_SCALE                       (1 << 9)
+# define HORIZ_INTERP_DISABLE                  (0 << 6)
+# define HORIZ_INTERP_BILINEAR                 (1 << 6)
+# define HORIZ_INTERP_MASK                     (3 << 6)
+# define HORIZ_AUTO_SCALE                      (1 << 5)
+# define PANEL_8TO6_DITHER_ENABLE              (1 << 3)
+
+#define PFIT_PGM_RATIOS        0x61234
+# define PFIT_VERT_SCALE_MASK                  0xfff00000
+# define PFIT_HORIZ_SCALE_MASK                 0x0000fff0
+
+#define PFIT_AUTO_RATIOS       0x61238
+
+
+#define DPLL_A         0x06014
+#define DPLL_B         0x06018
+# define DPLL_VCO_ENABLE                       (1 << 31)
+# define DPLL_DVO_HIGH_SPEED                   (1 << 30)
+# define DPLL_SYNCLOCK_ENABLE                  (1 << 29)
+# define DPLL_VGA_MODE_DIS                     (1 << 28)
+# define DPLLB_MODE_DAC_SERIAL                 (1 << 26) /* i915 */
+# define DPLLB_MODE_LVDS                       (2 << 26) /* i915 */
+# define DPLL_MODE_MASK                                (3 << 26)
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10       (0 << 24) /* i915 */
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5                (1 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_14            (0 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_7             (1 << 24) /* i915 */
+# define DPLL_P2_CLOCK_DIV_MASK                        0x03000000 /* i915 */
+# define DPLL_FPA01_P1_POST_DIV_MASK           0x00ff0000 /* i915 */
+/**
+ *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
+ * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830      0x001f0000
+/**
+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
+ * this field (only one bit may be set).
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
+# define DPLL_FPA01_P1_POST_DIV_SHIFT          16
+# define PLL_P2_DIVIDE_BY_4                    (1 << 23) /* i830, required in DVO non-gang */
+# define PLL_P1_DIVIDE_BY_TWO                  (1 << 21) /* i830 */
+# define PLL_REF_INPUT_DREFCLK                 (0 << 13)
+# define PLL_REF_INPUT_TVCLKINA                        (1 << 13) /* i830 */
+# define PLL_REF_INPUT_TVCLKINBC               (2 << 13) /* SDVO TVCLKIN */
+# define PLLB_REF_INPUT_SPREADSPECTRUMIN       (3 << 13)
+# define PLL_REF_INPUT_MASK                    (3 << 13)
+# define PLL_LOAD_PULSE_PHASE_SHIFT            9
+/*
+ * Parallel to Serial Load Pulse phase selection.
+ * Selects the phase for the 10X DPLL clock for the PCIe
+ * digital display port. The range is 4 to 13; 10 or more
+ * is just a flip delay. The default is 6
+ */
+# define PLL_LOAD_PULSE_PHASE_MASK             (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+# define DISPLAY_RATE_SELECT_FPA1              (1 << 8)
+
+/**
+ * SDVO multiplier for 945G/GM. Not used on 965.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+# define SDVO_MULTIPLIER_MASK                  0x000000ff
+# define SDVO_MULTIPLIER_SHIFT_HIRES           4
+# define SDVO_MULTIPLIER_SHIFT_VGA             0
+
+/** @defgroup DPLL_MD
+ * @{
+ */
+/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_A_MD              0x0601c
+/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_B_MD              0x06020
+/**
+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
+ *
+ * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
+ */
+# define DPLL_MD_UDI_DIVIDER_MASK              0x3f000000
+# define DPLL_MD_UDI_DIVIDER_SHIFT             24
+/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
+# define DPLL_MD_VGA_UDI_DIVIDER_MASK          0x003f0000
+# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT         16
+/**
+ * SDVO/UDI pixel multiplier.
+ *
+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
+ * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
+ * dummy bytes in the datastream at an increased clock rate, with both sides of
+ * the link knowing how many bytes are fill.
+ *
+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
+ * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
+ * through an SDVO command.
+ *
+ * This register field has values of multiplication factor minus 1, with
+ * a maximum multiplier of 5 for SDVO.
+ */
+# define DPLL_MD_UDI_MULTIPLIER_MASK           0x00003f00
+# define DPLL_MD_UDI_MULTIPLIER_SHIFT          8
+/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
+ * This best be set to the default value (3) or the CRT won't work. No,
+ * I don't entirely understand what this does...
+ */
+# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK       0x0000003f
+# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT      0
+/** @} */
+
+#define DPLL_TEST              0x606c
+# define DPLLB_TEST_SDVO_DIV_1                 (0 << 22)
+# define DPLLB_TEST_SDVO_DIV_2                 (1 << 22)
+# define DPLLB_TEST_SDVO_DIV_4                 (2 << 22)
+# define DPLLB_TEST_SDVO_DIV_MASK              (3 << 22)
+# define DPLLB_TEST_N_BYPASS                   (1 << 19)
+# define DPLLB_TEST_M_BYPASS                   (1 << 18)
+# define DPLLB_INPUT_BUFFER_ENABLE             (1 << 16)
+# define DPLLA_TEST_N_BYPASS                   (1 << 3)
+# define DPLLA_TEST_M_BYPASS                   (1 << 2)
+# define DPLLA_INPUT_BUFFER_ENABLE             (1 << 0)
+
+#define ADPA                   0x61100
+#define ADPA_DAC_ENABLE                (1<<31)
+#define ADPA_DAC_DISABLE       0
+#define ADPA_PIPE_SELECT_MASK  (1<<30)
+#define ADPA_PIPE_A_SELECT     0
+#define ADPA_PIPE_B_SELECT     (1<<30)
+#define ADPA_USE_VGA_HVPOLARITY (1<<15)
+#define ADPA_SETS_HVPOLARITY   0
+#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
+#define ADPA_VSYNC_CNTL_ENABLE 0
+#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
+#define ADPA_HSYNC_CNTL_ENABLE 0
+#define ADPA_VSYNC_ACTIVE_HIGH (1<<4)
+#define ADPA_VSYNC_ACTIVE_LOW  0
+#define ADPA_HSYNC_ACTIVE_HIGH (1<<3)
+#define ADPA_HSYNC_ACTIVE_LOW  0
+
+#define FPA0           0x06040
+#define FPA1           0x06044
+#define FPB0           0x06048
+#define FPB1           0x0604c
+# define FP_N_DIV_MASK                         0x003f0000
+# define FP_N_DIV_SHIFT                                16
+# define FP_M1_DIV_MASK                                0x00003f00
+# define FP_M1_DIV_SHIFT                       8
+# define FP_M2_DIV_MASK                                0x0000003f
+# define FP_M2_DIV_SHIFT                       0
+
+
+#define PORT_HOTPLUG_EN                0x61110
+# define SDVOB_HOTPLUG_INT_EN                  (1 << 26)
+# define SDVOC_HOTPLUG_INT_EN                  (1 << 25)
+# define TV_HOTPLUG_INT_EN                     (1 << 18)
+# define CRT_HOTPLUG_INT_EN                    (1 << 9)
+# define CRT_HOTPLUG_FORCE_DETECT              (1 << 3)
+
+#define PORT_HOTPLUG_STAT      0x61114
+# define CRT_HOTPLUG_INT_STATUS                        (1 << 11)
+# define TV_HOTPLUG_INT_STATUS                 (1 << 10)
+# define CRT_HOTPLUG_MONITOR_MASK              (3 << 8)
+# define CRT_HOTPLUG_MONITOR_COLOR             (3 << 8)
+# define CRT_HOTPLUG_MONITOR_MONO              (2 << 8)
+# define CRT_HOTPLUG_MONITOR_NONE              (0 << 8)
+# define SDVOC_HOTPLUG_INT_STATUS              (1 << 7)
+# define SDVOB_HOTPLUG_INT_STATUS              (1 << 6)
+
+#define SDVOB                  0x61140
+#define SDVOC                  0x61160
+#define SDVO_ENABLE                            (1 << 31)
+#define SDVO_PIPE_B_SELECT                     (1 << 30)
+#define SDVO_STALL_SELECT                      (1 << 29)
+#define SDVO_INTERRUPT_ENABLE                  (1 << 26)
+/**
+ * 915G/GM SDVO pixel multiplier.
+ *
+ * Programmed value is multiplier - 1, up to 5x.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+#define SDVO_PORT_MULTIPLY_MASK                        (7 << 23)
+#define SDVO_PORT_MULTIPLY_SHIFT               23
+#define SDVO_PHASE_SELECT_MASK                 (15 << 19)
+#define SDVO_PHASE_SELECT_DEFAULT              (6 << 19)
+#define SDVO_CLOCK_OUTPUT_INVERT               (1 << 18)
+#define SDVOC_GANG_MODE                                (1 << 16)
+#define SDVO_BORDER_ENABLE                     (1 << 7)
+#define SDVOB_PCIE_CONCURRENCY                 (1 << 3)
+#define SDVO_DETECTED                          (1 << 2)
+/* Bits to be preserved when writing */
+#define SDVOB_PRESERVE_MASK                    ((1 << 17) | (1 << 16) | (1 << 14))
+#define SDVOC_PRESERVE_MASK                    (1 << 17)
+
+/** @defgroup LVDS
+ * @{
+ */
+/**
+ * This register controls the LVDS output enable, pipe selection, and data
+ * format selection.
+ *
+ * All of the clock/data pairs are force powered down by power sequencing.
+ */
+#define LVDS                   0x61180
+/**
+ * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
+ * the DPLL semantics change when the LVDS is assigned to that pipe.
+ */
+# define LVDS_PORT_EN                  (1 << 31)
+/** Selects pipe B for LVDS data.  Must be set on pre-965. */
+# define LVDS_PIPEB_SELECT             (1 << 30)
+
+/**
+ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
+ * pixel.
+ */
+# define LVDS_A0A2_CLKA_POWER_MASK     (3 << 8)
+# define LVDS_A0A2_CLKA_POWER_DOWN     (0 << 8)
+# define LVDS_A0A2_CLKA_POWER_UP       (3 << 8)
+/**
+ * Controls the A3 data pair, which contains the additional LSBs for 24 bit
+ * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
+ * on.
+ */
+# define LVDS_A3_POWER_MASK            (3 << 6)
+# define LVDS_A3_POWER_DOWN            (0 << 6)
+# define LVDS_A3_POWER_UP              (3 << 6)
+/**
+ * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
+ * is set.
+ */
+# define LVDS_CLKB_POWER_MASK          (3 << 4)
+# define LVDS_CLKB_POWER_DOWN          (0 << 4)
+# define LVDS_CLKB_POWER_UP            (3 << 4)
+
+/**
+ * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
+ * setting for whether we are in dual-channel mode.  The B3 pair will
+ * additionally only be powered up when LVDS_A3_POWER_UP is set.
+ */
+# define LVDS_B0B3_POWER_MASK          (3 << 2)
+# define LVDS_B0B3_POWER_DOWN          (0 << 2)
+# define LVDS_B0B3_POWER_UP            (3 << 2)
+
+#define PIPEACONF 0x70008
+#define PIPEACONF_ENABLE       (1<<31)
+#define PIPEACONF_DISABLE      0
+#define PIPEACONF_DOUBLE_WIDE  (1<<30)
+#define I965_PIPECONF_ACTIVE   (1<<30)
+#define PIPEACONF_SINGLE_WIDE  0
+#define PIPEACONF_PIPE_UNLOCKED 0
+#define PIPEACONF_PIPE_LOCKED  (1<<25)
+#define PIPEACONF_PALETTE      0
+#define PIPEACONF_GAMMA                (1<<24)
+#define PIPECONF_FORCE_BORDER  (1<<25)
+#define PIPECONF_PROGRESSIVE   (0 << 21)
+#define PIPECONF_INTERLACE_W_FIELD_INDICATION  (6 << 21)
+#define PIPECONF_INTERLACE_FIELD_0_ONLY                (7 << 21)
+
+#define DSPARB   0x70030
+#define DSPARB_CSTART_MASK     (0x7f << 7)
+#define DSPARB_CSTART_SHIFT    7
+#define DSPARB_BSTART_MASK     (0x7f)           
+#define DSPARB_BSTART_SHIFT    0
+
+#define PIPEBCONF 0x71008
+#define PIPEBCONF_ENABLE       (1<<31)
+#define PIPEBCONF_DISABLE      0
+#define PIPEBCONF_DOUBLE_WIDE  (1<<30)
+#define PIPEBCONF_DISABLE      0
+#define PIPEBCONF_GAMMA                (1<<24)
+#define PIPEBCONF_PALETTE      0
+
+#define PIPEBGCMAXRED          0x71010
+#define PIPEBGCMAXGREEN                0x71014
+#define PIPEBGCMAXBLUE         0x71018
+#define PIPEBSTAT              0x71024
+#define PIPEBFRAMEHIGH         0x71040
+#define PIPEBFRAMEPIXEL                0x71044
+
+#define DSPACNTR               0x70180
+#define DSPBCNTR               0x71180
+#define DISPLAY_PLANE_ENABLE                   (1<<31)
+#define DISPLAY_PLANE_DISABLE                  0
+#define DISPPLANE_GAMMA_ENABLE                 (1<<30)
+#define DISPPLANE_GAMMA_DISABLE                        0
+#define DISPPLANE_PIXFORMAT_MASK               (0xf<<26)
+#define DISPPLANE_8BPP                         (0x2<<26)
+#define DISPPLANE_15_16BPP                     (0x4<<26)
+#define DISPPLANE_16BPP                                (0x5<<26)
+#define DISPPLANE_32BPP_NO_ALPHA               (0x6<<26)
+#define DISPPLANE_32BPP                                (0x7<<26)
+#define DISPPLANE_STEREO_ENABLE                        (1<<25)
+#define DISPPLANE_STEREO_DISABLE               0
+#define DISPPLANE_SEL_PIPE_MASK                        (1<<24)
+#define DISPPLANE_SEL_PIPE_A                   0
+#define DISPPLANE_SEL_PIPE_B                   (1<<24)
+#define DISPPLANE_SRC_KEY_ENABLE               (1<<22)
+#define DISPPLANE_SRC_KEY_DISABLE              0
+#define DISPPLANE_LINE_DOUBLE                  (1<<20)
+#define DISPPLANE_NO_LINE_DOUBLE               0
+#define DISPPLANE_STEREO_POLARITY_FIRST                0
+#define DISPPLANE_STEREO_POLARITY_SECOND       (1<<18)
+/* plane B only */
+#define DISPPLANE_ALPHA_TRANS_ENABLE           (1<<15)
+#define DISPPLANE_ALPHA_TRANS_DISABLE          0
+#define DISPPLANE_SPRITE_ABOVE_DISPLAYA                0
+#define DISPPLANE_SPRITE_ABOVE_OVERLAY         (1)
+
+#define DSPABASE               0x70184
+#define DSPASTRIDE             0x70188
+
+#define DSPBBASE               0x71184
+#define DSPBADDR               DSPBBASE
+#define DSPBSTRIDE             0x71188
+
+#define DSPAKEYVAL             0x70194
+#define DSPAKEYMASK            0x70198
+
+#define DSPAPOS                        0x7018C /* reserved */
+#define DSPASIZE               0x70190
+#define DSPBPOS                        0x7118C
+#define DSPBSIZE               0x71190
+
+#define DSPASURF               0x7019C
+#define DSPATILEOFF            0x701A4
+
+#define DSPBSURF               0x7119C
+#define DSPBTILEOFF            0x711A4
+
+#define VGACNTRL               0x71400
+# define VGA_DISP_DISABLE                      (1 << 31)
+# define VGA_2X_MODE                           (1 << 30)
+# define VGA_PIPE_B_SELECT                     (1 << 29)
+
+/*
+ * Some BIOS scratch area registers.  The 845 (and 830?) store the amount
+ * of video memory available to the BIOS in SWF1.
+ */
+
+#define SWF0                   0x71410
+
+/*
+ * 855 scratch registers.
+ */
+#define SWF10                  0x70410
+
+#define SWF30                  0x72414
+
+/*
+ * Overlay registers.  These are overlay registers accessed via MMIO.
+ * Those loaded via the overlay register page are defined in i830_video.c.
+ */
+#define OVADD                  0x30000
+
+#define DOVSTA                 0x30008
+#define OC_BUF                 (0x3<<20)
+
+#define OGAMC5                 0x30010
+#define OGAMC4                 0x30014
+#define OGAMC3                 0x30018
+#define OGAMC2                 0x3001c
+#define OGAMC1                 0x30020
+#define OGAMC0                 0x30024
+/*
+ * Palette registers
+ */
+#define PALETTE_A              0x0a000
+#define PALETTE_B              0x0a800
+
+#define IS_I830(dev) ((dev)->pci_device == 0x3577)
+#define IS_845G(dev) ((dev)->pci_device == 0x2562)
+#define IS_I85X(dev) ((dev)->pci_device == 0x3582)
+#define IS_I855(dev) ((dev)->pci_device == 0x3582)
+#define IS_I865G(dev) ((dev)->pci_device == 0x2572)
+
+#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a)
+#define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
+#define IS_I945G(dev) ((dev)->pci_device == 0x2772)
+#define IS_I945GM(dev) ((dev)->pci_device == 0x27A2 ||\
+                       (dev)->pci_device == 0x27AE)
+#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \
+                      (dev)->pci_device == 0x2982 || \
+                      (dev)->pci_device == 0x2992 || \
+                      (dev)->pci_device == 0x29A2 || \
+                      (dev)->pci_device == 0x2A02 || \
+                      (dev)->pci_device == 0x2A12 || \
+                      (dev)->pci_device == 0x2A42 || \
+                      (dev)->pci_device == 0x2E02 || \
+                      (dev)->pci_device == 0x2E12 || \
+                      (dev)->pci_device == 0x2E22)
+
+#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
+
+#define IS_IGD_GM(dev) ((dev)->pci_device == 0x2A42)
+
+#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \
+                    (dev)->pci_device == 0x2E12 || \
+                    (dev)->pci_device == 0x2E22)
+
+#define IS_G33(dev)    ((dev)->pci_device == 0x29C2 || \
+                       (dev)->pci_device == 0x29B2 ||  \
+                       (dev)->pci_device == 0x29D2)
+
+#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
+                     IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev))
+
+#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
+                       IS_I945GM(dev) || IS_I965GM(dev) || IS_IGD_GM(dev))
+
+#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_IGD_GM(dev) || IS_G4X(dev))
+
+#define PRIMARY_RINGBUFFER_SIZE         (128*1024)
+
+#endif
diff --git a/drivers/gpu/drm/i915/i915_ioc32.c b/drivers/gpu/drm/i915/i915_ioc32.c
new file mode 100644 (file)
index 0000000..1fe68a2
--- /dev/null
@@ -0,0 +1,222 @@
+/**
+ * \file i915_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the i915 DRM.
+ *
+ * \author Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ *
+ * Copyright (C) Paul Mackerras 2005
+ * Copyright (C) Alan Hourihane 2005
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <linux/compat.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+
+typedef struct _drm_i915_batchbuffer32 {
+       int start;              /* agp offset */
+       int used;               /* nr bytes in use */
+       int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
+       int DR4;                /* window origin for GFX_OP_DRAWRECT_INFO */
+       int num_cliprects;      /* mulitpass with multiple cliprects? */
+       u32 cliprects;          /* pointer to userspace cliprects */
+} drm_i915_batchbuffer32_t;
+
+static int compat_i915_batchbuffer(struct file *file, unsigned int cmd,
+                                  unsigned long arg)
+{
+       drm_i915_batchbuffer32_t batchbuffer32;
+       drm_i915_batchbuffer_t __user *batchbuffer;
+
+       if (copy_from_user
+           (&batchbuffer32, (void __user *)arg, sizeof(batchbuffer32)))
+               return -EFAULT;
+
+       batchbuffer = compat_alloc_user_space(sizeof(*batchbuffer));
+       if (!access_ok(VERIFY_WRITE, batchbuffer, sizeof(*batchbuffer))
+           || __put_user(batchbuffer32.start, &batchbuffer->start)
+           || __put_user(batchbuffer32.used, &batchbuffer->used)
+           || __put_user(batchbuffer32.DR1, &batchbuffer->DR1)
+           || __put_user(batchbuffer32.DR4, &batchbuffer->DR4)
+           || __put_user(batchbuffer32.num_cliprects,
+                         &batchbuffer->num_cliprects)
+           || __put_user((int __user *)(unsigned long)batchbuffer32.cliprects,
+                         &batchbuffer->cliprects))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_I915_BATCHBUFFER,
+                        (unsigned long)batchbuffer);
+}
+
+typedef struct _drm_i915_cmdbuffer32 {
+       u32 buf;                /* pointer to userspace command buffer */
+       int sz;                 /* nr bytes in buf */
+       int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
+       int DR4;                /* window origin for GFX_OP_DRAWRECT_INFO */
+       int num_cliprects;      /* mulitpass with multiple cliprects? */
+       u32 cliprects;          /* pointer to userspace cliprects */
+} drm_i915_cmdbuffer32_t;
+
+static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
+                                unsigned long arg)
+{
+       drm_i915_cmdbuffer32_t cmdbuffer32;
+       drm_i915_cmdbuffer_t __user *cmdbuffer;
+
+       if (copy_from_user
+           (&cmdbuffer32, (void __user *)arg, sizeof(cmdbuffer32)))
+               return -EFAULT;
+
+       cmdbuffer = compat_alloc_user_space(sizeof(*cmdbuffer));
+       if (!access_ok(VERIFY_WRITE, cmdbuffer, sizeof(*cmdbuffer))
+           || __put_user((int __user *)(unsigned long)cmdbuffer32.buf,
+                         &cmdbuffer->buf)
+           || __put_user(cmdbuffer32.sz, &cmdbuffer->sz)
+           || __put_user(cmdbuffer32.DR1, &cmdbuffer->DR1)
+           || __put_user(cmdbuffer32.DR4, &cmdbuffer->DR4)
+           || __put_user(cmdbuffer32.num_cliprects, &cmdbuffer->num_cliprects)
+           || __put_user((int __user *)(unsigned long)cmdbuffer32.cliprects,
+                         &cmdbuffer->cliprects))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer);
+}
+
+typedef struct drm_i915_irq_emit32 {
+       u32 irq_seq;
+} drm_i915_irq_emit32_t;
+
+static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
+                               unsigned long arg)
+{
+       drm_i915_irq_emit32_t req32;
+       drm_i915_irq_emit_t __user *request;
+
+       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user((int __user *)(unsigned long)req32.irq_seq,
+                         &request->irq_seq))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request);
+}
+typedef struct drm_i915_getparam32 {
+       int param;
+       u32 value;
+} drm_i915_getparam32_t;
+
+static int compat_i915_getparam(struct file *file, unsigned int cmd,
+                               unsigned long arg)
+{
+       drm_i915_getparam32_t req32;
+       drm_i915_getparam_t __user *request;
+
+       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user(req32.param, &request->param)
+           || __put_user((void __user *)(unsigned long)req32.value,
+                         &request->value))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_I915_GETPARAM, (unsigned long)request);
+}
+
+typedef struct drm_i915_mem_alloc32 {
+       int region;
+       int alignment;
+       int size;
+       u32 region_offset;      /* offset from start of fb or agp */
+} drm_i915_mem_alloc32_t;
+
+static int compat_i915_alloc(struct file *file, unsigned int cmd,
+                            unsigned long arg)
+{
+       drm_i915_mem_alloc32_t req32;
+       drm_i915_mem_alloc_t __user *request;
+
+       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user(req32.region, &request->region)
+           || __put_user(req32.alignment, &request->alignment)
+           || __put_user(req32.size, &request->size)
+           || __put_user((void __user *)(unsigned long)req32.region_offset,
+                         &request->region_offset))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_I915_ALLOC, (unsigned long)request);
+}
+
+drm_ioctl_compat_t *i915_compat_ioctls[] = {
+       [DRM_I915_BATCHBUFFER] = compat_i915_batchbuffer,
+       [DRM_I915_CMDBUFFER] = compat_i915_cmdbuffer,
+       [DRM_I915_GETPARAM] = compat_i915_getparam,
+       [DRM_I915_IRQ_EMIT] = compat_i915_irq_emit,
+       [DRM_I915_ALLOC] = compat_i915_alloc
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/dri/card<n>.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       unsigned int nr = DRM_IOCTL_NR(cmd);
+       drm_ioctl_compat_t *fn = NULL;
+       int ret;
+
+       if (nr < DRM_COMMAND_BASE)
+               return drm_compat_ioctl(filp, cmd, arg);
+
+       if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
+               fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
+
+       lock_kernel();          /* XXX for now */
+       if (fn != NULL)
+               ret = (*fn) (filp, cmd, arg);
+       else
+               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
+       unlock_kernel();
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
new file mode 100644 (file)
index 0000000..df03611
--- /dev/null
@@ -0,0 +1,623 @@
+/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-
+ */
+/*
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+#define USER_INT_FLAG (1<<1)
+#define VSYNC_PIPEB_FLAG (1<<5)
+#define VSYNC_PIPEA_FLAG (1<<7)
+
+#define MAX_NOPID ((u32)~0)
+
+/**
+ * Emit blits for scheduled buffer swaps.
+ *
+ * This function will be called with the HW lock held.
+ */
+static void i915_vblank_tasklet(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       unsigned long irqflags;
+       struct list_head *list, *tmp, hits, *hit;
+       int nhits, nrects, slice[2], upper[2], lower[2], i;
+       unsigned counter[2] = { atomic_read(&dev->vbl_received),
+                               atomic_read(&dev->vbl_received2) };
+       struct drm_drawable_info *drw;
+       drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       u32 cpp = dev_priv->cpp;
+       u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
+                               XY_SRC_COPY_BLT_WRITE_ALPHA |
+                               XY_SRC_COPY_BLT_WRITE_RGB)
+                            : XY_SRC_COPY_BLT_CMD;
+       u32 src_pitch = sarea_priv->pitch * cpp;
+       u32 dst_pitch = sarea_priv->pitch * cpp;
+       u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24);
+       RING_LOCALS;
+
+       if (IS_I965G(dev) && sarea_priv->front_tiled) {
+               cmd |= XY_SRC_COPY_BLT_DST_TILED;
+               dst_pitch >>= 2;
+       }
+       if (IS_I965G(dev) && sarea_priv->back_tiled) {
+               cmd |= XY_SRC_COPY_BLT_SRC_TILED;
+               src_pitch >>= 2;
+       }
+
+       DRM_DEBUG("\n");
+
+       INIT_LIST_HEAD(&hits);
+
+       nhits = nrects = 0;
+
+       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+       /* Find buffer swaps scheduled for this vertical blank */
+       list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
+               drm_i915_vbl_swap_t *vbl_swap =
+                       list_entry(list, drm_i915_vbl_swap_t, head);
+
+               if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
+                       continue;
+
+               list_del(list);
+               dev_priv->swaps_pending--;
+
+               spin_unlock(&dev_priv->swaps_lock);
+               spin_lock(&dev->drw_lock);
+
+               drw = drm_get_drawable_info(dev, vbl_swap->drw_id);
+
+               if (!drw) {
+                       spin_unlock(&dev->drw_lock);
+                       drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
+                       spin_lock(&dev_priv->swaps_lock);
+                       continue;
+               }
+
+               list_for_each(hit, &hits) {
+                       drm_i915_vbl_swap_t *swap_cmp =
+                               list_entry(hit, drm_i915_vbl_swap_t, head);
+                       struct drm_drawable_info *drw_cmp =
+                               drm_get_drawable_info(dev, swap_cmp->drw_id);
+
+                       if (drw_cmp &&
+                           drw_cmp->rects[0].y1 > drw->rects[0].y1) {
+                               list_add_tail(list, hit);
+                               break;
+                       }
+               }
+
+               spin_unlock(&dev->drw_lock);
+
+               /* List of hits was empty, or we reached the end of it */
+               if (hit == &hits)
+                       list_add_tail(list, hits.prev);
+
+               nhits++;
+
+               spin_lock(&dev_priv->swaps_lock);
+       }
+
+       if (nhits == 0) {
+               spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+               return;
+       }
+
+       spin_unlock(&dev_priv->swaps_lock);
+
+       i915_kernel_lost_context(dev);
+
+       if (IS_I965G(dev)) {
+               BEGIN_LP_RING(4);
+
+               OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
+               OUT_RING(0);
+               OUT_RING(((sarea_priv->width - 1) & 0xffff) | ((sarea_priv->height - 1) << 16));
+               OUT_RING(0);
+               ADVANCE_LP_RING();
+       } else {
+               BEGIN_LP_RING(6);
+
+               OUT_RING(GFX_OP_DRAWRECT_INFO);
+               OUT_RING(0);
+               OUT_RING(0);
+               OUT_RING(sarea_priv->width | sarea_priv->height << 16);
+               OUT_RING(sarea_priv->width | sarea_priv->height << 16);
+               OUT_RING(0);
+
+               ADVANCE_LP_RING();
+       }
+
+       sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
+
+       upper[0] = upper[1] = 0;
+       slice[0] = max(sarea_priv->pipeA_h / nhits, 1);
+       slice[1] = max(sarea_priv->pipeB_h / nhits, 1);
+       lower[0] = sarea_priv->pipeA_y + slice[0];
+       lower[1] = sarea_priv->pipeB_y + slice[0];
+
+       spin_lock(&dev->drw_lock);
+
+       /* Emit blits for buffer swaps, partitioning both outputs into as many
+        * slices as there are buffer swaps scheduled in order to avoid tearing
+        * (based on the assumption that a single buffer swap would always
+        * complete before scanout starts).
+        */
+       for (i = 0; i++ < nhits;
+            upper[0] = lower[0], lower[0] += slice[0],
+            upper[1] = lower[1], lower[1] += slice[1]) {
+               if (i == nhits)
+                       lower[0] = lower[1] = sarea_priv->height;
+
+               list_for_each(hit, &hits) {
+                       drm_i915_vbl_swap_t *swap_hit =
+                               list_entry(hit, drm_i915_vbl_swap_t, head);
+                       struct drm_clip_rect *rect;
+                       int num_rects, pipe;
+                       unsigned short top, bottom;
+
+                       drw = drm_get_drawable_info(dev, swap_hit->drw_id);
+
+                       if (!drw)
+                               continue;
+
+                       rect = drw->rects;
+                       pipe = swap_hit->pipe;
+                       top = upper[pipe];
+                       bottom = lower[pipe];
+
+                       for (num_rects = drw->num_rects; num_rects--; rect++) {
+                               int y1 = max(rect->y1, top);
+                               int y2 = min(rect->y2, bottom);
+
+                               if (y1 >= y2)
+                                       continue;
+
+                               BEGIN_LP_RING(8);
+
+                               OUT_RING(cmd);
+                               OUT_RING(ropcpp | dst_pitch);
+                               OUT_RING((y1 << 16) | rect->x1);
+                               OUT_RING((y2 << 16) | rect->x2);
+                               OUT_RING(sarea_priv->front_offset);
+                               OUT_RING((y1 << 16) | rect->x1);
+                               OUT_RING(src_pitch);
+                               OUT_RING(sarea_priv->back_offset);
+
+                               ADVANCE_LP_RING();
+                       }
+               }
+       }
+
+       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+       list_for_each_safe(hit, tmp, &hits) {
+               drm_i915_vbl_swap_t *swap_hit =
+                       list_entry(hit, drm_i915_vbl_swap_t, head);
+
+               list_del(hit);
+
+               drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER);
+       }
+}
+
+irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u16 temp;
+       u32 pipea_stats, pipeb_stats;
+
+       pipea_stats = I915_READ(I915REG_PIPEASTAT);
+       pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
+
+       temp = I915_READ16(I915REG_INT_IDENTITY_R);
+
+       temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
+
+       DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
+
+       if (temp == 0)
+               return IRQ_NONE;
+
+       I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+       (void) I915_READ16(I915REG_INT_IDENTITY_R);
+       DRM_READMEMORYBARRIER();
+
+       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+
+       if (temp & USER_INT_FLAG)
+               DRM_WAKEUP(&dev_priv->irq_queue);
+
+       if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
+               int vblank_pipe = dev_priv->vblank_pipe;
+
+               if ((vblank_pipe &
+                    (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
+                   == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
+                       if (temp & VSYNC_PIPEA_FLAG)
+                               atomic_inc(&dev->vbl_received);
+                       if (temp & VSYNC_PIPEB_FLAG)
+                               atomic_inc(&dev->vbl_received2);
+               } else if (((temp & VSYNC_PIPEA_FLAG) &&
+                           (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
+                          ((temp & VSYNC_PIPEB_FLAG) &&
+                           (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
+                       atomic_inc(&dev->vbl_received);
+
+               DRM_WAKEUP(&dev->vbl_queue);
+               drm_vbl_send_signals(dev);
+
+               if (dev_priv->swaps_pending > 0)
+                       drm_locked_tasklet(dev, i915_vblank_tasklet);
+               I915_WRITE(I915REG_PIPEASTAT,
+                       pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
+                       I915_VBLANK_CLEAR);
+               I915_WRITE(I915REG_PIPEBSTAT,
+                       pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
+                       I915_VBLANK_CLEAR);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int i915_emit_irq(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       i915_kernel_lost_context(dev);
+
+       DRM_DEBUG("\n");
+
+       dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
+
+       if (dev_priv->counter > 0x7FFFFFFFUL)
+               dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
+
+       BEGIN_LP_RING(6);
+       OUT_RING(CMD_STORE_DWORD_IDX);
+       OUT_RING(20);
+       OUT_RING(dev_priv->counter);
+       OUT_RING(0);
+       OUT_RING(0);
+       OUT_RING(GFX_OP_USER_INTERRUPT);
+       ADVANCE_LP_RING();
+
+       return dev_priv->counter;
+}
+
+static int i915_wait_irq(struct drm_device * dev, int irq_nr)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int ret = 0;
+
+       DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
+                 READ_BREADCRUMB(dev_priv));
+
+       if (READ_BREADCRUMB(dev_priv) >= irq_nr)
+               return 0;
+
+       dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+
+       DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
+                   READ_BREADCRUMB(dev_priv) >= irq_nr);
+
+       if (ret == -EBUSY) {
+               DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
+                         READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
+       }
+
+       dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+       return ret;
+}
+
+static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
+                                     atomic_t *counter)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       unsigned int cur_vblank;
+       int ret = 0;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+                   (((cur_vblank = atomic_read(counter))
+                       - *sequence) <= (1<<23)));
+
+       *sequence = cur_vblank;
+
+       return ret;
+}
+
+
+int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
+{
+       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
+}
+
+int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
+{
+       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
+}
+
+/* Needs the lock as it touches the ring.
+ */
+int i915_irq_emit(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_irq_emit_t *emit = data;
+       int result;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       result = i915_emit_irq(dev);
+
+       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
+               DRM_ERROR("copy_to_user\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/* Doesn't need the hardware lock.
+ */
+int i915_irq_wait(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_irq_wait_t *irqwait = data;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       return i915_wait_irq(dev, irqwait->irq_seq);
+}
+
+static void i915_enable_interrupt (struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u16 flag;
+
+       flag = 0;
+       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
+               flag |= VSYNC_PIPEA_FLAG;
+       if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
+               flag |= VSYNC_PIPEB_FLAG;
+
+       I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
+}
+
+/* Set the vblank monitor pipe
+ */
+int i915_vblank_pipe_set(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_vblank_pipe_t *pipe = data;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
+               DRM_ERROR("called with invalid pipe 0x%x\n", pipe->pipe);
+               return -EINVAL;
+       }
+
+       dev_priv->vblank_pipe = pipe->pipe;
+
+       i915_enable_interrupt (dev);
+
+       return 0;
+}
+
+int i915_vblank_pipe_get(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_vblank_pipe_t *pipe = data;
+       u16 flag;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       flag = I915_READ(I915REG_INT_ENABLE_R);
+       pipe->pipe = 0;
+       if (flag & VSYNC_PIPEA_FLAG)
+               pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
+       if (flag & VSYNC_PIPEB_FLAG)
+               pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
+
+       return 0;
+}
+
+/**
+ * Schedule buffer swap at given vertical blank.
+ */
+int i915_vblank_swap(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_vblank_swap_t *swap = data;
+       drm_i915_vbl_swap_t *vbl_swap;
+       unsigned int pipe, seqtype, curseq;
+       unsigned long irqflags;
+       struct list_head *list;
+
+       if (!dev_priv) {
+               DRM_ERROR("%s called with no initialization\n", __func__);
+               return -EINVAL;
+       }
+
+       if (dev_priv->sarea_priv->rotation) {
+               DRM_DEBUG("Rotation not supported\n");
+               return -EINVAL;
+       }
+
+       if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
+                            _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
+               DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype);
+               return -EINVAL;
+       }
+
+       pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
+
+       seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
+
+       if (!(dev_priv->vblank_pipe & (1 << pipe))) {
+               DRM_ERROR("Invalid pipe %d\n", pipe);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&dev->drw_lock, irqflags);
+
+       if (!drm_get_drawable_info(dev, swap->drawable)) {
+               spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+               DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable);
+               return -EINVAL;
+       }
+
+       spin_unlock_irqrestore(&dev->drw_lock, irqflags);
+
+       curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
+
+       if (seqtype == _DRM_VBLANK_RELATIVE)
+               swap->sequence += curseq;
+
+       if ((curseq - swap->sequence) <= (1<<23)) {
+               if (swap->seqtype & _DRM_VBLANK_NEXTONMISS) {
+                       swap->sequence = curseq + 1;
+               } else {
+                       DRM_DEBUG("Missed target sequence\n");
+                       return -EINVAL;
+               }
+       }
+
+       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+       list_for_each(list, &dev_priv->vbl_swaps.head) {
+               vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
+
+               if (vbl_swap->drw_id == swap->drawable &&
+                   vbl_swap->pipe == pipe &&
+                   vbl_swap->sequence == swap->sequence) {
+                       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+                       DRM_DEBUG("Already scheduled\n");
+                       return 0;
+               }
+       }
+
+       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+
+       if (dev_priv->swaps_pending >= 100) {
+               DRM_DEBUG("Too many swaps queued\n");
+               return -EBUSY;
+       }
+
+       vbl_swap = drm_calloc(1, sizeof(*vbl_swap), DRM_MEM_DRIVER);
+
+       if (!vbl_swap) {
+               DRM_ERROR("Failed to allocate memory to queue swap\n");
+               return -ENOMEM;
+       }
+
+       DRM_DEBUG("\n");
+
+       vbl_swap->drw_id = swap->drawable;
+       vbl_swap->pipe = pipe;
+       vbl_swap->sequence = swap->sequence;
+
+       spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
+       list_add_tail(&vbl_swap->head, &dev_priv->vbl_swaps.head);
+       dev_priv->swaps_pending++;
+
+       spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+
+       return 0;
+}
+
+/* drm_dma.h hooks
+*/
+void i915_driver_irq_preinstall(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+       I915_WRITE16(I915REG_HWSTAM, 0xfffe);
+       I915_WRITE16(I915REG_INT_MASK_R, 0x0);
+       I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+}
+
+void i915_driver_irq_postinstall(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+       spin_lock_init(&dev_priv->swaps_lock);
+       INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
+       dev_priv->swaps_pending = 0;
+
+       if (!dev_priv->vblank_pipe)
+               dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
+       i915_enable_interrupt(dev);
+       DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
+}
+
+void i915_driver_irq_uninstall(struct drm_device * dev)
+{
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       u16 temp;
+
+       if (!dev_priv)
+               return;
+
+       I915_WRITE16(I915REG_HWSTAM, 0xffff);
+       I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
+       I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+
+       temp = I915_READ16(I915REG_INT_IDENTITY_R);
+       I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+}
diff --git a/drivers/gpu/drm/i915/i915_mem.c b/drivers/gpu/drm/i915/i915_mem.c
new file mode 100644 (file)
index 0000000..6126a60
--- /dev/null
@@ -0,0 +1,386 @@
+/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
+ */
+/*
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+/* This memory manager is integrated into the global/local lru
+ * mechanisms used by the clients.  Specifically, it operates by
+ * setting the 'in_use' fields of the global LRU to indicate whether
+ * this region is privately allocated to a client.
+ *
+ * This does require the client to actually respect that field.
+ *
+ * Currently no effort is made to allocate 'private' memory in any
+ * clever way - the LRU information isn't used to determine which
+ * block to allocate, and the ring is drained prior to allocations --
+ * in other words allocation is expensive.
+ */
+static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       struct drm_tex_region *list;
+       unsigned shift, nr;
+       unsigned start;
+       unsigned end;
+       unsigned i;
+       int age;
+
+       shift = dev_priv->tex_lru_log_granularity;
+       nr = I915_NR_TEX_REGIONS;
+
+       start = p->start >> shift;
+       end = (p->start + p->size - 1) >> shift;
+
+       age = ++sarea_priv->texAge;
+       list = sarea_priv->texList;
+
+       /* Mark the regions with the new flag and update their age.  Move
+        * them to head of list to preserve LRU semantics.
+        */
+       for (i = start; i <= end; i++) {
+               list[i].in_use = in_use;
+               list[i].age = age;
+
+               /* remove_from_list(i)
+                */
+               list[(unsigned)list[i].next].prev = list[i].prev;
+               list[(unsigned)list[i].prev].next = list[i].next;
+
+               /* insert_at_head(list, i)
+                */
+               list[i].prev = nr;
+               list[i].next = list[nr].next;
+               list[(unsigned)list[nr].next].prev = i;
+               list[nr].next = i;
+       }
+}
+
+/* Very simple allocator for agp memory, working on a static range
+ * already mapped into each client's address space.
+ */
+
+static struct mem_block *split_block(struct mem_block *p, int start, int size,
+                                    struct drm_file *file_priv)
+{
+       /* Maybe cut off the start of an existing block */
+       if (start > p->start) {
+               struct mem_block *newblock =
+                   drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
+               if (!newblock)
+                       goto out;
+               newblock->start = start;
+               newblock->size = p->size - (start - p->start);
+               newblock->file_priv = NULL;
+               newblock->next = p->next;
+               newblock->prev = p;
+               p->next->prev = newblock;
+               p->next = newblock;
+               p->size -= newblock->size;
+               p = newblock;
+       }
+
+       /* Maybe cut off the end of an existing block */
+       if (size < p->size) {
+               struct mem_block *newblock =
+                   drm_alloc(sizeof(*newblock), DRM_MEM_BUFLISTS);
+               if (!newblock)
+                       goto out;
+               newblock->start = start + size;
+               newblock->size = p->size - size;
+               newblock->file_priv = NULL;
+               newblock->next = p->next;
+               newblock->prev = p;
+               p->next->prev = newblock;
+               p->next = newblock;
+               p->size = size;
+       }
+
+      out:
+       /* Our block is in the middle */
+       p->file_priv = file_priv;
+       return p;
+}
+
+static struct mem_block *alloc_block(struct mem_block *heap, int size,
+                                    int align2, struct drm_file *file_priv)
+{
+       struct mem_block *p;
+       int mask = (1 << align2) - 1;
+
+       for (p = heap->next; p != heap; p = p->next) {
+               int start = (p->start + mask) & ~mask;
+               if (p->file_priv == NULL && start + size <= p->start + p->size)
+                       return split_block(p, start, size, file_priv);
+       }
+
+       return NULL;
+}
+
+static struct mem_block *find_block(struct mem_block *heap, int start)
+{
+       struct mem_block *p;
+
+       for (p = heap->next; p != heap; p = p->next)
+               if (p->start == start)
+                       return p;
+
+       return NULL;
+}
+
+static void free_block(struct mem_block *p)
+{
+       p->file_priv = NULL;
+
+       /* Assumes a single contiguous range.  Needs a special file_priv in
+        * 'heap' to stop it being subsumed.
+        */
+       if (p->next->file_priv == NULL) {
+               struct mem_block *q = p->next;
+               p->size += q->size;
+               p->next = q->next;
+               p->next->prev = p;
+               drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
+       }
+
+       if (p->prev->file_priv == NULL) {
+               struct mem_block *q = p->prev;
+               q->size += p->size;
+               q->next = p->next;
+               q->next->prev = q;
+               drm_free(p, sizeof(*q), DRM_MEM_BUFLISTS);
+       }
+}
+
+/* Initialize.  How to check for an uninitialized heap?
+ */
+static int init_heap(struct mem_block **heap, int start, int size)
+{
+       struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFLISTS);
+
+       if (!blocks)
+               return -ENOMEM;
+
+       *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFLISTS);
+       if (!*heap) {
+               drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFLISTS);
+               return -ENOMEM;
+       }
+
+       blocks->start = start;
+       blocks->size = size;
+       blocks->file_priv = NULL;
+       blocks->next = blocks->prev = *heap;
+
+       memset(*heap, 0, sizeof(**heap));
+       (*heap)->file_priv = (struct drm_file *) - 1;
+       (*heap)->next = (*heap)->prev = blocks;
+       return 0;
+}
+
+/* Free all blocks associated with the releasing file.
+ */
+void i915_mem_release(struct drm_device * dev, struct drm_file *file_priv,
+                     struct mem_block *heap)
+{
+       struct mem_block *p;
+
+       if (!heap || !heap->next)
+               return;
+
+       for (p = heap->next; p != heap; p = p->next) {
+               if (p->file_priv == file_priv) {
+                       p->file_priv = NULL;
+                       mark_block(dev, p, 0);
+               }
+       }
+
+       /* Assumes a single contiguous range.  Needs a special file_priv in
+        * 'heap' to stop it being subsumed.
+        */
+       for (p = heap->next; p != heap; p = p->next) {
+               while (p->file_priv == NULL && p->next->file_priv == NULL) {
+                       struct mem_block *q = p->next;
+                       p->size += q->size;
+                       p->next = q->next;
+                       p->next->prev = p;
+                       drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
+               }
+       }
+}
+
+/* Shutdown.
+ */
+void i915_mem_takedown(struct mem_block **heap)
+{
+       struct mem_block *p;
+
+       if (!*heap)
+               return;
+
+       for (p = (*heap)->next; p != *heap;) {
+               struct mem_block *q = p;
+               p = p->next;
+               drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS);
+       }
+
+       drm_free(*heap, sizeof(**heap), DRM_MEM_BUFLISTS);
+       *heap = NULL;
+}
+
+static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region)
+{
+       switch (region) {
+       case I915_MEM_REGION_AGP:
+               return &dev_priv->agp_heap;
+       default:
+               return NULL;
+       }
+}
+
+/* IOCTL HANDLERS */
+
+int i915_mem_alloc(struct drm_device *dev, void *data,
+                  struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_mem_alloc_t *alloc = data;
+       struct mem_block *block, **heap;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       heap = get_heap(dev_priv, alloc->region);
+       if (!heap || !*heap)
+               return -EFAULT;
+
+       /* Make things easier on ourselves: all allocations at least
+        * 4k aligned.
+        */
+       if (alloc->alignment < 12)
+               alloc->alignment = 12;
+
+       block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv);
+
+       if (!block)
+               return -ENOMEM;
+
+       mark_block(dev, block, 1);
+
+       if (DRM_COPY_TO_USER(alloc->region_offset, &block->start,
+                            sizeof(int))) {
+               DRM_ERROR("copy_to_user\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+int i915_mem_free(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_mem_free_t *memfree = data;
+       struct mem_block *block, **heap;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       heap = get_heap(dev_priv, memfree->region);
+       if (!heap || !*heap)
+               return -EFAULT;
+
+       block = find_block(*heap, memfree->region_offset);
+       if (!block)
+               return -EFAULT;
+
+       if (block->file_priv != file_priv)
+               return -EPERM;
+
+       mark_block(dev, block, 0);
+       free_block(block);
+       return 0;
+}
+
+int i915_mem_init_heap(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_mem_init_heap_t *initheap = data;
+       struct mem_block **heap;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       heap = get_heap(dev_priv, initheap->region);
+       if (!heap)
+               return -EFAULT;
+
+       if (*heap) {
+               DRM_ERROR("heap already initialized?");
+               return -EFAULT;
+       }
+
+       return init_heap(heap, initheap->start, initheap->size);
+}
+
+int i915_mem_destroy_heap( struct drm_device *dev, void *data,
+                          struct drm_file *file_priv )
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       drm_i915_mem_destroy_heap_t *destroyheap = data;
+       struct mem_block **heap;
+
+       if ( !dev_priv ) {
+               DRM_ERROR( "called with no initialization\n" );
+               return -EINVAL;
+       }
+
+       heap = get_heap( dev_priv, destroyheap->region );
+       if (!heap) {
+               DRM_ERROR("get_heap failed");
+               return -EFAULT;
+       }
+
+       if (!*heap) {
+               DRM_ERROR("heap not initialized?");
+               return -EFAULT;
+       }
+
+       i915_mem_takedown( heap );
+       return 0;
+}
diff --git a/drivers/gpu/drm/mga/Makefile b/drivers/gpu/drm/mga/Makefile
new file mode 100644 (file)
index 0000000..6068478
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+mga-y := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
+
+mga-$(CONFIG_COMPAT) += mga_ioc32.o
+
+obj-$(CONFIG_DRM_MGA)  += mga.o
+
diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c
new file mode 100644 (file)
index 0000000..c1d12db
--- /dev/null
@@ -0,0 +1,1162 @@
+/* mga_dma.c -- DMA support for mga g200/g400 -*- linux-c -*-
+ * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file mga_dma.c
+ * DMA support for MGA G200 / G400.
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Jeff Hartmann <jhartmann@valinux.com>
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_sarea.h"
+#include "mga_drm.h"
+#include "mga_drv.h"
+
+#define MGA_DEFAULT_USEC_TIMEOUT       10000
+#define MGA_FREELIST_DEBUG             0
+
+#define MINIMAL_CLEANUP 0
+#define FULL_CLEANUP 1
+static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup);
+
+/* ================================================================
+ * Engine control
+ */
+
+int mga_do_wait_for_idle(drm_mga_private_t * dev_priv)
+{
+       u32 status = 0;
+       int i;
+       DRM_DEBUG("\n");
+
+       for (i = 0; i < dev_priv->usec_timeout; i++) {
+               status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
+               if (status == MGA_ENDPRDMASTS) {
+                       MGA_WRITE8(MGA_CRTC_INDEX, 0);
+                       return 0;
+               }
+               DRM_UDELAY(1);
+       }
+
+#if MGA_DMA_DEBUG
+       DRM_ERROR("failed!\n");
+       DRM_INFO("   status=0x%08x\n", status);
+#endif
+       return -EBUSY;
+}
+
+static int mga_do_dma_reset(drm_mga_private_t * dev_priv)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+
+       DRM_DEBUG("\n");
+
+       /* The primary DMA stream should look like new right about now.
+        */
+       primary->tail = 0;
+       primary->space = primary->size;
+       primary->last_flush = 0;
+
+       sarea_priv->last_wrap = 0;
+
+       /* FIXME: Reset counters, buffer ages etc...
+        */
+
+       /* FIXME: What else do we need to reinitialize?  WARP stuff?
+        */
+
+       return 0;
+}
+
+/* ================================================================
+ * Primary DMA stream
+ */
+
+void mga_do_dma_flush(drm_mga_private_t * dev_priv)
+{
+       drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+       u32 head, tail;
+       u32 status = 0;
+       int i;
+       DMA_LOCALS;
+       DRM_DEBUG("\n");
+
+       /* We need to wait so that we can do an safe flush */
+       for (i = 0; i < dev_priv->usec_timeout; i++) {
+               status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
+               if (status == MGA_ENDPRDMASTS)
+                       break;
+               DRM_UDELAY(1);
+       }
+
+       if (primary->tail == primary->last_flush) {
+               DRM_DEBUG("   bailing out...\n");
+               return;
+       }
+
+       tail = primary->tail + dev_priv->primary->offset;
+
+       /* We need to pad the stream between flushes, as the card
+        * actually (partially?) reads the first of these commands.
+        * See page 4-16 in the G400 manual, middle of the page or so.
+        */
+       BEGIN_DMA(1);
+
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+       ADVANCE_DMA();
+
+       primary->last_flush = primary->tail;
+
+       head = MGA_READ(MGA_PRIMADDRESS);
+
+       if (head <= tail) {
+               primary->space = primary->size - primary->tail;
+       } else {
+               primary->space = head - tail;
+       }
+
+       DRM_DEBUG("   head = 0x%06lx\n", head - dev_priv->primary->offset);
+       DRM_DEBUG("   tail = 0x%06lx\n", tail - dev_priv->primary->offset);
+       DRM_DEBUG("  space = 0x%06x\n", primary->space);
+
+       mga_flush_write_combine();
+       MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
+
+       DRM_DEBUG("done.\n");
+}
+
+void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
+{
+       drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+       u32 head, tail;
+       DMA_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_DMA_WRAP();
+
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+       ADVANCE_DMA();
+
+       tail = primary->tail + dev_priv->primary->offset;
+
+       primary->tail = 0;
+       primary->last_flush = 0;
+       primary->last_wrap++;
+
+       head = MGA_READ(MGA_PRIMADDRESS);
+
+       if (head == dev_priv->primary->offset) {
+               primary->space = primary->size;
+       } else {
+               primary->space = head - dev_priv->primary->offset;
+       }
+
+       DRM_DEBUG("   head = 0x%06lx\n", head - dev_priv->primary->offset);
+       DRM_DEBUG("   tail = 0x%06x\n", primary->tail);
+       DRM_DEBUG("   wrap = %d\n", primary->last_wrap);
+       DRM_DEBUG("  space = 0x%06x\n", primary->space);
+
+       mga_flush_write_combine();
+       MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access);
+
+       set_bit(0, &primary->wrapped);
+       DRM_DEBUG("done.\n");
+}
+
+void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv)
+{
+       drm_mga_primary_buffer_t *primary = &dev_priv->prim;
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       u32 head = dev_priv->primary->offset;
+       DRM_DEBUG("\n");
+
+       sarea_priv->last_wrap++;
+       DRM_DEBUG("   wrap = %d\n", sarea_priv->last_wrap);
+
+       mga_flush_write_combine();
+       MGA_WRITE(MGA_PRIMADDRESS, head | MGA_DMA_GENERAL);
+
+       clear_bit(0, &primary->wrapped);
+       DRM_DEBUG("done.\n");
+}
+
+/* ================================================================
+ * Freelist management
+ */
+
+#define MGA_BUFFER_USED                ~0
+#define MGA_BUFFER_FREE                0
+
+#if MGA_FREELIST_DEBUG
+static void mga_freelist_print(struct drm_device * dev)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_freelist_t *entry;
+
+       DRM_INFO("\n");
+       DRM_INFO("current dispatch: last=0x%x done=0x%x\n",
+                dev_priv->sarea_priv->last_dispatch,
+                (unsigned int)(MGA_READ(MGA_PRIMADDRESS) -
+                               dev_priv->primary->offset));
+       DRM_INFO("current freelist:\n");
+
+       for (entry = dev_priv->head->next; entry; entry = entry->next) {
+               DRM_INFO("   %p   idx=%2d  age=0x%x 0x%06lx\n",
+                        entry, entry->buf->idx, entry->age.head,
+                        entry->age.head - dev_priv->primary->offset);
+       }
+       DRM_INFO("\n");
+}
+#endif
+
+static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_mga_buf_priv_t *buf_priv;
+       drm_mga_freelist_t *entry;
+       int i;
+       DRM_DEBUG("count=%d\n", dma->buf_count);
+
+       dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+       if (dev_priv->head == NULL)
+               return -ENOMEM;
+
+       memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t));
+       SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0);
+
+       for (i = 0; i < dma->buf_count; i++) {
+               buf = dma->buflist[i];
+               buf_priv = buf->dev_private;
+
+               entry = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+               if (entry == NULL)
+                       return -ENOMEM;
+
+               memset(entry, 0, sizeof(drm_mga_freelist_t));
+
+               entry->next = dev_priv->head->next;
+               entry->prev = dev_priv->head;
+               SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
+               entry->buf = buf;
+
+               if (dev_priv->head->next != NULL)
+                       dev_priv->head->next->prev = entry;
+               if (entry->next == NULL)
+                       dev_priv->tail = entry;
+
+               buf_priv->list_entry = entry;
+               buf_priv->discard = 0;
+               buf_priv->dispatched = 0;
+
+               dev_priv->head->next = entry;
+       }
+
+       return 0;
+}
+
+static void mga_freelist_cleanup(struct drm_device * dev)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_freelist_t *entry;
+       drm_mga_freelist_t *next;
+       DRM_DEBUG("\n");
+
+       entry = dev_priv->head;
+       while (entry) {
+               next = entry->next;
+               drm_free(entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER);
+               entry = next;
+       }
+
+       dev_priv->head = dev_priv->tail = NULL;
+}
+
+#if 0
+/* FIXME: Still needed?
+ */
+static void mga_freelist_reset(struct drm_device * dev)
+{
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_mga_buf_priv_t *buf_priv;
+       int i;
+
+       for (i = 0; i < dma->buf_count; i++) {
+               buf = dma->buflist[i];
+               buf_priv = buf->dev_private;
+               SET_AGE(&buf_priv->list_entry->age, MGA_BUFFER_FREE, 0);
+       }
+}
+#endif
+
+static struct drm_buf *mga_freelist_get(struct drm_device * dev)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_freelist_t *next;
+       drm_mga_freelist_t *prev;
+       drm_mga_freelist_t *tail = dev_priv->tail;
+       u32 head, wrap;
+       DRM_DEBUG("\n");
+
+       head = MGA_READ(MGA_PRIMADDRESS);
+       wrap = dev_priv->sarea_priv->last_wrap;
+
+       DRM_DEBUG("   tail=0x%06lx %d\n",
+                 tail->age.head ?
+                 tail->age.head - dev_priv->primary->offset : 0,
+                 tail->age.wrap);
+       DRM_DEBUG("   head=0x%06lx %d\n",
+                 head - dev_priv->primary->offset, wrap);
+
+       if (TEST_AGE(&tail->age, head, wrap)) {
+               prev = dev_priv->tail->prev;
+               next = dev_priv->tail;
+               prev->next = NULL;
+               next->prev = next->next = NULL;
+               dev_priv->tail = prev;
+               SET_AGE(&next->age, MGA_BUFFER_USED, 0);
+               return next->buf;
+       }
+
+       DRM_DEBUG("returning NULL!\n");
+       return NULL;
+}
+
+int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+       drm_mga_freelist_t *head, *entry, *prev;
+
+       DRM_DEBUG("age=0x%06lx wrap=%d\n",
+                 buf_priv->list_entry->age.head -
+                 dev_priv->primary->offset, buf_priv->list_entry->age.wrap);
+
+       entry = buf_priv->list_entry;
+       head = dev_priv->head;
+
+       if (buf_priv->list_entry->age.head == MGA_BUFFER_USED) {
+               SET_AGE(&entry->age, MGA_BUFFER_FREE, 0);
+               prev = dev_priv->tail;
+               prev->next = entry;
+               entry->prev = prev;
+               entry->next = NULL;
+       } else {
+               prev = head->next;
+               head->next = entry;
+               prev->prev = entry;
+               entry->prev = head;
+               entry->next = prev;
+       }
+
+       return 0;
+}
+
+/* ================================================================
+ * DMA initialization, cleanup
+ */
+
+int mga_driver_load(struct drm_device * dev, unsigned long flags)
+{
+       drm_mga_private_t *dev_priv;
+
+       dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+       if (!dev_priv)
+               return -ENOMEM;
+
+       dev->dev_private = (void *)dev_priv;
+       memset(dev_priv, 0, sizeof(drm_mga_private_t));
+
+       dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
+       dev_priv->chipset = flags;
+
+       dev_priv->mmio_base = drm_get_resource_start(dev, 1);
+       dev_priv->mmio_size = drm_get_resource_len(dev, 1);
+
+       dev->counters += 3;
+       dev->types[6] = _DRM_STAT_IRQ;
+       dev->types[7] = _DRM_STAT_PRIMARY;
+       dev->types[8] = _DRM_STAT_SECONDARY;
+
+       return 0;
+}
+
+#if __OS_HAS_AGP
+/**
+ * Bootstrap the driver for AGP DMA.
+ *
+ * \todo
+ * Investigate whether there is any benifit to storing the WARP microcode in
+ * AGP memory.  If not, the microcode may as well always be put in PCI
+ * memory.
+ *
+ * \todo
+ * This routine needs to set dma_bs->agp_mode to the mode actually configured
+ * in the hardware.  Looking just at the Linux AGP driver code, I don't see
+ * an easy way to determine this.
+ *
+ * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
+ */
+static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
+                                   drm_mga_dma_bootstrap_t * dma_bs)
+{
+       drm_mga_private_t *const dev_priv =
+           (drm_mga_private_t *) dev->dev_private;
+       unsigned int warp_size = mga_warp_microcode_size(dev_priv);
+       int err;
+       unsigned offset;
+       const unsigned secondary_size = dma_bs->secondary_bin_count
+           * dma_bs->secondary_bin_size;
+       const unsigned agp_size = (dma_bs->agp_size << 20);
+       struct drm_buf_desc req;
+       struct drm_agp_mode mode;
+       struct drm_agp_info info;
+       struct drm_agp_buffer agp_req;
+       struct drm_agp_binding bind_req;
+
+       /* Acquire AGP. */
+       err = drm_agp_acquire(dev);
+       if (err) {
+               DRM_ERROR("Unable to acquire AGP: %d\n", err);
+               return err;
+       }
+
+       err = drm_agp_info(dev, &info);
+       if (err) {
+               DRM_ERROR("Unable to get AGP info: %d\n", err);
+               return err;
+       }
+
+       mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode;
+       err = drm_agp_enable(dev, mode);
+       if (err) {
+               DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode);
+               return err;
+       }
+
+       /* In addition to the usual AGP mode configuration, the G200 AGP cards
+        * need to have the AGP mode "manually" set.
+        */
+
+       if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
+               if (mode.mode & 0x02) {
+                       MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
+               } else {
+                       MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
+               }
+       }
+
+       /* Allocate and bind AGP memory. */
+       agp_req.size = agp_size;
+       agp_req.type = 0;
+       err = drm_agp_alloc(dev, &agp_req);
+       if (err) {
+               dev_priv->agp_size = 0;
+               DRM_ERROR("Unable to allocate %uMB AGP memory\n",
+                         dma_bs->agp_size);
+               return err;
+       }
+
+       dev_priv->agp_size = agp_size;
+       dev_priv->agp_handle = agp_req.handle;
+
+       bind_req.handle = agp_req.handle;
+       bind_req.offset = 0;
+       err = drm_agp_bind(dev, &bind_req);
+       if (err) {
+               DRM_ERROR("Unable to bind AGP memory: %d\n", err);
+               return err;
+       }
+
+       /* Make drm_addbufs happy by not trying to create a mapping for less
+        * than a page.
+        */
+       if (warp_size < PAGE_SIZE)
+               warp_size = PAGE_SIZE;
+
+       offset = 0;
+       err = drm_addmap(dev, offset, warp_size,
+                        _DRM_AGP, _DRM_READ_ONLY, &dev_priv->warp);
+       if (err) {
+               DRM_ERROR("Unable to map WARP microcode: %d\n", err);
+               return err;
+       }
+
+       offset += warp_size;
+       err = drm_addmap(dev, offset, dma_bs->primary_size,
+                        _DRM_AGP, _DRM_READ_ONLY, &dev_priv->primary);
+       if (err) {
+               DRM_ERROR("Unable to map primary DMA region: %d\n", err);
+               return err;
+       }
+
+       offset += dma_bs->primary_size;
+       err = drm_addmap(dev, offset, secondary_size,
+                        _DRM_AGP, 0, &dev->agp_buffer_map);
+       if (err) {
+               DRM_ERROR("Unable to map secondary DMA region: %d\n", err);
+               return err;
+       }
+
+       (void)memset(&req, 0, sizeof(req));
+       req.count = dma_bs->secondary_bin_count;
+       req.size = dma_bs->secondary_bin_size;
+       req.flags = _DRM_AGP_BUFFER;
+       req.agp_start = offset;
+
+       err = drm_addbufs_agp(dev, &req);
+       if (err) {
+               DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
+               return err;
+       }
+
+       {
+               struct drm_map_list *_entry;
+               unsigned long agp_token = 0;
+
+               list_for_each_entry(_entry, &dev->maplist, head) {
+                       if (_entry->map == dev->agp_buffer_map)
+                               agp_token = _entry->user_token;
+               }
+               if (!agp_token)
+                       return -EFAULT;
+
+               dev->agp_buffer_token = agp_token;
+       }
+
+       offset += secondary_size;
+       err = drm_addmap(dev, offset, agp_size - offset,
+                        _DRM_AGP, 0, &dev_priv->agp_textures);
+       if (err) {
+               DRM_ERROR("Unable to map AGP texture region %d\n", err);
+               return err;
+       }
+
+       drm_core_ioremap(dev_priv->warp, dev);
+       drm_core_ioremap(dev_priv->primary, dev);
+       drm_core_ioremap(dev->agp_buffer_map, dev);
+
+       if (!dev_priv->warp->handle ||
+           !dev_priv->primary->handle || !dev->agp_buffer_map->handle) {
+               DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n",
+                         dev_priv->warp->handle, dev_priv->primary->handle,
+                         dev->agp_buffer_map->handle);
+               return -ENOMEM;
+       }
+
+       dev_priv->dma_access = MGA_PAGPXFER;
+       dev_priv->wagp_enable = MGA_WAGP_ENABLE;
+
+       DRM_INFO("Initialized card for AGP DMA.\n");
+       return 0;
+}
+#else
+static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
+                                   drm_mga_dma_bootstrap_t * dma_bs)
+{
+       return -EINVAL;
+}
+#endif
+
+/**
+ * Bootstrap the driver for PCI DMA.
+ *
+ * \todo
+ * The algorithm for decreasing the size of the primary DMA buffer could be
+ * better.  The size should be rounded up to the nearest page size, then
+ * decrease the request size by a single page each pass through the loop.
+ *
+ * \todo
+ * Determine whether the maximum address passed to drm_pci_alloc is correct.
+ * The same goes for drm_addbufs_pci.
+ *
+ * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
+ */
+static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
+                                   drm_mga_dma_bootstrap_t * dma_bs)
+{
+       drm_mga_private_t *const dev_priv =
+           (drm_mga_private_t *) dev->dev_private;
+       unsigned int warp_size = mga_warp_microcode_size(dev_priv);
+       unsigned int primary_size;
+       unsigned int bin_count;
+       int err;
+       struct drm_buf_desc req;
+
+       if (dev->dma == NULL) {
+               DRM_ERROR("dev->dma is NULL\n");
+               return -EFAULT;
+       }
+
+       /* Make drm_addbufs happy by not trying to create a mapping for less
+        * than a page.
+        */
+       if (warp_size < PAGE_SIZE)
+               warp_size = PAGE_SIZE;
+
+       /* The proper alignment is 0x100 for this mapping */
+       err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT,
+                        _DRM_READ_ONLY, &dev_priv->warp);
+       if (err != 0) {
+               DRM_ERROR("Unable to create mapping for WARP microcode: %d\n",
+                         err);
+               return err;
+       }
+
+       /* Other than the bottom two bits being used to encode other
+        * information, there don't appear to be any restrictions on the
+        * alignment of the primary or secondary DMA buffers.
+        */
+
+       for (primary_size = dma_bs->primary_size; primary_size != 0;
+            primary_size >>= 1) {
+               /* The proper alignment for this mapping is 0x04 */
+               err = drm_addmap(dev, 0, primary_size, _DRM_CONSISTENT,
+                                _DRM_READ_ONLY, &dev_priv->primary);
+               if (!err)
+                       break;
+       }
+
+       if (err != 0) {
+               DRM_ERROR("Unable to allocate primary DMA region: %d\n", err);
+               return -ENOMEM;
+       }
+
+       if (dev_priv->primary->size != dma_bs->primary_size) {
+               DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n",
+                        dma_bs->primary_size,
+                        (unsigned)dev_priv->primary->size);
+               dma_bs->primary_size = dev_priv->primary->size;
+       }
+
+       for (bin_count = dma_bs->secondary_bin_count; bin_count > 0;
+            bin_count--) {
+               (void)memset(&req, 0, sizeof(req));
+               req.count = bin_count;
+               req.size = dma_bs->secondary_bin_size;
+
+               err = drm_addbufs_pci(dev, &req);
+               if (!err) {
+                       break;
+               }
+       }
+
+       if (bin_count == 0) {
+               DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
+               return err;
+       }
+
+       if (bin_count != dma_bs->secondary_bin_count) {
+               DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u "
+                        "to %u.\n", dma_bs->secondary_bin_count, bin_count);
+
+               dma_bs->secondary_bin_count = bin_count;
+       }
+
+       dev_priv->dma_access = 0;
+       dev_priv->wagp_enable = 0;
+
+       dma_bs->agp_mode = 0;
+
+       DRM_INFO("Initialized card for PCI DMA.\n");
+       return 0;
+}
+
+static int mga_do_dma_bootstrap(struct drm_device * dev,
+                               drm_mga_dma_bootstrap_t * dma_bs)
+{
+       const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
+       int err;
+       drm_mga_private_t *const dev_priv =
+           (drm_mga_private_t *) dev->dev_private;
+
+       dev_priv->used_new_dma_init = 1;
+
+       /* The first steps are the same for both PCI and AGP based DMA.  Map
+        * the cards MMIO registers and map a status page.
+        */
+       err = drm_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size,
+                        _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio);
+       if (err) {
+               DRM_ERROR("Unable to map MMIO region: %d\n", err);
+               return err;
+       }
+
+       err = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM,
+                        _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
+                        &dev_priv->status);
+       if (err) {
+               DRM_ERROR("Unable to map status region: %d\n", err);
+               return err;
+       }
+
+       /* The DMA initialization procedure is slightly different for PCI and
+        * AGP cards.  AGP cards just allocate a large block of AGP memory and
+        * carve off portions of it for internal uses.  The remaining memory
+        * is returned to user-mode to be used for AGP textures.
+        */
+       if (is_agp) {
+               err = mga_do_agp_dma_bootstrap(dev, dma_bs);
+       }
+
+       /* If we attempted to initialize the card for AGP DMA but failed,
+        * clean-up any mess that may have been created.
+        */
+
+       if (err) {
+               mga_do_cleanup_dma(dev, MINIMAL_CLEANUP);
+       }
+
+       /* Not only do we want to try and initialized PCI cards for PCI DMA,
+        * but we also try to initialized AGP cards that could not be
+        * initialized for AGP DMA.  This covers the case where we have an AGP
+        * card in a system with an unsupported AGP chipset.  In that case the
+        * card will be detected as AGP, but we won't be able to allocate any
+        * AGP memory, etc.
+        */
+
+       if (!is_agp || err) {
+               err = mga_do_pci_dma_bootstrap(dev, dma_bs);
+       }
+
+       return err;
+}
+
+int mga_dma_bootstrap(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv)
+{
+       drm_mga_dma_bootstrap_t *bootstrap = data;
+       int err;
+       static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 };
+       const drm_mga_private_t *const dev_priv =
+               (drm_mga_private_t *) dev->dev_private;
+
+       err = mga_do_dma_bootstrap(dev, bootstrap);
+       if (err) {
+               mga_do_cleanup_dma(dev, FULL_CLEANUP);
+               return err;
+       }
+
+       if (dev_priv->agp_textures != NULL) {
+               bootstrap->texture_handle = dev_priv->agp_textures->offset;
+               bootstrap->texture_size = dev_priv->agp_textures->size;
+       } else {
+               bootstrap->texture_handle = 0;
+               bootstrap->texture_size = 0;
+       }
+
+       bootstrap->agp_mode = modes[bootstrap->agp_mode & 0x07];
+
+       return err;
+}
+
+static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init)
+{
+       drm_mga_private_t *dev_priv;
+       int ret;
+       DRM_DEBUG("\n");
+
+       dev_priv = dev->dev_private;
+
+       if (init->sgram) {
+               dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
+       } else {
+               dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
+       }
+       dev_priv->maccess = init->maccess;
+
+       dev_priv->fb_cpp = init->fb_cpp;
+       dev_priv->front_offset = init->front_offset;
+       dev_priv->front_pitch = init->front_pitch;
+       dev_priv->back_offset = init->back_offset;
+       dev_priv->back_pitch = init->back_pitch;
+
+       dev_priv->depth_cpp = init->depth_cpp;
+       dev_priv->depth_offset = init->depth_offset;
+       dev_priv->depth_pitch = init->depth_pitch;
+
+       /* FIXME: Need to support AGP textures...
+        */
+       dev_priv->texture_offset = init->texture_offset[0];
+       dev_priv->texture_size = init->texture_size[0];
+
+       dev_priv->sarea = drm_getsarea(dev);
+       if (!dev_priv->sarea) {
+               DRM_ERROR("failed to find sarea!\n");
+               return -EINVAL;
+       }
+
+       if (!dev_priv->used_new_dma_init) {
+
+               dev_priv->dma_access = MGA_PAGPXFER;
+               dev_priv->wagp_enable = MGA_WAGP_ENABLE;
+
+               dev_priv->status = drm_core_findmap(dev, init->status_offset);
+               if (!dev_priv->status) {
+                       DRM_ERROR("failed to find status page!\n");
+                       return -EINVAL;
+               }
+               dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+               if (!dev_priv->mmio) {
+                       DRM_ERROR("failed to find mmio region!\n");
+                       return -EINVAL;
+               }
+               dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
+               if (!dev_priv->warp) {
+                       DRM_ERROR("failed to find warp microcode region!\n");
+                       return -EINVAL;
+               }
+               dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
+               if (!dev_priv->primary) {
+                       DRM_ERROR("failed to find primary dma region!\n");
+                       return -EINVAL;
+               }
+               dev->agp_buffer_token = init->buffers_offset;
+               dev->agp_buffer_map =
+                   drm_core_findmap(dev, init->buffers_offset);
+               if (!dev->agp_buffer_map) {
+                       DRM_ERROR("failed to find dma buffer region!\n");
+                       return -EINVAL;
+               }
+
+               drm_core_ioremap(dev_priv->warp, dev);
+               drm_core_ioremap(dev_priv->primary, dev);
+               drm_core_ioremap(dev->agp_buffer_map, dev);
+       }
+
+       dev_priv->sarea_priv =
+           (drm_mga_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+                                init->sarea_priv_offset);
+
+       if (!dev_priv->warp->handle ||
+           !dev_priv->primary->handle ||
+           ((dev_priv->dma_access != 0) &&
+            ((dev->agp_buffer_map == NULL) ||
+             (dev->agp_buffer_map->handle == NULL)))) {
+               DRM_ERROR("failed to ioremap agp regions!\n");
+               return -ENOMEM;
+       }
+
+       ret = mga_warp_install_microcode(dev_priv);
+       if (ret < 0) {
+               DRM_ERROR("failed to install WARP ucode!: %d\n", ret);
+               return ret;
+       }
+
+       ret = mga_warp_init(dev_priv);
+       if (ret < 0) {
+               DRM_ERROR("failed to init WARP engine!: %d\n", ret);
+               return ret;
+       }
+
+       dev_priv->prim.status = (u32 *) dev_priv->status->handle;
+
+       mga_do_wait_for_idle(dev_priv);
+
+       /* Init the primary DMA registers.
+        */
+       MGA_WRITE(MGA_PRIMADDRESS, dev_priv->primary->offset | MGA_DMA_GENERAL);
+#if 0
+       MGA_WRITE(MGA_PRIMPTR, virt_to_bus((void *)dev_priv->prim.status) | MGA_PRIMPTREN0 |    /* Soft trap, SECEND, SETUPEND */
+                 MGA_PRIMPTREN1);      /* DWGSYNC */
+#endif
+
+       dev_priv->prim.start = (u8 *) dev_priv->primary->handle;
+       dev_priv->prim.end = ((u8 *) dev_priv->primary->handle
+                             + dev_priv->primary->size);
+       dev_priv->prim.size = dev_priv->primary->size;
+
+       dev_priv->prim.tail = 0;
+       dev_priv->prim.space = dev_priv->prim.size;
+       dev_priv->prim.wrapped = 0;
+
+       dev_priv->prim.last_flush = 0;
+       dev_priv->prim.last_wrap = 0;
+
+       dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;
+
+       dev_priv->prim.status[0] = dev_priv->primary->offset;
+       dev_priv->prim.status[1] = 0;
+
+       dev_priv->sarea_priv->last_wrap = 0;
+       dev_priv->sarea_priv->last_frame.head = 0;
+       dev_priv->sarea_priv->last_frame.wrap = 0;
+
+       if (mga_freelist_init(dev, dev_priv) < 0) {
+               DRM_ERROR("could not initialize freelist\n");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
+{
+       int err = 0;
+       DRM_DEBUG("\n");
+
+       /* Make sure interrupts are disabled here because the uninstall ioctl
+        * may not have been called from userspace and after dev_private
+        * is freed, it's too late.
+        */
+       if (dev->irq_enabled)
+               drm_irq_uninstall(dev);
+
+       if (dev->dev_private) {
+               drm_mga_private_t *dev_priv = dev->dev_private;
+
+               if ((dev_priv->warp != NULL)
+                   && (dev_priv->warp->type != _DRM_CONSISTENT))
+                       drm_core_ioremapfree(dev_priv->warp, dev);
+
+               if ((dev_priv->primary != NULL)
+                   && (dev_priv->primary->type != _DRM_CONSISTENT))
+                       drm_core_ioremapfree(dev_priv->primary, dev);
+
+               if (dev->agp_buffer_map != NULL)
+                       drm_core_ioremapfree(dev->agp_buffer_map, dev);
+
+               if (dev_priv->used_new_dma_init) {
+#if __OS_HAS_AGP
+                       if (dev_priv->agp_handle != 0) {
+                               struct drm_agp_binding unbind_req;
+                               struct drm_agp_buffer free_req;
+
+                               unbind_req.handle = dev_priv->agp_handle;
+                               drm_agp_unbind(dev, &unbind_req);
+
+                               free_req.handle = dev_priv->agp_handle;
+                               drm_agp_free(dev, &free_req);
+
+                               dev_priv->agp_textures = NULL;
+                               dev_priv->agp_size = 0;
+                               dev_priv->agp_handle = 0;
+                       }
+
+                       if ((dev->agp != NULL) && dev->agp->acquired) {
+                               err = drm_agp_release(dev);
+                       }
+#endif
+               }
+
+               dev_priv->warp = NULL;
+               dev_priv->primary = NULL;
+               dev_priv->sarea = NULL;
+               dev_priv->sarea_priv = NULL;
+               dev->agp_buffer_map = NULL;
+
+               if (full_cleanup) {
+                       dev_priv->mmio = NULL;
+                       dev_priv->status = NULL;
+                       dev_priv->used_new_dma_init = 0;
+               }
+
+               memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
+               dev_priv->warp_pipe = 0;
+               memset(dev_priv->warp_pipe_phys, 0,
+                      sizeof(dev_priv->warp_pipe_phys));
+
+               if (dev_priv->head != NULL) {
+                       mga_freelist_cleanup(dev);
+               }
+       }
+
+       return err;
+}
+
+int mga_dma_init(struct drm_device *dev, void *data,
+                struct drm_file *file_priv)
+{
+       drm_mga_init_t *init = data;
+       int err;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       switch (init->func) {
+       case MGA_INIT_DMA:
+               err = mga_do_init_dma(dev, init);
+               if (err) {
+                       (void)mga_do_cleanup_dma(dev, FULL_CLEANUP);
+               }
+               return err;
+       case MGA_CLEANUP_DMA:
+               return mga_do_cleanup_dma(dev, FULL_CLEANUP);
+       }
+
+       return -EINVAL;
+}
+
+/* ================================================================
+ * Primary DMA stream management
+ */
+
+int mga_dma_flush(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
+{
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+       struct drm_lock *lock = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       DRM_DEBUG("%s%s%s\n",
+                 (lock->flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
+                 (lock->flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
+                 (lock->flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "");
+
+       WRAP_WAIT_WITH_RETURN(dev_priv);
+
+       if (lock->flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) {
+               mga_do_dma_flush(dev_priv);
+       }
+
+       if (lock->flags & _DRM_LOCK_QUIESCENT) {
+#if MGA_DMA_DEBUG
+               int ret = mga_do_wait_for_idle(dev_priv);
+               if (ret < 0)
+                       DRM_INFO("-EBUSY\n");
+               return ret;
+#else
+               return mga_do_wait_for_idle(dev_priv);
+#endif
+       } else {
+               return 0;
+       }
+}
+
+int mga_dma_reset(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
+{
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       return mga_do_dma_reset(dev_priv);
+}
+
+/* ================================================================
+ * DMA buffer management
+ */
+
+static int mga_dma_get_buffers(struct drm_device * dev,
+                              struct drm_file *file_priv, struct drm_dma * d)
+{
+       struct drm_buf *buf;
+       int i;
+
+       for (i = d->granted_count; i < d->request_count; i++) {
+               buf = mga_freelist_get(dev);
+               if (!buf)
+                       return -EAGAIN;
+
+               buf->file_priv = file_priv;
+
+               if (DRM_COPY_TO_USER(&d->request_indices[i],
+                                    &buf->idx, sizeof(buf->idx)))
+                       return -EFAULT;
+               if (DRM_COPY_TO_USER(&d->request_sizes[i],
+                                    &buf->total, sizeof(buf->total)))
+                       return -EFAULT;
+
+               d->granted_count++;
+       }
+       return 0;
+}
+
+int mga_dma_buffers(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+       struct drm_dma *d = data;
+       int ret = 0;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       /* Please don't send us buffers.
+        */
+       if (d->send_count != 0) {
+               DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+                         DRM_CURRENTPID, d->send_count);
+               return -EINVAL;
+       }
+
+       /* We'll send you buffers.
+        */
+       if (d->request_count < 0 || d->request_count > dma->buf_count) {
+               DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+                         DRM_CURRENTPID, d->request_count, dma->buf_count);
+               return -EINVAL;
+       }
+
+       WRAP_TEST_WITH_RETURN(dev_priv);
+
+       d->granted_count = 0;
+
+       if (d->request_count) {
+               ret = mga_dma_get_buffers(dev, file_priv, d);
+       }
+
+       return ret;
+}
+
+/**
+ * Called just before the module is unloaded.
+ */
+int mga_driver_unload(struct drm_device * dev)
+{
+       drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+       dev->dev_private = NULL;
+
+       return 0;
+}
+
+/**
+ * Called when the last opener of the device is closed.
+ */
+void mga_driver_lastclose(struct drm_device * dev)
+{
+       mga_do_cleanup_dma(dev, FULL_CLEANUP);
+}
+
+int mga_driver_dma_quiescent(struct drm_device * dev)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       return mga_do_wait_for_idle(dev_priv);
+}
diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c
new file mode 100644 (file)
index 0000000..5572939
--- /dev/null
@@ -0,0 +1,141 @@
+/* mga_drv.c -- Matrox G200/G400 driver -*- linux-c -*-
+ * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
+#include "mga_drv.h"
+
+#include "drm_pciids.h"
+
+static int mga_driver_device_is_agp(struct drm_device * dev);
+
+static struct pci_device_id pciidlist[] = {
+       mga_PCI_IDS
+};
+
+static struct drm_driver driver = {
+       .driver_features =
+           DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
+           DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
+           DRIVER_IRQ_VBL,
+       .dev_priv_size = sizeof(drm_mga_buf_priv_t),
+       .load = mga_driver_load,
+       .unload = mga_driver_unload,
+       .lastclose = mga_driver_lastclose,
+       .dma_quiescent = mga_driver_dma_quiescent,
+       .device_is_agp = mga_driver_device_is_agp,
+       .vblank_wait = mga_driver_vblank_wait,
+       .irq_preinstall = mga_driver_irq_preinstall,
+       .irq_postinstall = mga_driver_irq_postinstall,
+       .irq_uninstall = mga_driver_irq_uninstall,
+       .irq_handler = mga_driver_irq_handler,
+       .reclaim_buffers = drm_core_reclaim_buffers,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .ioctls = mga_ioctls,
+       .dma_ioctl = mga_dma_buffers,
+       .fops = {
+                .owner = THIS_MODULE,
+                .open = drm_open,
+                .release = drm_release,
+                .ioctl = drm_ioctl,
+                .mmap = drm_mmap,
+                .poll = drm_poll,
+                .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+                .compat_ioctl = mga_compat_ioctl,
+#endif
+                },
+       .pci_driver = {
+                .name = DRIVER_NAME,
+                .id_table = pciidlist,
+       },
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int __init mga_init(void)
+{
+       driver.num_ioctls = mga_max_ioctl;
+       return drm_init(&driver);
+}
+
+static void __exit mga_exit(void)
+{
+       drm_exit(&driver);
+}
+
+module_init(mga_init);
+module_exit(mga_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
+
+/**
+ * Determine if the device really is AGP or not.
+ *
+ * In addition to the usual tests performed by \c drm_device_is_agp, this
+ * function detects PCI G450 cards that appear to the system exactly like
+ * AGP G450 cards.
+ *
+ * \param dev   The device to be tested.
+ *
+ * \returns
+ * If the device is a PCI G450, zero is returned.  Otherwise 2 is returned.
+ */
+static int mga_driver_device_is_agp(struct drm_device * dev)
+{
+       const struct pci_dev *const pdev = dev->pdev;
+
+       /* There are PCI versions of the G450.  These cards have the
+        * same PCI ID as the AGP G450, but have an additional PCI-to-PCI
+        * bridge chip.  We detect these cards, which are not currently
+        * supported by this driver, by looking at the device ID of the
+        * bus the "card" is on.  If vendor is 0x3388 (Hint Corp) and the
+        * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the
+        * device.
+        */
+
+       if ((pdev->device == 0x0525) && pdev->bus->self
+           && (pdev->bus->self->vendor == 0x3388)
+           && (pdev->bus->self->device == 0x0021)) {
+               return 0;
+       }
+
+       return 2;
+}
diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h
new file mode 100644 (file)
index 0000000..f6ebd24
--- /dev/null
@@ -0,0 +1,687 @@
+/* mga_drv.h -- Private header for the Matrox G200/G400 driver -*- linux-c -*-
+ * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __MGA_DRV_H__
+#define __MGA_DRV_H__
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR          "Gareth Hughes, VA Linux Systems Inc."
+
+#define DRIVER_NAME            "mga"
+#define DRIVER_DESC            "Matrox G200/G400"
+#define DRIVER_DATE            "20051102"
+
+#define DRIVER_MAJOR           3
+#define DRIVER_MINOR           2
+#define DRIVER_PATCHLEVEL      1
+
+typedef struct drm_mga_primary_buffer {
+       u8 *start;
+       u8 *end;
+       int size;
+
+       u32 tail;
+       int space;
+       volatile long wrapped;
+
+       volatile u32 *status;
+
+       u32 last_flush;
+       u32 last_wrap;
+
+       u32 high_mark;
+} drm_mga_primary_buffer_t;
+
+typedef struct drm_mga_freelist {
+       struct drm_mga_freelist *next;
+       struct drm_mga_freelist *prev;
+       drm_mga_age_t age;
+       struct drm_buf *buf;
+} drm_mga_freelist_t;
+
+typedef struct {
+       drm_mga_freelist_t *list_entry;
+       int discard;
+       int dispatched;
+} drm_mga_buf_priv_t;
+
+typedef struct drm_mga_private {
+       drm_mga_primary_buffer_t prim;
+       drm_mga_sarea_t *sarea_priv;
+
+       drm_mga_freelist_t *head;
+       drm_mga_freelist_t *tail;
+
+       unsigned int warp_pipe;
+       unsigned long warp_pipe_phys[MGA_MAX_WARP_PIPES];
+
+       int chipset;
+       int usec_timeout;
+
+       /**
+        * If set, the new DMA initialization sequence was used.  This is
+        * primarilly used to select how the driver should uninitialized its
+        * internal DMA structures.
+        */
+       int used_new_dma_init;
+
+       /**
+        * If AGP memory is used for DMA buffers, this will be the value
+        * \c MGA_PAGPXFER.  Otherwise, it will be zero (for a PCI transfer).
+        */
+       u32 dma_access;
+
+       /**
+        * If AGP memory is used for DMA buffers, this will be the value
+        * \c MGA_WAGP_ENABLE.  Otherwise, it will be zero (for a PCI
+        * transfer).
+        */
+       u32 wagp_enable;
+
+       /**
+        * \name MMIO region parameters.
+        *
+        * \sa drm_mga_private_t::mmio
+        */
+       /*@{ */
+       u32 mmio_base;             /**< Bus address of base of MMIO. */
+       u32 mmio_size;             /**< Size of the MMIO region. */
+       /*@} */
+
+       u32 clear_cmd;
+       u32 maccess;
+
+       wait_queue_head_t fence_queue;
+       atomic_t last_fence_retired;
+       u32 next_fence_to_post;
+
+       unsigned int fb_cpp;
+       unsigned int front_offset;
+       unsigned int front_pitch;
+       unsigned int back_offset;
+       unsigned int back_pitch;
+
+       unsigned int depth_cpp;
+       unsigned int depth_offset;
+       unsigned int depth_pitch;
+
+       unsigned int texture_offset;
+       unsigned int texture_size;
+
+       drm_local_map_t *sarea;
+       drm_local_map_t *mmio;
+       drm_local_map_t *status;
+       drm_local_map_t *warp;
+       drm_local_map_t *primary;
+       drm_local_map_t *agp_textures;
+
+       unsigned long agp_handle;
+       unsigned int agp_size;
+} drm_mga_private_t;
+
+extern struct drm_ioctl_desc mga_ioctls[];
+extern int mga_max_ioctl;
+
+                               /* mga_dma.c */
+extern int mga_dma_bootstrap(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv);
+extern int mga_dma_init(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int mga_dma_flush(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int mga_dma_reset(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int mga_dma_buffers(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int mga_driver_load(struct drm_device *dev, unsigned long flags);
+extern int mga_driver_unload(struct drm_device * dev);
+extern void mga_driver_lastclose(struct drm_device * dev);
+extern int mga_driver_dma_quiescent(struct drm_device * dev);
+
+extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
+
+extern void mga_do_dma_flush(drm_mga_private_t * dev_priv);
+extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv);
+extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
+
+extern int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf);
+
+                               /* mga_warp.c */
+extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
+extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
+extern int mga_warp_init(drm_mga_private_t * dev_priv);
+
+                               /* mga_irq.c */
+extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
+extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
+extern void mga_driver_irq_preinstall(struct drm_device * dev);
+extern void mga_driver_irq_postinstall(struct drm_device * dev);
+extern void mga_driver_irq_uninstall(struct drm_device * dev);
+extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
+                            unsigned long arg);
+
+#define mga_flush_write_combine()      DRM_WRITEMEMORYBARRIER()
+
+#if defined(__linux__) && defined(__alpha__)
+#define MGA_BASE( reg )                ((unsigned long)(dev_priv->mmio->handle))
+#define MGA_ADDR( reg )                (MGA_BASE(reg) + reg)
+
+#define MGA_DEREF( reg )       *(volatile u32 *)MGA_ADDR( reg )
+#define MGA_DEREF8( reg )      *(volatile u8 *)MGA_ADDR( reg )
+
+#define MGA_READ( reg )                (_MGA_READ((u32 *)MGA_ADDR(reg)))
+#define MGA_READ8( reg )       (_MGA_READ((u8 *)MGA_ADDR(reg)))
+#define MGA_WRITE( reg, val )  do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF( reg ) = val; } while (0)
+#define MGA_WRITE8( reg, val )  do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8( reg ) = val; } while (0)
+
+static inline u32 _MGA_READ(u32 * addr)
+{
+       DRM_MEMORYBARRIER();
+       return *(volatile u32 *)addr;
+}
+#else
+#define MGA_READ8( reg )       DRM_READ8(dev_priv->mmio, (reg))
+#define MGA_READ( reg )                DRM_READ32(dev_priv->mmio, (reg))
+#define MGA_WRITE8( reg, val )  DRM_WRITE8(dev_priv->mmio, (reg), (val))
+#define MGA_WRITE( reg, val )  DRM_WRITE32(dev_priv->mmio, (reg), (val))
+#endif
+
+#define DWGREG0                0x1c00
+#define DWGREG0_END    0x1dff
+#define DWGREG1                0x2c00
+#define DWGREG1_END    0x2dff
+
+#define ISREG0(r)      (r >= DWGREG0 && r <= DWGREG0_END)
+#define DMAREG0(r)     (u8)((r - DWGREG0) >> 2)
+#define DMAREG1(r)     (u8)(((r - DWGREG1) >> 2) | 0x80)
+#define DMAREG(r)      (ISREG0(r) ? DMAREG0(r) : DMAREG1(r))
+
+/* ================================================================
+ * Helper macross...
+ */
+
+#define MGA_EMIT_STATE( dev_priv, dirty )                              \
+do {                                                                   \
+       if ( (dirty) & ~MGA_UPLOAD_CLIPRECTS ) {                        \
+               if ( dev_priv->chipset >= MGA_CARD_TYPE_G400 ) {        \
+                       mga_g400_emit_state( dev_priv );                \
+               } else {                                                \
+                       mga_g200_emit_state( dev_priv );                \
+               }                                                       \
+       }                                                               \
+} while (0)
+
+#define WRAP_TEST_WITH_RETURN( dev_priv )                              \
+do {                                                                   \
+       if ( test_bit( 0, &dev_priv->prim.wrapped ) ) {                 \
+               if ( mga_is_idle( dev_priv ) ) {                        \
+                       mga_do_dma_wrap_end( dev_priv );                \
+               } else if ( dev_priv->prim.space <                      \
+                           dev_priv->prim.high_mark ) {                \
+                       if ( MGA_DMA_DEBUG )                            \
+                               DRM_INFO( "wrap...\n");         \
+                       return -EBUSY;                  \
+               }                                                       \
+       }                                                               \
+} while (0)
+
+#define WRAP_WAIT_WITH_RETURN( dev_priv )                              \
+do {                                                                   \
+       if ( test_bit( 0, &dev_priv->prim.wrapped ) ) {                 \
+               if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {           \
+                       if ( MGA_DMA_DEBUG )                            \
+                               DRM_INFO( "wrap...\n");         \
+                       return -EBUSY;                  \
+               }                                                       \
+               mga_do_dma_wrap_end( dev_priv );                        \
+       }                                                               \
+} while (0)
+
+/* ================================================================
+ * Primary DMA command stream
+ */
+
+#define MGA_VERBOSE    0
+
+#define DMA_LOCALS     unsigned int write; volatile u8 *prim;
+
+#define DMA_BLOCK_SIZE (5 * sizeof(u32))
+
+#define BEGIN_DMA( n )                                                 \
+do {                                                                   \
+       if ( MGA_VERBOSE ) {                                            \
+               DRM_INFO( "BEGIN_DMA( %d )\n", (n) );           \
+               DRM_INFO( "   space=0x%x req=0x%Zx\n",                  \
+                         dev_priv->prim.space, (n) * DMA_BLOCK_SIZE ); \
+       }                                                               \
+       prim = dev_priv->prim.start;                                    \
+       write = dev_priv->prim.tail;                                    \
+} while (0)
+
+#define BEGIN_DMA_WRAP()                                               \
+do {                                                                   \
+       if ( MGA_VERBOSE ) {                                            \
+               DRM_INFO( "BEGIN_DMA()\n" );                            \
+               DRM_INFO( "   space=0x%x\n", dev_priv->prim.space );    \
+       }                                                               \
+       prim = dev_priv->prim.start;                                    \
+       write = dev_priv->prim.tail;                                    \
+} while (0)
+
+#define ADVANCE_DMA()                                                  \
+do {                                                                   \
+       dev_priv->prim.tail = write;                                    \
+       if ( MGA_VERBOSE ) {                                            \
+               DRM_INFO( "ADVANCE_DMA() tail=0x%05x sp=0x%x\n",        \
+                         write, dev_priv->prim.space );                \
+       }                                                               \
+} while (0)
+
+#define FLUSH_DMA()                                                    \
+do {                                                                   \
+       if ( 0 ) {                                                      \
+               DRM_INFO( "\n" );                                       \
+               DRM_INFO( "   tail=0x%06x head=0x%06lx\n",              \
+                         dev_priv->prim.tail,                          \
+                         MGA_READ( MGA_PRIMADDRESS ) -                 \
+                         dev_priv->primary->offset );                  \
+       }                                                               \
+       if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) {                \
+               if ( dev_priv->prim.space <                             \
+                    dev_priv->prim.high_mark ) {                       \
+                       mga_do_dma_wrap_start( dev_priv );              \
+               } else {                                                \
+                       mga_do_dma_flush( dev_priv );                   \
+               }                                                       \
+       }                                                               \
+} while (0)
+
+/* Never use this, always use DMA_BLOCK(...) for primary DMA output.
+ */
+#define DMA_WRITE( offset, val )                                       \
+do {                                                                   \
+       if ( MGA_VERBOSE ) {                                            \
+               DRM_INFO( "   DMA_WRITE( 0x%08x ) at 0x%04Zx\n",        \
+                         (u32)(val), write + (offset) * sizeof(u32) ); \
+       }                                                               \
+       *(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \
+} while (0)
+
+#define DMA_BLOCK( reg0, val0, reg1, val1, reg2, val2, reg3, val3 )    \
+do {                                                                   \
+       DMA_WRITE( 0, ((DMAREG( reg0 ) << 0) |                          \
+                      (DMAREG( reg1 ) << 8) |                          \
+                      (DMAREG( reg2 ) << 16) |                         \
+                      (DMAREG( reg3 ) << 24)) );                       \
+       DMA_WRITE( 1, val0 );                                           \
+       DMA_WRITE( 2, val1 );                                           \
+       DMA_WRITE( 3, val2 );                                           \
+       DMA_WRITE( 4, val3 );                                           \
+       write += DMA_BLOCK_SIZE;                                        \
+} while (0)
+
+/* Buffer aging via primary DMA stream head pointer.
+ */
+
+#define SET_AGE( age, h, w )                                           \
+do {                                                                   \
+       (age)->head = h;                                                \
+       (age)->wrap = w;                                                \
+} while (0)
+
+#define TEST_AGE( age, h, w )          ( (age)->wrap < w ||            \
+                                         ( (age)->wrap == w &&         \
+                                           (age)->head < h ) )
+
+#define AGE_BUFFER( buf_priv )                                         \
+do {                                                                   \
+       drm_mga_freelist_t *entry = (buf_priv)->list_entry;             \
+       if ( (buf_priv)->dispatched ) {                                 \
+               entry->age.head = (dev_priv->prim.tail +                \
+                                  dev_priv->primary->offset);          \
+               entry->age.wrap = dev_priv->sarea_priv->last_wrap;      \
+       } else {                                                        \
+               entry->age.head = 0;                                    \
+               entry->age.wrap = 0;                                    \
+       }                                                               \
+} while (0)
+
+#define MGA_ENGINE_IDLE_MASK           (MGA_SOFTRAPEN |                \
+                                        MGA_DWGENGSTS |                \
+                                        MGA_ENDPRDMASTS)
+#define MGA_DMA_IDLE_MASK              (MGA_SOFTRAPEN |                \
+                                        MGA_ENDPRDMASTS)
+
+#define MGA_DMA_DEBUG                  0
+
+/* A reduced set of the mga registers.
+ */
+#define MGA_CRTC_INDEX                 0x1fd4
+#define MGA_CRTC_DATA                  0x1fd5
+
+/* CRTC11 */
+#define MGA_VINTCLR                    (1 << 4)
+#define MGA_VINTEN                     (1 << 5)
+
+#define MGA_ALPHACTRL                  0x2c7c
+#define MGA_AR0                                0x1c60
+#define MGA_AR1                                0x1c64
+#define MGA_AR2                                0x1c68
+#define MGA_AR3                                0x1c6c
+#define MGA_AR4                                0x1c70
+#define MGA_AR5                                0x1c74
+#define MGA_AR6                                0x1c78
+
+#define MGA_CXBNDRY                    0x1c80
+#define MGA_CXLEFT                     0x1ca0
+#define MGA_CXRIGHT                    0x1ca4
+
+#define MGA_DMAPAD                     0x1c54
+#define MGA_DSTORG                     0x2cb8
+#define MGA_DWGCTL                     0x1c00
+#      define MGA_OPCOD_MASK                   (15 << 0)
+#      define MGA_OPCOD_TRAP                   (4 << 0)
+#      define MGA_OPCOD_TEXTURE_TRAP           (6 << 0)
+#      define MGA_OPCOD_BITBLT                 (8 << 0)
+#      define MGA_OPCOD_ILOAD                  (9 << 0)
+#      define MGA_ATYPE_MASK                   (7 << 4)
+#      define MGA_ATYPE_RPL                    (0 << 4)
+#      define MGA_ATYPE_RSTR                   (1 << 4)
+#      define MGA_ATYPE_ZI                     (3 << 4)
+#      define MGA_ATYPE_BLK                    (4 << 4)
+#      define MGA_ATYPE_I                      (7 << 4)
+#      define MGA_LINEAR                       (1 << 7)
+#      define MGA_ZMODE_MASK                   (7 << 8)
+#      define MGA_ZMODE_NOZCMP                 (0 << 8)
+#      define MGA_ZMODE_ZE                     (2 << 8)
+#      define MGA_ZMODE_ZNE                    (3 << 8)
+#      define MGA_ZMODE_ZLT                    (4 << 8)
+#      define MGA_ZMODE_ZLTE                   (5 << 8)
+#      define MGA_ZMODE_ZGT                    (6 << 8)
+#      define MGA_ZMODE_ZGTE                   (7 << 8)
+#      define MGA_SOLID                        (1 << 11)
+#      define MGA_ARZERO                       (1 << 12)
+#      define MGA_SGNZERO                      (1 << 13)
+#      define MGA_SHIFTZERO                    (1 << 14)
+#      define MGA_BOP_MASK                     (15 << 16)
+#      define MGA_BOP_ZERO                     (0 << 16)
+#      define MGA_BOP_DST                      (10 << 16)
+#      define MGA_BOP_SRC                      (12 << 16)
+#      define MGA_BOP_ONE                      (15 << 16)
+#      define MGA_TRANS_SHIFT                  20
+#      define MGA_TRANS_MASK                   (15 << 20)
+#      define MGA_BLTMOD_MASK                  (15 << 25)
+#      define MGA_BLTMOD_BMONOLEF              (0 << 25)
+#      define MGA_BLTMOD_BMONOWF               (4 << 25)
+#      define MGA_BLTMOD_PLAN                  (1 << 25)
+#      define MGA_BLTMOD_BFCOL                 (2 << 25)
+#      define MGA_BLTMOD_BU32BGR               (3 << 25)
+#      define MGA_BLTMOD_BU32RGB               (7 << 25)
+#      define MGA_BLTMOD_BU24BGR               (11 << 25)
+#      define MGA_BLTMOD_BU24RGB               (15 << 25)
+#      define MGA_PATTERN                      (1 << 29)
+#      define MGA_TRANSC                       (1 << 30)
+#      define MGA_CLIPDIS                      (1 << 31)
+#define MGA_DWGSYNC                    0x2c4c
+
+#define MGA_FCOL                       0x1c24
+#define MGA_FIFOSTATUS                 0x1e10
+#define MGA_FOGCOL                     0x1cf4
+#define MGA_FXBNDRY                    0x1c84
+#define MGA_FXLEFT                     0x1ca8
+#define MGA_FXRIGHT                    0x1cac
+
+#define MGA_ICLEAR                     0x1e18
+#      define MGA_SOFTRAPICLR                  (1 << 0)
+#      define MGA_VLINEICLR                    (1 << 5)
+#define MGA_IEN                                0x1e1c
+#      define MGA_SOFTRAPIEN                   (1 << 0)
+#      define MGA_VLINEIEN                     (1 << 5)
+
+#define MGA_LEN                                0x1c5c
+
+#define MGA_MACCESS                    0x1c04
+
+#define MGA_PITCH                      0x1c8c
+#define MGA_PLNWT                      0x1c1c
+#define MGA_PRIMADDRESS                        0x1e58
+#      define MGA_DMA_GENERAL                  (0 << 0)
+#      define MGA_DMA_BLIT                     (1 << 0)
+#      define MGA_DMA_VECTOR                   (2 << 0)
+#      define MGA_DMA_VERTEX                   (3 << 0)
+#define MGA_PRIMEND                    0x1e5c
+#      define MGA_PRIMNOSTART                  (1 << 0)
+#      define MGA_PAGPXFER                     (1 << 1)
+#define MGA_PRIMPTR                    0x1e50
+#      define MGA_PRIMPTREN0                   (1 << 0)
+#      define MGA_PRIMPTREN1                   (1 << 1)
+
+#define MGA_RST                                0x1e40
+#      define MGA_SOFTRESET                    (1 << 0)
+#      define MGA_SOFTEXTRST                   (1 << 1)
+
+#define MGA_SECADDRESS                 0x2c40
+#define MGA_SECEND                     0x2c44
+#define MGA_SETUPADDRESS               0x2cd0
+#define MGA_SETUPEND                   0x2cd4
+#define MGA_SGN                                0x1c58
+#define MGA_SOFTRAP                    0x2c48
+#define MGA_SRCORG                     0x2cb4
+#      define MGA_SRMMAP_MASK                  (1 << 0)
+#      define MGA_SRCMAP_FB                    (0 << 0)
+#      define MGA_SRCMAP_SYSMEM                (1 << 0)
+#      define MGA_SRCACC_MASK                  (1 << 1)
+#      define MGA_SRCACC_PCI                   (0 << 1)
+#      define MGA_SRCACC_AGP                   (1 << 1)
+#define MGA_STATUS                     0x1e14
+#      define MGA_SOFTRAPEN                    (1 << 0)
+#      define MGA_VSYNCPEN                     (1 << 4)
+#      define MGA_VLINEPEN                     (1 << 5)
+#      define MGA_DWGENGSTS                    (1 << 16)
+#      define MGA_ENDPRDMASTS                  (1 << 17)
+#define MGA_STENCIL                    0x2cc8
+#define MGA_STENCILCTL                 0x2ccc
+
+#define MGA_TDUALSTAGE0                        0x2cf8
+#define MGA_TDUALSTAGE1                        0x2cfc
+#define MGA_TEXBORDERCOL               0x2c5c
+#define MGA_TEXCTL                     0x2c30
+#define MGA_TEXCTL2                    0x2c3c
+#      define MGA_DUALTEX                      (1 << 7)
+#      define MGA_G400_TC2_MAGIC               (1 << 15)
+#      define MGA_MAP1_ENABLE                  (1 << 31)
+#define MGA_TEXFILTER                  0x2c58
+#define MGA_TEXHEIGHT                  0x2c2c
+#define MGA_TEXORG                     0x2c24
+#      define MGA_TEXORGMAP_MASK               (1 << 0)
+#      define MGA_TEXORGMAP_FB                 (0 << 0)
+#      define MGA_TEXORGMAP_SYSMEM             (1 << 0)
+#      define MGA_TEXORGACC_MASK               (1 << 1)
+#      define MGA_TEXORGACC_PCI                (0 << 1)
+#      define MGA_TEXORGACC_AGP                (1 << 1)
+#define MGA_TEXORG1                    0x2ca4
+#define MGA_TEXORG2                    0x2ca8
+#define MGA_TEXORG3                    0x2cac
+#define MGA_TEXORG4                    0x2cb0
+#define MGA_TEXTRANS                   0x2c34
+#define MGA_TEXTRANSHIGH               0x2c38
+#define MGA_TEXWIDTH                   0x2c28
+
+#define MGA_WACCEPTSEQ                 0x1dd4
+#define MGA_WCODEADDR                  0x1e6c
+#define MGA_WFLAG                      0x1dc4
+#define MGA_WFLAG1                     0x1de0
+#define MGA_WFLAGNB                    0x1e64
+#define MGA_WFLAGNB1                   0x1e08
+#define MGA_WGETMSB                    0x1dc8
+#define MGA_WIADDR                     0x1dc0
+#define MGA_WIADDR2                    0x1dd8
+#      define MGA_WMODE_SUSPEND                (0 << 0)
+#      define MGA_WMODE_RESUME                 (1 << 0)
+#      define MGA_WMODE_JUMP                   (2 << 0)
+#      define MGA_WMODE_START                  (3 << 0)
+#      define MGA_WAGP_ENABLE                  (1 << 2)
+#define MGA_WMISC                      0x1e70
+#      define MGA_WUCODECACHE_ENABLE           (1 << 0)
+#      define MGA_WMASTER_ENABLE               (1 << 1)
+#      define MGA_WCACHEFLUSH_ENABLE           (1 << 3)
+#define MGA_WVRTXSZ                    0x1dcc
+
+#define MGA_YBOT                       0x1c9c
+#define MGA_YDST                       0x1c90
+#define MGA_YDSTLEN                    0x1c88
+#define MGA_YDSTORG                    0x1c94
+#define MGA_YTOP                       0x1c98
+
+#define MGA_ZORG                       0x1c0c
+
+/* This finishes the current batch of commands
+ */
+#define MGA_EXEC                       0x0100
+
+/* AGP PLL encoding (for G200 only).
+ */
+#define MGA_AGP_PLL                    0x1e4c
+#      define MGA_AGP2XPLL_DISABLE             (0 << 0)
+#      define MGA_AGP2XPLL_ENABLE              (1 << 0)
+
+/* Warp registers
+ */
+#define MGA_WR0                                0x2d00
+#define MGA_WR1                                0x2d04
+#define MGA_WR2                                0x2d08
+#define MGA_WR3                                0x2d0c
+#define MGA_WR4                                0x2d10
+#define MGA_WR5                                0x2d14
+#define MGA_WR6                                0x2d18
+#define MGA_WR7                                0x2d1c
+#define MGA_WR8                                0x2d20
+#define MGA_WR9                                0x2d24
+#define MGA_WR10                       0x2d28
+#define MGA_WR11                       0x2d2c
+#define MGA_WR12                       0x2d30
+#define MGA_WR13                       0x2d34
+#define MGA_WR14                       0x2d38
+#define MGA_WR15                       0x2d3c
+#define MGA_WR16                       0x2d40
+#define MGA_WR17                       0x2d44
+#define MGA_WR18                       0x2d48
+#define MGA_WR19                       0x2d4c
+#define MGA_WR20                       0x2d50
+#define MGA_WR21                       0x2d54
+#define MGA_WR22                       0x2d58
+#define MGA_WR23                       0x2d5c
+#define MGA_WR24                       0x2d60
+#define MGA_WR25                       0x2d64
+#define MGA_WR26                       0x2d68
+#define MGA_WR27                       0x2d6c
+#define MGA_WR28                       0x2d70
+#define MGA_WR29                       0x2d74
+#define MGA_WR30                       0x2d78
+#define MGA_WR31                       0x2d7c
+#define MGA_WR32                       0x2d80
+#define MGA_WR33                       0x2d84
+#define MGA_WR34                       0x2d88
+#define MGA_WR35                       0x2d8c
+#define MGA_WR36                       0x2d90
+#define MGA_WR37                       0x2d94
+#define MGA_WR38                       0x2d98
+#define MGA_WR39                       0x2d9c
+#define MGA_WR40                       0x2da0
+#define MGA_WR41                       0x2da4
+#define MGA_WR42                       0x2da8
+#define MGA_WR43                       0x2dac
+#define MGA_WR44                       0x2db0
+#define MGA_WR45                       0x2db4
+#define MGA_WR46                       0x2db8
+#define MGA_WR47                       0x2dbc
+#define MGA_WR48                       0x2dc0
+#define MGA_WR49                       0x2dc4
+#define MGA_WR50                       0x2dc8
+#define MGA_WR51                       0x2dcc
+#define MGA_WR52                       0x2dd0
+#define MGA_WR53                       0x2dd4
+#define MGA_WR54                       0x2dd8
+#define MGA_WR55                       0x2ddc
+#define MGA_WR56                       0x2de0
+#define MGA_WR57                       0x2de4
+#define MGA_WR58                       0x2de8
+#define MGA_WR59                       0x2dec
+#define MGA_WR60                       0x2df0
+#define MGA_WR61                       0x2df4
+#define MGA_WR62                       0x2df8
+#define MGA_WR63                       0x2dfc
+#      define MGA_G400_WR_MAGIC                (1 << 6)
+#      define MGA_G400_WR56_MAGIC              0x46480000      /* 12800.0f */
+
+#define MGA_ILOAD_ALIGN                64
+#define MGA_ILOAD_MASK         (MGA_ILOAD_ALIGN - 1)
+
+#define MGA_DWGCTL_FLUSH       (MGA_OPCOD_TEXTURE_TRAP |               \
+                                MGA_ATYPE_I |                          \
+                                MGA_ZMODE_NOZCMP |                     \
+                                MGA_ARZERO |                           \
+                                MGA_SGNZERO |                          \
+                                MGA_BOP_SRC |                          \
+                                (15 << MGA_TRANS_SHIFT))
+
+#define MGA_DWGCTL_CLEAR       (MGA_OPCOD_TRAP |                       \
+                                MGA_ZMODE_NOZCMP |                     \
+                                MGA_SOLID |                            \
+                                MGA_ARZERO |                           \
+                                MGA_SGNZERO |                          \
+                                MGA_SHIFTZERO |                        \
+                                MGA_BOP_SRC |                          \
+                                (0 << MGA_TRANS_SHIFT) |               \
+                                MGA_BLTMOD_BMONOLEF |                  \
+                                MGA_TRANSC |                           \
+                                MGA_CLIPDIS)
+
+#define MGA_DWGCTL_COPY                (MGA_OPCOD_BITBLT |                     \
+                                MGA_ATYPE_RPL |                        \
+                                MGA_SGNZERO |                          \
+                                MGA_SHIFTZERO |                        \
+                                MGA_BOP_SRC |                          \
+                                (0 << MGA_TRANS_SHIFT) |               \
+                                MGA_BLTMOD_BFCOL |                     \
+                                MGA_CLIPDIS)
+
+/* Simple idle test.
+ */
+static __inline__ int mga_is_idle(drm_mga_private_t * dev_priv)
+{
+       u32 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
+       return (status == MGA_ENDPRDMASTS);
+}
+
+#endif
diff --git a/drivers/gpu/drm/mga/mga_ioc32.c b/drivers/gpu/drm/mga/mga_ioc32.c
new file mode 100644 (file)
index 0000000..30d0047
--- /dev/null
@@ -0,0 +1,231 @@
+/**
+ * \file mga_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the MGA DRM.
+ *
+ * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich
+ *
+ *
+ * Copyright (C) Paul Mackerras 2005
+ * Copyright (C) Egbert Eich 2003,2004
+ * Copyright (C) Dave Airlie 2005
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <linux/compat.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
+
+typedef struct drm32_mga_init {
+       int func;
+       u32 sarea_priv_offset;
+       int chipset;
+       int sgram;
+       unsigned int maccess;
+       unsigned int fb_cpp;
+       unsigned int front_offset, front_pitch;
+       unsigned int back_offset, back_pitch;
+       unsigned int depth_cpp;
+       unsigned int depth_offset, depth_pitch;
+       unsigned int texture_offset[MGA_NR_TEX_HEAPS];
+       unsigned int texture_size[MGA_NR_TEX_HEAPS];
+       u32 fb_offset;
+       u32 mmio_offset;
+       u32 status_offset;
+       u32 warp_offset;
+       u32 primary_offset;
+       u32 buffers_offset;
+} drm_mga_init32_t;
+
+static int compat_mga_init(struct file *file, unsigned int cmd,
+                          unsigned long arg)
+{
+       drm_mga_init32_t init32;
+       drm_mga_init_t __user *init;
+       int err = 0, i;
+
+       if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
+               return -EFAULT;
+
+       init = compat_alloc_user_space(sizeof(*init));
+       if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
+           || __put_user(init32.func, &init->func)
+           || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
+           || __put_user(init32.chipset, &init->chipset)
+           || __put_user(init32.sgram, &init->sgram)
+           || __put_user(init32.maccess, &init->maccess)
+           || __put_user(init32.fb_cpp, &init->fb_cpp)
+           || __put_user(init32.front_offset, &init->front_offset)
+           || __put_user(init32.front_pitch, &init->front_pitch)
+           || __put_user(init32.back_offset, &init->back_offset)
+           || __put_user(init32.back_pitch, &init->back_pitch)
+           || __put_user(init32.depth_cpp, &init->depth_cpp)
+           || __put_user(init32.depth_offset, &init->depth_offset)
+           || __put_user(init32.depth_pitch, &init->depth_pitch)
+           || __put_user(init32.fb_offset, &init->fb_offset)
+           || __put_user(init32.mmio_offset, &init->mmio_offset)
+           || __put_user(init32.status_offset, &init->status_offset)
+           || __put_user(init32.warp_offset, &init->warp_offset)
+           || __put_user(init32.primary_offset, &init->primary_offset)
+           || __put_user(init32.buffers_offset, &init->buffers_offset))
+               return -EFAULT;
+
+       for (i = 0; i < MGA_NR_TEX_HEAPS; i++) {
+               err |=
+                   __put_user(init32.texture_offset[i],
+                              &init->texture_offset[i]);
+               err |=
+                   __put_user(init32.texture_size[i], &init->texture_size[i]);
+       }
+       if (err)
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_MGA_INIT, (unsigned long)init);
+}
+
+typedef struct drm_mga_getparam32 {
+       int param;
+       u32 value;
+} drm_mga_getparam32_t;
+
+static int compat_mga_getparam(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       drm_mga_getparam32_t getparam32;
+       drm_mga_getparam_t __user *getparam;
+
+       if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
+               return -EFAULT;
+
+       getparam = compat_alloc_user_space(sizeof(*getparam));
+       if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
+           || __put_user(getparam32.param, &getparam->param)
+           || __put_user((void __user *)(unsigned long)getparam32.value,
+                         &getparam->value))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
+}
+
+typedef struct drm_mga_drm_bootstrap32 {
+       u32 texture_handle;
+       u32 texture_size;
+       u32 primary_size;
+       u32 secondary_bin_count;
+       u32 secondary_bin_size;
+       u32 agp_mode;
+       u8 agp_size;
+} drm_mga_dma_bootstrap32_t;
+
+static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd,
+                                   unsigned long arg)
+{
+       drm_mga_dma_bootstrap32_t dma_bootstrap32;
+       drm_mga_dma_bootstrap_t __user *dma_bootstrap;
+       int err;
+
+       if (copy_from_user(&dma_bootstrap32, (void __user *)arg,
+                          sizeof(dma_bootstrap32)))
+               return -EFAULT;
+
+       dma_bootstrap = compat_alloc_user_space(sizeof(*dma_bootstrap));
+       if (!access_ok(VERIFY_WRITE, dma_bootstrap, sizeof(*dma_bootstrap))
+           || __put_user(dma_bootstrap32.texture_handle,
+                         &dma_bootstrap->texture_handle)
+           || __put_user(dma_bootstrap32.texture_size,
+                         &dma_bootstrap->texture_size)
+           || __put_user(dma_bootstrap32.primary_size,
+                         &dma_bootstrap->primary_size)
+           || __put_user(dma_bootstrap32.secondary_bin_count,
+                         &dma_bootstrap->secondary_bin_count)
+           || __put_user(dma_bootstrap32.secondary_bin_size,
+                         &dma_bootstrap->secondary_bin_size)
+           || __put_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
+           || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
+               return -EFAULT;
+
+       err = drm_ioctl(file->f_path.dentry->d_inode, file,
+                       DRM_IOCTL_MGA_DMA_BOOTSTRAP,
+                       (unsigned long)dma_bootstrap);
+       if (err)
+               return err;
+
+       if (__get_user(dma_bootstrap32.texture_handle,
+                      &dma_bootstrap->texture_handle)
+           || __get_user(dma_bootstrap32.texture_size,
+                         &dma_bootstrap->texture_size)
+           || __get_user(dma_bootstrap32.primary_size,
+                         &dma_bootstrap->primary_size)
+           || __get_user(dma_bootstrap32.secondary_bin_count,
+                         &dma_bootstrap->secondary_bin_count)
+           || __get_user(dma_bootstrap32.secondary_bin_size,
+                         &dma_bootstrap->secondary_bin_size)
+           || __get_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
+           || __get_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
+               return -EFAULT;
+
+       if (copy_to_user((void __user *)arg, &dma_bootstrap32,
+                        sizeof(dma_bootstrap32)))
+               return -EFAULT;
+
+       return 0;
+}
+
+drm_ioctl_compat_t *mga_compat_ioctls[] = {
+       [DRM_MGA_INIT] = compat_mga_init,
+       [DRM_MGA_GETPARAM] = compat_mga_getparam,
+       [DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap,
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/dri/card<n>.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       unsigned int nr = DRM_IOCTL_NR(cmd);
+       drm_ioctl_compat_t *fn = NULL;
+       int ret;
+
+       if (nr < DRM_COMMAND_BASE)
+               return drm_compat_ioctl(filp, cmd, arg);
+
+       if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls))
+               fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE];
+
+       lock_kernel();          /* XXX for now */
+       if (fn != NULL)
+               ret = (*fn) (filp, cmd, arg);
+       else
+               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
+       unlock_kernel();
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c
new file mode 100644 (file)
index 0000000..9302cb8
--- /dev/null
@@ -0,0 +1,148 @@
+/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Eric Anholt <anholt@FreeBSD.org>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
+#include "mga_drv.h"
+
+irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+       int status;
+       int handled = 0;
+
+       status = MGA_READ(MGA_STATUS);
+
+       /* VBLANK interrupt */
+       if (status & MGA_VLINEPEN) {
+               MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
+               atomic_inc(&dev->vbl_received);
+               DRM_WAKEUP(&dev->vbl_queue);
+               drm_vbl_send_signals(dev);
+               handled = 1;
+       }
+
+       /* SOFTRAP interrupt */
+       if (status & MGA_SOFTRAPEN) {
+               const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
+               const u32 prim_end = MGA_READ(MGA_PRIMEND);
+
+               MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);
+
+               /* In addition to clearing the interrupt-pending bit, we
+                * have to write to MGA_PRIMEND to re-start the DMA operation.
+                */
+               if ((prim_start & ~0x03) != (prim_end & ~0x03)) {
+                       MGA_WRITE(MGA_PRIMEND, prim_end);
+               }
+
+               atomic_inc(&dev_priv->last_fence_retired);
+               DRM_WAKEUP(&dev_priv->fence_queue);
+               handled = 1;
+       }
+
+       if (handled) {
+               return IRQ_HANDLED;
+       }
+       return IRQ_NONE;
+}
+
+int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+{
+       unsigned int cur_vblank;
+       int ret = 0;
+
+       /* Assume that the user has missed the current sequence number
+        * by about a day rather than she wants to wait for years
+        * using vertical blanks...
+        */
+       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+                   (((cur_vblank = atomic_read(&dev->vbl_received))
+                     - *sequence) <= (1 << 23)));
+
+       *sequence = cur_vblank;
+
+       return ret;
+}
+
+int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
+{
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+       unsigned int cur_fence;
+       int ret = 0;
+
+       /* Assume that the user has missed the current sequence number
+        * by about a day rather than she wants to wait for years
+        * using fences.
+        */
+       DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * DRM_HZ,
+                   (((cur_fence = atomic_read(&dev_priv->last_fence_retired))
+                     - *sequence) <= (1 << 23)));
+
+       *sequence = cur_fence;
+
+       return ret;
+}
+
+void mga_driver_irq_preinstall(struct drm_device * dev)
+{
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+       /* Disable *all* interrupts */
+       MGA_WRITE(MGA_IEN, 0);
+       /* Clear bits if they're already high */
+       MGA_WRITE(MGA_ICLEAR, ~0);
+}
+
+void mga_driver_irq_postinstall(struct drm_device * dev)
+{
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+
+       DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
+
+       /* Turn on vertical blank interrupt and soft trap interrupt. */
+       MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
+}
+
+void mga_driver_irq_uninstall(struct drm_device * dev)
+{
+       drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
+       if (!dev_priv)
+               return;
+
+       /* Disable *all* interrupts */
+       MGA_WRITE(MGA_IEN, 0);
+
+       dev->irq_enabled = 0;
+}
diff --git a/drivers/gpu/drm/mga/mga_state.c b/drivers/gpu/drm/mga/mga_state.c
new file mode 100644 (file)
index 0000000..d3f8aad
--- /dev/null
@@ -0,0 +1,1104 @@
+/* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*-
+ * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Jeff Hartmann <jhartmann@valinux.com>
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * Rewritten by:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
+#include "mga_drv.h"
+
+/* ================================================================
+ * DMA hardware state programming functions
+ */
+
+static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
+                              struct drm_clip_rect * box)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+       unsigned int pitch = dev_priv->front_pitch;
+       DMA_LOCALS;
+
+       BEGIN_DMA(2);
+
+       /* Force reset of DWGCTL on G400 (eliminates clip disable bit).
+        */
+       if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
+               DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl,
+                         MGA_LEN + MGA_EXEC, 0x80000000,
+                         MGA_DWGCTL, ctx->dwgctl,
+                         MGA_LEN + MGA_EXEC, 0x80000000);
+       }
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1,
+                 MGA_YTOP, box->y1 * pitch, MGA_YBOT, (box->y2 - 1) * pitch);
+
+       ADVANCE_DMA();
+}
+
+static __inline__ void mga_g200_emit_context(drm_mga_private_t * dev_priv)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+       DMA_LOCALS;
+
+       BEGIN_DMA(3);
+
+       DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
+                 MGA_MACCESS, ctx->maccess,
+                 MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
+
+       DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
+                 MGA_FOGCOL, ctx->fogcolor,
+                 MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset);
+
+       DMA_BLOCK(MGA_FCOL, ctx->fcol,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+       ADVANCE_DMA();
+}
+
+static __inline__ void mga_g400_emit_context(drm_mga_private_t * dev_priv)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+       DMA_LOCALS;
+
+       BEGIN_DMA(4);
+
+       DMA_BLOCK(MGA_DSTORG, ctx->dstorg,
+                 MGA_MACCESS, ctx->maccess,
+                 MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
+
+       DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl,
+                 MGA_FOGCOL, ctx->fogcolor,
+                 MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset);
+
+       DMA_BLOCK(MGA_WFLAG1, ctx->wflag,
+                 MGA_TDUALSTAGE0, ctx->tdualstage0,
+                 MGA_TDUALSTAGE1, ctx->tdualstage1, MGA_FCOL, ctx->fcol);
+
+       DMA_BLOCK(MGA_STENCIL, ctx->stencil,
+                 MGA_STENCILCTL, ctx->stencilctl,
+                 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+       ADVANCE_DMA();
+}
+
+static __inline__ void mga_g200_emit_tex0(drm_mga_private_t * dev_priv)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
+       DMA_LOCALS;
+
+       BEGIN_DMA(4);
+
+       DMA_BLOCK(MGA_TEXCTL2, tex->texctl2,
+                 MGA_TEXCTL, tex->texctl,
+                 MGA_TEXFILTER, tex->texfilter,
+                 MGA_TEXBORDERCOL, tex->texbordercol);
+
+       DMA_BLOCK(MGA_TEXORG, tex->texorg,
+                 MGA_TEXORG1, tex->texorg1,
+                 MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
+
+       DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
+                 MGA_TEXWIDTH, tex->texwidth,
+                 MGA_TEXHEIGHT, tex->texheight, MGA_WR24, tex->texwidth);
+
+       DMA_BLOCK(MGA_WR34, tex->texheight,
+                 MGA_TEXTRANS, 0x0000ffff,
+                 MGA_TEXTRANSHIGH, 0x0000ffff, MGA_DMAPAD, 0x00000000);
+
+       ADVANCE_DMA();
+}
+
+static __inline__ void mga_g400_emit_tex0(drm_mga_private_t * dev_priv)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
+       DMA_LOCALS;
+
+/*     printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */
+/*            tex->texctl, tex->texctl2); */
+
+       BEGIN_DMA(6);
+
+       DMA_BLOCK(MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC,
+                 MGA_TEXCTL, tex->texctl,
+                 MGA_TEXFILTER, tex->texfilter,
+                 MGA_TEXBORDERCOL, tex->texbordercol);
+
+       DMA_BLOCK(MGA_TEXORG, tex->texorg,
+                 MGA_TEXORG1, tex->texorg1,
+                 MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
+
+       DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
+                 MGA_TEXWIDTH, tex->texwidth,
+                 MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000);
+
+       DMA_BLOCK(MGA_WR57, 0x00000000,
+                 MGA_WR53, 0x00000000,
+                 MGA_WR61, 0x00000000, MGA_WR52, MGA_G400_WR_MAGIC);
+
+       DMA_BLOCK(MGA_WR60, MGA_G400_WR_MAGIC,
+                 MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC,
+                 MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC,
+                 MGA_DMAPAD, 0x00000000);
+
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_TEXTRANS, 0x0000ffff, MGA_TEXTRANSHIGH, 0x0000ffff);
+
+       ADVANCE_DMA();
+}
+
+static __inline__ void mga_g400_emit_tex1(drm_mga_private_t * dev_priv)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
+       DMA_LOCALS;
+
+/*     printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg,  */
+/*            tex->texctl, tex->texctl2); */
+
+       BEGIN_DMA(5);
+
+       DMA_BLOCK(MGA_TEXCTL2, (tex->texctl2 |
+                               MGA_MAP1_ENABLE |
+                               MGA_G400_TC2_MAGIC),
+                 MGA_TEXCTL, tex->texctl,
+                 MGA_TEXFILTER, tex->texfilter,
+                 MGA_TEXBORDERCOL, tex->texbordercol);
+
+       DMA_BLOCK(MGA_TEXORG, tex->texorg,
+                 MGA_TEXORG1, tex->texorg1,
+                 MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3);
+
+       DMA_BLOCK(MGA_TEXORG4, tex->texorg4,
+                 MGA_TEXWIDTH, tex->texwidth,
+                 MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000);
+
+       DMA_BLOCK(MGA_WR57, 0x00000000,
+                 MGA_WR53, 0x00000000,
+                 MGA_WR61, 0x00000000,
+                 MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC);
+
+       DMA_BLOCK(MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC,
+                 MGA_TEXTRANS, 0x0000ffff,
+                 MGA_TEXTRANSHIGH, 0x0000ffff,
+                 MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC);
+
+       ADVANCE_DMA();
+}
+
+static __inline__ void mga_g200_emit_pipe(drm_mga_private_t * dev_priv)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned int pipe = sarea_priv->warp_pipe;
+       DMA_LOCALS;
+
+       BEGIN_DMA(3);
+
+       DMA_BLOCK(MGA_WIADDR, MGA_WMODE_SUSPEND,
+                 MGA_WVRTXSZ, 0x00000007,
+                 MGA_WFLAG, 0x00000000, MGA_WR24, 0x00000000);
+
+       DMA_BLOCK(MGA_WR25, 0x00000100,
+                 MGA_WR34, 0x00000000,
+                 MGA_WR42, 0x0000ffff, MGA_WR60, 0x0000ffff);
+
+       /* Padding required to to hardware bug.
+        */
+       DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
+                 MGA_DMAPAD, 0xffffffff,
+                 MGA_DMAPAD, 0xffffffff,
+                 MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] |
+                              MGA_WMODE_START | dev_priv->wagp_enable));
+
+       ADVANCE_DMA();
+}
+
+static __inline__ void mga_g400_emit_pipe(drm_mga_private_t * dev_priv)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned int pipe = sarea_priv->warp_pipe;
+       DMA_LOCALS;
+
+/*     printk("mga_g400_emit_pipe %x\n", pipe); */
+
+       BEGIN_DMA(10);
+
+       DMA_BLOCK(MGA_WIADDR2, MGA_WMODE_SUSPEND,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+       if (pipe & MGA_T2) {
+               DMA_BLOCK(MGA_WVRTXSZ, 0x00001e09,
+                         MGA_DMAPAD, 0x00000000,
+                         MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+               DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
+                         MGA_WACCEPTSEQ, 0x00000000,
+                         MGA_WACCEPTSEQ, 0x00000000,
+                         MGA_WACCEPTSEQ, 0x1e000000);
+       } else {
+               if (dev_priv->warp_pipe & MGA_T2) {
+                       /* Flush the WARP pipe */
+                       DMA_BLOCK(MGA_YDST, 0x00000000,
+                                 MGA_FXLEFT, 0x00000000,
+                                 MGA_FXRIGHT, 0x00000001,
+                                 MGA_DWGCTL, MGA_DWGCTL_FLUSH);
+
+                       DMA_BLOCK(MGA_LEN + MGA_EXEC, 0x00000001,
+                                 MGA_DWGSYNC, 0x00007000,
+                                 MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
+                                 MGA_LEN + MGA_EXEC, 0x00000000);
+
+                       DMA_BLOCK(MGA_TEXCTL2, (MGA_DUALTEX |
+                                               MGA_G400_TC2_MAGIC),
+                                 MGA_LEN + MGA_EXEC, 0x00000000,
+                                 MGA_TEXCTL2, MGA_G400_TC2_MAGIC,
+                                 MGA_DMAPAD, 0x00000000);
+               }
+
+               DMA_BLOCK(MGA_WVRTXSZ, 0x00001807,
+                         MGA_DMAPAD, 0x00000000,
+                         MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000);
+
+               DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000,
+                         MGA_WACCEPTSEQ, 0x00000000,
+                         MGA_WACCEPTSEQ, 0x00000000,
+                         MGA_WACCEPTSEQ, 0x18000000);
+       }
+
+       DMA_BLOCK(MGA_WFLAG, 0x00000000,
+                 MGA_WFLAG1, 0x00000000,
+                 MGA_WR56, MGA_G400_WR56_MAGIC, MGA_DMAPAD, 0x00000000);
+
+       DMA_BLOCK(MGA_WR49, 0x00000000, /* tex0              */
+                 MGA_WR57, 0x00000000, /* tex0              */
+                 MGA_WR53, 0x00000000, /* tex1              */
+                 MGA_WR61, 0x00000000);        /* tex1              */
+
+       DMA_BLOCK(MGA_WR54, MGA_G400_WR_MAGIC,  /* tex0 width        */
+                 MGA_WR62, MGA_G400_WR_MAGIC,  /* tex0 height       */
+                 MGA_WR52, MGA_G400_WR_MAGIC,  /* tex1 width        */
+                 MGA_WR60, MGA_G400_WR_MAGIC); /* tex1 height       */
+
+       /* Padding required to to hardware bug */
+       DMA_BLOCK(MGA_DMAPAD, 0xffffffff,
+                 MGA_DMAPAD, 0xffffffff,
+                 MGA_DMAPAD, 0xffffffff,
+                 MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] |
+                               MGA_WMODE_START | dev_priv->wagp_enable));
+
+       ADVANCE_DMA();
+}
+
+static void mga_g200_emit_state(drm_mga_private_t * dev_priv)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned int dirty = sarea_priv->dirty;
+
+       if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
+               mga_g200_emit_pipe(dev_priv);
+               dev_priv->warp_pipe = sarea_priv->warp_pipe;
+       }
+
+       if (dirty & MGA_UPLOAD_CONTEXT) {
+               mga_g200_emit_context(dev_priv);
+               sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
+       }
+
+       if (dirty & MGA_UPLOAD_TEX0) {
+               mga_g200_emit_tex0(dev_priv);
+               sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
+       }
+}
+
+static void mga_g400_emit_state(drm_mga_private_t * dev_priv)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned int dirty = sarea_priv->dirty;
+       int multitex = sarea_priv->warp_pipe & MGA_T2;
+
+       if (sarea_priv->warp_pipe != dev_priv->warp_pipe) {
+               mga_g400_emit_pipe(dev_priv);
+               dev_priv->warp_pipe = sarea_priv->warp_pipe;
+       }
+
+       if (dirty & MGA_UPLOAD_CONTEXT) {
+               mga_g400_emit_context(dev_priv);
+               sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT;
+       }
+
+       if (dirty & MGA_UPLOAD_TEX0) {
+               mga_g400_emit_tex0(dev_priv);
+               sarea_priv->dirty &= ~MGA_UPLOAD_TEX0;
+       }
+
+       if ((dirty & MGA_UPLOAD_TEX1) && multitex) {
+               mga_g400_emit_tex1(dev_priv);
+               sarea_priv->dirty &= ~MGA_UPLOAD_TEX1;
+       }
+}
+
+/* ================================================================
+ * SAREA state verification
+ */
+
+/* Disallow all write destinations except the front and backbuffer.
+ */
+static int mga_verify_context(drm_mga_private_t * dev_priv)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+
+       if (ctx->dstorg != dev_priv->front_offset &&
+           ctx->dstorg != dev_priv->back_offset) {
+               DRM_ERROR("*** bad DSTORG: %x (front %x, back %x)\n\n",
+                         ctx->dstorg, dev_priv->front_offset,
+                         dev_priv->back_offset);
+               ctx->dstorg = 0;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* Disallow texture reads from PCI space.
+ */
+static int mga_verify_tex(drm_mga_private_t * dev_priv, int unit)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
+       unsigned int org;
+
+       org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK);
+
+       if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) {
+               DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit);
+               tex->texorg = 0;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int mga_verify_state(drm_mga_private_t * dev_priv)
+{
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned int dirty = sarea_priv->dirty;
+       int ret = 0;
+
+       if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+               sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+       if (dirty & MGA_UPLOAD_CONTEXT)
+               ret |= mga_verify_context(dev_priv);
+
+       if (dirty & MGA_UPLOAD_TEX0)
+               ret |= mga_verify_tex(dev_priv, 0);
+
+       if (dev_priv->chipset >= MGA_CARD_TYPE_G400) {
+               if (dirty & MGA_UPLOAD_TEX1)
+                       ret |= mga_verify_tex(dev_priv, 1);
+
+               if (dirty & MGA_UPLOAD_PIPE)
+                       ret |= (sarea_priv->warp_pipe > MGA_MAX_G400_PIPES);
+       } else {
+               if (dirty & MGA_UPLOAD_PIPE)
+                       ret |= (sarea_priv->warp_pipe > MGA_MAX_G200_PIPES);
+       }
+
+       return (ret == 0);
+}
+
+static int mga_verify_iload(drm_mga_private_t * dev_priv,
+                           unsigned int dstorg, unsigned int length)
+{
+       if (dstorg < dev_priv->texture_offset ||
+           dstorg + length > (dev_priv->texture_offset +
+                              dev_priv->texture_size)) {
+               DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg);
+               return -EINVAL;
+       }
+
+       if (length & MGA_ILOAD_MASK) {
+               DRM_ERROR("*** bad iload length: 0x%x\n",
+                         length & MGA_ILOAD_MASK);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int mga_verify_blit(drm_mga_private_t * dev_priv,
+                          unsigned int srcorg, unsigned int dstorg)
+{
+       if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
+           (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) {
+               DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* ================================================================
+ *
+ */
+
+static void mga_dma_dispatch_clear(struct drm_device * dev, drm_mga_clear_t * clear)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
+       int nbox = sarea_priv->nbox;
+       int i;
+       DMA_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_DMA(1);
+
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
+
+       ADVANCE_DMA();
+
+       for (i = 0; i < nbox; i++) {
+               struct drm_clip_rect *box = &pbox[i];
+               u32 height = box->y2 - box->y1;
+
+               DRM_DEBUG("   from=%d,%d to=%d,%d\n",
+                         box->x1, box->y1, box->x2, box->y2);
+
+               if (clear->flags & MGA_FRONT) {
+                       BEGIN_DMA(2);
+
+                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                                 MGA_PLNWT, clear->color_mask,
+                                 MGA_YDSTLEN, (box->y1 << 16) | height,
+                                 MGA_FXBNDRY, (box->x2 << 16) | box->x1);
+
+                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                                 MGA_FCOL, clear->clear_color,
+                                 MGA_DSTORG, dev_priv->front_offset,
+                                 MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
+
+                       ADVANCE_DMA();
+               }
+
+               if (clear->flags & MGA_BACK) {
+                       BEGIN_DMA(2);
+
+                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                                 MGA_PLNWT, clear->color_mask,
+                                 MGA_YDSTLEN, (box->y1 << 16) | height,
+                                 MGA_FXBNDRY, (box->x2 << 16) | box->x1);
+
+                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                                 MGA_FCOL, clear->clear_color,
+                                 MGA_DSTORG, dev_priv->back_offset,
+                                 MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
+
+                       ADVANCE_DMA();
+               }
+
+               if (clear->flags & MGA_DEPTH) {
+                       BEGIN_DMA(2);
+
+                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                                 MGA_PLNWT, clear->depth_mask,
+                                 MGA_YDSTLEN, (box->y1 << 16) | height,
+                                 MGA_FXBNDRY, (box->x2 << 16) | box->x1);
+
+                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                                 MGA_FCOL, clear->clear_depth,
+                                 MGA_DSTORG, dev_priv->depth_offset,
+                                 MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd);
+
+                       ADVANCE_DMA();
+               }
+
+       }
+
+       BEGIN_DMA(1);
+
+       /* Force reset of DWGCTL */
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl);
+
+       ADVANCE_DMA();
+
+       FLUSH_DMA();
+}
+
+static void mga_dma_dispatch_swap(struct drm_device * dev)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
+       int nbox = sarea_priv->nbox;
+       int i;
+       DMA_LOCALS;
+       DRM_DEBUG("\n");
+
+       sarea_priv->last_frame.head = dev_priv->prim.tail;
+       sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap;
+
+       BEGIN_DMA(4 + nbox);
+
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
+
+       DMA_BLOCK(MGA_DSTORG, dev_priv->front_offset,
+                 MGA_MACCESS, dev_priv->maccess,
+                 MGA_SRCORG, dev_priv->back_offset,
+                 MGA_AR5, dev_priv->front_pitch);
+
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY);
+
+       for (i = 0; i < nbox; i++) {
+               struct drm_clip_rect *box = &pbox[i];
+               u32 height = box->y2 - box->y1;
+               u32 start = box->y1 * dev_priv->front_pitch;
+
+               DRM_DEBUG("   from=%d,%d to=%d,%d\n",
+                         box->x1, box->y1, box->x2, box->y2);
+
+               DMA_BLOCK(MGA_AR0, start + box->x2 - 1,
+                         MGA_AR3, start + box->x1,
+                         MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1,
+                         MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height);
+       }
+
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_PLNWT, ctx->plnwt,
+                 MGA_SRCORG, dev_priv->front_offset, MGA_DWGCTL, ctx->dwgctl);
+
+       ADVANCE_DMA();
+
+       FLUSH_DMA();
+
+       DRM_DEBUG("... done.\n");
+}
+
+static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       u32 address = (u32) buf->bus_address;
+       u32 length = (u32) buf->used;
+       int i = 0;
+       DMA_LOCALS;
+       DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used);
+
+       if (buf->used) {
+               buf_priv->dispatched = 1;
+
+               MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
+
+               do {
+                       if (i < sarea_priv->nbox) {
+                               mga_emit_clip_rect(dev_priv,
+                                                  &sarea_priv->boxes[i]);
+                       }
+
+                       BEGIN_DMA(1);
+
+                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                                 MGA_DMAPAD, 0x00000000,
+                                 MGA_SECADDRESS, (address |
+                                                  MGA_DMA_VERTEX),
+                                 MGA_SECEND, ((address + length) |
+                                              dev_priv->dma_access));
+
+                       ADVANCE_DMA();
+               } while (++i < sarea_priv->nbox);
+       }
+
+       if (buf_priv->discard) {
+               AGE_BUFFER(buf_priv);
+               buf->pending = 0;
+               buf->used = 0;
+               buf_priv->dispatched = 0;
+
+               mga_freelist_put(dev, buf);
+       }
+
+       FLUSH_DMA();
+}
+
+static void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * buf,
+                                    unsigned int start, unsigned int end)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       u32 address = (u32) buf->bus_address;
+       int i = 0;
+       DMA_LOCALS;
+       DRM_DEBUG("buf=%d start=%d end=%d\n", buf->idx, start, end);
+
+       if (start != end) {
+               buf_priv->dispatched = 1;
+
+               MGA_EMIT_STATE(dev_priv, sarea_priv->dirty);
+
+               do {
+                       if (i < sarea_priv->nbox) {
+                               mga_emit_clip_rect(dev_priv,
+                                                  &sarea_priv->boxes[i]);
+                       }
+
+                       BEGIN_DMA(1);
+
+                       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                                 MGA_DMAPAD, 0x00000000,
+                                 MGA_SETUPADDRESS, address + start,
+                                 MGA_SETUPEND, ((address + end) |
+                                                dev_priv->dma_access));
+
+                       ADVANCE_DMA();
+               } while (++i < sarea_priv->nbox);
+       }
+
+       if (buf_priv->discard) {
+               AGE_BUFFER(buf_priv);
+               buf->pending = 0;
+               buf->used = 0;
+               buf_priv->dispatched = 0;
+
+               mga_freelist_put(dev, buf);
+       }
+
+       FLUSH_DMA();
+}
+
+/* This copies a 64 byte aligned agp region to the frambuffer with a
+ * standard blit, the ioctl needs to do checking.
+ */
+static void mga_dma_dispatch_iload(struct drm_device * dev, struct drm_buf * buf,
+                                  unsigned int dstorg, unsigned int length)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_buf_priv_t *buf_priv = buf->dev_private;
+       drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state;
+       u32 srcorg =
+           buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM;
+       u32 y2;
+       DMA_LOCALS;
+       DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used);
+
+       y2 = length / 64;
+
+       BEGIN_DMA(5);
+
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
+
+       DMA_BLOCK(MGA_DSTORG, dstorg,
+                 MGA_MACCESS, 0x00000000, MGA_SRCORG, srcorg, MGA_AR5, 64);
+
+       DMA_BLOCK(MGA_PITCH, 64,
+                 MGA_PLNWT, 0xffffffff,
+                 MGA_DMAPAD, 0x00000000, MGA_DWGCTL, MGA_DWGCTL_COPY);
+
+       DMA_BLOCK(MGA_AR0, 63,
+                 MGA_AR3, 0,
+                 MGA_FXBNDRY, (63 << 16) | 0, MGA_YDSTLEN + MGA_EXEC, y2);
+
+       DMA_BLOCK(MGA_PLNWT, ctx->plnwt,
+                 MGA_SRCORG, dev_priv->front_offset,
+                 MGA_PITCH, dev_priv->front_pitch, MGA_DWGSYNC, 0x00007000);
+
+       ADVANCE_DMA();
+
+       AGE_BUFFER(buf_priv);
+
+       buf->pending = 0;
+       buf->used = 0;
+       buf_priv->dispatched = 0;
+
+       mga_freelist_put(dev, buf);
+
+       FLUSH_DMA();
+}
+
+static void mga_dma_dispatch_blit(struct drm_device * dev, drm_mga_blit_t * blit)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
+       int nbox = sarea_priv->nbox;
+       u32 scandir = 0, i;
+       DMA_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_DMA(4 + nbox);
+
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000);
+
+       DMA_BLOCK(MGA_DWGCTL, MGA_DWGCTL_COPY,
+                 MGA_PLNWT, blit->planemask,
+                 MGA_SRCORG, blit->srcorg, MGA_DSTORG, blit->dstorg);
+
+       DMA_BLOCK(MGA_SGN, scandir,
+                 MGA_MACCESS, dev_priv->maccess,
+                 MGA_AR5, blit->ydir * blit->src_pitch,
+                 MGA_PITCH, blit->dst_pitch);
+
+       for (i = 0; i < nbox; i++) {
+               int srcx = pbox[i].x1 + blit->delta_sx;
+               int srcy = pbox[i].y1 + blit->delta_sy;
+               int dstx = pbox[i].x1 + blit->delta_dx;
+               int dsty = pbox[i].y1 + blit->delta_dy;
+               int h = pbox[i].y2 - pbox[i].y1;
+               int w = pbox[i].x2 - pbox[i].x1 - 1;
+               int start;
+
+               if (blit->ydir == -1) {
+                       srcy = blit->height - srcy - 1;
+               }
+
+               start = srcy * blit->src_pitch + srcx;
+
+               DMA_BLOCK(MGA_AR0, start + w,
+                         MGA_AR3, start,
+                         MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff),
+                         MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h);
+       }
+
+       /* Do something to flush AGP?
+        */
+
+       /* Force reset of DWGCTL */
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_PLNWT, ctx->plnwt,
+                 MGA_PITCH, dev_priv->front_pitch, MGA_DWGCTL, ctx->dwgctl);
+
+       ADVANCE_DMA();
+}
+
+/* ================================================================
+ *
+ */
+
+static int mga_dma_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_clear_t *clear = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+               sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+       WRAP_TEST_WITH_RETURN(dev_priv);
+
+       mga_dma_dispatch_clear(dev, clear);
+
+       /* Make sure we restore the 3D state next time.
+        */
+       dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
+       return 0;
+}
+
+static int mga_dma_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+               sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+       WRAP_TEST_WITH_RETURN(dev_priv);
+
+       mga_dma_dispatch_swap(dev);
+
+       /* Make sure we restore the 3D state next time.
+        */
+       dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
+       return 0;
+}
+
+static int mga_dma_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_mga_buf_priv_t *buf_priv;
+       drm_mga_vertex_t *vertex = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (vertex->idx < 0 || vertex->idx > dma->buf_count)
+               return -EINVAL;
+       buf = dma->buflist[vertex->idx];
+       buf_priv = buf->dev_private;
+
+       buf->used = vertex->used;
+       buf_priv->discard = vertex->discard;
+
+       if (!mga_verify_state(dev_priv)) {
+               if (vertex->discard) {
+                       if (buf_priv->dispatched == 1)
+                               AGE_BUFFER(buf_priv);
+                       buf_priv->dispatched = 0;
+                       mga_freelist_put(dev, buf);
+               }
+               return -EINVAL;
+       }
+
+       WRAP_TEST_WITH_RETURN(dev_priv);
+
+       mga_dma_dispatch_vertex(dev, buf);
+
+       return 0;
+}
+
+static int mga_dma_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_mga_buf_priv_t *buf_priv;
+       drm_mga_indices_t *indices = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (indices->idx < 0 || indices->idx > dma->buf_count)
+               return -EINVAL;
+
+       buf = dma->buflist[indices->idx];
+       buf_priv = buf->dev_private;
+
+       buf_priv->discard = indices->discard;
+
+       if (!mga_verify_state(dev_priv)) {
+               if (indices->discard) {
+                       if (buf_priv->dispatched == 1)
+                               AGE_BUFFER(buf_priv);
+                       buf_priv->dispatched = 0;
+                       mga_freelist_put(dev, buf);
+               }
+               return -EINVAL;
+       }
+
+       WRAP_TEST_WITH_RETURN(dev_priv);
+
+       mga_dma_dispatch_indices(dev, buf, indices->start, indices->end);
+
+       return 0;
+}
+
+static int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       struct drm_buf *buf;
+       drm_mga_buf_priv_t *buf_priv;
+       drm_mga_iload_t *iload = data;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+#if 0
+       if (mga_do_wait_for_idle(dev_priv) < 0) {
+               if (MGA_DMA_DEBUG)
+                       DRM_INFO("-EBUSY\n");
+               return -EBUSY;
+       }
+#endif
+       if (iload->idx < 0 || iload->idx > dma->buf_count)
+               return -EINVAL;
+
+       buf = dma->buflist[iload->idx];
+       buf_priv = buf->dev_private;
+
+       if (mga_verify_iload(dev_priv, iload->dstorg, iload->length)) {
+               mga_freelist_put(dev, buf);
+               return -EINVAL;
+       }
+
+       WRAP_TEST_WITH_RETURN(dev_priv);
+
+       mga_dma_dispatch_iload(dev, buf, iload->dstorg, iload->length);
+
+       /* Make sure we restore the 3D state next time.
+        */
+       dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
+       return 0;
+}
+
+static int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_mga_blit_t *blit = data;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS)
+               sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS;
+
+       if (mga_verify_blit(dev_priv, blit->srcorg, blit->dstorg))
+               return -EINVAL;
+
+       WRAP_TEST_WITH_RETURN(dev_priv);
+
+       mga_dma_dispatch_blit(dev, blit);
+
+       /* Make sure we restore the 3D state next time.
+        */
+       dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT;
+
+       return 0;
+}
+
+static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       drm_mga_getparam_t *param = data;
+       int value;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+       switch (param->param) {
+       case MGA_PARAM_IRQ_NR:
+               value = dev->irq;
+               break;
+       case MGA_PARAM_CARD_TYPE:
+               value = dev_priv->chipset;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
+               DRM_ERROR("copy_to_user\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       u32 *fence = data;
+       DMA_LOCALS;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+       /* I would normal do this assignment in the declaration of fence,
+        * but dev_priv may be NULL.
+        */
+
+       *fence = dev_priv->next_fence_to_post;
+       dev_priv->next_fence_to_post++;
+
+       BEGIN_DMA(1);
+       DMA_BLOCK(MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000,
+                 MGA_DMAPAD, 0x00000000, MGA_SOFTRAP, 0x00000000);
+       ADVANCE_DMA();
+
+       return 0;
+}
+
+static int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file *
+file_priv)
+{
+       drm_mga_private_t *dev_priv = dev->dev_private;
+       u32 *fence = data;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+       mga_driver_fence_wait(dev, fence);
+       return 0;
+}
+
+struct drm_ioctl_desc mga_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_MGA_FLUSH, mga_dma_flush, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_RESET, mga_dma_reset, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_SWAP, mga_dma_swap, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_CLEAR, mga_dma_clear, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_VERTEX, mga_dma_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_INDICES, mga_dma_indices, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_ILOAD, mga_dma_iload, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_BLIT, mga_dma_blit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_GETPARAM, mga_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_SET_FENCE, mga_set_fence, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+};
+
+int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
diff --git a/drivers/gpu/drm/mga/mga_ucode.h b/drivers/gpu/drm/mga/mga_ucode.h
new file mode 100644 (file)
index 0000000..b611e27
--- /dev/null
@@ -0,0 +1,11645 @@
+/* mga_ucode.h -- Matrox G200/G400 WARP engine microcode -*- linux-c -*-
+ * Created: Thu Jan 11 21:20:43 2001 by gareth@valinux.com
+ *
+ * Copyright 1999 Matrox Graphics Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * MATROX GRAPHICS INC., OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Kernel-based WARP engine management:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * WARP pipes are named according to the functions they perform, where:
+ *
+ *   - T stands for computation of texture stage 0
+ *   - T2 stands for computation of both texture stage 0 and texture stage 1
+ *   - G stands for computation of triangle intensity (Gouraud interpolation)
+ *   - Z stands for computation of Z buffer interpolation
+ *   - S stands for computation of specular highlight
+ *   - A stands for computation of the alpha channel
+ *   - F stands for computation of vertex fog interpolation
+ */
+
+static unsigned char warp_g200_tgz[] = {
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x98, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x81, 0x04,
+       0x89, 0x04,
+       0x01, 0x04,
+       0x09, 0x04,
+
+       0xC9, 0x41, 0xC0, 0xEC,
+       0x11, 0x04,
+       0x00, 0xE0,
+
+       0x41, 0xCC, 0x41, 0xCD,
+       0x49, 0xCC, 0x49, 0xCD,
+
+       0xD1, 0x41, 0xC0, 0xEC,
+       0x51, 0xCC, 0x51, 0xCD,
+
+       0x80, 0x04,
+       0x10, 0x04,
+       0x08, 0x04,
+       0x00, 0xE0,
+
+       0x00, 0xCC, 0xC0, 0xCD,
+       0xD1, 0x49, 0xC0, 0xEC,
+
+       0x8A, 0x1F, 0x20, 0xE9,
+       0x8B, 0x3F, 0x20, 0xE9,
+
+       0x41, 0x3C, 0x41, 0xAD,
+       0x49, 0x3C, 0x49, 0xAD,
+
+       0x10, 0xCC, 0x10, 0xCD,
+       0x08, 0xCC, 0x08, 0xCD,
+
+       0xB9, 0x41, 0x49, 0xBB,
+       0x1F, 0xF0, 0x41, 0xCD,
+
+       0x51, 0x3C, 0x51, 0xAD,
+       0x00, 0x98, 0x80, 0xE9,
+
+       0x72, 0x80, 0x07, 0xEA,
+       0x24, 0x1F, 0x20, 0xE9,
+
+       0x15, 0x41, 0x49, 0xBD,
+       0x1D, 0x41, 0x51, 0xBD,
+
+       0x2E, 0x41, 0x2A, 0xB8,
+       0x34, 0x53, 0xA0, 0xE8,
+
+       0x15, 0x30,
+       0x1D, 0x30,
+       0x58, 0xE3,
+       0x00, 0xE0,
+
+       0xB5, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x24, 0x43, 0xA0, 0xE8,
+       0x2C, 0x4B, 0xA0, 0xE8,
+
+       0x15, 0x72,
+       0x09, 0xE3,
+       0x00, 0xE0,
+       0x1D, 0x72,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0x97, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x6C, 0x64, 0xC8, 0xEC,
+       0x98, 0xE1,
+       0xB5, 0x05,
+
+       0xBD, 0x05,
+       0x2E, 0x30,
+       0x32, 0xC0, 0xA0, 0xE8,
+
+       0x33, 0xC0, 0xA0, 0xE8,
+       0x74, 0x64, 0xC8, 0xEC,
+
+       0x40, 0x3C, 0x40, 0xAD,
+       0x32, 0x6A,
+       0x2A, 0x30,
+
+       0x20, 0x73,
+       0x33, 0x6A,
+       0x00, 0xE0,
+       0x28, 0x73,
+
+       0x1C, 0x72,
+       0x83, 0xE2,
+       0x60, 0x80, 0x15, 0xEA,
+
+       0xB8, 0x3D, 0x28, 0xDF,
+       0x30, 0x35, 0x20, 0xDF,
+
+       0x40, 0x30,
+       0x00, 0xE0,
+       0xCC, 0xE2,
+       0x64, 0x72,
+
+       0x25, 0x42, 0x52, 0xBF,
+       0x2D, 0x42, 0x4A, 0xBF,
+
+       0x30, 0x2E, 0x30, 0xDF,
+       0x38, 0x2E, 0x38, 0xDF,
+
+       0x18, 0x1D, 0x45, 0xE9,
+       0x1E, 0x15, 0x45, 0xE9,
+
+       0x2B, 0x49, 0x51, 0xBD,
+       0x00, 0xE0,
+       0x1F, 0x73,
+
+       0x38, 0x38, 0x40, 0xAF,
+       0x30, 0x30, 0x40, 0xAF,
+
+       0x24, 0x1F, 0x24, 0xDF,
+       0x1D, 0x32, 0x20, 0xE9,
+
+       0x2C, 0x1F, 0x2C, 0xDF,
+       0x1A, 0x33, 0x20, 0xE9,
+
+       0xB0, 0x10,
+       0x08, 0xE3,
+       0x40, 0x10,
+       0xB8, 0x10,
+
+       0x26, 0xF0, 0x30, 0xCD,
+       0x2F, 0xF0, 0x38, 0xCD,
+
+       0x2B, 0x80, 0x20, 0xE9,
+       0x2A, 0x80, 0x20, 0xE9,
+
+       0xA6, 0x20,
+       0x88, 0xE2,
+       0x00, 0xE0,
+       0xAF, 0x20,
+
+       0x28, 0x2A, 0x26, 0xAF,
+       0x20, 0x2A, 0xC0, 0xAF,
+
+       0x34, 0x1F, 0x34, 0xDF,
+       0x46, 0x24, 0x46, 0xDF,
+
+       0x28, 0x30, 0x80, 0xBF,
+       0x20, 0x38, 0x80, 0xBF,
+
+       0x47, 0x24, 0x47, 0xDF,
+       0x4E, 0x2C, 0x4E, 0xDF,
+
+       0x4F, 0x2C, 0x4F, 0xDF,
+       0x56, 0x34, 0x56, 0xDF,
+
+       0x28, 0x15, 0x28, 0xDF,
+       0x20, 0x1D, 0x20, 0xDF,
+
+       0x57, 0x34, 0x57, 0xDF,
+       0x00, 0xE0,
+       0x1D, 0x05,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x89, 0xE2,
+       0x2B, 0x30,
+
+       0x3F, 0xC1, 0x1D, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA0, 0x68,
+       0xBF, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x20, 0xC0, 0x20, 0xAF,
+       0x28, 0x05,
+       0x97, 0x74,
+
+       0x00, 0xE0,
+       0x2A, 0x10,
+       0x16, 0xC0, 0x20, 0xE9,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x8C, 0xE2,
+       0x95, 0x05,
+
+       0x28, 0xC1, 0x28, 0xAD,
+       0x1F, 0xC1, 0x15, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA8, 0x67,
+       0x9F, 0x6B,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x28, 0xC0, 0x28, 0xAD,
+       0x1D, 0x25,
+       0x20, 0x05,
+
+       0x28, 0x32, 0x80, 0xAD,
+       0x40, 0x2A, 0x40, 0xBD,
+
+       0x1C, 0x80, 0x20, 0xE9,
+       0x20, 0x33, 0x20, 0xAD,
+
+       0x20, 0x73,
+       0x00, 0xE0,
+       0xB6, 0x49, 0x51, 0xBB,
+
+       0x26, 0x2F, 0xB0, 0xE8,
+       0x19, 0x20, 0x20, 0xE9,
+
+       0x35, 0x20, 0x35, 0xDF,
+       0x3D, 0x20, 0x3D, 0xDF,
+
+       0x15, 0x20, 0x15, 0xDF,
+       0x1D, 0x20, 0x1D, 0xDF,
+
+       0x26, 0xD0, 0x26, 0xCD,
+       0x29, 0x49, 0x2A, 0xB8,
+
+       0x26, 0x40, 0x80, 0xBD,
+       0x3B, 0x48, 0x50, 0xBD,
+
+       0x3E, 0x54, 0x57, 0x9F,
+       0x00, 0xE0,
+       0x82, 0xE1,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x26, 0x30,
+       0x29, 0x30,
+       0x48, 0x3C, 0x48, 0xAD,
+
+       0x2B, 0x72,
+       0xC2, 0xE1,
+       0x2C, 0xC0, 0x44, 0xC2,
+
+       0x05, 0x24, 0x34, 0xBF,
+       0x0D, 0x24, 0x2C, 0xBF,
+
+       0x2D, 0x46, 0x4E, 0xBF,
+       0x25, 0x46, 0x56, 0xBF,
+
+       0x20, 0x1D, 0x6F, 0x8F,
+       0x32, 0x3E, 0x5F, 0xE9,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x30,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x33, 0x1E, 0x5F, 0xE9,
+
+       0x05, 0x44, 0x54, 0xB2,
+       0x0D, 0x44, 0x4C, 0xB2,
+
+       0x19, 0xC0, 0xB0, 0xE8,
+       0x34, 0xC0, 0x44, 0xC4,
+
+       0x33, 0x73,
+       0x00, 0xE0,
+       0x3E, 0x62, 0x57, 0x9F,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0xE0,
+       0x0D, 0x20,
+
+       0x84, 0x3E, 0x58, 0xE9,
+       0x28, 0x1D, 0x6F, 0x8F,
+
+       0x05, 0x20,
+       0x00, 0xE0,
+       0x85, 0x1E, 0x58, 0xE9,
+
+       0x9B, 0x3B, 0x33, 0xDF,
+       0x20, 0x20, 0x42, 0xAF,
+
+       0x30, 0x42, 0x56, 0x9F,
+       0x80, 0x3E, 0x57, 0xE9,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x30, 0x80, 0x5F, 0xE9,
+
+       0x28, 0x28, 0x24, 0xAF,
+       0x81, 0x1E, 0x57, 0xE9,
+
+       0x05, 0x47, 0x57, 0xBF,
+       0x0D, 0x47, 0x4F, 0xBF,
+
+       0x88, 0x80, 0x58, 0xE9,
+       0x1B, 0x29, 0x1B, 0xDF,
+
+       0x30, 0x1D, 0x6F, 0x8F,
+       0x3A, 0x30, 0x4F, 0xE9,
+
+       0x1C, 0x30, 0x26, 0xDF,
+       0x09, 0xE3,
+       0x3B, 0x05,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x3B, 0x3F, 0x4F, 0xE9,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x00, 0xE0,
+       0xAC, 0x20,
+
+       0x2D, 0x44, 0x4C, 0xB4,
+       0x2C, 0x1C, 0xC0, 0xAF,
+
+       0x25, 0x44, 0x54, 0xB4,
+       0x00, 0xE0,
+       0xC8, 0x30,
+
+       0x30, 0x46, 0x30, 0xAF,
+       0x1B, 0x1B, 0x48, 0xAF,
+
+       0x00, 0xE0,
+       0x25, 0x20,
+       0x38, 0x2C, 0x4F, 0xE9,
+
+       0x86, 0x80, 0x57, 0xE9,
+       0x38, 0x1D, 0x6F, 0x8F,
+
+       0x28, 0x74,
+       0x00, 0xE0,
+       0x0D, 0x44, 0x4C, 0xB0,
+
+       0x05, 0x44, 0x54, 0xB0,
+       0x2D, 0x20,
+       0x9B, 0x10,
+
+       0x82, 0x3E, 0x57, 0xE9,
+       0x32, 0xF0, 0x1B, 0xCD,
+
+       0x1E, 0xBD, 0x59, 0x9F,
+       0x83, 0x1E, 0x57, 0xE9,
+
+       0x38, 0x47, 0x38, 0xAF,
+       0x34, 0x20,
+       0x2A, 0x30,
+
+       0x00, 0xE0,
+       0x0D, 0x20,
+       0x32, 0x20,
+       0x05, 0x20,
+
+       0x87, 0x80, 0x57, 0xE9,
+       0x1F, 0x54, 0x57, 0x9F,
+
+       0x17, 0x42, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x6A,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x37, 0x1E, 0x4F, 0xE9,
+
+       0x37, 0x32, 0x2A, 0xAF,
+       0x00, 0xE0,
+       0x32, 0x00,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x27, 0xC0, 0x44, 0xC0,
+
+       0x36, 0x1F, 0x4F, 0xE9,
+       0x1F, 0x1F, 0x26, 0xDF,
+
+       0x37, 0x1B, 0x37, 0xBF,
+       0x17, 0x26, 0x17, 0xDF,
+
+       0x3E, 0x17, 0x4F, 0xE9,
+       0x3F, 0x3F, 0x4F, 0xE9,
+
+       0x34, 0x1F, 0x34, 0xAF,
+       0x2B, 0x05,
+       0xA7, 0x20,
+
+       0x33, 0x2B, 0x37, 0xDF,
+       0x27, 0x17, 0xC0, 0xAF,
+
+       0x34, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x03, 0x80, 0x0A, 0xEA,
+       0x17, 0xC1, 0x2B, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xB3, 0x68,
+       0x97, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x33, 0xC0, 0x33, 0xAF,
+       0x3C, 0x27, 0x4F, 0xE9,
+
+       0x57, 0x39, 0x20, 0xE9,
+       0x28, 0x19, 0x60, 0xEC,
+
+       0x2B, 0x32, 0x20, 0xE9,
+       0x1D, 0x3B, 0x20, 0xE9,
+
+       0xB3, 0x05,
+       0x00, 0xE0,
+       0x16, 0x28, 0x20, 0xE9,
+
+       0x23, 0x3B, 0x33, 0xAD,
+       0x1E, 0x2B, 0x20, 0xE9,
+
+       0x1C, 0x80, 0x20, 0xE9,
+       0x57, 0x36, 0x20, 0xE9,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x90, 0xE2,
+       0x00, 0xE0,
+
+       0x85, 0xFF, 0x20, 0xEA,
+       0x19, 0xC8, 0xC1, 0xCD,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x9F, 0x41, 0x49, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x25, 0x41, 0x49, 0xBD,
+       0x2D, 0x41, 0x51, 0xBD,
+
+       0x0D, 0x80, 0x07, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x35, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x25, 0x30,
+       0x2D, 0x30,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0xA7, 0x5B, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x84, 0xFF, 0x0A, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC9, 0x41, 0xC8, 0xEC,
+       0x42, 0xE1,
+       0x00, 0xE0,
+
+       0x82, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC8, 0x40, 0xC0, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x7F, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgza[] = {
+
+       0x00, 0x98, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x81, 0x04,
+       0x89, 0x04,
+       0x01, 0x04,
+       0x09, 0x04,
+
+       0xC9, 0x41, 0xC0, 0xEC,
+       0x11, 0x04,
+       0x00, 0xE0,
+
+       0x41, 0xCC, 0x41, 0xCD,
+       0x49, 0xCC, 0x49, 0xCD,
+
+       0xD1, 0x41, 0xC0, 0xEC,
+       0x51, 0xCC, 0x51, 0xCD,
+
+       0x80, 0x04,
+       0x10, 0x04,
+       0x08, 0x04,
+       0x00, 0xE0,
+
+       0x00, 0xCC, 0xC0, 0xCD,
+       0xD1, 0x49, 0xC0, 0xEC,
+
+       0x8A, 0x1F, 0x20, 0xE9,
+       0x8B, 0x3F, 0x20, 0xE9,
+
+       0x41, 0x3C, 0x41, 0xAD,
+       0x49, 0x3C, 0x49, 0xAD,
+
+       0x10, 0xCC, 0x10, 0xCD,
+       0x08, 0xCC, 0x08, 0xCD,
+
+       0xB9, 0x41, 0x49, 0xBB,
+       0x1F, 0xF0, 0x41, 0xCD,
+
+       0x51, 0x3C, 0x51, 0xAD,
+       0x00, 0x98, 0x80, 0xE9,
+
+       0x7D, 0x80, 0x07, 0xEA,
+       0x24, 0x1F, 0x20, 0xE9,
+
+       0x15, 0x41, 0x49, 0xBD,
+       0x1D, 0x41, 0x51, 0xBD,
+
+       0x2E, 0x41, 0x2A, 0xB8,
+       0x34, 0x53, 0xA0, 0xE8,
+
+       0x15, 0x30,
+       0x1D, 0x30,
+       0x58, 0xE3,
+       0x00, 0xE0,
+
+       0xB5, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x24, 0x43, 0xA0, 0xE8,
+       0x2C, 0x4B, 0xA0, 0xE8,
+
+       0x15, 0x72,
+       0x09, 0xE3,
+       0x00, 0xE0,
+       0x1D, 0x72,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0x97, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x6C, 0x64, 0xC8, 0xEC,
+       0x98, 0xE1,
+       0xB5, 0x05,
+
+       0xBD, 0x05,
+       0x2E, 0x30,
+       0x32, 0xC0, 0xA0, 0xE8,
+
+       0x33, 0xC0, 0xA0, 0xE8,
+       0x74, 0x64, 0xC8, 0xEC,
+
+       0x40, 0x3C, 0x40, 0xAD,
+       0x32, 0x6A,
+       0x2A, 0x30,
+
+       0x20, 0x73,
+       0x33, 0x6A,
+       0x00, 0xE0,
+       0x28, 0x73,
+
+       0x1C, 0x72,
+       0x83, 0xE2,
+       0x6B, 0x80, 0x15, 0xEA,
+
+       0xB8, 0x3D, 0x28, 0xDF,
+       0x30, 0x35, 0x20, 0xDF,
+
+       0x40, 0x30,
+       0x00, 0xE0,
+       0xCC, 0xE2,
+       0x64, 0x72,
+
+       0x25, 0x42, 0x52, 0xBF,
+       0x2D, 0x42, 0x4A, 0xBF,
+
+       0x30, 0x2E, 0x30, 0xDF,
+       0x38, 0x2E, 0x38, 0xDF,
+
+       0x18, 0x1D, 0x45, 0xE9,
+       0x1E, 0x15, 0x45, 0xE9,
+
+       0x2B, 0x49, 0x51, 0xBD,
+       0x00, 0xE0,
+       0x1F, 0x73,
+
+       0x38, 0x38, 0x40, 0xAF,
+       0x30, 0x30, 0x40, 0xAF,
+
+       0x24, 0x1F, 0x24, 0xDF,
+       0x1D, 0x32, 0x20, 0xE9,
+
+       0x2C, 0x1F, 0x2C, 0xDF,
+       0x1A, 0x33, 0x20, 0xE9,
+
+       0xB0, 0x10,
+       0x08, 0xE3,
+       0x40, 0x10,
+       0xB8, 0x10,
+
+       0x26, 0xF0, 0x30, 0xCD,
+       0x2F, 0xF0, 0x38, 0xCD,
+
+       0x2B, 0x80, 0x20, 0xE9,
+       0x2A, 0x80, 0x20, 0xE9,
+
+       0xA6, 0x20,
+       0x88, 0xE2,
+       0x00, 0xE0,
+       0xAF, 0x20,
+
+       0x28, 0x2A, 0x26, 0xAF,
+       0x20, 0x2A, 0xC0, 0xAF,
+
+       0x34, 0x1F, 0x34, 0xDF,
+       0x46, 0x24, 0x46, 0xDF,
+
+       0x28, 0x30, 0x80, 0xBF,
+       0x20, 0x38, 0x80, 0xBF,
+
+       0x47, 0x24, 0x47, 0xDF,
+       0x4E, 0x2C, 0x4E, 0xDF,
+
+       0x4F, 0x2C, 0x4F, 0xDF,
+       0x56, 0x34, 0x56, 0xDF,
+
+       0x28, 0x15, 0x28, 0xDF,
+       0x20, 0x1D, 0x20, 0xDF,
+
+       0x57, 0x34, 0x57, 0xDF,
+       0x00, 0xE0,
+       0x1D, 0x05,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x89, 0xE2,
+       0x2B, 0x30,
+
+       0x3F, 0xC1, 0x1D, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA0, 0x68,
+       0xBF, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x20, 0xC0, 0x20, 0xAF,
+       0x28, 0x05,
+       0x97, 0x74,
+
+       0x00, 0xE0,
+       0x2A, 0x10,
+       0x16, 0xC0, 0x20, 0xE9,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x8C, 0xE2,
+       0x95, 0x05,
+
+       0x28, 0xC1, 0x28, 0xAD,
+       0x1F, 0xC1, 0x15, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA8, 0x67,
+       0x9F, 0x6B,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x28, 0xC0, 0x28, 0xAD,
+       0x1D, 0x25,
+       0x20, 0x05,
+
+       0x28, 0x32, 0x80, 0xAD,
+       0x40, 0x2A, 0x40, 0xBD,
+
+       0x1C, 0x80, 0x20, 0xE9,
+       0x20, 0x33, 0x20, 0xAD,
+
+       0x20, 0x73,
+       0x00, 0xE0,
+       0xB6, 0x49, 0x51, 0xBB,
+
+       0x26, 0x2F, 0xB0, 0xE8,
+       0x19, 0x20, 0x20, 0xE9,
+
+       0x35, 0x20, 0x35, 0xDF,
+       0x3D, 0x20, 0x3D, 0xDF,
+
+       0x15, 0x20, 0x15, 0xDF,
+       0x1D, 0x20, 0x1D, 0xDF,
+
+       0x26, 0xD0, 0x26, 0xCD,
+       0x29, 0x49, 0x2A, 0xB8,
+
+       0x26, 0x40, 0x80, 0xBD,
+       0x3B, 0x48, 0x50, 0xBD,
+
+       0x3E, 0x54, 0x57, 0x9F,
+       0x00, 0xE0,
+       0x82, 0xE1,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x26, 0x30,
+       0x29, 0x30,
+       0x48, 0x3C, 0x48, 0xAD,
+
+       0x2B, 0x72,
+       0xC2, 0xE1,
+       0x2C, 0xC0, 0x44, 0xC2,
+
+       0x05, 0x24, 0x34, 0xBF,
+       0x0D, 0x24, 0x2C, 0xBF,
+
+       0x2D, 0x46, 0x4E, 0xBF,
+       0x25, 0x46, 0x56, 0xBF,
+
+       0x20, 0x1D, 0x6F, 0x8F,
+       0x32, 0x3E, 0x5F, 0xE9,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x30,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x33, 0x1E, 0x5F, 0xE9,
+
+       0x05, 0x44, 0x54, 0xB2,
+       0x0D, 0x44, 0x4C, 0xB2,
+
+       0x19, 0xC0, 0xB0, 0xE8,
+       0x34, 0xC0, 0x44, 0xC4,
+
+       0x33, 0x73,
+       0x00, 0xE0,
+       0x3E, 0x62, 0x57, 0x9F,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0xE0,
+       0x0D, 0x20,
+
+       0x84, 0x3E, 0x58, 0xE9,
+       0x28, 0x1D, 0x6F, 0x8F,
+
+       0x05, 0x20,
+       0x00, 0xE0,
+       0x85, 0x1E, 0x58, 0xE9,
+
+       0x9B, 0x3B, 0x33, 0xDF,
+       0x20, 0x20, 0x42, 0xAF,
+
+       0x30, 0x42, 0x56, 0x9F,
+       0x80, 0x3E, 0x57, 0xE9,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x30, 0x80, 0x5F, 0xE9,
+
+       0x28, 0x28, 0x24, 0xAF,
+       0x81, 0x1E, 0x57, 0xE9,
+
+       0x05, 0x47, 0x57, 0xBF,
+       0x0D, 0x47, 0x4F, 0xBF,
+
+       0x88, 0x80, 0x58, 0xE9,
+       0x1B, 0x29, 0x1B, 0xDF,
+
+       0x30, 0x1D, 0x6F, 0x8F,
+       0x3A, 0x30, 0x4F, 0xE9,
+
+       0x1C, 0x30, 0x26, 0xDF,
+       0x09, 0xE3,
+       0x3B, 0x05,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x3B, 0x3F, 0x4F, 0xE9,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x00, 0xE0,
+       0xAC, 0x20,
+
+       0x2D, 0x44, 0x4C, 0xB4,
+       0x2C, 0x1C, 0xC0, 0xAF,
+
+       0x25, 0x44, 0x54, 0xB4,
+       0x00, 0xE0,
+       0xC8, 0x30,
+
+       0x30, 0x46, 0x30, 0xAF,
+       0x1B, 0x1B, 0x48, 0xAF,
+
+       0x00, 0xE0,
+       0x25, 0x20,
+       0x38, 0x2C, 0x4F, 0xE9,
+
+       0x86, 0x80, 0x57, 0xE9,
+       0x38, 0x1D, 0x6F, 0x8F,
+
+       0x28, 0x74,
+       0x00, 0xE0,
+       0x0D, 0x44, 0x4C, 0xB0,
+
+       0x05, 0x44, 0x54, 0xB0,
+       0x2D, 0x20,
+       0x9B, 0x10,
+
+       0x82, 0x3E, 0x57, 0xE9,
+       0x32, 0xF0, 0x1B, 0xCD,
+
+       0x1E, 0xBD, 0x59, 0x9F,
+       0x83, 0x1E, 0x57, 0xE9,
+
+       0x38, 0x47, 0x38, 0xAF,
+       0x34, 0x20,
+       0x2A, 0x30,
+
+       0x00, 0xE0,
+       0x0D, 0x20,
+       0x32, 0x20,
+       0x05, 0x20,
+
+       0x87, 0x80, 0x57, 0xE9,
+       0x1F, 0x54, 0x57, 0x9F,
+
+       0x17, 0x42, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x6A,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x37, 0x1E, 0x4F, 0xE9,
+
+       0x37, 0x32, 0x2A, 0xAF,
+       0x00, 0xE0,
+       0x32, 0x00,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x27, 0xC0, 0x44, 0xC0,
+
+       0x36, 0x1F, 0x4F, 0xE9,
+       0x1F, 0x1F, 0x26, 0xDF,
+
+       0x37, 0x1B, 0x37, 0xBF,
+       0x17, 0x26, 0x17, 0xDF,
+
+       0x3E, 0x17, 0x4F, 0xE9,
+       0x3F, 0x3F, 0x4F, 0xE9,
+
+       0x34, 0x1F, 0x34, 0xAF,
+       0x2B, 0x05,
+       0xA7, 0x20,
+
+       0x33, 0x2B, 0x37, 0xDF,
+       0x27, 0x17, 0xC0, 0xAF,
+
+       0x34, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x2D, 0x44, 0x4C, 0xB6,
+       0x25, 0x44, 0x54, 0xB6,
+
+       0x03, 0x80, 0x2A, 0xEA,
+       0x17, 0xC1, 0x2B, 0xBD,
+
+       0x2D, 0x20,
+       0x25, 0x20,
+       0x07, 0xC0, 0x44, 0xC6,
+
+       0xB3, 0x68,
+       0x97, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x33, 0xC0, 0x33, 0xAF,
+       0x3C, 0x27, 0x4F, 0xE9,
+
+       0x1F, 0x62, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x3F, 0x3D, 0x5D, 0x9F,
+       0x00, 0xE0,
+       0x07, 0x20,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x28, 0x19, 0x60, 0xEC,
+
+       0xB3, 0x05,
+       0x00, 0xE0,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x23, 0x3B, 0x33, 0xAD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x1F, 0x26, 0x1F, 0xDF,
+       0x9D, 0x1F, 0x4F, 0xE9,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x9E, 0x3F, 0x4F, 0xE9,
+
+       0x07, 0x07, 0x1F, 0xAF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x9C, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x57, 0x39, 0x20, 0xE9,
+
+       0x16, 0x28, 0x20, 0xE9,
+       0x1D, 0x3B, 0x20, 0xE9,
+
+       0x1E, 0x2B, 0x20, 0xE9,
+       0x2B, 0x32, 0x20, 0xE9,
+
+       0x1C, 0x23, 0x20, 0xE9,
+       0x57, 0x36, 0x20, 0xE9,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x90, 0xE2,
+       0x00, 0xE0,
+
+       0x7A, 0xFF, 0x20, 0xEA,
+       0x19, 0xC8, 0xC1, 0xCD,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x9F, 0x41, 0x49, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x25, 0x41, 0x49, 0xBD,
+       0x2D, 0x41, 0x51, 0xBD,
+
+       0x0D, 0x80, 0x07, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x35, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x25, 0x30,
+       0x2D, 0x30,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0xA7, 0x5B, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x79, 0xFF, 0x0A, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC9, 0x41, 0xC8, 0xEC,
+       0x42, 0xE1,
+       0x00, 0xE0,
+
+       0x77, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC8, 0x40, 0xC0, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x74, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzaf[] = {
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x98, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x81, 0x04,
+       0x89, 0x04,
+       0x01, 0x04,
+       0x09, 0x04,
+
+       0xC9, 0x41, 0xC0, 0xEC,
+       0x11, 0x04,
+       0x00, 0xE0,
+
+       0x41, 0xCC, 0x41, 0xCD,
+       0x49, 0xCC, 0x49, 0xCD,
+
+       0xD1, 0x41, 0xC0, 0xEC,
+       0x51, 0xCC, 0x51, 0xCD,
+
+       0x80, 0x04,
+       0x10, 0x04,
+       0x08, 0x04,
+       0x00, 0xE0,
+
+       0x00, 0xCC, 0xC0, 0xCD,
+       0xD1, 0x49, 0xC0, 0xEC,
+
+       0x8A, 0x1F, 0x20, 0xE9,
+       0x8B, 0x3F, 0x20, 0xE9,
+
+       0x41, 0x3C, 0x41, 0xAD,
+       0x49, 0x3C, 0x49, 0xAD,
+
+       0x10, 0xCC, 0x10, 0xCD,
+       0x08, 0xCC, 0x08, 0xCD,
+
+       0xB9, 0x41, 0x49, 0xBB,
+       0x1F, 0xF0, 0x41, 0xCD,
+
+       0x51, 0x3C, 0x51, 0xAD,
+       0x00, 0x98, 0x80, 0xE9,
+
+       0x83, 0x80, 0x07, 0xEA,
+       0x24, 0x1F, 0x20, 0xE9,
+
+       0x21, 0x45, 0x80, 0xE8,
+       0x1A, 0x4D, 0x80, 0xE8,
+
+       0x31, 0x55, 0x80, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0x41, 0x49, 0xBD,
+       0x1D, 0x41, 0x51, 0xBD,
+
+       0x2E, 0x41, 0x2A, 0xB8,
+       0x34, 0x53, 0xA0, 0xE8,
+
+       0x15, 0x30,
+       0x1D, 0x30,
+       0x58, 0xE3,
+       0x00, 0xE0,
+
+       0xB5, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x24, 0x43, 0xA0, 0xE8,
+       0x2C, 0x4B, 0xA0, 0xE8,
+
+       0x15, 0x72,
+       0x09, 0xE3,
+       0x00, 0xE0,
+       0x1D, 0x72,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0x97, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x6C, 0x64, 0xC8, 0xEC,
+       0x98, 0xE1,
+       0xB5, 0x05,
+
+       0xBD, 0x05,
+       0x2E, 0x30,
+       0x32, 0xC0, 0xA0, 0xE8,
+
+       0x33, 0xC0, 0xA0, 0xE8,
+       0x74, 0x64, 0xC8, 0xEC,
+
+       0x40, 0x3C, 0x40, 0xAD,
+       0x32, 0x6A,
+       0x2A, 0x30,
+
+       0x20, 0x73,
+       0x33, 0x6A,
+       0x00, 0xE0,
+       0x28, 0x73,
+
+       0x1C, 0x72,
+       0x83, 0xE2,
+       0x6F, 0x80, 0x15, 0xEA,
+
+       0xB8, 0x3D, 0x28, 0xDF,
+       0x30, 0x35, 0x20, 0xDF,
+
+       0x40, 0x30,
+       0x00, 0xE0,
+       0xCC, 0xE2,
+       0x64, 0x72,
+
+       0x25, 0x42, 0x52, 0xBF,
+       0x2D, 0x42, 0x4A, 0xBF,
+
+       0x30, 0x2E, 0x30, 0xDF,
+       0x38, 0x2E, 0x38, 0xDF,
+
+       0x18, 0x1D, 0x45, 0xE9,
+       0x1E, 0x15, 0x45, 0xE9,
+
+       0x2B, 0x49, 0x51, 0xBD,
+       0x00, 0xE0,
+       0x1F, 0x73,
+
+       0x38, 0x38, 0x40, 0xAF,
+       0x30, 0x30, 0x40, 0xAF,
+
+       0x24, 0x1F, 0x24, 0xDF,
+       0x1D, 0x32, 0x20, 0xE9,
+
+       0x2C, 0x1F, 0x2C, 0xDF,
+       0x1A, 0x33, 0x20, 0xE9,
+
+       0xB0, 0x10,
+       0x08, 0xE3,
+       0x40, 0x10,
+       0xB8, 0x10,
+
+       0x26, 0xF0, 0x30, 0xCD,
+       0x2F, 0xF0, 0x38, 0xCD,
+
+       0x2B, 0x80, 0x20, 0xE9,
+       0x2A, 0x80, 0x20, 0xE9,
+
+       0xA6, 0x20,
+       0x88, 0xE2,
+       0x00, 0xE0,
+       0xAF, 0x20,
+
+       0x28, 0x2A, 0x26, 0xAF,
+       0x20, 0x2A, 0xC0, 0xAF,
+
+       0x34, 0x1F, 0x34, 0xDF,
+       0x46, 0x24, 0x46, 0xDF,
+
+       0x28, 0x30, 0x80, 0xBF,
+       0x20, 0x38, 0x80, 0xBF,
+
+       0x47, 0x24, 0x47, 0xDF,
+       0x4E, 0x2C, 0x4E, 0xDF,
+
+       0x4F, 0x2C, 0x4F, 0xDF,
+       0x56, 0x34, 0x56, 0xDF,
+
+       0x28, 0x15, 0x28, 0xDF,
+       0x20, 0x1D, 0x20, 0xDF,
+
+       0x57, 0x34, 0x57, 0xDF,
+       0x00, 0xE0,
+       0x1D, 0x05,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x89, 0xE2,
+       0x2B, 0x30,
+
+       0x3F, 0xC1, 0x1D, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA0, 0x68,
+       0xBF, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x20, 0xC0, 0x20, 0xAF,
+       0x28, 0x05,
+       0x97, 0x74,
+
+       0x00, 0xE0,
+       0x2A, 0x10,
+       0x16, 0xC0, 0x20, 0xE9,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x8C, 0xE2,
+       0x95, 0x05,
+
+       0x28, 0xC1, 0x28, 0xAD,
+       0x1F, 0xC1, 0x15, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA8, 0x67,
+       0x9F, 0x6B,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x28, 0xC0, 0x28, 0xAD,
+       0x1D, 0x25,
+       0x20, 0x05,
+
+       0x28, 0x32, 0x80, 0xAD,
+       0x40, 0x2A, 0x40, 0xBD,
+
+       0x1C, 0x80, 0x20, 0xE9,
+       0x20, 0x33, 0x20, 0xAD,
+
+       0x20, 0x73,
+       0x00, 0xE0,
+       0xB6, 0x49, 0x51, 0xBB,
+
+       0x26, 0x2F, 0xB0, 0xE8,
+       0x19, 0x20, 0x20, 0xE9,
+
+       0x35, 0x20, 0x35, 0xDF,
+       0x3D, 0x20, 0x3D, 0xDF,
+
+       0x15, 0x20, 0x15, 0xDF,
+       0x1D, 0x20, 0x1D, 0xDF,
+
+       0x26, 0xD0, 0x26, 0xCD,
+       0x29, 0x49, 0x2A, 0xB8,
+
+       0x26, 0x40, 0x80, 0xBD,
+       0x3B, 0x48, 0x50, 0xBD,
+
+       0x3E, 0x54, 0x57, 0x9F,
+       0x00, 0xE0,
+       0x82, 0xE1,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x26, 0x30,
+       0x29, 0x30,
+       0x48, 0x3C, 0x48, 0xAD,
+
+       0x2B, 0x72,
+       0xC2, 0xE1,
+       0x2C, 0xC0, 0x44, 0xC2,
+
+       0x05, 0x24, 0x34, 0xBF,
+       0x0D, 0x24, 0x2C, 0xBF,
+
+       0x2D, 0x46, 0x4E, 0xBF,
+       0x25, 0x46, 0x56, 0xBF,
+
+       0x20, 0x1D, 0x6F, 0x8F,
+       0x32, 0x3E, 0x5F, 0xE9,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x30,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x33, 0x1E, 0x5F, 0xE9,
+
+       0x05, 0x44, 0x54, 0xB2,
+       0x0D, 0x44, 0x4C, 0xB2,
+
+       0x19, 0xC0, 0xB0, 0xE8,
+       0x34, 0xC0, 0x44, 0xC4,
+
+       0x33, 0x73,
+       0x00, 0xE0,
+       0x3E, 0x62, 0x57, 0x9F,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0xE0,
+       0x0D, 0x20,
+
+       0x84, 0x3E, 0x58, 0xE9,
+       0x28, 0x1D, 0x6F, 0x8F,
+
+       0x05, 0x20,
+       0x00, 0xE0,
+       0x85, 0x1E, 0x58, 0xE9,
+
+       0x9B, 0x3B, 0x33, 0xDF,
+       0x20, 0x20, 0x42, 0xAF,
+
+       0x30, 0x42, 0x56, 0x9F,
+       0x80, 0x3E, 0x57, 0xE9,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x30, 0x80, 0x5F, 0xE9,
+
+       0x28, 0x28, 0x24, 0xAF,
+       0x81, 0x1E, 0x57, 0xE9,
+
+       0x05, 0x47, 0x57, 0xBF,
+       0x0D, 0x47, 0x4F, 0xBF,
+
+       0x88, 0x80, 0x58, 0xE9,
+       0x1B, 0x29, 0x1B, 0xDF,
+
+       0x30, 0x1D, 0x6F, 0x8F,
+       0x3A, 0x30, 0x4F, 0xE9,
+
+       0x1C, 0x30, 0x26, 0xDF,
+       0x09, 0xE3,
+       0x3B, 0x05,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x3B, 0x3F, 0x4F, 0xE9,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x00, 0xE0,
+       0xAC, 0x20,
+
+       0x2D, 0x44, 0x4C, 0xB4,
+       0x2C, 0x1C, 0xC0, 0xAF,
+
+       0x25, 0x44, 0x54, 0xB4,
+       0x00, 0xE0,
+       0xC8, 0x30,
+
+       0x30, 0x46, 0x30, 0xAF,
+       0x1B, 0x1B, 0x48, 0xAF,
+
+       0x00, 0xE0,
+       0x25, 0x20,
+       0x38, 0x2C, 0x4F, 0xE9,
+
+       0x86, 0x80, 0x57, 0xE9,
+       0x38, 0x1D, 0x6F, 0x8F,
+
+       0x28, 0x74,
+       0x00, 0xE0,
+       0x0D, 0x44, 0x4C, 0xB0,
+
+       0x05, 0x44, 0x54, 0xB0,
+       0x2D, 0x20,
+       0x9B, 0x10,
+
+       0x82, 0x3E, 0x57, 0xE9,
+       0x32, 0xF0, 0x1B, 0xCD,
+
+       0x1E, 0xBD, 0x59, 0x9F,
+       0x83, 0x1E, 0x57, 0xE9,
+
+       0x38, 0x47, 0x38, 0xAF,
+       0x34, 0x20,
+       0x2A, 0x30,
+
+       0x00, 0xE0,
+       0x0D, 0x20,
+       0x32, 0x20,
+       0x05, 0x20,
+
+       0x87, 0x80, 0x57, 0xE9,
+       0x1F, 0x54, 0x57, 0x9F,
+
+       0x17, 0x42, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x6A,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x37, 0x1E, 0x4F, 0xE9,
+
+       0x37, 0x32, 0x2A, 0xAF,
+       0x00, 0xE0,
+       0x32, 0x00,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x27, 0xC0, 0x44, 0xC0,
+
+       0x36, 0x1F, 0x4F, 0xE9,
+       0x1F, 0x1F, 0x26, 0xDF,
+
+       0x37, 0x1B, 0x37, 0xBF,
+       0x17, 0x26, 0x17, 0xDF,
+
+       0x3E, 0x17, 0x4F, 0xE9,
+       0x3F, 0x3F, 0x4F, 0xE9,
+
+       0x34, 0x1F, 0x34, 0xAF,
+       0x2B, 0x05,
+       0xA7, 0x20,
+
+       0x33, 0x2B, 0x37, 0xDF,
+       0x27, 0x17, 0xC0, 0xAF,
+
+       0x34, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x0D, 0x21, 0x1A, 0xB6,
+       0x05, 0x21, 0x31, 0xB6,
+
+       0x2D, 0x44, 0x4C, 0xB6,
+       0x25, 0x44, 0x54, 0xB6,
+
+       0x03, 0x80, 0x2A, 0xEA,
+       0x17, 0xC1, 0x2B, 0xBD,
+
+       0x0D, 0x20,
+       0x05, 0x20,
+       0x2F, 0xC0, 0x21, 0xC6,
+
+       0xB3, 0x68,
+       0x97, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x33, 0xC0, 0x33, 0xAF,
+       0x3C, 0x27, 0x4F, 0xE9,
+
+       0x00, 0xE0,
+       0x25, 0x20,
+       0x07, 0xC0, 0x44, 0xC6,
+
+       0x17, 0x50, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x2D, 0x20,
+
+       0x37, 0x0F, 0x5C, 0x9F,
+       0x00, 0xE0,
+       0x2F, 0x20,
+
+       0x1F, 0x62, 0x57, 0x9F,
+       0x00, 0xE0,
+       0x07, 0x20,
+
+       0x3F, 0x3D, 0x5D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x28, 0x19, 0x60, 0xEC,
+
+       0xB3, 0x05,
+       0x00, 0xE0,
+       0x17, 0x26, 0x17, 0xDF,
+
+       0x23, 0x3B, 0x33, 0xAD,
+       0x35, 0x17, 0x4F, 0xE9,
+
+       0x1F, 0x26, 0x1F, 0xDF,
+       0x9D, 0x1F, 0x4F, 0xE9,
+
+       0x9E, 0x3F, 0x4F, 0xE9,
+       0x39, 0x37, 0x4F, 0xE9,
+
+       0x2F, 0x2F, 0x17, 0xAF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x07, 0x07, 0x1F, 0xAF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x31, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x9C, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x57, 0x39, 0x20, 0xE9,
+
+       0x16, 0x28, 0x20, 0xE9,
+       0x1D, 0x3B, 0x20, 0xE9,
+
+       0x1E, 0x2B, 0x20, 0xE9,
+       0x2B, 0x32, 0x20, 0xE9,
+
+       0x1C, 0x23, 0x20, 0xE9,
+       0x57, 0x36, 0x20, 0xE9,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x90, 0xE2,
+       0x00, 0xE0,
+
+       0x74, 0xFF, 0x20, 0xEA,
+       0x19, 0xC8, 0xC1, 0xCD,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x9F, 0x41, 0x49, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x25, 0x41, 0x49, 0xBD,
+       0x2D, 0x41, 0x51, 0xBD,
+
+       0x0D, 0x80, 0x07, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x35, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x25, 0x30,
+       0x2D, 0x30,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0xA7, 0x5B, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x73, 0xFF, 0x0A, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC9, 0x41, 0xC8, 0xEC,
+       0x42, 0xE1,
+       0x00, 0xE0,
+
+       0x71, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC8, 0x40, 0xC0, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x6E, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzf[] = {
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x98, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x81, 0x04,
+       0x89, 0x04,
+       0x01, 0x04,
+       0x09, 0x04,
+
+       0xC9, 0x41, 0xC0, 0xEC,
+       0x11, 0x04,
+       0x00, 0xE0,
+
+       0x41, 0xCC, 0x41, 0xCD,
+       0x49, 0xCC, 0x49, 0xCD,
+
+       0xD1, 0x41, 0xC0, 0xEC,
+       0x51, 0xCC, 0x51, 0xCD,
+
+       0x80, 0x04,
+       0x10, 0x04,
+       0x08, 0x04,
+       0x00, 0xE0,
+
+       0x00, 0xCC, 0xC0, 0xCD,
+       0xD1, 0x49, 0xC0, 0xEC,
+
+       0x8A, 0x1F, 0x20, 0xE9,
+       0x8B, 0x3F, 0x20, 0xE9,
+
+       0x41, 0x3C, 0x41, 0xAD,
+       0x49, 0x3C, 0x49, 0xAD,
+
+       0x10, 0xCC, 0x10, 0xCD,
+       0x08, 0xCC, 0x08, 0xCD,
+
+       0xB9, 0x41, 0x49, 0xBB,
+       0x1F, 0xF0, 0x41, 0xCD,
+
+       0x51, 0x3C, 0x51, 0xAD,
+       0x00, 0x98, 0x80, 0xE9,
+
+       0x7F, 0x80, 0x07, 0xEA,
+       0x24, 0x1F, 0x20, 0xE9,
+
+       0x21, 0x45, 0x80, 0xE8,
+       0x1A, 0x4D, 0x80, 0xE8,
+
+       0x31, 0x55, 0x80, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0x41, 0x49, 0xBD,
+       0x1D, 0x41, 0x51, 0xBD,
+
+       0x2E, 0x41, 0x2A, 0xB8,
+       0x34, 0x53, 0xA0, 0xE8,
+
+       0x15, 0x30,
+       0x1D, 0x30,
+       0x58, 0xE3,
+       0x00, 0xE0,
+
+       0xB5, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x24, 0x43, 0xA0, 0xE8,
+       0x2C, 0x4B, 0xA0, 0xE8,
+
+       0x15, 0x72,
+       0x09, 0xE3,
+       0x00, 0xE0,
+       0x1D, 0x72,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0x97, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x6C, 0x64, 0xC8, 0xEC,
+       0x98, 0xE1,
+       0xB5, 0x05,
+
+       0xBD, 0x05,
+       0x2E, 0x30,
+       0x32, 0xC0, 0xA0, 0xE8,
+
+       0x33, 0xC0, 0xA0, 0xE8,
+       0x74, 0x64, 0xC8, 0xEC,
+
+       0x40, 0x3C, 0x40, 0xAD,
+       0x32, 0x6A,
+       0x2A, 0x30,
+
+       0x20, 0x73,
+       0x33, 0x6A,
+       0x00, 0xE0,
+       0x28, 0x73,
+
+       0x1C, 0x72,
+       0x83, 0xE2,
+       0x6B, 0x80, 0x15, 0xEA,
+
+       0xB8, 0x3D, 0x28, 0xDF,
+       0x30, 0x35, 0x20, 0xDF,
+
+       0x40, 0x30,
+       0x00, 0xE0,
+       0xCC, 0xE2,
+       0x64, 0x72,
+
+       0x25, 0x42, 0x52, 0xBF,
+       0x2D, 0x42, 0x4A, 0xBF,
+
+       0x30, 0x2E, 0x30, 0xDF,
+       0x38, 0x2E, 0x38, 0xDF,
+
+       0x18, 0x1D, 0x45, 0xE9,
+       0x1E, 0x15, 0x45, 0xE9,
+
+       0x2B, 0x49, 0x51, 0xBD,
+       0x00, 0xE0,
+       0x1F, 0x73,
+
+       0x38, 0x38, 0x40, 0xAF,
+       0x30, 0x30, 0x40, 0xAF,
+
+       0x24, 0x1F, 0x24, 0xDF,
+       0x1D, 0x32, 0x20, 0xE9,
+
+       0x2C, 0x1F, 0x2C, 0xDF,
+       0x1A, 0x33, 0x20, 0xE9,
+
+       0xB0, 0x10,
+       0x08, 0xE3,
+       0x40, 0x10,
+       0xB8, 0x10,
+
+       0x26, 0xF0, 0x30, 0xCD,
+       0x2F, 0xF0, 0x38, 0xCD,
+
+       0x2B, 0x80, 0x20, 0xE9,
+       0x2A, 0x80, 0x20, 0xE9,
+
+       0xA6, 0x20,
+       0x88, 0xE2,
+       0x00, 0xE0,
+       0xAF, 0x20,
+
+       0x28, 0x2A, 0x26, 0xAF,
+       0x20, 0x2A, 0xC0, 0xAF,
+
+       0x34, 0x1F, 0x34, 0xDF,
+       0x46, 0x24, 0x46, 0xDF,
+
+       0x28, 0x30, 0x80, 0xBF,
+       0x20, 0x38, 0x80, 0xBF,
+
+       0x47, 0x24, 0x47, 0xDF,
+       0x4E, 0x2C, 0x4E, 0xDF,
+
+       0x4F, 0x2C, 0x4F, 0xDF,
+       0x56, 0x34, 0x56, 0xDF,
+
+       0x28, 0x15, 0x28, 0xDF,
+       0x20, 0x1D, 0x20, 0xDF,
+
+       0x57, 0x34, 0x57, 0xDF,
+       0x00, 0xE0,
+       0x1D, 0x05,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x89, 0xE2,
+       0x2B, 0x30,
+
+       0x3F, 0xC1, 0x1D, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA0, 0x68,
+       0xBF, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x20, 0xC0, 0x20, 0xAF,
+       0x28, 0x05,
+       0x97, 0x74,
+
+       0x00, 0xE0,
+       0x2A, 0x10,
+       0x16, 0xC0, 0x20, 0xE9,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x8C, 0xE2,
+       0x95, 0x05,
+
+       0x28, 0xC1, 0x28, 0xAD,
+       0x1F, 0xC1, 0x15, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA8, 0x67,
+       0x9F, 0x6B,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x28, 0xC0, 0x28, 0xAD,
+       0x1D, 0x25,
+       0x20, 0x05,
+
+       0x28, 0x32, 0x80, 0xAD,
+       0x40, 0x2A, 0x40, 0xBD,
+
+       0x1C, 0x80, 0x20, 0xE9,
+       0x20, 0x33, 0x20, 0xAD,
+
+       0x20, 0x73,
+       0x00, 0xE0,
+       0xB6, 0x49, 0x51, 0xBB,
+
+       0x26, 0x2F, 0xB0, 0xE8,
+       0x19, 0x20, 0x20, 0xE9,
+
+       0x35, 0x20, 0x35, 0xDF,
+       0x3D, 0x20, 0x3D, 0xDF,
+
+       0x15, 0x20, 0x15, 0xDF,
+       0x1D, 0x20, 0x1D, 0xDF,
+
+       0x26, 0xD0, 0x26, 0xCD,
+       0x29, 0x49, 0x2A, 0xB8,
+
+       0x26, 0x40, 0x80, 0xBD,
+       0x3B, 0x48, 0x50, 0xBD,
+
+       0x3E, 0x54, 0x57, 0x9F,
+       0x00, 0xE0,
+       0x82, 0xE1,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x26, 0x30,
+       0x29, 0x30,
+       0x48, 0x3C, 0x48, 0xAD,
+
+       0x2B, 0x72,
+       0xC2, 0xE1,
+       0x2C, 0xC0, 0x44, 0xC2,
+
+       0x05, 0x24, 0x34, 0xBF,
+       0x0D, 0x24, 0x2C, 0xBF,
+
+       0x2D, 0x46, 0x4E, 0xBF,
+       0x25, 0x46, 0x56, 0xBF,
+
+       0x20, 0x1D, 0x6F, 0x8F,
+       0x32, 0x3E, 0x5F, 0xE9,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x30,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x33, 0x1E, 0x5F, 0xE9,
+
+       0x05, 0x44, 0x54, 0xB2,
+       0x0D, 0x44, 0x4C, 0xB2,
+
+       0x19, 0xC0, 0xB0, 0xE8,
+       0x34, 0xC0, 0x44, 0xC4,
+
+       0x33, 0x73,
+       0x00, 0xE0,
+       0x3E, 0x62, 0x57, 0x9F,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0xE0,
+       0x0D, 0x20,
+
+       0x84, 0x3E, 0x58, 0xE9,
+       0x28, 0x1D, 0x6F, 0x8F,
+
+       0x05, 0x20,
+       0x00, 0xE0,
+       0x85, 0x1E, 0x58, 0xE9,
+
+       0x9B, 0x3B, 0x33, 0xDF,
+       0x20, 0x20, 0x42, 0xAF,
+
+       0x30, 0x42, 0x56, 0x9F,
+       0x80, 0x3E, 0x57, 0xE9,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x30, 0x80, 0x5F, 0xE9,
+
+       0x28, 0x28, 0x24, 0xAF,
+       0x81, 0x1E, 0x57, 0xE9,
+
+       0x05, 0x47, 0x57, 0xBF,
+       0x0D, 0x47, 0x4F, 0xBF,
+
+       0x88, 0x80, 0x58, 0xE9,
+       0x1B, 0x29, 0x1B, 0xDF,
+
+       0x30, 0x1D, 0x6F, 0x8F,
+       0x3A, 0x30, 0x4F, 0xE9,
+
+       0x1C, 0x30, 0x26, 0xDF,
+       0x09, 0xE3,
+       0x3B, 0x05,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x3B, 0x3F, 0x4F, 0xE9,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x00, 0xE0,
+       0xAC, 0x20,
+
+       0x2D, 0x44, 0x4C, 0xB4,
+       0x2C, 0x1C, 0xC0, 0xAF,
+
+       0x25, 0x44, 0x54, 0xB4,
+       0x00, 0xE0,
+       0xC8, 0x30,
+
+       0x30, 0x46, 0x30, 0xAF,
+       0x1B, 0x1B, 0x48, 0xAF,
+
+       0x00, 0xE0,
+       0x25, 0x20,
+       0x38, 0x2C, 0x4F, 0xE9,
+
+       0x86, 0x80, 0x57, 0xE9,
+       0x38, 0x1D, 0x6F, 0x8F,
+
+       0x28, 0x74,
+       0x00, 0xE0,
+       0x0D, 0x44, 0x4C, 0xB0,
+
+       0x05, 0x44, 0x54, 0xB0,
+       0x2D, 0x20,
+       0x9B, 0x10,
+
+       0x82, 0x3E, 0x57, 0xE9,
+       0x32, 0xF0, 0x1B, 0xCD,
+
+       0x1E, 0xBD, 0x59, 0x9F,
+       0x83, 0x1E, 0x57, 0xE9,
+
+       0x38, 0x47, 0x38, 0xAF,
+       0x34, 0x20,
+       0x2A, 0x30,
+
+       0x00, 0xE0,
+       0x0D, 0x20,
+       0x32, 0x20,
+       0x05, 0x20,
+
+       0x87, 0x80, 0x57, 0xE9,
+       0x1F, 0x54, 0x57, 0x9F,
+
+       0x17, 0x42, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x6A,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x37, 0x1E, 0x4F, 0xE9,
+
+       0x37, 0x32, 0x2A, 0xAF,
+       0x00, 0xE0,
+       0x32, 0x00,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x27, 0xC0, 0x44, 0xC0,
+
+       0x36, 0x1F, 0x4F, 0xE9,
+       0x1F, 0x1F, 0x26, 0xDF,
+
+       0x37, 0x1B, 0x37, 0xBF,
+       0x17, 0x26, 0x17, 0xDF,
+
+       0x3E, 0x17, 0x4F, 0xE9,
+       0x3F, 0x3F, 0x4F, 0xE9,
+
+       0x34, 0x1F, 0x34, 0xAF,
+       0x2B, 0x05,
+       0xA7, 0x20,
+
+       0x33, 0x2B, 0x37, 0xDF,
+       0x27, 0x17, 0xC0, 0xAF,
+
+       0x34, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x0D, 0x21, 0x1A, 0xB6,
+       0x05, 0x21, 0x31, 0xB6,
+
+       0x03, 0x80, 0x2A, 0xEA,
+       0x17, 0xC1, 0x2B, 0xBD,
+
+       0x0D, 0x20,
+       0x05, 0x20,
+       0x2F, 0xC0, 0x21, 0xC6,
+
+       0xB3, 0x68,
+       0x97, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x33, 0xC0, 0x33, 0xAF,
+       0x3C, 0x27, 0x4F, 0xE9,
+
+       0x17, 0x50, 0x56, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x37, 0x0F, 0x5C, 0x9F,
+       0x00, 0xE0,
+       0x2F, 0x20,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x28, 0x19, 0x60, 0xEC,
+
+       0xB3, 0x05,
+       0x00, 0xE0,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x23, 0x3B, 0x33, 0xAD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x17, 0x26, 0x17, 0xDF,
+       0x35, 0x17, 0x4F, 0xE9,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x39, 0x37, 0x4F, 0xE9,
+
+       0x2F, 0x2F, 0x17, 0xAF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x31, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x57, 0x39, 0x20, 0xE9,
+
+       0x16, 0x28, 0x20, 0xE9,
+       0x1D, 0x3B, 0x20, 0xE9,
+
+       0x1E, 0x2B, 0x20, 0xE9,
+       0x2B, 0x32, 0x20, 0xE9,
+
+       0x1C, 0x23, 0x20, 0xE9,
+       0x57, 0x36, 0x20, 0xE9,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x90, 0xE2,
+       0x00, 0xE0,
+
+       0x78, 0xFF, 0x20, 0xEA,
+       0x19, 0xC8, 0xC1, 0xCD,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x9F, 0x41, 0x49, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x25, 0x41, 0x49, 0xBD,
+       0x2D, 0x41, 0x51, 0xBD,
+
+       0x0D, 0x80, 0x07, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x35, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x25, 0x30,
+       0x2D, 0x30,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0xA7, 0x5B, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x77, 0xFF, 0x0A, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC9, 0x41, 0xC8, 0xEC,
+       0x42, 0xE1,
+       0x00, 0xE0,
+
+       0x75, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC8, 0x40, 0xC0, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x72, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzs[] = {
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x98, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x81, 0x04,
+       0x89, 0x04,
+       0x01, 0x04,
+       0x09, 0x04,
+
+       0xC9, 0x41, 0xC0, 0xEC,
+       0x11, 0x04,
+       0x00, 0xE0,
+
+       0x41, 0xCC, 0x41, 0xCD,
+       0x49, 0xCC, 0x49, 0xCD,
+
+       0xD1, 0x41, 0xC0, 0xEC,
+       0x51, 0xCC, 0x51, 0xCD,
+
+       0x80, 0x04,
+       0x10, 0x04,
+       0x08, 0x04,
+       0x00, 0xE0,
+
+       0x00, 0xCC, 0xC0, 0xCD,
+       0xD1, 0x49, 0xC0, 0xEC,
+
+       0x8A, 0x1F, 0x20, 0xE9,
+       0x8B, 0x3F, 0x20, 0xE9,
+
+       0x41, 0x3C, 0x41, 0xAD,
+       0x49, 0x3C, 0x49, 0xAD,
+
+       0x10, 0xCC, 0x10, 0xCD,
+       0x08, 0xCC, 0x08, 0xCD,
+
+       0xB9, 0x41, 0x49, 0xBB,
+       0x1F, 0xF0, 0x41, 0xCD,
+
+       0x51, 0x3C, 0x51, 0xAD,
+       0x00, 0x98, 0x80, 0xE9,
+
+       0x8B, 0x80, 0x07, 0xEA,
+       0x24, 0x1F, 0x20, 0xE9,
+
+       0x21, 0x45, 0x80, 0xE8,
+       0x1A, 0x4D, 0x80, 0xE8,
+
+       0x31, 0x55, 0x80, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0x41, 0x49, 0xBD,
+       0x1D, 0x41, 0x51, 0xBD,
+
+       0x2E, 0x41, 0x2A, 0xB8,
+       0x34, 0x53, 0xA0, 0xE8,
+
+       0x15, 0x30,
+       0x1D, 0x30,
+       0x58, 0xE3,
+       0x00, 0xE0,
+
+       0xB5, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x24, 0x43, 0xA0, 0xE8,
+       0x2C, 0x4B, 0xA0, 0xE8,
+
+       0x15, 0x72,
+       0x09, 0xE3,
+       0x00, 0xE0,
+       0x1D, 0x72,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0x97, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x6C, 0x64, 0xC8, 0xEC,
+       0x98, 0xE1,
+       0xB5, 0x05,
+
+       0xBD, 0x05,
+       0x2E, 0x30,
+       0x32, 0xC0, 0xA0, 0xE8,
+
+       0x33, 0xC0, 0xA0, 0xE8,
+       0x74, 0x64, 0xC8, 0xEC,
+
+       0x40, 0x3C, 0x40, 0xAD,
+       0x32, 0x6A,
+       0x2A, 0x30,
+
+       0x20, 0x73,
+       0x33, 0x6A,
+       0x00, 0xE0,
+       0x28, 0x73,
+
+       0x1C, 0x72,
+       0x83, 0xE2,
+       0x77, 0x80, 0x15, 0xEA,
+
+       0xB8, 0x3D, 0x28, 0xDF,
+       0x30, 0x35, 0x20, 0xDF,
+
+       0x40, 0x30,
+       0x00, 0xE0,
+       0xCC, 0xE2,
+       0x64, 0x72,
+
+       0x25, 0x42, 0x52, 0xBF,
+       0x2D, 0x42, 0x4A, 0xBF,
+
+       0x30, 0x2E, 0x30, 0xDF,
+       0x38, 0x2E, 0x38, 0xDF,
+
+       0x18, 0x1D, 0x45, 0xE9,
+       0x1E, 0x15, 0x45, 0xE9,
+
+       0x2B, 0x49, 0x51, 0xBD,
+       0x00, 0xE0,
+       0x1F, 0x73,
+
+       0x38, 0x38, 0x40, 0xAF,
+       0x30, 0x30, 0x40, 0xAF,
+
+       0x24, 0x1F, 0x24, 0xDF,
+       0x1D, 0x32, 0x20, 0xE9,
+
+       0x2C, 0x1F, 0x2C, 0xDF,
+       0x1A, 0x33, 0x20, 0xE9,
+
+       0xB0, 0x10,
+       0x08, 0xE3,
+       0x40, 0x10,
+       0xB8, 0x10,
+
+       0x26, 0xF0, 0x30, 0xCD,
+       0x2F, 0xF0, 0x38, 0xCD,
+
+       0x2B, 0x80, 0x20, 0xE9,
+       0x2A, 0x80, 0x20, 0xE9,
+
+       0xA6, 0x20,
+       0x88, 0xE2,
+       0x00, 0xE0,
+       0xAF, 0x20,
+
+       0x28, 0x2A, 0x26, 0xAF,
+       0x20, 0x2A, 0xC0, 0xAF,
+
+       0x34, 0x1F, 0x34, 0xDF,
+       0x46, 0x24, 0x46, 0xDF,
+
+       0x28, 0x30, 0x80, 0xBF,
+       0x20, 0x38, 0x80, 0xBF,
+
+       0x47, 0x24, 0x47, 0xDF,
+       0x4E, 0x2C, 0x4E, 0xDF,
+
+       0x4F, 0x2C, 0x4F, 0xDF,
+       0x56, 0x34, 0x56, 0xDF,
+
+       0x28, 0x15, 0x28, 0xDF,
+       0x20, 0x1D, 0x20, 0xDF,
+
+       0x57, 0x34, 0x57, 0xDF,
+       0x00, 0xE0,
+       0x1D, 0x05,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x89, 0xE2,
+       0x2B, 0x30,
+
+       0x3F, 0xC1, 0x1D, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA0, 0x68,
+       0xBF, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x20, 0xC0, 0x20, 0xAF,
+       0x28, 0x05,
+       0x97, 0x74,
+
+       0x00, 0xE0,
+       0x2A, 0x10,
+       0x16, 0xC0, 0x20, 0xE9,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x8C, 0xE2,
+       0x95, 0x05,
+
+       0x28, 0xC1, 0x28, 0xAD,
+       0x1F, 0xC1, 0x15, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA8, 0x67,
+       0x9F, 0x6B,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x28, 0xC0, 0x28, 0xAD,
+       0x1D, 0x25,
+       0x20, 0x05,
+
+       0x28, 0x32, 0x80, 0xAD,
+       0x40, 0x2A, 0x40, 0xBD,
+
+       0x1C, 0x80, 0x20, 0xE9,
+       0x20, 0x33, 0x20, 0xAD,
+
+       0x20, 0x73,
+       0x00, 0xE0,
+       0xB6, 0x49, 0x51, 0xBB,
+
+       0x26, 0x2F, 0xB0, 0xE8,
+       0x19, 0x20, 0x20, 0xE9,
+
+       0x35, 0x20, 0x35, 0xDF,
+       0x3D, 0x20, 0x3D, 0xDF,
+
+       0x15, 0x20, 0x15, 0xDF,
+       0x1D, 0x20, 0x1D, 0xDF,
+
+       0x26, 0xD0, 0x26, 0xCD,
+       0x29, 0x49, 0x2A, 0xB8,
+
+       0x26, 0x40, 0x80, 0xBD,
+       0x3B, 0x48, 0x50, 0xBD,
+
+       0x3E, 0x54, 0x57, 0x9F,
+       0x00, 0xE0,
+       0x82, 0xE1,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x26, 0x30,
+       0x29, 0x30,
+       0x48, 0x3C, 0x48, 0xAD,
+
+       0x2B, 0x72,
+       0xC2, 0xE1,
+       0x2C, 0xC0, 0x44, 0xC2,
+
+       0x05, 0x24, 0x34, 0xBF,
+       0x0D, 0x24, 0x2C, 0xBF,
+
+       0x2D, 0x46, 0x4E, 0xBF,
+       0x25, 0x46, 0x56, 0xBF,
+
+       0x20, 0x1D, 0x6F, 0x8F,
+       0x32, 0x3E, 0x5F, 0xE9,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x30,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x33, 0x1E, 0x5F, 0xE9,
+
+       0x05, 0x44, 0x54, 0xB2,
+       0x0D, 0x44, 0x4C, 0xB2,
+
+       0x19, 0xC0, 0xB0, 0xE8,
+       0x34, 0xC0, 0x44, 0xC4,
+
+       0x33, 0x73,
+       0x00, 0xE0,
+       0x3E, 0x62, 0x57, 0x9F,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0xE0,
+       0x0D, 0x20,
+
+       0x84, 0x3E, 0x58, 0xE9,
+       0x28, 0x1D, 0x6F, 0x8F,
+
+       0x05, 0x20,
+       0x00, 0xE0,
+       0x85, 0x1E, 0x58, 0xE9,
+
+       0x9B, 0x3B, 0x33, 0xDF,
+       0x20, 0x20, 0x42, 0xAF,
+
+       0x30, 0x42, 0x56, 0x9F,
+       0x80, 0x3E, 0x57, 0xE9,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x30, 0x80, 0x5F, 0xE9,
+
+       0x28, 0x28, 0x24, 0xAF,
+       0x81, 0x1E, 0x57, 0xE9,
+
+       0x05, 0x47, 0x57, 0xBF,
+       0x0D, 0x47, 0x4F, 0xBF,
+
+       0x88, 0x80, 0x58, 0xE9,
+       0x1B, 0x29, 0x1B, 0xDF,
+
+       0x30, 0x1D, 0x6F, 0x8F,
+       0x3A, 0x30, 0x4F, 0xE9,
+
+       0x1C, 0x30, 0x26, 0xDF,
+       0x09, 0xE3,
+       0x3B, 0x05,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x3B, 0x3F, 0x4F, 0xE9,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x00, 0xE0,
+       0xAC, 0x20,
+
+       0x2D, 0x44, 0x4C, 0xB4,
+       0x2C, 0x1C, 0xC0, 0xAF,
+
+       0x25, 0x44, 0x54, 0xB4,
+       0x00, 0xE0,
+       0xC8, 0x30,
+
+       0x30, 0x46, 0x30, 0xAF,
+       0x1B, 0x1B, 0x48, 0xAF,
+
+       0x00, 0xE0,
+       0x25, 0x20,
+       0x38, 0x2C, 0x4F, 0xE9,
+
+       0x86, 0x80, 0x57, 0xE9,
+       0x38, 0x1D, 0x6F, 0x8F,
+
+       0x28, 0x74,
+       0x00, 0xE0,
+       0x0D, 0x44, 0x4C, 0xB0,
+
+       0x05, 0x44, 0x54, 0xB0,
+       0x2D, 0x20,
+       0x9B, 0x10,
+
+       0x82, 0x3E, 0x57, 0xE9,
+       0x32, 0xF0, 0x1B, 0xCD,
+
+       0x1E, 0xBD, 0x59, 0x9F,
+       0x83, 0x1E, 0x57, 0xE9,
+
+       0x38, 0x47, 0x38, 0xAF,
+       0x34, 0x20,
+       0x2A, 0x30,
+
+       0x00, 0xE0,
+       0x0D, 0x20,
+       0x32, 0x20,
+       0x05, 0x20,
+
+       0x87, 0x80, 0x57, 0xE9,
+       0x1F, 0x54, 0x57, 0x9F,
+
+       0x17, 0x42, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x6A,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x37, 0x1E, 0x4F, 0xE9,
+
+       0x37, 0x32, 0x2A, 0xAF,
+       0x00, 0xE0,
+       0x32, 0x00,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x27, 0xC0, 0x44, 0xC0,
+
+       0x36, 0x1F, 0x4F, 0xE9,
+       0x1F, 0x1F, 0x26, 0xDF,
+
+       0x37, 0x1B, 0x37, 0xBF,
+       0x17, 0x26, 0x17, 0xDF,
+
+       0x3E, 0x17, 0x4F, 0xE9,
+       0x3F, 0x3F, 0x4F, 0xE9,
+
+       0x34, 0x1F, 0x34, 0xAF,
+       0x2B, 0x05,
+       0xA7, 0x20,
+
+       0x33, 0x2B, 0x37, 0xDF,
+       0x27, 0x17, 0xC0, 0xAF,
+
+       0x34, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x2D, 0x21, 0x1A, 0xB0,
+       0x25, 0x21, 0x31, 0xB0,
+
+       0x0D, 0x21, 0x1A, 0xB2,
+       0x05, 0x21, 0x31, 0xB2,
+
+       0x03, 0x80, 0x2A, 0xEA,
+       0x17, 0xC1, 0x2B, 0xBD,
+
+       0x2D, 0x20,
+       0x25, 0x20,
+       0x05, 0x20,
+       0x0D, 0x20,
+
+       0xB3, 0x68,
+       0x97, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x33, 0xC0, 0x33, 0xAF,
+       0x2F, 0xC0, 0x21, 0xC0,
+
+       0x16, 0x42, 0x56, 0x9F,
+       0x3C, 0x27, 0x4F, 0xE9,
+
+       0x1E, 0x62, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x25, 0x21, 0x31, 0xB4,
+       0x2D, 0x21, 0x1A, 0xB4,
+
+       0x3F, 0x2F, 0x5D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x33, 0x05,
+       0x00, 0xE0,
+       0x28, 0x19, 0x60, 0xEC,
+
+       0x37, 0x0F, 0x5C, 0x9F,
+       0x00, 0xE0,
+       0x2F, 0x20,
+
+       0x23, 0x3B, 0x33, 0xAD,
+       0x1E, 0x26, 0x1E, 0xDF,
+
+       0xA7, 0x1E, 0x4F, 0xE9,
+       0x17, 0x26, 0x16, 0xDF,
+
+       0x2D, 0x20,
+       0x00, 0xE0,
+       0xA8, 0x3F, 0x4F, 0xE9,
+
+       0x2F, 0x2F, 0x1E, 0xAF,
+       0x25, 0x20,
+       0x00, 0xE0,
+
+       0xA4, 0x16, 0x4F, 0xE9,
+       0x0F, 0xC0, 0x21, 0xC2,
+
+       0xA6, 0x80, 0x4F, 0xE9,
+       0x1F, 0x62, 0x57, 0x9F,
+
+       0x3F, 0x2F, 0x5D, 0x9F,
+       0x00, 0xE0,
+       0x8F, 0x20,
+
+       0xA5, 0x37, 0x4F, 0xE9,
+       0x0F, 0x17, 0x0F, 0xAF,
+
+       0x06, 0xC0, 0x21, 0xC4,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0xA3, 0x80, 0x4F, 0xE9,
+
+       0x06, 0x20,
+       0x00, 0xE0,
+       0x1F, 0x26, 0x1F, 0xDF,
+
+       0xA1, 0x1F, 0x4F, 0xE9,
+       0xA2, 0x3F, 0x4F, 0xE9,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x06, 0x06, 0x1F, 0xAF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA0, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x57, 0x39, 0x20, 0xE9,
+
+       0x16, 0x28, 0x20, 0xE9,
+       0x1D, 0x3B, 0x20, 0xE9,
+
+       0x1E, 0x2B, 0x20, 0xE9,
+       0x2B, 0x32, 0x20, 0xE9,
+
+       0x1C, 0x23, 0x20, 0xE9,
+       0x57, 0x36, 0x20, 0xE9,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x90, 0xE2,
+       0x00, 0xE0,
+
+       0x6C, 0xFF, 0x20, 0xEA,
+       0x19, 0xC8, 0xC1, 0xCD,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x9F, 0x41, 0x49, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x25, 0x41, 0x49, 0xBD,
+       0x2D, 0x41, 0x51, 0xBD,
+
+       0x0D, 0x80, 0x07, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x35, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x25, 0x30,
+       0x2D, 0x30,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0xA7, 0x5B, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x6B, 0xFF, 0x0A, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC9, 0x41, 0xC8, 0xEC,
+       0x42, 0xE1,
+       0x00, 0xE0,
+
+       0x69, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC8, 0x40, 0xC0, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x66, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzsa[] = {
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x98, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x81, 0x04,
+       0x89, 0x04,
+       0x01, 0x04,
+       0x09, 0x04,
+
+       0xC9, 0x41, 0xC0, 0xEC,
+       0x11, 0x04,
+       0x00, 0xE0,
+
+       0x41, 0xCC, 0x41, 0xCD,
+       0x49, 0xCC, 0x49, 0xCD,
+
+       0xD1, 0x41, 0xC0, 0xEC,
+       0x51, 0xCC, 0x51, 0xCD,
+
+       0x80, 0x04,
+       0x10, 0x04,
+       0x08, 0x04,
+       0x00, 0xE0,
+
+       0x00, 0xCC, 0xC0, 0xCD,
+       0xD1, 0x49, 0xC0, 0xEC,
+
+       0x8A, 0x1F, 0x20, 0xE9,
+       0x8B, 0x3F, 0x20, 0xE9,
+
+       0x41, 0x3C, 0x41, 0xAD,
+       0x49, 0x3C, 0x49, 0xAD,
+
+       0x10, 0xCC, 0x10, 0xCD,
+       0x08, 0xCC, 0x08, 0xCD,
+
+       0xB9, 0x41, 0x49, 0xBB,
+       0x1F, 0xF0, 0x41, 0xCD,
+
+       0x51, 0x3C, 0x51, 0xAD,
+       0x00, 0x98, 0x80, 0xE9,
+
+       0x8F, 0x80, 0x07, 0xEA,
+       0x24, 0x1F, 0x20, 0xE9,
+
+       0x21, 0x45, 0x80, 0xE8,
+       0x1A, 0x4D, 0x80, 0xE8,
+
+       0x31, 0x55, 0x80, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0x41, 0x49, 0xBD,
+       0x1D, 0x41, 0x51, 0xBD,
+
+       0x2E, 0x41, 0x2A, 0xB8,
+       0x34, 0x53, 0xA0, 0xE8,
+
+       0x15, 0x30,
+       0x1D, 0x30,
+       0x58, 0xE3,
+       0x00, 0xE0,
+
+       0xB5, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x24, 0x43, 0xA0, 0xE8,
+       0x2C, 0x4B, 0xA0, 0xE8,
+
+       0x15, 0x72,
+       0x09, 0xE3,
+       0x00, 0xE0,
+       0x1D, 0x72,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0x97, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x6C, 0x64, 0xC8, 0xEC,
+       0x98, 0xE1,
+       0xB5, 0x05,
+
+       0xBD, 0x05,
+       0x2E, 0x30,
+       0x32, 0xC0, 0xA0, 0xE8,
+
+       0x33, 0xC0, 0xA0, 0xE8,
+       0x74, 0x64, 0xC8, 0xEC,
+
+       0x40, 0x3C, 0x40, 0xAD,
+       0x32, 0x6A,
+       0x2A, 0x30,
+
+       0x20, 0x73,
+       0x33, 0x6A,
+       0x00, 0xE0,
+       0x28, 0x73,
+
+       0x1C, 0x72,
+       0x83, 0xE2,
+       0x7B, 0x80, 0x15, 0xEA,
+
+       0xB8, 0x3D, 0x28, 0xDF,
+       0x30, 0x35, 0x20, 0xDF,
+
+       0x40, 0x30,
+       0x00, 0xE0,
+       0xCC, 0xE2,
+       0x64, 0x72,
+
+       0x25, 0x42, 0x52, 0xBF,
+       0x2D, 0x42, 0x4A, 0xBF,
+
+       0x30, 0x2E, 0x30, 0xDF,
+       0x38, 0x2E, 0x38, 0xDF,
+
+       0x18, 0x1D, 0x45, 0xE9,
+       0x1E, 0x15, 0x45, 0xE9,
+
+       0x2B, 0x49, 0x51, 0xBD,
+       0x00, 0xE0,
+       0x1F, 0x73,
+
+       0x38, 0x38, 0x40, 0xAF,
+       0x30, 0x30, 0x40, 0xAF,
+
+       0x24, 0x1F, 0x24, 0xDF,
+       0x1D, 0x32, 0x20, 0xE9,
+
+       0x2C, 0x1F, 0x2C, 0xDF,
+       0x1A, 0x33, 0x20, 0xE9,
+
+       0xB0, 0x10,
+       0x08, 0xE3,
+       0x40, 0x10,
+       0xB8, 0x10,
+
+       0x26, 0xF0, 0x30, 0xCD,
+       0x2F, 0xF0, 0x38, 0xCD,
+
+       0x2B, 0x80, 0x20, 0xE9,
+       0x2A, 0x80, 0x20, 0xE9,
+
+       0xA6, 0x20,
+       0x88, 0xE2,
+       0x00, 0xE0,
+       0xAF, 0x20,
+
+       0x28, 0x2A, 0x26, 0xAF,
+       0x20, 0x2A, 0xC0, 0xAF,
+
+       0x34, 0x1F, 0x34, 0xDF,
+       0x46, 0x24, 0x46, 0xDF,
+
+       0x28, 0x30, 0x80, 0xBF,
+       0x20, 0x38, 0x80, 0xBF,
+
+       0x47, 0x24, 0x47, 0xDF,
+       0x4E, 0x2C, 0x4E, 0xDF,
+
+       0x4F, 0x2C, 0x4F, 0xDF,
+       0x56, 0x34, 0x56, 0xDF,
+
+       0x28, 0x15, 0x28, 0xDF,
+       0x20, 0x1D, 0x20, 0xDF,
+
+       0x57, 0x34, 0x57, 0xDF,
+       0x00, 0xE0,
+       0x1D, 0x05,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x89, 0xE2,
+       0x2B, 0x30,
+
+       0x3F, 0xC1, 0x1D, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA0, 0x68,
+       0xBF, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x20, 0xC0, 0x20, 0xAF,
+       0x28, 0x05,
+       0x97, 0x74,
+
+       0x00, 0xE0,
+       0x2A, 0x10,
+       0x16, 0xC0, 0x20, 0xE9,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x8C, 0xE2,
+       0x95, 0x05,
+
+       0x28, 0xC1, 0x28, 0xAD,
+       0x1F, 0xC1, 0x15, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA8, 0x67,
+       0x9F, 0x6B,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x28, 0xC0, 0x28, 0xAD,
+       0x1D, 0x25,
+       0x20, 0x05,
+
+       0x28, 0x32, 0x80, 0xAD,
+       0x40, 0x2A, 0x40, 0xBD,
+
+       0x1C, 0x80, 0x20, 0xE9,
+       0x20, 0x33, 0x20, 0xAD,
+
+       0x20, 0x73,
+       0x00, 0xE0,
+       0xB6, 0x49, 0x51, 0xBB,
+
+       0x26, 0x2F, 0xB0, 0xE8,
+       0x19, 0x20, 0x20, 0xE9,
+
+       0x35, 0x20, 0x35, 0xDF,
+       0x3D, 0x20, 0x3D, 0xDF,
+
+       0x15, 0x20, 0x15, 0xDF,
+       0x1D, 0x20, 0x1D, 0xDF,
+
+       0x26, 0xD0, 0x26, 0xCD,
+       0x29, 0x49, 0x2A, 0xB8,
+
+       0x26, 0x40, 0x80, 0xBD,
+       0x3B, 0x48, 0x50, 0xBD,
+
+       0x3E, 0x54, 0x57, 0x9F,
+       0x00, 0xE0,
+       0x82, 0xE1,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x26, 0x30,
+       0x29, 0x30,
+       0x48, 0x3C, 0x48, 0xAD,
+
+       0x2B, 0x72,
+       0xC2, 0xE1,
+       0x2C, 0xC0, 0x44, 0xC2,
+
+       0x05, 0x24, 0x34, 0xBF,
+       0x0D, 0x24, 0x2C, 0xBF,
+
+       0x2D, 0x46, 0x4E, 0xBF,
+       0x25, 0x46, 0x56, 0xBF,
+
+       0x20, 0x1D, 0x6F, 0x8F,
+       0x32, 0x3E, 0x5F, 0xE9,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x30,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x33, 0x1E, 0x5F, 0xE9,
+
+       0x05, 0x44, 0x54, 0xB2,
+       0x0D, 0x44, 0x4C, 0xB2,
+
+       0x19, 0xC0, 0xB0, 0xE8,
+       0x34, 0xC0, 0x44, 0xC4,
+
+       0x33, 0x73,
+       0x00, 0xE0,
+       0x3E, 0x62, 0x57, 0x9F,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0xE0,
+       0x0D, 0x20,
+
+       0x84, 0x3E, 0x58, 0xE9,
+       0x28, 0x1D, 0x6F, 0x8F,
+
+       0x05, 0x20,
+       0x00, 0xE0,
+       0x85, 0x1E, 0x58, 0xE9,
+
+       0x9B, 0x3B, 0x33, 0xDF,
+       0x20, 0x20, 0x42, 0xAF,
+
+       0x30, 0x42, 0x56, 0x9F,
+       0x80, 0x3E, 0x57, 0xE9,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x30, 0x80, 0x5F, 0xE9,
+
+       0x28, 0x28, 0x24, 0xAF,
+       0x81, 0x1E, 0x57, 0xE9,
+
+       0x05, 0x47, 0x57, 0xBF,
+       0x0D, 0x47, 0x4F, 0xBF,
+
+       0x88, 0x80, 0x58, 0xE9,
+       0x1B, 0x29, 0x1B, 0xDF,
+
+       0x30, 0x1D, 0x6F, 0x8F,
+       0x3A, 0x30, 0x4F, 0xE9,
+
+       0x1C, 0x30, 0x26, 0xDF,
+       0x09, 0xE3,
+       0x3B, 0x05,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x3B, 0x3F, 0x4F, 0xE9,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x00, 0xE0,
+       0xAC, 0x20,
+
+       0x2D, 0x44, 0x4C, 0xB4,
+       0x2C, 0x1C, 0xC0, 0xAF,
+
+       0x25, 0x44, 0x54, 0xB4,
+       0x00, 0xE0,
+       0xC8, 0x30,
+
+       0x30, 0x46, 0x30, 0xAF,
+       0x1B, 0x1B, 0x48, 0xAF,
+
+       0x00, 0xE0,
+       0x25, 0x20,
+       0x38, 0x2C, 0x4F, 0xE9,
+
+       0x86, 0x80, 0x57, 0xE9,
+       0x38, 0x1D, 0x6F, 0x8F,
+
+       0x28, 0x74,
+       0x00, 0xE0,
+       0x0D, 0x44, 0x4C, 0xB0,
+
+       0x05, 0x44, 0x54, 0xB0,
+       0x2D, 0x20,
+       0x9B, 0x10,
+
+       0x82, 0x3E, 0x57, 0xE9,
+       0x32, 0xF0, 0x1B, 0xCD,
+
+       0x1E, 0xBD, 0x59, 0x9F,
+       0x83, 0x1E, 0x57, 0xE9,
+
+       0x38, 0x47, 0x38, 0xAF,
+       0x34, 0x20,
+       0x2A, 0x30,
+
+       0x00, 0xE0,
+       0x0D, 0x20,
+       0x32, 0x20,
+       0x05, 0x20,
+
+       0x87, 0x80, 0x57, 0xE9,
+       0x1F, 0x54, 0x57, 0x9F,
+
+       0x17, 0x42, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x6A,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x37, 0x1E, 0x4F, 0xE9,
+
+       0x37, 0x32, 0x2A, 0xAF,
+       0x00, 0xE0,
+       0x32, 0x00,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x27, 0xC0, 0x44, 0xC0,
+
+       0x36, 0x1F, 0x4F, 0xE9,
+       0x1F, 0x1F, 0x26, 0xDF,
+
+       0x37, 0x1B, 0x37, 0xBF,
+       0x17, 0x26, 0x17, 0xDF,
+
+       0x3E, 0x17, 0x4F, 0xE9,
+       0x3F, 0x3F, 0x4F, 0xE9,
+
+       0x34, 0x1F, 0x34, 0xAF,
+       0x2B, 0x05,
+       0xA7, 0x20,
+
+       0x33, 0x2B, 0x37, 0xDF,
+       0x27, 0x17, 0xC0, 0xAF,
+
+       0x34, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x2D, 0x21, 0x1A, 0xB0,
+       0x25, 0x21, 0x31, 0xB0,
+
+       0x0D, 0x21, 0x1A, 0xB2,
+       0x05, 0x21, 0x31, 0xB2,
+
+       0x03, 0x80, 0x2A, 0xEA,
+       0x17, 0xC1, 0x2B, 0xBD,
+
+       0x2D, 0x20,
+       0x25, 0x20,
+       0x05, 0x20,
+       0x0D, 0x20,
+
+       0xB3, 0x68,
+       0x97, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x33, 0xC0, 0x33, 0xAF,
+       0x2F, 0xC0, 0x21, 0xC0,
+
+       0x16, 0x42, 0x56, 0x9F,
+       0x3C, 0x27, 0x4F, 0xE9,
+
+       0x1E, 0x62, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x25, 0x21, 0x31, 0xB4,
+       0x2D, 0x21, 0x1A, 0xB4,
+
+       0x3F, 0x2F, 0x5D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x33, 0x05,
+       0x00, 0xE0,
+       0x28, 0x19, 0x60, 0xEC,
+
+       0x0D, 0x44, 0x4C, 0xB6,
+       0x05, 0x44, 0x54, 0xB6,
+
+       0x37, 0x0F, 0x5C, 0x9F,
+       0x00, 0xE0,
+       0x2F, 0x20,
+
+       0x23, 0x3B, 0x33, 0xAD,
+       0x1E, 0x26, 0x1E, 0xDF,
+
+       0xA7, 0x1E, 0x4F, 0xE9,
+       0x17, 0x26, 0x16, 0xDF,
+
+       0x2D, 0x20,
+       0x00, 0xE0,
+       0xA8, 0x3F, 0x4F, 0xE9,
+
+       0x2F, 0x2F, 0x1E, 0xAF,
+       0x25, 0x20,
+       0x00, 0xE0,
+
+       0xA4, 0x16, 0x4F, 0xE9,
+       0x0F, 0xC0, 0x21, 0xC2,
+
+       0xA6, 0x80, 0x4F, 0xE9,
+       0x1F, 0x62, 0x57, 0x9F,
+
+       0x0D, 0x20,
+       0x05, 0x20,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x3F, 0x2F, 0x5D, 0x9F,
+       0x00, 0xE0,
+       0x0F, 0x20,
+
+       0x17, 0x50, 0x56, 0x9F,
+       0xA5, 0x37, 0x4F, 0xE9,
+
+       0x06, 0xC0, 0x21, 0xC4,
+       0x0F, 0x17, 0x0F, 0xAF,
+
+       0x37, 0x0F, 0x5C, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x2F, 0xC0, 0x44, 0xC6,
+       0xA3, 0x80, 0x4F, 0xE9,
+
+       0x06, 0x20,
+       0x00, 0xE0,
+       0x1F, 0x26, 0x1F, 0xDF,
+
+       0x17, 0x26, 0x17, 0xDF,
+       0x9D, 0x17, 0x4F, 0xE9,
+
+       0xA1, 0x1F, 0x4F, 0xE9,
+       0xA2, 0x3F, 0x4F, 0xE9,
+
+       0x06, 0x06, 0x1F, 0xAF,
+       0x00, 0xE0,
+       0xAF, 0x20,
+
+       0x9E, 0x37, 0x4F, 0xE9,
+       0x2F, 0x17, 0x2F, 0xAF,
+
+       0xA0, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x9C, 0x80, 0x4F, 0xE9,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x57, 0x39, 0x20, 0xE9,
+
+       0x16, 0x28, 0x20, 0xE9,
+       0x1D, 0x3B, 0x20, 0xE9,
+
+       0x1E, 0x2B, 0x20, 0xE9,
+       0x2B, 0x32, 0x20, 0xE9,
+
+       0x1C, 0x23, 0x20, 0xE9,
+       0x57, 0x36, 0x20, 0xE9,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x90, 0xE2,
+       0x00, 0xE0,
+
+       0x68, 0xFF, 0x20, 0xEA,
+       0x19, 0xC8, 0xC1, 0xCD,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x9F, 0x41, 0x49, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x25, 0x41, 0x49, 0xBD,
+       0x2D, 0x41, 0x51, 0xBD,
+
+       0x0D, 0x80, 0x07, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x35, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x25, 0x30,
+       0x2D, 0x30,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0xA7, 0x5B, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x67, 0xFF, 0x0A, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC9, 0x41, 0xC8, 0xEC,
+       0x42, 0xE1,
+       0x00, 0xE0,
+
+       0x65, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC8, 0x40, 0xC0, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x62, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzsaf[] = {
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x98, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x81, 0x04,
+       0x89, 0x04,
+       0x01, 0x04,
+       0x09, 0x04,
+
+       0xC9, 0x41, 0xC0, 0xEC,
+       0x11, 0x04,
+       0x00, 0xE0,
+
+       0x41, 0xCC, 0x41, 0xCD,
+       0x49, 0xCC, 0x49, 0xCD,
+
+       0xD1, 0x41, 0xC0, 0xEC,
+       0x51, 0xCC, 0x51, 0xCD,
+
+       0x80, 0x04,
+       0x10, 0x04,
+       0x08, 0x04,
+       0x00, 0xE0,
+
+       0x00, 0xCC, 0xC0, 0xCD,
+       0xD1, 0x49, 0xC0, 0xEC,
+
+       0x8A, 0x1F, 0x20, 0xE9,
+       0x8B, 0x3F, 0x20, 0xE9,
+
+       0x41, 0x3C, 0x41, 0xAD,
+       0x49, 0x3C, 0x49, 0xAD,
+
+       0x10, 0xCC, 0x10, 0xCD,
+       0x08, 0xCC, 0x08, 0xCD,
+
+       0xB9, 0x41, 0x49, 0xBB,
+       0x1F, 0xF0, 0x41, 0xCD,
+
+       0x51, 0x3C, 0x51, 0xAD,
+       0x00, 0x98, 0x80, 0xE9,
+
+       0x94, 0x80, 0x07, 0xEA,
+       0x24, 0x1F, 0x20, 0xE9,
+
+       0x21, 0x45, 0x80, 0xE8,
+       0x1A, 0x4D, 0x80, 0xE8,
+
+       0x31, 0x55, 0x80, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0x41, 0x49, 0xBD,
+       0x1D, 0x41, 0x51, 0xBD,
+
+       0x2E, 0x41, 0x2A, 0xB8,
+       0x34, 0x53, 0xA0, 0xE8,
+
+       0x15, 0x30,
+       0x1D, 0x30,
+       0x58, 0xE3,
+       0x00, 0xE0,
+
+       0xB5, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x24, 0x43, 0xA0, 0xE8,
+       0x2C, 0x4B, 0xA0, 0xE8,
+
+       0x15, 0x72,
+       0x09, 0xE3,
+       0x00, 0xE0,
+       0x1D, 0x72,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0x97, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x6C, 0x64, 0xC8, 0xEC,
+       0x98, 0xE1,
+       0xB5, 0x05,
+
+       0xBD, 0x05,
+       0x2E, 0x30,
+       0x32, 0xC0, 0xA0, 0xE8,
+
+       0x33, 0xC0, 0xA0, 0xE8,
+       0x74, 0x64, 0xC8, 0xEC,
+
+       0x40, 0x3C, 0x40, 0xAD,
+       0x32, 0x6A,
+       0x2A, 0x30,
+
+       0x20, 0x73,
+       0x33, 0x6A,
+       0x00, 0xE0,
+       0x28, 0x73,
+
+       0x1C, 0x72,
+       0x83, 0xE2,
+       0x80, 0x80, 0x15, 0xEA,
+
+       0xB8, 0x3D, 0x28, 0xDF,
+       0x30, 0x35, 0x20, 0xDF,
+
+       0x40, 0x30,
+       0x00, 0xE0,
+       0xCC, 0xE2,
+       0x64, 0x72,
+
+       0x25, 0x42, 0x52, 0xBF,
+       0x2D, 0x42, 0x4A, 0xBF,
+
+       0x30, 0x2E, 0x30, 0xDF,
+       0x38, 0x2E, 0x38, 0xDF,
+
+       0x18, 0x1D, 0x45, 0xE9,
+       0x1E, 0x15, 0x45, 0xE9,
+
+       0x2B, 0x49, 0x51, 0xBD,
+       0x00, 0xE0,
+       0x1F, 0x73,
+
+       0x38, 0x38, 0x40, 0xAF,
+       0x30, 0x30, 0x40, 0xAF,
+
+       0x24, 0x1F, 0x24, 0xDF,
+       0x1D, 0x32, 0x20, 0xE9,
+
+       0x2C, 0x1F, 0x2C, 0xDF,
+       0x1A, 0x33, 0x20, 0xE9,
+
+       0xB0, 0x10,
+       0x08, 0xE3,
+       0x40, 0x10,
+       0xB8, 0x10,
+
+       0x26, 0xF0, 0x30, 0xCD,
+       0x2F, 0xF0, 0x38, 0xCD,
+
+       0x2B, 0x80, 0x20, 0xE9,
+       0x2A, 0x80, 0x20, 0xE9,
+
+       0xA6, 0x20,
+       0x88, 0xE2,
+       0x00, 0xE0,
+       0xAF, 0x20,
+
+       0x28, 0x2A, 0x26, 0xAF,
+       0x20, 0x2A, 0xC0, 0xAF,
+
+       0x34, 0x1F, 0x34, 0xDF,
+       0x46, 0x24, 0x46, 0xDF,
+
+       0x28, 0x30, 0x80, 0xBF,
+       0x20, 0x38, 0x80, 0xBF,
+
+       0x47, 0x24, 0x47, 0xDF,
+       0x4E, 0x2C, 0x4E, 0xDF,
+
+       0x4F, 0x2C, 0x4F, 0xDF,
+       0x56, 0x34, 0x56, 0xDF,
+
+       0x28, 0x15, 0x28, 0xDF,
+       0x20, 0x1D, 0x20, 0xDF,
+
+       0x57, 0x34, 0x57, 0xDF,
+       0x00, 0xE0,
+       0x1D, 0x05,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x89, 0xE2,
+       0x2B, 0x30,
+
+       0x3F, 0xC1, 0x1D, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA0, 0x68,
+       0xBF, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x20, 0xC0, 0x20, 0xAF,
+       0x28, 0x05,
+       0x97, 0x74,
+
+       0x00, 0xE0,
+       0x2A, 0x10,
+       0x16, 0xC0, 0x20, 0xE9,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x8C, 0xE2,
+       0x95, 0x05,
+
+       0x28, 0xC1, 0x28, 0xAD,
+       0x1F, 0xC1, 0x15, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA8, 0x67,
+       0x9F, 0x6B,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x28, 0xC0, 0x28, 0xAD,
+       0x1D, 0x25,
+       0x20, 0x05,
+
+       0x28, 0x32, 0x80, 0xAD,
+       0x40, 0x2A, 0x40, 0xBD,
+
+       0x1C, 0x80, 0x20, 0xE9,
+       0x20, 0x33, 0x20, 0xAD,
+
+       0x20, 0x73,
+       0x00, 0xE0,
+       0xB6, 0x49, 0x51, 0xBB,
+
+       0x26, 0x2F, 0xB0, 0xE8,
+       0x19, 0x20, 0x20, 0xE9,
+
+       0x35, 0x20, 0x35, 0xDF,
+       0x3D, 0x20, 0x3D, 0xDF,
+
+       0x15, 0x20, 0x15, 0xDF,
+       0x1D, 0x20, 0x1D, 0xDF,
+
+       0x26, 0xD0, 0x26, 0xCD,
+       0x29, 0x49, 0x2A, 0xB8,
+
+       0x26, 0x40, 0x80, 0xBD,
+       0x3B, 0x48, 0x50, 0xBD,
+
+       0x3E, 0x54, 0x57, 0x9F,
+       0x00, 0xE0,
+       0x82, 0xE1,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x26, 0x30,
+       0x29, 0x30,
+       0x48, 0x3C, 0x48, 0xAD,
+
+       0x2B, 0x72,
+       0xC2, 0xE1,
+       0x2C, 0xC0, 0x44, 0xC2,
+
+       0x05, 0x24, 0x34, 0xBF,
+       0x0D, 0x24, 0x2C, 0xBF,
+
+       0x2D, 0x46, 0x4E, 0xBF,
+       0x25, 0x46, 0x56, 0xBF,
+
+       0x20, 0x1D, 0x6F, 0x8F,
+       0x32, 0x3E, 0x5F, 0xE9,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x30,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x33, 0x1E, 0x5F, 0xE9,
+
+       0x05, 0x44, 0x54, 0xB2,
+       0x0D, 0x44, 0x4C, 0xB2,
+
+       0x19, 0xC0, 0xB0, 0xE8,
+       0x34, 0xC0, 0x44, 0xC4,
+
+       0x33, 0x73,
+       0x00, 0xE0,
+       0x3E, 0x62, 0x57, 0x9F,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0xE0,
+       0x0D, 0x20,
+
+       0x84, 0x3E, 0x58, 0xE9,
+       0x28, 0x1D, 0x6F, 0x8F,
+
+       0x05, 0x20,
+       0x00, 0xE0,
+       0x85, 0x1E, 0x58, 0xE9,
+
+       0x9B, 0x3B, 0x33, 0xDF,
+       0x20, 0x20, 0x42, 0xAF,
+
+       0x30, 0x42, 0x56, 0x9F,
+       0x80, 0x3E, 0x57, 0xE9,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x30, 0x80, 0x5F, 0xE9,
+
+       0x28, 0x28, 0x24, 0xAF,
+       0x81, 0x1E, 0x57, 0xE9,
+
+       0x05, 0x47, 0x57, 0xBF,
+       0x0D, 0x47, 0x4F, 0xBF,
+
+       0x88, 0x80, 0x58, 0xE9,
+       0x1B, 0x29, 0x1B, 0xDF,
+
+       0x30, 0x1D, 0x6F, 0x8F,
+       0x3A, 0x30, 0x4F, 0xE9,
+
+       0x1C, 0x30, 0x26, 0xDF,
+       0x09, 0xE3,
+       0x3B, 0x05,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x3B, 0x3F, 0x4F, 0xE9,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x00, 0xE0,
+       0xAC, 0x20,
+
+       0x2D, 0x44, 0x4C, 0xB4,
+       0x2C, 0x1C, 0xC0, 0xAF,
+
+       0x25, 0x44, 0x54, 0xB4,
+       0x00, 0xE0,
+       0xC8, 0x30,
+
+       0x30, 0x46, 0x30, 0xAF,
+       0x1B, 0x1B, 0x48, 0xAF,
+
+       0x00, 0xE0,
+       0x25, 0x20,
+       0x38, 0x2C, 0x4F, 0xE9,
+
+       0x86, 0x80, 0x57, 0xE9,
+       0x38, 0x1D, 0x6F, 0x8F,
+
+       0x28, 0x74,
+       0x00, 0xE0,
+       0x0D, 0x44, 0x4C, 0xB0,
+
+       0x05, 0x44, 0x54, 0xB0,
+       0x2D, 0x20,
+       0x9B, 0x10,
+
+       0x82, 0x3E, 0x57, 0xE9,
+       0x32, 0xF0, 0x1B, 0xCD,
+
+       0x1E, 0xBD, 0x59, 0x9F,
+       0x83, 0x1E, 0x57, 0xE9,
+
+       0x38, 0x47, 0x38, 0xAF,
+       0x34, 0x20,
+       0x2A, 0x30,
+
+       0x00, 0xE0,
+       0x0D, 0x20,
+       0x32, 0x20,
+       0x05, 0x20,
+
+       0x87, 0x80, 0x57, 0xE9,
+       0x1F, 0x54, 0x57, 0x9F,
+
+       0x17, 0x42, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x6A,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x37, 0x1E, 0x4F, 0xE9,
+
+       0x37, 0x32, 0x2A, 0xAF,
+       0x00, 0xE0,
+       0x32, 0x00,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x27, 0xC0, 0x44, 0xC0,
+
+       0x36, 0x1F, 0x4F, 0xE9,
+       0x1F, 0x1F, 0x26, 0xDF,
+
+       0x37, 0x1B, 0x37, 0xBF,
+       0x17, 0x26, 0x17, 0xDF,
+
+       0x3E, 0x17, 0x4F, 0xE9,
+       0x3F, 0x3F, 0x4F, 0xE9,
+
+       0x34, 0x1F, 0x34, 0xAF,
+       0x2B, 0x05,
+       0xA7, 0x20,
+
+       0x33, 0x2B, 0x37, 0xDF,
+       0x27, 0x17, 0xC0, 0xAF,
+
+       0x34, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x2D, 0x21, 0x1A, 0xB0,
+       0x25, 0x21, 0x31, 0xB0,
+
+       0x0D, 0x21, 0x1A, 0xB2,
+       0x05, 0x21, 0x31, 0xB2,
+
+       0x03, 0x80, 0x2A, 0xEA,
+       0x17, 0xC1, 0x2B, 0xBD,
+
+       0x2D, 0x20,
+       0x25, 0x20,
+       0x05, 0x20,
+       0x0D, 0x20,
+
+       0xB3, 0x68,
+       0x97, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x33, 0xC0, 0x33, 0xAF,
+       0x2F, 0xC0, 0x21, 0xC0,
+
+       0x16, 0x42, 0x56, 0x9F,
+       0x3C, 0x27, 0x4F, 0xE9,
+
+       0x1E, 0x62, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x25, 0x21, 0x31, 0xB4,
+       0x2D, 0x21, 0x1A, 0xB4,
+
+       0x3F, 0x2F, 0x5D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x33, 0x05,
+       0x00, 0xE0,
+       0x28, 0x19, 0x60, 0xEC,
+
+       0x0D, 0x21, 0x1A, 0xB6,
+       0x05, 0x21, 0x31, 0xB6,
+
+       0x37, 0x0F, 0x5C, 0x9F,
+       0x00, 0xE0,
+       0x2F, 0x20,
+
+       0x23, 0x3B, 0x33, 0xAD,
+       0x1E, 0x26, 0x1E, 0xDF,
+
+       0xA7, 0x1E, 0x4F, 0xE9,
+       0x17, 0x26, 0x16, 0xDF,
+
+       0x2D, 0x20,
+       0x00, 0xE0,
+       0xA8, 0x3F, 0x4F, 0xE9,
+
+       0x2F, 0x2F, 0x1E, 0xAF,
+       0x25, 0x20,
+       0x00, 0xE0,
+
+       0xA4, 0x16, 0x4F, 0xE9,
+       0x0F, 0xC0, 0x21, 0xC2,
+
+       0xA6, 0x80, 0x4F, 0xE9,
+       0x1F, 0x62, 0x57, 0x9F,
+
+       0x0D, 0x20,
+       0x05, 0x20,
+       0x2F, 0xC0, 0x21, 0xC6,
+
+       0x2D, 0x44, 0x4C, 0xB6,
+       0x25, 0x44, 0x54, 0xB6,
+
+       0x3F, 0x2F, 0x5D, 0x9F,
+       0x00, 0xE0,
+       0x0F, 0x20,
+
+       0x2D, 0x20,
+       0x25, 0x20,
+       0x07, 0xC0, 0x44, 0xC6,
+
+       0x17, 0x50, 0x56, 0x9F,
+       0xA5, 0x37, 0x4F, 0xE9,
+
+       0x06, 0xC0, 0x21, 0xC4,
+       0x0F, 0x17, 0x0F, 0xAF,
+
+       0x37, 0x0F, 0x5C, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x1E, 0x62, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x3E, 0x3D, 0x5D, 0x9F,
+       0x00, 0xE0,
+       0x07, 0x20,
+
+       0x2F, 0x20,
+       0x00, 0xE0,
+       0xA3, 0x0F, 0x4F, 0xE9,
+
+       0x06, 0x20,
+       0x00, 0xE0,
+       0x1F, 0x26, 0x1F, 0xDF,
+
+       0x17, 0x26, 0x17, 0xDF,
+       0xA1, 0x1F, 0x4F, 0xE9,
+
+       0x1E, 0x26, 0x1E, 0xDF,
+       0x9D, 0x1E, 0x4F, 0xE9,
+
+       0x35, 0x17, 0x4F, 0xE9,
+       0xA2, 0x3F, 0x4F, 0xE9,
+
+       0x06, 0x06, 0x1F, 0xAF,
+       0x39, 0x37, 0x4F, 0xE9,
+
+       0x2F, 0x2F, 0x17, 0xAF,
+       0x07, 0x07, 0x1E, 0xAF,
+
+       0xA0, 0x80, 0x4F, 0xE9,
+       0x9E, 0x3E, 0x4F, 0xE9,
+
+       0x31, 0x80, 0x4F, 0xE9,
+       0x9C, 0x80, 0x4F, 0xE9,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x57, 0x39, 0x20, 0xE9,
+
+       0x16, 0x28, 0x20, 0xE9,
+       0x1D, 0x3B, 0x20, 0xE9,
+
+       0x1E, 0x2B, 0x20, 0xE9,
+       0x2B, 0x32, 0x20, 0xE9,
+
+       0x1C, 0x23, 0x20, 0xE9,
+       0x57, 0x36, 0x20, 0xE9,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x90, 0xE2,
+       0x00, 0xE0,
+
+       0x63, 0xFF, 0x20, 0xEA,
+       0x19, 0xC8, 0xC1, 0xCD,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x9F, 0x41, 0x49, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x25, 0x41, 0x49, 0xBD,
+       0x2D, 0x41, 0x51, 0xBD,
+
+       0x0D, 0x80, 0x07, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x35, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x25, 0x30,
+       0x2D, 0x30,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0xA7, 0x5B, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x62, 0xFF, 0x0A, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC9, 0x41, 0xC8, 0xEC,
+       0x42, 0xE1,
+       0x00, 0xE0,
+
+       0x60, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC8, 0x40, 0xC0, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x5D, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g200_tgzsf[] = {
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x98, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x81, 0x04,
+       0x89, 0x04,
+       0x01, 0x04,
+       0x09, 0x04,
+
+       0xC9, 0x41, 0xC0, 0xEC,
+       0x11, 0x04,
+       0x00, 0xE0,
+
+       0x41, 0xCC, 0x41, 0xCD,
+       0x49, 0xCC, 0x49, 0xCD,
+
+       0xD1, 0x41, 0xC0, 0xEC,
+       0x51, 0xCC, 0x51, 0xCD,
+
+       0x80, 0x04,
+       0x10, 0x04,
+       0x08, 0x04,
+       0x00, 0xE0,
+
+       0x00, 0xCC, 0xC0, 0xCD,
+       0xD1, 0x49, 0xC0, 0xEC,
+
+       0x8A, 0x1F, 0x20, 0xE9,
+       0x8B, 0x3F, 0x20, 0xE9,
+
+       0x41, 0x3C, 0x41, 0xAD,
+       0x49, 0x3C, 0x49, 0xAD,
+
+       0x10, 0xCC, 0x10, 0xCD,
+       0x08, 0xCC, 0x08, 0xCD,
+
+       0xB9, 0x41, 0x49, 0xBB,
+       0x1F, 0xF0, 0x41, 0xCD,
+
+       0x51, 0x3C, 0x51, 0xAD,
+       0x00, 0x98, 0x80, 0xE9,
+
+       0x8F, 0x80, 0x07, 0xEA,
+       0x24, 0x1F, 0x20, 0xE9,
+
+       0x21, 0x45, 0x80, 0xE8,
+       0x1A, 0x4D, 0x80, 0xE8,
+
+       0x31, 0x55, 0x80, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0x41, 0x49, 0xBD,
+       0x1D, 0x41, 0x51, 0xBD,
+
+       0x2E, 0x41, 0x2A, 0xB8,
+       0x34, 0x53, 0xA0, 0xE8,
+
+       0x15, 0x30,
+       0x1D, 0x30,
+       0x58, 0xE3,
+       0x00, 0xE0,
+
+       0xB5, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x24, 0x43, 0xA0, 0xE8,
+       0x2C, 0x4B, 0xA0, 0xE8,
+
+       0x15, 0x72,
+       0x09, 0xE3,
+       0x00, 0xE0,
+       0x1D, 0x72,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0x97, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x6C, 0x64, 0xC8, 0xEC,
+       0x98, 0xE1,
+       0xB5, 0x05,
+
+       0xBD, 0x05,
+       0x2E, 0x30,
+       0x32, 0xC0, 0xA0, 0xE8,
+
+       0x33, 0xC0, 0xA0, 0xE8,
+       0x74, 0x64, 0xC8, 0xEC,
+
+       0x40, 0x3C, 0x40, 0xAD,
+       0x32, 0x6A,
+       0x2A, 0x30,
+
+       0x20, 0x73,
+       0x33, 0x6A,
+       0x00, 0xE0,
+       0x28, 0x73,
+
+       0x1C, 0x72,
+       0x83, 0xE2,
+       0x7B, 0x80, 0x15, 0xEA,
+
+       0xB8, 0x3D, 0x28, 0xDF,
+       0x30, 0x35, 0x20, 0xDF,
+
+       0x40, 0x30,
+       0x00, 0xE0,
+       0xCC, 0xE2,
+       0x64, 0x72,
+
+       0x25, 0x42, 0x52, 0xBF,
+       0x2D, 0x42, 0x4A, 0xBF,
+
+       0x30, 0x2E, 0x30, 0xDF,
+       0x38, 0x2E, 0x38, 0xDF,
+
+       0x18, 0x1D, 0x45, 0xE9,
+       0x1E, 0x15, 0x45, 0xE9,
+
+       0x2B, 0x49, 0x51, 0xBD,
+       0x00, 0xE0,
+       0x1F, 0x73,
+
+       0x38, 0x38, 0x40, 0xAF,
+       0x30, 0x30, 0x40, 0xAF,
+
+       0x24, 0x1F, 0x24, 0xDF,
+       0x1D, 0x32, 0x20, 0xE9,
+
+       0x2C, 0x1F, 0x2C, 0xDF,
+       0x1A, 0x33, 0x20, 0xE9,
+
+       0xB0, 0x10,
+       0x08, 0xE3,
+       0x40, 0x10,
+       0xB8, 0x10,
+
+       0x26, 0xF0, 0x30, 0xCD,
+       0x2F, 0xF0, 0x38, 0xCD,
+
+       0x2B, 0x80, 0x20, 0xE9,
+       0x2A, 0x80, 0x20, 0xE9,
+
+       0xA6, 0x20,
+       0x88, 0xE2,
+       0x00, 0xE0,
+       0xAF, 0x20,
+
+       0x28, 0x2A, 0x26, 0xAF,
+       0x20, 0x2A, 0xC0, 0xAF,
+
+       0x34, 0x1F, 0x34, 0xDF,
+       0x46, 0x24, 0x46, 0xDF,
+
+       0x28, 0x30, 0x80, 0xBF,
+       0x20, 0x38, 0x80, 0xBF,
+
+       0x47, 0x24, 0x47, 0xDF,
+       0x4E, 0x2C, 0x4E, 0xDF,
+
+       0x4F, 0x2C, 0x4F, 0xDF,
+       0x56, 0x34, 0x56, 0xDF,
+
+       0x28, 0x15, 0x28, 0xDF,
+       0x20, 0x1D, 0x20, 0xDF,
+
+       0x57, 0x34, 0x57, 0xDF,
+       0x00, 0xE0,
+       0x1D, 0x05,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x89, 0xE2,
+       0x2B, 0x30,
+
+       0x3F, 0xC1, 0x1D, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA0, 0x68,
+       0xBF, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x20, 0xC0, 0x20, 0xAF,
+       0x28, 0x05,
+       0x97, 0x74,
+
+       0x00, 0xE0,
+       0x2A, 0x10,
+       0x16, 0xC0, 0x20, 0xE9,
+
+       0x04, 0x80, 0x10, 0xEA,
+       0x8C, 0xE2,
+       0x95, 0x05,
+
+       0x28, 0xC1, 0x28, 0xAD,
+       0x1F, 0xC1, 0x15, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA8, 0x67,
+       0x9F, 0x6B,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x28, 0xC0, 0x28, 0xAD,
+       0x1D, 0x25,
+       0x20, 0x05,
+
+       0x28, 0x32, 0x80, 0xAD,
+       0x40, 0x2A, 0x40, 0xBD,
+
+       0x1C, 0x80, 0x20, 0xE9,
+       0x20, 0x33, 0x20, 0xAD,
+
+       0x20, 0x73,
+       0x00, 0xE0,
+       0xB6, 0x49, 0x51, 0xBB,
+
+       0x26, 0x2F, 0xB0, 0xE8,
+       0x19, 0x20, 0x20, 0xE9,
+
+       0x35, 0x20, 0x35, 0xDF,
+       0x3D, 0x20, 0x3D, 0xDF,
+
+       0x15, 0x20, 0x15, 0xDF,
+       0x1D, 0x20, 0x1D, 0xDF,
+
+       0x26, 0xD0, 0x26, 0xCD,
+       0x29, 0x49, 0x2A, 0xB8,
+
+       0x26, 0x40, 0x80, 0xBD,
+       0x3B, 0x48, 0x50, 0xBD,
+
+       0x3E, 0x54, 0x57, 0x9F,
+       0x00, 0xE0,
+       0x82, 0xE1,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x26, 0x30,
+       0x29, 0x30,
+       0x48, 0x3C, 0x48, 0xAD,
+
+       0x2B, 0x72,
+       0xC2, 0xE1,
+       0x2C, 0xC0, 0x44, 0xC2,
+
+       0x05, 0x24, 0x34, 0xBF,
+       0x0D, 0x24, 0x2C, 0xBF,
+
+       0x2D, 0x46, 0x4E, 0xBF,
+       0x25, 0x46, 0x56, 0xBF,
+
+       0x20, 0x1D, 0x6F, 0x8F,
+       0x32, 0x3E, 0x5F, 0xE9,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x30,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x33, 0x1E, 0x5F, 0xE9,
+
+       0x05, 0x44, 0x54, 0xB2,
+       0x0D, 0x44, 0x4C, 0xB2,
+
+       0x19, 0xC0, 0xB0, 0xE8,
+       0x34, 0xC0, 0x44, 0xC4,
+
+       0x33, 0x73,
+       0x00, 0xE0,
+       0x3E, 0x62, 0x57, 0x9F,
+
+       0x1E, 0xAF, 0x59, 0x9F,
+       0x00, 0xE0,
+       0x0D, 0x20,
+
+       0x84, 0x3E, 0x58, 0xE9,
+       0x28, 0x1D, 0x6F, 0x8F,
+
+       0x05, 0x20,
+       0x00, 0xE0,
+       0x85, 0x1E, 0x58, 0xE9,
+
+       0x9B, 0x3B, 0x33, 0xDF,
+       0x20, 0x20, 0x42, 0xAF,
+
+       0x30, 0x42, 0x56, 0x9F,
+       0x80, 0x3E, 0x57, 0xE9,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x30, 0x80, 0x5F, 0xE9,
+
+       0x28, 0x28, 0x24, 0xAF,
+       0x81, 0x1E, 0x57, 0xE9,
+
+       0x05, 0x47, 0x57, 0xBF,
+       0x0D, 0x47, 0x4F, 0xBF,
+
+       0x88, 0x80, 0x58, 0xE9,
+       0x1B, 0x29, 0x1B, 0xDF,
+
+       0x30, 0x1D, 0x6F, 0x8F,
+       0x3A, 0x30, 0x4F, 0xE9,
+
+       0x1C, 0x30, 0x26, 0xDF,
+       0x09, 0xE3,
+       0x3B, 0x05,
+
+       0x3E, 0x50, 0x56, 0x9F,
+       0x3B, 0x3F, 0x4F, 0xE9,
+
+       0x1E, 0x8F, 0x51, 0x9F,
+       0x00, 0xE0,
+       0xAC, 0x20,
+
+       0x2D, 0x44, 0x4C, 0xB4,
+       0x2C, 0x1C, 0xC0, 0xAF,
+
+       0x25, 0x44, 0x54, 0xB4,
+       0x00, 0xE0,
+       0xC8, 0x30,
+
+       0x30, 0x46, 0x30, 0xAF,
+       0x1B, 0x1B, 0x48, 0xAF,
+
+       0x00, 0xE0,
+       0x25, 0x20,
+       0x38, 0x2C, 0x4F, 0xE9,
+
+       0x86, 0x80, 0x57, 0xE9,
+       0x38, 0x1D, 0x6F, 0x8F,
+
+       0x28, 0x74,
+       0x00, 0xE0,
+       0x0D, 0x44, 0x4C, 0xB0,
+
+       0x05, 0x44, 0x54, 0xB0,
+       0x2D, 0x20,
+       0x9B, 0x10,
+
+       0x82, 0x3E, 0x57, 0xE9,
+       0x32, 0xF0, 0x1B, 0xCD,
+
+       0x1E, 0xBD, 0x59, 0x9F,
+       0x83, 0x1E, 0x57, 0xE9,
+
+       0x38, 0x47, 0x38, 0xAF,
+       0x34, 0x20,
+       0x2A, 0x30,
+
+       0x00, 0xE0,
+       0x0D, 0x20,
+       0x32, 0x20,
+       0x05, 0x20,
+
+       0x87, 0x80, 0x57, 0xE9,
+       0x1F, 0x54, 0x57, 0x9F,
+
+       0x17, 0x42, 0x56, 0x9F,
+       0x00, 0xE0,
+       0x3B, 0x6A,
+
+       0x3F, 0x8F, 0x51, 0x9F,
+       0x37, 0x1E, 0x4F, 0xE9,
+
+       0x37, 0x32, 0x2A, 0xAF,
+       0x00, 0xE0,
+       0x32, 0x00,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x27, 0xC0, 0x44, 0xC0,
+
+       0x36, 0x1F, 0x4F, 0xE9,
+       0x1F, 0x1F, 0x26, 0xDF,
+
+       0x37, 0x1B, 0x37, 0xBF,
+       0x17, 0x26, 0x17, 0xDF,
+
+       0x3E, 0x17, 0x4F, 0xE9,
+       0x3F, 0x3F, 0x4F, 0xE9,
+
+       0x34, 0x1F, 0x34, 0xAF,
+       0x2B, 0x05,
+       0xA7, 0x20,
+
+       0x33, 0x2B, 0x37, 0xDF,
+       0x27, 0x17, 0xC0, 0xAF,
+
+       0x34, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x2D, 0x21, 0x1A, 0xB0,
+       0x25, 0x21, 0x31, 0xB0,
+
+       0x0D, 0x21, 0x1A, 0xB2,
+       0x05, 0x21, 0x31, 0xB2,
+
+       0x03, 0x80, 0x2A, 0xEA,
+       0x17, 0xC1, 0x2B, 0xBD,
+
+       0x2D, 0x20,
+       0x25, 0x20,
+       0x05, 0x20,
+       0x0D, 0x20,
+
+       0xB3, 0x68,
+       0x97, 0x25,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x33, 0xC0, 0x33, 0xAF,
+       0x2F, 0xC0, 0x21, 0xC0,
+
+       0x16, 0x42, 0x56, 0x9F,
+       0x3C, 0x27, 0x4F, 0xE9,
+
+       0x1E, 0x62, 0x57, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x25, 0x21, 0x31, 0xB4,
+       0x2D, 0x21, 0x1A, 0xB4,
+
+       0x3F, 0x2F, 0x5D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x33, 0x05,
+       0x00, 0xE0,
+       0x28, 0x19, 0x60, 0xEC,
+
+       0x0D, 0x21, 0x1A, 0xB6,
+       0x05, 0x21, 0x31, 0xB6,
+
+       0x37, 0x0F, 0x5C, 0x9F,
+       0x00, 0xE0,
+       0x2F, 0x20,
+
+       0x23, 0x3B, 0x33, 0xAD,
+       0x1E, 0x26, 0x1E, 0xDF,
+
+       0xA7, 0x1E, 0x4F, 0xE9,
+       0x17, 0x26, 0x16, 0xDF,
+
+       0x2D, 0x20,
+       0x00, 0xE0,
+       0xA8, 0x3F, 0x4F, 0xE9,
+
+       0x2F, 0x2F, 0x1E, 0xAF,
+       0x25, 0x20,
+       0x00, 0xE0,
+
+       0xA4, 0x16, 0x4F, 0xE9,
+       0x0F, 0xC0, 0x21, 0xC2,
+
+       0xA6, 0x80, 0x4F, 0xE9,
+       0x1F, 0x62, 0x57, 0x9F,
+
+       0x0D, 0x20,
+       0x05, 0x20,
+       0x2F, 0xC0, 0x21, 0xC6,
+
+       0x3F, 0x2F, 0x5D, 0x9F,
+       0x00, 0xE0,
+       0x0F, 0x20,
+
+       0x17, 0x50, 0x56, 0x9F,
+       0xA5, 0x37, 0x4F, 0xE9,
+
+       0x06, 0xC0, 0x21, 0xC4,
+       0x0F, 0x17, 0x0F, 0xAF,
+
+       0x37, 0x0F, 0x5C, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x2F, 0x20,
+       0x00, 0xE0,
+       0xA3, 0x80, 0x4F, 0xE9,
+
+       0x06, 0x20,
+       0x00, 0xE0,
+       0x1F, 0x26, 0x1F, 0xDF,
+
+       0x17, 0x26, 0x17, 0xDF,
+       0x35, 0x17, 0x4F, 0xE9,
+
+       0xA1, 0x1F, 0x4F, 0xE9,
+       0xA2, 0x3F, 0x4F, 0xE9,
+
+       0x06, 0x06, 0x1F, 0xAF,
+       0x39, 0x37, 0x4F, 0xE9,
+
+       0x2F, 0x2F, 0x17, 0xAF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xA0, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x31, 0x80, 0x4F, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x57, 0x39, 0x20, 0xE9,
+
+       0x16, 0x28, 0x20, 0xE9,
+       0x1D, 0x3B, 0x20, 0xE9,
+
+       0x1E, 0x2B, 0x20, 0xE9,
+       0x2B, 0x32, 0x20, 0xE9,
+
+       0x1C, 0x23, 0x20, 0xE9,
+       0x57, 0x36, 0x20, 0xE9,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x40, 0x40, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x90, 0xE2,
+       0x00, 0xE0,
+
+       0x68, 0xFF, 0x20, 0xEA,
+       0x19, 0xC8, 0xC1, 0xCD,
+
+       0x1F, 0xD7, 0x18, 0xBD,
+       0x3F, 0xD7, 0x22, 0xBD,
+
+       0x9F, 0x41, 0x49, 0xBD,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x25, 0x41, 0x49, 0xBD,
+       0x2D, 0x41, 0x51, 0xBD,
+
+       0x0D, 0x80, 0x07, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x35, 0x40, 0x48, 0xBD,
+       0x3D, 0x40, 0x50, 0xBD,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x25, 0x30,
+       0x2D, 0x30,
+
+       0x35, 0x30,
+       0xB5, 0x30,
+       0xBD, 0x30,
+       0x3D, 0x30,
+
+       0x9C, 0xA7, 0x5B, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x67, 0xFF, 0x0A, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC9, 0x41, 0xC8, 0xEC,
+       0x42, 0xE1,
+       0x00, 0xE0,
+
+       0x65, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xC8, 0x40, 0xC0, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x62, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+};
+
+static unsigned char warp_g400_t2gz[] = {
+
+       0x00, 0x8A, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x0A, 0x40, 0x50, 0xBF,
+       0x2A, 0x40, 0x60, 0xBF,
+
+       0x32, 0x41, 0x51, 0xBF,
+       0x3A, 0x41, 0x61, 0xBF,
+
+       0xC3, 0x6B,
+       0xD3, 0x6B,
+       0x00, 0x8A, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x23, 0x9F,
+       0x00, 0xE0,
+       0x51, 0x04,
+
+       0x90, 0xE2,
+       0x61, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x51, 0x41, 0xE0, 0xEC,
+       0x39, 0x67, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x63, 0xA0, 0xE8,
+
+       0x61, 0x41, 0xE0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x78, 0x80, 0x15, 0xEA,
+       0x10, 0x04,
+       0x20, 0x04,
+
+       0x61, 0x51, 0xE0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x52, 0xBF,
+       0x0F, 0x52, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x62, 0xBF,
+       0x1E, 0x51, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x0E, 0x61, 0x60, 0xEA,
+
+       0x32, 0x40, 0x50, 0xBD,
+       0x22, 0x40, 0x60, 0xBD,
+
+       0x12, 0x41, 0x51, 0xBD,
+       0x3A, 0x41, 0x61, 0xBD,
+
+       0xBF, 0x2F, 0x0E, 0xBD,
+       0x97, 0xE2,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x35, 0x48, 0xB1, 0xE8,
+       0x3D, 0x59, 0xB1, 0xE8,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x56, 0x31, 0x56, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x66, 0x31, 0x66, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x57, 0x39, 0x57, 0xBF,
+       0x67, 0x39, 0x67, 0xBF,
+
+       0x69, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x35, 0x00,
+       0x3D, 0x00,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0x8D, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x75, 0xF8, 0xEC,
+       0x35, 0x20,
+       0x3D, 0x20,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x53, 0x53, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x0E, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x48, 0x35, 0x48, 0xBF,
+       0x58, 0x35, 0x58, 0xBF,
+
+       0x68, 0x35, 0x68, 0xBF,
+       0x49, 0x3D, 0x49, 0xBF,
+
+       0x59, 0x3D, 0x59, 0xBF,
+       0x69, 0x3D, 0x69, 0xBF,
+
+       0x63, 0x63, 0x2D, 0xDF,
+       0x4D, 0x7D, 0xF8, 0xEC,
+
+       0x59, 0xE3,
+       0x00, 0xE0,
+       0xB8, 0x38, 0x33, 0xBF,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x18, 0x3A, 0x41, 0xE9,
+
+       0x3F, 0x53, 0xA0, 0xE8,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x63, 0xA0, 0xE8,
+
+       0x50, 0x70, 0xF8, 0xEC,
+       0x2B, 0x50, 0x3C, 0xE9,
+
+       0x1F, 0x0F, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x59, 0x78, 0xF8, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x56, 0x3F, 0x56, 0xDF,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x66, 0x3D, 0x66, 0xDF,
+
+       0x1D, 0x32, 0x41, 0xE9,
+       0x67, 0x3D, 0x67, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3F, 0x57, 0xDF,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x59, 0x3F, 0x59, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x69, 0x3D, 0x69, 0xDF,
+
+       0x48, 0x37, 0x48, 0xDF,
+       0x58, 0x3F, 0x58, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x68, 0x3D, 0x68, 0xDF,
+       0x49, 0x37, 0x49, 0xDF,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x34, 0x80, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x0A, 0x44, 0x54, 0xB0,
+       0x02, 0x44, 0x64, 0xB0,
+
+       0x2A, 0x44, 0x54, 0xB2,
+       0x1A, 0x44, 0x64, 0xB2,
+
+       0x25, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x3D, 0xCF, 0x74, 0xC2,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x2A, 0x44, 0x54, 0xB4,
+       0x1A, 0x44, 0x64, 0xB4,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x38, 0x3D, 0x20, 0xE9,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x2A, 0x46, 0x56, 0xBF,
+       0x1A, 0x46, 0x66, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x0A, 0x47, 0x57, 0xBF,
+       0x02, 0x47, 0x67, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x53, 0xBF,
+       0x1A, 0x43, 0x63, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x36, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x37, 0x39, 0x4F, 0xE9,
+
+       0x0A, 0x48, 0x58, 0xBF,
+       0x02, 0x48, 0x68, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x2A, 0x49, 0x59, 0xBF,
+       0x1A, 0x49, 0x69, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x82, 0x30, 0x57, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x83, 0x38, 0x57, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x84, 0x31, 0x5E, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x85, 0x39, 0x5E, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x87, 0x77, 0x57, 0xE9,
+       0x8B, 0x3E, 0xBF, 0xEA,
+
+       0x80, 0x30, 0x57, 0xE9,
+       0x81, 0x38, 0x57, 0xE9,
+
+       0x82, 0x31, 0x57, 0xE9,
+       0x86, 0x78, 0x57, 0xE9,
+
+       0x83, 0x39, 0x57, 0xE9,
+       0x87, 0x79, 0x57, 0xE9,
+
+       0x30, 0x1F, 0x5F, 0xE9,
+       0x8A, 0x34, 0x20, 0xE9,
+
+       0x8B, 0x3C, 0x20, 0xE9,
+       0x37, 0x50, 0x60, 0xBD,
+
+       0x57, 0x0D, 0x20, 0xE9,
+       0x35, 0x51, 0x61, 0xBD,
+
+       0x2B, 0x50, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x0E, 0x77,
+
+       0x24, 0x51, 0x20, 0xE9,
+       0x9F, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x0E, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x0B, 0x46, 0xA0, 0xE8,
+       0x1B, 0x56, 0xA0, 0xE8,
+
+       0x2B, 0x66, 0xA0, 0xE8,
+       0x0C, 0x47, 0xA0, 0xE8,
+
+       0x1C, 0x57, 0xA0, 0xE8,
+       0x2C, 0x67, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x57, 0x80, 0x57, 0xCF,
+
+       0x66, 0x33, 0x66, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x67, 0x3B, 0x67, 0xCF,
+
+       0x0B, 0x48, 0xA0, 0xE8,
+       0x1B, 0x58, 0xA0, 0xE8,
+
+       0x2B, 0x68, 0xA0, 0xE8,
+       0x0C, 0x49, 0xA0, 0xE8,
+
+       0x1C, 0x59, 0xA0, 0xE8,
+       0x2C, 0x69, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x34, 0xD7, 0x34, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3C, 0xD7, 0x3C, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x34, 0x80, 0x34, 0xBD,
+       0x3C, 0x80, 0x3C, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x48, 0x80, 0x48, 0xCF,
+       0x59, 0x80, 0x59, 0xCF,
+
+       0x68, 0x33, 0x68, 0xCF,
+       0x49, 0x3B, 0x49, 0xCF,
+
+       0xBE, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x58, 0x33, 0x58, 0xCF,
+       0x69, 0x3B, 0x69, 0xCF,
+
+       0x7D, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gza[] = {
+
+       0x00, 0x8A, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x0A, 0x40, 0x50, 0xBF,
+       0x2A, 0x40, 0x60, 0xBF,
+
+       0x32, 0x41, 0x51, 0xBF,
+       0x3A, 0x41, 0x61, 0xBF,
+
+       0xC3, 0x6B,
+       0xD3, 0x6B,
+       0x00, 0x8A, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x23, 0x9F,
+       0x00, 0xE0,
+       0x51, 0x04,
+
+       0x90, 0xE2,
+       0x61, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x51, 0x41, 0xE0, 0xEC,
+       0x39, 0x67, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x63, 0xA0, 0xE8,
+
+       0x61, 0x41, 0xE0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x7C, 0x80, 0x15, 0xEA,
+       0x10, 0x04,
+       0x20, 0x04,
+
+       0x61, 0x51, 0xE0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x52, 0xBF,
+       0x0F, 0x52, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x62, 0xBF,
+       0x1E, 0x51, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x0E, 0x61, 0x60, 0xEA,
+
+       0x32, 0x40, 0x50, 0xBD,
+       0x22, 0x40, 0x60, 0xBD,
+
+       0x12, 0x41, 0x51, 0xBD,
+       0x3A, 0x41, 0x61, 0xBD,
+
+       0xBF, 0x2F, 0x0E, 0xBD,
+       0x97, 0xE2,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x35, 0x48, 0xB1, 0xE8,
+       0x3D, 0x59, 0xB1, 0xE8,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x56, 0x31, 0x56, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x66, 0x31, 0x66, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x57, 0x39, 0x57, 0xBF,
+       0x67, 0x39, 0x67, 0xBF,
+
+       0x6D, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x35, 0x00,
+       0x3D, 0x00,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0x8D, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x75, 0xF8, 0xEC,
+       0x35, 0x20,
+       0x3D, 0x20,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x53, 0x53, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x0E, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x48, 0x35, 0x48, 0xBF,
+       0x58, 0x35, 0x58, 0xBF,
+
+       0x68, 0x35, 0x68, 0xBF,
+       0x49, 0x3D, 0x49, 0xBF,
+
+       0x59, 0x3D, 0x59, 0xBF,
+       0x69, 0x3D, 0x69, 0xBF,
+
+       0x63, 0x63, 0x2D, 0xDF,
+       0x4D, 0x7D, 0xF8, 0xEC,
+
+       0x59, 0xE3,
+       0x00, 0xE0,
+       0xB8, 0x38, 0x33, 0xBF,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x18, 0x3A, 0x41, 0xE9,
+
+       0x3F, 0x53, 0xA0, 0xE8,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x63, 0xA0, 0xE8,
+
+       0x50, 0x70, 0xF8, 0xEC,
+       0x2B, 0x50, 0x3C, 0xE9,
+
+       0x1F, 0x0F, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x59, 0x78, 0xF8, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x56, 0x3F, 0x56, 0xDF,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x66, 0x3D, 0x66, 0xDF,
+
+       0x1D, 0x32, 0x41, 0xE9,
+       0x67, 0x3D, 0x67, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3F, 0x57, 0xDF,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x59, 0x3F, 0x59, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x69, 0x3D, 0x69, 0xDF,
+
+       0x48, 0x37, 0x48, 0xDF,
+       0x58, 0x3F, 0x58, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x68, 0x3D, 0x68, 0xDF,
+       0x49, 0x37, 0x49, 0xDF,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x34, 0x80, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x0A, 0x44, 0x54, 0xB0,
+       0x02, 0x44, 0x64, 0xB0,
+
+       0x2A, 0x44, 0x54, 0xB2,
+       0x1A, 0x44, 0x64, 0xB2,
+
+       0x29, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x0F, 0xCF, 0x74, 0xC6,
+       0x3D, 0xCF, 0x74, 0xC2,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x9C, 0x0F, 0x20, 0xE9,
+
+       0x0A, 0x44, 0x54, 0xB4,
+       0x02, 0x44, 0x64, 0xB4,
+
+       0x2A, 0x44, 0x54, 0xB6,
+       0x1A, 0x44, 0x64, 0xB6,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x38, 0x3D, 0x20, 0xE9,
+
+       0x0A, 0x20,
+       0x02, 0x20,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x0A, 0x47, 0x57, 0xBF,
+       0x02, 0x47, 0x67, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x46, 0x56, 0xBF,
+       0x1A, 0x46, 0x66, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x36, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x37, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x53, 0xBF,
+       0x1A, 0x43, 0x63, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x9D, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x9E, 0x39, 0x4F, 0xE9,
+
+       0x0A, 0x48, 0x58, 0xBF,
+       0x02, 0x48, 0x68, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x2A, 0x49, 0x59, 0xBF,
+       0x1A, 0x49, 0x69, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x82, 0x30, 0x57, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x83, 0x38, 0x57, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x84, 0x31, 0x5E, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x85, 0x39, 0x5E, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x87, 0x77, 0x57, 0xE9,
+       0x8B, 0x3E, 0xBF, 0xEA,
+
+       0x80, 0x30, 0x57, 0xE9,
+       0x81, 0x38, 0x57, 0xE9,
+
+       0x82, 0x31, 0x57, 0xE9,
+       0x86, 0x78, 0x57, 0xE9,
+
+       0x83, 0x39, 0x57, 0xE9,
+       0x87, 0x79, 0x57, 0xE9,
+
+       0x30, 0x1F, 0x5F, 0xE9,
+       0x8A, 0x34, 0x20, 0xE9,
+
+       0x8B, 0x3C, 0x20, 0xE9,
+       0x37, 0x50, 0x60, 0xBD,
+
+       0x57, 0x0D, 0x20, 0xE9,
+       0x35, 0x51, 0x61, 0xBD,
+
+       0x2B, 0x50, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x0E, 0x77,
+
+       0x24, 0x51, 0x20, 0xE9,
+       0x9B, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x0E, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x0B, 0x46, 0xA0, 0xE8,
+       0x1B, 0x56, 0xA0, 0xE8,
+
+       0x2B, 0x66, 0xA0, 0xE8,
+       0x0C, 0x47, 0xA0, 0xE8,
+
+       0x1C, 0x57, 0xA0, 0xE8,
+       0x2C, 0x67, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x57, 0x80, 0x57, 0xCF,
+
+       0x66, 0x33, 0x66, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x67, 0x3B, 0x67, 0xCF,
+
+       0x0B, 0x48, 0xA0, 0xE8,
+       0x1B, 0x58, 0xA0, 0xE8,
+
+       0x2B, 0x68, 0xA0, 0xE8,
+       0x0C, 0x49, 0xA0, 0xE8,
+
+       0x1C, 0x59, 0xA0, 0xE8,
+       0x2C, 0x69, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x34, 0xD7, 0x34, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3C, 0xD7, 0x3C, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x34, 0x80, 0x34, 0xBD,
+       0x3C, 0x80, 0x3C, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x48, 0x80, 0x48, 0xCF,
+       0x59, 0x80, 0x59, 0xCF,
+
+       0x68, 0x33, 0x68, 0xCF,
+       0x49, 0x3B, 0x49, 0xCF,
+
+       0xBA, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x58, 0x33, 0x58, 0xCF,
+       0x69, 0x3B, 0x69, 0xCF,
+
+       0x79, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzaf[] = {
+
+       0x00, 0x8A, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x0A, 0x40, 0x50, 0xBF,
+       0x2A, 0x40, 0x60, 0xBF,
+
+       0x32, 0x41, 0x51, 0xBF,
+       0x3A, 0x41, 0x61, 0xBF,
+
+       0xC3, 0x6B,
+       0xD3, 0x6B,
+       0x00, 0x8A, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x23, 0x9F,
+       0x00, 0xE0,
+       0x51, 0x04,
+
+       0x90, 0xE2,
+       0x61, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x51, 0x41, 0xE0, 0xEC,
+       0x39, 0x67, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x63, 0xA0, 0xE8,
+
+       0x61, 0x41, 0xE0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x81, 0x80, 0x15, 0xEA,
+       0x10, 0x04,
+       0x20, 0x04,
+
+       0x61, 0x51, 0xE0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x52, 0xBF,
+       0x0F, 0x52, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x62, 0xBF,
+       0x1E, 0x51, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x0E, 0x61, 0x60, 0xEA,
+
+       0x32, 0x40, 0x50, 0xBD,
+       0x22, 0x40, 0x60, 0xBD,
+
+       0x12, 0x41, 0x51, 0xBD,
+       0x3A, 0x41, 0x61, 0xBD,
+
+       0xBF, 0x2F, 0x0E, 0xBD,
+       0x97, 0xE2,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x35, 0x48, 0xB1, 0xE8,
+       0x3D, 0x59, 0xB1, 0xE8,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x56, 0x31, 0x56, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x66, 0x31, 0x66, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x57, 0x39, 0x57, 0xBF,
+       0x67, 0x39, 0x67, 0xBF,
+
+       0x72, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x35, 0x00,
+       0x3D, 0x00,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0x8D, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x75, 0xF8, 0xEC,
+       0x35, 0x20,
+       0x3D, 0x20,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x53, 0x53, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x0E, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x48, 0x35, 0x48, 0xBF,
+       0x58, 0x35, 0x58, 0xBF,
+
+       0x68, 0x35, 0x68, 0xBF,
+       0x49, 0x3D, 0x49, 0xBF,
+
+       0x59, 0x3D, 0x59, 0xBF,
+       0x69, 0x3D, 0x69, 0xBF,
+
+       0x63, 0x63, 0x2D, 0xDF,
+       0x4D, 0x7D, 0xF8, 0xEC,
+
+       0x59, 0xE3,
+       0x00, 0xE0,
+       0xB8, 0x38, 0x33, 0xBF,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x18, 0x3A, 0x41, 0xE9,
+
+       0x3F, 0x53, 0xA0, 0xE8,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x63, 0xA0, 0xE8,
+
+       0x50, 0x70, 0xF8, 0xEC,
+       0x2B, 0x50, 0x3C, 0xE9,
+
+       0x1F, 0x0F, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x59, 0x78, 0xF8, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x56, 0x3F, 0x56, 0xDF,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x66, 0x3D, 0x66, 0xDF,
+
+       0x1D, 0x32, 0x41, 0xE9,
+       0x67, 0x3D, 0x67, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3F, 0x57, 0xDF,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x59, 0x3F, 0x59, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x69, 0x3D, 0x69, 0xDF,
+
+       0x48, 0x37, 0x48, 0xDF,
+       0x58, 0x3F, 0x58, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x68, 0x3D, 0x68, 0xDF,
+       0x49, 0x37, 0x49, 0xDF,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x0A, 0x44, 0x54, 0xB0,
+       0x02, 0x44, 0x64, 0xB0,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x34, 0x37, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x54, 0xB2,
+       0x1A, 0x44, 0x64, 0xB2,
+
+       0x2E, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x3D, 0xCF, 0x74, 0xC2,
+       0x0F, 0xCF, 0x74, 0xC6,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x9C, 0x0F, 0x20, 0xE9,
+
+       0x0A, 0x44, 0x54, 0xB4,
+       0x02, 0x44, 0x64, 0xB4,
+
+       0x2A, 0x44, 0x54, 0xB6,
+       0x1A, 0x44, 0x64, 0xB6,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x38, 0x3D, 0x20, 0xE9,
+
+       0x0A, 0x20,
+       0x02, 0x20,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x3D, 0xCF, 0x75, 0xC6,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x0A, 0x45, 0x55, 0xB6,
+       0x02, 0x45, 0x65, 0xB6,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x3D, 0x20, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x2A, 0x46, 0x56, 0xBF,
+       0x1A, 0x46, 0x66, 0xBF,
+
+       0x0A, 0x47, 0x57, 0xBF,
+       0x02, 0x47, 0x67, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x36, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x37, 0x38, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x9D, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x9E, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x53, 0xBF,
+       0x1A, 0x43, 0x63, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x35, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x39, 0x38, 0x4F, 0xE9,
+
+       0x0A, 0x48, 0x58, 0xBF,
+       0x02, 0x48, 0x68, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x2A, 0x49, 0x59, 0xBF,
+       0x1A, 0x49, 0x69, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x82, 0x30, 0x57, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x83, 0x38, 0x57, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x84, 0x31, 0x5E, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x85, 0x39, 0x5E, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x87, 0x77, 0x57, 0xE9,
+       0x8B, 0x3E, 0xBF, 0xEA,
+
+       0x80, 0x30, 0x57, 0xE9,
+       0x81, 0x38, 0x57, 0xE9,
+
+       0x82, 0x31, 0x57, 0xE9,
+       0x86, 0x78, 0x57, 0xE9,
+
+       0x83, 0x39, 0x57, 0xE9,
+       0x87, 0x79, 0x57, 0xE9,
+
+       0x30, 0x1F, 0x5F, 0xE9,
+       0x8A, 0x34, 0x20, 0xE9,
+
+       0x8B, 0x3C, 0x20, 0xE9,
+       0x37, 0x50, 0x60, 0xBD,
+
+       0x57, 0x0D, 0x20, 0xE9,
+       0x35, 0x51, 0x61, 0xBD,
+
+       0x2B, 0x50, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x0E, 0x77,
+
+       0x24, 0x51, 0x20, 0xE9,
+       0x96, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x0E, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x0B, 0x46, 0xA0, 0xE8,
+       0x1B, 0x56, 0xA0, 0xE8,
+
+       0x2B, 0x66, 0xA0, 0xE8,
+       0x0C, 0x47, 0xA0, 0xE8,
+
+       0x1C, 0x57, 0xA0, 0xE8,
+       0x2C, 0x67, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x57, 0x80, 0x57, 0xCF,
+
+       0x66, 0x33, 0x66, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x67, 0x3B, 0x67, 0xCF,
+
+       0x0B, 0x48, 0xA0, 0xE8,
+       0x1B, 0x58, 0xA0, 0xE8,
+
+       0x2B, 0x68, 0xA0, 0xE8,
+       0x0C, 0x49, 0xA0, 0xE8,
+
+       0x1C, 0x59, 0xA0, 0xE8,
+       0x2C, 0x69, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x34, 0xD7, 0x34, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3C, 0xD7, 0x3C, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x34, 0x80, 0x34, 0xBD,
+       0x3C, 0x80, 0x3C, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x48, 0x80, 0x48, 0xCF,
+       0x59, 0x80, 0x59, 0xCF,
+
+       0x68, 0x33, 0x68, 0xCF,
+       0x49, 0x3B, 0x49, 0xCF,
+
+       0xB5, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x58, 0x33, 0x58, 0xCF,
+       0x69, 0x3B, 0x69, 0xCF,
+
+       0x74, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzf[] = {
+
+       0x00, 0x8A, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x0A, 0x40, 0x50, 0xBF,
+       0x2A, 0x40, 0x60, 0xBF,
+
+       0x32, 0x41, 0x51, 0xBF,
+       0x3A, 0x41, 0x61, 0xBF,
+
+       0xC3, 0x6B,
+       0xD3, 0x6B,
+       0x00, 0x8A, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x23, 0x9F,
+       0x00, 0xE0,
+       0x51, 0x04,
+
+       0x90, 0xE2,
+       0x61, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x51, 0x41, 0xE0, 0xEC,
+       0x39, 0x67, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x63, 0xA0, 0xE8,
+
+       0x61, 0x41, 0xE0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x7D, 0x80, 0x15, 0xEA,
+       0x10, 0x04,
+       0x20, 0x04,
+
+       0x61, 0x51, 0xE0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x52, 0xBF,
+       0x0F, 0x52, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x62, 0xBF,
+       0x1E, 0x51, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x0E, 0x61, 0x60, 0xEA,
+
+       0x32, 0x40, 0x50, 0xBD,
+       0x22, 0x40, 0x60, 0xBD,
+
+       0x12, 0x41, 0x51, 0xBD,
+       0x3A, 0x41, 0x61, 0xBD,
+
+       0xBF, 0x2F, 0x0E, 0xBD,
+       0x97, 0xE2,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x35, 0x48, 0xB1, 0xE8,
+       0x3D, 0x59, 0xB1, 0xE8,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x56, 0x31, 0x56, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x66, 0x31, 0x66, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x57, 0x39, 0x57, 0xBF,
+       0x67, 0x39, 0x67, 0xBF,
+
+       0x6E, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x35, 0x00,
+       0x3D, 0x00,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0x8D, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x75, 0xF8, 0xEC,
+       0x35, 0x20,
+       0x3D, 0x20,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x53, 0x53, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x0E, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x48, 0x35, 0x48, 0xBF,
+       0x58, 0x35, 0x58, 0xBF,
+
+       0x68, 0x35, 0x68, 0xBF,
+       0x49, 0x3D, 0x49, 0xBF,
+
+       0x59, 0x3D, 0x59, 0xBF,
+       0x69, 0x3D, 0x69, 0xBF,
+
+       0x63, 0x63, 0x2D, 0xDF,
+       0x4D, 0x7D, 0xF8, 0xEC,
+
+       0x59, 0xE3,
+       0x00, 0xE0,
+       0xB8, 0x38, 0x33, 0xBF,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x18, 0x3A, 0x41, 0xE9,
+
+       0x3F, 0x53, 0xA0, 0xE8,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x63, 0xA0, 0xE8,
+
+       0x50, 0x70, 0xF8, 0xEC,
+       0x2B, 0x50, 0x3C, 0xE9,
+
+       0x1F, 0x0F, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x59, 0x78, 0xF8, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x56, 0x3F, 0x56, 0xDF,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x66, 0x3D, 0x66, 0xDF,
+
+       0x1D, 0x32, 0x41, 0xE9,
+       0x67, 0x3D, 0x67, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3F, 0x57, 0xDF,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x59, 0x3F, 0x59, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x69, 0x3D, 0x69, 0xDF,
+
+       0x48, 0x37, 0x48, 0xDF,
+       0x58, 0x3F, 0x58, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x68, 0x3D, 0x68, 0xDF,
+       0x49, 0x37, 0x49, 0xDF,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x34, 0x80, 0x20, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x0F, 0xCF, 0x75, 0xC6,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x0A, 0x44, 0x54, 0xB0,
+       0x02, 0x44, 0x64, 0xB0,
+
+       0x2A, 0x44, 0x54, 0xB2,
+       0x1A, 0x44, 0x64, 0xB2,
+
+       0x28, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x3D, 0xCF, 0x74, 0xC2,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x31, 0x0F, 0x20, 0xE9,
+
+       0x0A, 0x44, 0x54, 0xB4,
+       0x02, 0x44, 0x64, 0xB4,
+
+       0x2A, 0x45, 0x55, 0xB6,
+       0x1A, 0x45, 0x65, 0xB6,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x38, 0x3D, 0x20, 0xE9,
+
+       0x0A, 0x20,
+       0x02, 0x20,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x0A, 0x47, 0x57, 0xBF,
+       0x02, 0x47, 0x67, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x46, 0x56, 0xBF,
+       0x1A, 0x46, 0x66, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x36, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x37, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x53, 0xBF,
+       0x1A, 0x43, 0x63, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x35, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x39, 0x39, 0x4F, 0xE9,
+
+       0x0A, 0x48, 0x58, 0xBF,
+       0x02, 0x48, 0x68, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x2A, 0x49, 0x59, 0xBF,
+       0x1A, 0x49, 0x69, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x82, 0x30, 0x57, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x83, 0x38, 0x57, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x84, 0x31, 0x5E, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x85, 0x39, 0x5E, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x87, 0x77, 0x57, 0xE9,
+       0x8B, 0x3E, 0xBF, 0xEA,
+
+       0x80, 0x30, 0x57, 0xE9,
+       0x81, 0x38, 0x57, 0xE9,
+
+       0x82, 0x31, 0x57, 0xE9,
+       0x86, 0x78, 0x57, 0xE9,
+
+       0x83, 0x39, 0x57, 0xE9,
+       0x87, 0x79, 0x57, 0xE9,
+
+       0x30, 0x1F, 0x5F, 0xE9,
+       0x8A, 0x34, 0x20, 0xE9,
+
+       0x8B, 0x3C, 0x20, 0xE9,
+       0x37, 0x50, 0x60, 0xBD,
+
+       0x57, 0x0D, 0x20, 0xE9,
+       0x35, 0x51, 0x61, 0xBD,
+
+       0x2B, 0x50, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x0E, 0x77,
+
+       0x24, 0x51, 0x20, 0xE9,
+       0x9A, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x0E, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x0B, 0x46, 0xA0, 0xE8,
+       0x1B, 0x56, 0xA0, 0xE8,
+
+       0x2B, 0x66, 0xA0, 0xE8,
+       0x0C, 0x47, 0xA0, 0xE8,
+
+       0x1C, 0x57, 0xA0, 0xE8,
+       0x2C, 0x67, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x57, 0x80, 0x57, 0xCF,
+
+       0x66, 0x33, 0x66, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x67, 0x3B, 0x67, 0xCF,
+
+       0x0B, 0x48, 0xA0, 0xE8,
+       0x1B, 0x58, 0xA0, 0xE8,
+
+       0x2B, 0x68, 0xA0, 0xE8,
+       0x0C, 0x49, 0xA0, 0xE8,
+
+       0x1C, 0x59, 0xA0, 0xE8,
+       0x2C, 0x69, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x34, 0xD7, 0x34, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3C, 0xD7, 0x3C, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x34, 0x80, 0x34, 0xBD,
+       0x3C, 0x80, 0x3C, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x48, 0x80, 0x48, 0xCF,
+       0x59, 0x80, 0x59, 0xCF,
+
+       0x68, 0x33, 0x68, 0xCF,
+       0x49, 0x3B, 0x49, 0xCF,
+
+       0xBB, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x58, 0x33, 0x58, 0xCF,
+       0x69, 0x3B, 0x69, 0xCF,
+
+       0x78, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzs[] = {
+
+       0x00, 0x8A, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x0A, 0x40, 0x50, 0xBF,
+       0x2A, 0x40, 0x60, 0xBF,
+
+       0x32, 0x41, 0x51, 0xBF,
+       0x3A, 0x41, 0x61, 0xBF,
+
+       0xC3, 0x6B,
+       0xD3, 0x6B,
+       0x00, 0x8A, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x23, 0x9F,
+       0x00, 0xE0,
+       0x51, 0x04,
+
+       0x90, 0xE2,
+       0x61, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x51, 0x41, 0xE0, 0xEC,
+       0x39, 0x67, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x63, 0xA0, 0xE8,
+
+       0x61, 0x41, 0xE0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x85, 0x80, 0x15, 0xEA,
+       0x10, 0x04,
+       0x20, 0x04,
+
+       0x61, 0x51, 0xE0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x52, 0xBF,
+       0x0F, 0x52, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x62, 0xBF,
+       0x1E, 0x51, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x0E, 0x61, 0x60, 0xEA,
+
+       0x32, 0x40, 0x50, 0xBD,
+       0x22, 0x40, 0x60, 0xBD,
+
+       0x12, 0x41, 0x51, 0xBD,
+       0x3A, 0x41, 0x61, 0xBD,
+
+       0xBF, 0x2F, 0x0E, 0xBD,
+       0x97, 0xE2,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x35, 0x48, 0xB1, 0xE8,
+       0x3D, 0x59, 0xB1, 0xE8,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x56, 0x31, 0x56, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x66, 0x31, 0x66, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x57, 0x39, 0x57, 0xBF,
+       0x67, 0x39, 0x67, 0xBF,
+
+       0x76, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x35, 0x00,
+       0x3D, 0x00,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0x8D, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x75, 0xF8, 0xEC,
+       0x35, 0x20,
+       0x3D, 0x20,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x53, 0x53, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x0E, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x48, 0x35, 0x48, 0xBF,
+       0x58, 0x35, 0x58, 0xBF,
+
+       0x68, 0x35, 0x68, 0xBF,
+       0x49, 0x3D, 0x49, 0xBF,
+
+       0x59, 0x3D, 0x59, 0xBF,
+       0x69, 0x3D, 0x69, 0xBF,
+
+       0x63, 0x63, 0x2D, 0xDF,
+       0x4D, 0x7D, 0xF8, 0xEC,
+
+       0x59, 0xE3,
+       0x00, 0xE0,
+       0xB8, 0x38, 0x33, 0xBF,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x18, 0x3A, 0x41, 0xE9,
+
+       0x3F, 0x53, 0xA0, 0xE8,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x63, 0xA0, 0xE8,
+
+       0x50, 0x70, 0xF8, 0xEC,
+       0x2B, 0x50, 0x3C, 0xE9,
+
+       0x1F, 0x0F, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x59, 0x78, 0xF8, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x56, 0x3F, 0x56, 0xDF,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x66, 0x3D, 0x66, 0xDF,
+
+       0x1D, 0x32, 0x41, 0xE9,
+       0x67, 0x3D, 0x67, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3F, 0x57, 0xDF,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x59, 0x3F, 0x59, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x69, 0x3D, 0x69, 0xDF,
+
+       0x48, 0x37, 0x48, 0xDF,
+       0x58, 0x3F, 0x58, 0xDF,
+
+       0x68, 0x3D, 0x68, 0xDF,
+       0x49, 0x37, 0x49, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x0F, 0xCF, 0x74, 0xC2,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x0A, 0x44, 0x54, 0xB0,
+       0x02, 0x44, 0x64, 0xB0,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x34, 0x37, 0x20, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x38, 0x0F, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x54, 0xB2,
+       0x1A, 0x44, 0x64, 0xB2,
+
+       0x31, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x0F, 0xCF, 0x75, 0xC0,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x3D, 0xCF, 0x75, 0xC2,
+       0x37, 0xCF, 0x75, 0xC4,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA6, 0x0F, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA3, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x54, 0xB4,
+       0x1A, 0x44, 0x64, 0xB4,
+
+       0x0A, 0x45, 0x55, 0xB0,
+       0x02, 0x45, 0x65, 0xB0,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA0, 0x37, 0x20, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x2A, 0x45, 0x55, 0xB2,
+       0x1A, 0x45, 0x65, 0xB2,
+
+       0x0A, 0x45, 0x55, 0xB4,
+       0x02, 0x45, 0x65, 0xB4,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x20,
+       0x1A, 0x20,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x2A, 0x46, 0x56, 0xBF,
+       0x1A, 0x46, 0x66, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x36, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x37, 0x39, 0x4F, 0xE9,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0xA7, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0xA8, 0x38, 0x4F, 0xE9,
+
+       0x0A, 0x47, 0x57, 0xBF,
+       0x02, 0x47, 0x67, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA4, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA5, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x53, 0xBF,
+       0x1A, 0x43, 0x63, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0xA1, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0xA2, 0x38, 0x4F, 0xE9,
+
+       0x0A, 0x48, 0x58, 0xBF,
+       0x02, 0x48, 0x68, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x2A, 0x49, 0x59, 0xBF,
+       0x1A, 0x49, 0x69, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x82, 0x30, 0x57, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x83, 0x38, 0x57, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x84, 0x31, 0x5E, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x85, 0x39, 0x5E, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x87, 0x77, 0x57, 0xE9,
+       0x8B, 0x3E, 0xBF, 0xEA,
+
+       0x80, 0x30, 0x57, 0xE9,
+       0x81, 0x38, 0x57, 0xE9,
+
+       0x82, 0x31, 0x57, 0xE9,
+       0x86, 0x78, 0x57, 0xE9,
+
+       0x83, 0x39, 0x57, 0xE9,
+       0x87, 0x79, 0x57, 0xE9,
+
+       0x30, 0x1F, 0x5F, 0xE9,
+       0x8A, 0x34, 0x20, 0xE9,
+
+       0x8B, 0x3C, 0x20, 0xE9,
+       0x37, 0x50, 0x60, 0xBD,
+
+       0x57, 0x0D, 0x20, 0xE9,
+       0x35, 0x51, 0x61, 0xBD,
+
+       0x2B, 0x50, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x0E, 0x77,
+
+       0x24, 0x51, 0x20, 0xE9,
+       0x92, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x0E, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x0B, 0x46, 0xA0, 0xE8,
+       0x1B, 0x56, 0xA0, 0xE8,
+
+       0x2B, 0x66, 0xA0, 0xE8,
+       0x0C, 0x47, 0xA0, 0xE8,
+
+       0x1C, 0x57, 0xA0, 0xE8,
+       0x2C, 0x67, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x57, 0x80, 0x57, 0xCF,
+
+       0x66, 0x33, 0x66, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x67, 0x3B, 0x67, 0xCF,
+
+       0x0B, 0x48, 0xA0, 0xE8,
+       0x1B, 0x58, 0xA0, 0xE8,
+
+       0x2B, 0x68, 0xA0, 0xE8,
+       0x0C, 0x49, 0xA0, 0xE8,
+
+       0x1C, 0x59, 0xA0, 0xE8,
+       0x2C, 0x69, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x34, 0xD7, 0x34, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3C, 0xD7, 0x3C, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x34, 0x80, 0x34, 0xBD,
+       0x3C, 0x80, 0x3C, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x48, 0x80, 0x48, 0xCF,
+       0x59, 0x80, 0x59, 0xCF,
+
+       0x68, 0x33, 0x68, 0xCF,
+       0x49, 0x3B, 0x49, 0xCF,
+
+       0xB2, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x58, 0x33, 0x58, 0xCF,
+       0x69, 0x3B, 0x69, 0xCF,
+
+       0x70, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzsa[] = {
+
+       0x00, 0x8A, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x0A, 0x40, 0x50, 0xBF,
+       0x2A, 0x40, 0x60, 0xBF,
+
+       0x32, 0x41, 0x51, 0xBF,
+       0x3A, 0x41, 0x61, 0xBF,
+
+       0xC3, 0x6B,
+       0xD3, 0x6B,
+       0x00, 0x8A, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x23, 0x9F,
+       0x00, 0xE0,
+       0x51, 0x04,
+
+       0x90, 0xE2,
+       0x61, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x51, 0x41, 0xE0, 0xEC,
+       0x39, 0x67, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x63, 0xA0, 0xE8,
+
+       0x61, 0x41, 0xE0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x8A, 0x80, 0x15, 0xEA,
+       0x10, 0x04,
+       0x20, 0x04,
+
+       0x61, 0x51, 0xE0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x52, 0xBF,
+       0x0F, 0x52, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x62, 0xBF,
+       0x1E, 0x51, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x0E, 0x61, 0x60, 0xEA,
+
+       0x32, 0x40, 0x50, 0xBD,
+       0x22, 0x40, 0x60, 0xBD,
+
+       0x12, 0x41, 0x51, 0xBD,
+       0x3A, 0x41, 0x61, 0xBD,
+
+       0xBF, 0x2F, 0x0E, 0xBD,
+       0x97, 0xE2,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x35, 0x48, 0xB1, 0xE8,
+       0x3D, 0x59, 0xB1, 0xE8,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x56, 0x31, 0x56, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x66, 0x31, 0x66, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x57, 0x39, 0x57, 0xBF,
+       0x67, 0x39, 0x67, 0xBF,
+
+       0x7B, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x35, 0x00,
+       0x3D, 0x00,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0x8D, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x75, 0xF8, 0xEC,
+       0x35, 0x20,
+       0x3D, 0x20,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x53, 0x53, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x0E, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x48, 0x35, 0x48, 0xBF,
+       0x58, 0x35, 0x58, 0xBF,
+
+       0x68, 0x35, 0x68, 0xBF,
+       0x49, 0x3D, 0x49, 0xBF,
+
+       0x59, 0x3D, 0x59, 0xBF,
+       0x69, 0x3D, 0x69, 0xBF,
+
+       0x63, 0x63, 0x2D, 0xDF,
+       0x4D, 0x7D, 0xF8, 0xEC,
+
+       0x59, 0xE3,
+       0x00, 0xE0,
+       0xB8, 0x38, 0x33, 0xBF,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x18, 0x3A, 0x41, 0xE9,
+
+       0x3F, 0x53, 0xA0, 0xE8,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x63, 0xA0, 0xE8,
+
+       0x50, 0x70, 0xF8, 0xEC,
+       0x2B, 0x50, 0x3C, 0xE9,
+
+       0x1F, 0x0F, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x59, 0x78, 0xF8, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x56, 0x3F, 0x56, 0xDF,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x66, 0x3D, 0x66, 0xDF,
+
+       0x1D, 0x32, 0x41, 0xE9,
+       0x67, 0x3D, 0x67, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3F, 0x57, 0xDF,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x59, 0x3F, 0x59, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x69, 0x3D, 0x69, 0xDF,
+
+       0x48, 0x37, 0x48, 0xDF,
+       0x58, 0x3F, 0x58, 0xDF,
+
+       0x68, 0x3D, 0x68, 0xDF,
+       0x49, 0x37, 0x49, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x0F, 0xCF, 0x74, 0xC2,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x0A, 0x44, 0x54, 0xB0,
+       0x02, 0x44, 0x64, 0xB0,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x34, 0x37, 0x20, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x38, 0x0F, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x54, 0xB2,
+       0x1A, 0x44, 0x64, 0xB2,
+
+       0x36, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x0F, 0xCF, 0x75, 0xC0,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x3D, 0xCF, 0x75, 0xC2,
+       0x37, 0xCF, 0x75, 0xC4,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA6, 0x0F, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA3, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x54, 0xB4,
+       0x1A, 0x44, 0x64, 0xB4,
+
+       0x0A, 0x45, 0x55, 0xB0,
+       0x02, 0x45, 0x65, 0xB0,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA0, 0x37, 0x20, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x45, 0x55, 0xB2,
+       0x1A, 0x45, 0x65, 0xB2,
+
+       0x0A, 0x45, 0x55, 0xB4,
+       0x02, 0x45, 0x65, 0xB4,
+
+       0x0F, 0xCF, 0x74, 0xC6,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA7, 0x30, 0x4F, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x9C, 0x0F, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA8, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x44, 0x54, 0xB6,
+       0x1A, 0x44, 0x64, 0xB6,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x36, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x37, 0x39, 0x4F, 0xE9,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x2A, 0x46, 0x56, 0xBF,
+       0x1A, 0x46, 0x66, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA4, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA5, 0x39, 0x4F, 0xE9,
+
+       0x0A, 0x47, 0x57, 0xBF,
+       0x02, 0x47, 0x67, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA1, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA2, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x53, 0xBF,
+       0x1A, 0x43, 0x63, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x9D, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x9E, 0x39, 0x4F, 0xE9,
+
+       0x0A, 0x48, 0x58, 0xBF,
+       0x02, 0x48, 0x68, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x2A, 0x49, 0x59, 0xBF,
+       0x1A, 0x49, 0x69, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x82, 0x30, 0x57, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x83, 0x38, 0x57, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x84, 0x31, 0x5E, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x85, 0x39, 0x5E, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x87, 0x77, 0x57, 0xE9,
+       0x8B, 0x3E, 0xBF, 0xEA,
+
+       0x80, 0x30, 0x57, 0xE9,
+       0x81, 0x38, 0x57, 0xE9,
+
+       0x82, 0x31, 0x57, 0xE9,
+       0x86, 0x78, 0x57, 0xE9,
+
+       0x83, 0x39, 0x57, 0xE9,
+       0x87, 0x79, 0x57, 0xE9,
+
+       0x30, 0x1F, 0x5F, 0xE9,
+       0x8A, 0x34, 0x20, 0xE9,
+
+       0x8B, 0x3C, 0x20, 0xE9,
+       0x37, 0x50, 0x60, 0xBD,
+
+       0x57, 0x0D, 0x20, 0xE9,
+       0x35, 0x51, 0x61, 0xBD,
+
+       0x2B, 0x50, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x0E, 0x77,
+
+       0x24, 0x51, 0x20, 0xE9,
+       0x8D, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x0E, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x0B, 0x46, 0xA0, 0xE8,
+       0x1B, 0x56, 0xA0, 0xE8,
+
+       0x2B, 0x66, 0xA0, 0xE8,
+       0x0C, 0x47, 0xA0, 0xE8,
+
+       0x1C, 0x57, 0xA0, 0xE8,
+       0x2C, 0x67, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x57, 0x80, 0x57, 0xCF,
+
+       0x66, 0x33, 0x66, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x67, 0x3B, 0x67, 0xCF,
+
+       0x0B, 0x48, 0xA0, 0xE8,
+       0x1B, 0x58, 0xA0, 0xE8,
+
+       0x2B, 0x68, 0xA0, 0xE8,
+       0x0C, 0x49, 0xA0, 0xE8,
+
+       0x1C, 0x59, 0xA0, 0xE8,
+       0x2C, 0x69, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x34, 0xD7, 0x34, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3C, 0xD7, 0x3C, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x34, 0x80, 0x34, 0xBD,
+       0x3C, 0x80, 0x3C, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x48, 0x80, 0x48, 0xCF,
+       0x59, 0x80, 0x59, 0xCF,
+
+       0x68, 0x33, 0x68, 0xCF,
+       0x49, 0x3B, 0x49, 0xCF,
+
+       0xAD, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x58, 0x33, 0x58, 0xCF,
+       0x69, 0x3B, 0x69, 0xCF,
+
+       0x6B, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzsaf[] = {
+
+       0x00, 0x8A, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x0A, 0x40, 0x50, 0xBF,
+       0x2A, 0x40, 0x60, 0xBF,
+
+       0x32, 0x41, 0x51, 0xBF,
+       0x3A, 0x41, 0x61, 0xBF,
+
+       0xC3, 0x6B,
+       0xD3, 0x6B,
+       0x00, 0x8A, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x23, 0x9F,
+       0x00, 0xE0,
+       0x51, 0x04,
+
+       0x90, 0xE2,
+       0x61, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x51, 0x41, 0xE0, 0xEC,
+       0x39, 0x67, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x63, 0xA0, 0xE8,
+
+       0x61, 0x41, 0xE0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x8E, 0x80, 0x15, 0xEA,
+       0x10, 0x04,
+       0x20, 0x04,
+
+       0x61, 0x51, 0xE0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x52, 0xBF,
+       0x0F, 0x52, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x62, 0xBF,
+       0x1E, 0x51, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x0E, 0x61, 0x60, 0xEA,
+
+       0x32, 0x40, 0x50, 0xBD,
+       0x22, 0x40, 0x60, 0xBD,
+
+       0x12, 0x41, 0x51, 0xBD,
+       0x3A, 0x41, 0x61, 0xBD,
+
+       0xBF, 0x2F, 0x0E, 0xBD,
+       0x97, 0xE2,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x35, 0x48, 0xB1, 0xE8,
+       0x3D, 0x59, 0xB1, 0xE8,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x56, 0x31, 0x56, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x66, 0x31, 0x66, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x57, 0x39, 0x57, 0xBF,
+       0x67, 0x39, 0x67, 0xBF,
+
+       0x7F, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x35, 0x00,
+       0x3D, 0x00,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0x8D, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x75, 0xF8, 0xEC,
+       0x35, 0x20,
+       0x3D, 0x20,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x53, 0x53, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x0E, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x48, 0x35, 0x48, 0xBF,
+       0x58, 0x35, 0x58, 0xBF,
+
+       0x68, 0x35, 0x68, 0xBF,
+       0x49, 0x3D, 0x49, 0xBF,
+
+       0x59, 0x3D, 0x59, 0xBF,
+       0x69, 0x3D, 0x69, 0xBF,
+
+       0x63, 0x63, 0x2D, 0xDF,
+       0x4D, 0x7D, 0xF8, 0xEC,
+
+       0x59, 0xE3,
+       0x00, 0xE0,
+       0xB8, 0x38, 0x33, 0xBF,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x18, 0x3A, 0x41, 0xE9,
+
+       0x3F, 0x53, 0xA0, 0xE8,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x63, 0xA0, 0xE8,
+
+       0x50, 0x70, 0xF8, 0xEC,
+       0x2B, 0x50, 0x3C, 0xE9,
+
+       0x1F, 0x0F, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x59, 0x78, 0xF8, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x56, 0x3F, 0x56, 0xDF,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x66, 0x3D, 0x66, 0xDF,
+
+       0x1D, 0x32, 0x41, 0xE9,
+       0x67, 0x3D, 0x67, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3F, 0x57, 0xDF,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x59, 0x3F, 0x59, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x69, 0x3D, 0x69, 0xDF,
+
+       0x48, 0x37, 0x48, 0xDF,
+       0x58, 0x3F, 0x58, 0xDF,
+
+       0x68, 0x3D, 0x68, 0xDF,
+       0x49, 0x37, 0x49, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x0F, 0xCF, 0x74, 0xC2,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x0A, 0x44, 0x54, 0xB0,
+       0x02, 0x44, 0x64, 0xB0,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x34, 0x37, 0x20, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x38, 0x0F, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x54, 0xB2,
+       0x1A, 0x44, 0x64, 0xB2,
+
+       0x3A, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x0F, 0xCF, 0x75, 0xC0,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x3D, 0xCF, 0x75, 0xC2,
+       0x37, 0xCF, 0x75, 0xC4,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA6, 0x0F, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA3, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x54, 0xB4,
+       0x1A, 0x44, 0x64, 0xB4,
+
+       0x0A, 0x45, 0x55, 0xB0,
+       0x02, 0x45, 0x65, 0xB0,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA0, 0x37, 0x20, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x45, 0x55, 0xB2,
+       0x1A, 0x45, 0x65, 0xB2,
+
+       0x0A, 0x45, 0x55, 0xB4,
+       0x02, 0x45, 0x65, 0xB4,
+
+       0x0F, 0xCF, 0x74, 0xC6,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA7, 0x30, 0x4F, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x9C, 0x0F, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA8, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x44, 0x54, 0xB6,
+       0x1A, 0x44, 0x64, 0xB6,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x36, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x37, 0x39, 0x4F, 0xE9,
+
+       0x0A, 0x45, 0x55, 0xB6,
+       0x02, 0x45, 0x65, 0xB6,
+
+       0x3D, 0xCF, 0x75, 0xC6,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x2A, 0x46, 0x56, 0xBF,
+       0x1A, 0x46, 0x66, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA4, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA5, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x3D, 0x20, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x0A, 0x47, 0x57, 0xBF,
+       0x02, 0x47, 0x67, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0xA1, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0xA2, 0x38, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x9D, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x9E, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x53, 0xBF,
+       0x1A, 0x43, 0x63, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x35, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x39, 0x38, 0x4F, 0xE9,
+
+       0x0A, 0x48, 0x58, 0xBF,
+       0x02, 0x48, 0x68, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x2A, 0x49, 0x59, 0xBF,
+       0x1A, 0x49, 0x69, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x82, 0x30, 0x57, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x83, 0x38, 0x57, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x84, 0x31, 0x5E, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x85, 0x39, 0x5E, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x87, 0x77, 0x57, 0xE9,
+       0x8B, 0x3E, 0xBF, 0xEA,
+
+       0x80, 0x30, 0x57, 0xE9,
+       0x81, 0x38, 0x57, 0xE9,
+
+       0x82, 0x31, 0x57, 0xE9,
+       0x86, 0x78, 0x57, 0xE9,
+
+       0x83, 0x39, 0x57, 0xE9,
+       0x87, 0x79, 0x57, 0xE9,
+
+       0x30, 0x1F, 0x5F, 0xE9,
+       0x8A, 0x34, 0x20, 0xE9,
+
+       0x8B, 0x3C, 0x20, 0xE9,
+       0x37, 0x50, 0x60, 0xBD,
+
+       0x57, 0x0D, 0x20, 0xE9,
+       0x35, 0x51, 0x61, 0xBD,
+
+       0x2B, 0x50, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x0E, 0x77,
+
+       0x24, 0x51, 0x20, 0xE9,
+       0x89, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x0E, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x0B, 0x46, 0xA0, 0xE8,
+       0x1B, 0x56, 0xA0, 0xE8,
+
+       0x2B, 0x66, 0xA0, 0xE8,
+       0x0C, 0x47, 0xA0, 0xE8,
+
+       0x1C, 0x57, 0xA0, 0xE8,
+       0x2C, 0x67, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x57, 0x80, 0x57, 0xCF,
+
+       0x66, 0x33, 0x66, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x67, 0x3B, 0x67, 0xCF,
+
+       0x0B, 0x48, 0xA0, 0xE8,
+       0x1B, 0x58, 0xA0, 0xE8,
+
+       0x2B, 0x68, 0xA0, 0xE8,
+       0x0C, 0x49, 0xA0, 0xE8,
+
+       0x1C, 0x59, 0xA0, 0xE8,
+       0x2C, 0x69, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x34, 0xD7, 0x34, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3C, 0xD7, 0x3C, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x34, 0x80, 0x34, 0xBD,
+       0x3C, 0x80, 0x3C, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x48, 0x80, 0x48, 0xCF,
+       0x59, 0x80, 0x59, 0xCF,
+
+       0x68, 0x33, 0x68, 0xCF,
+       0x49, 0x3B, 0x49, 0xCF,
+
+       0xA9, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x58, 0x33, 0x58, 0xCF,
+       0x69, 0x3B, 0x69, 0xCF,
+
+       0x67, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_t2gzsf[] = {
+
+       0x00, 0x8A, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x0A, 0x40, 0x50, 0xBF,
+       0x2A, 0x40, 0x60, 0xBF,
+
+       0x32, 0x41, 0x51, 0xBF,
+       0x3A, 0x41, 0x61, 0xBF,
+
+       0xC3, 0x6B,
+       0xD3, 0x6B,
+       0x00, 0x8A, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x23, 0x9F,
+       0x00, 0xE0,
+       0x51, 0x04,
+
+       0x90, 0xE2,
+       0x61, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x51, 0x41, 0xE0, 0xEC,
+       0x39, 0x67, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x63, 0xA0, 0xE8,
+
+       0x61, 0x41, 0xE0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x8A, 0x80, 0x15, 0xEA,
+       0x10, 0x04,
+       0x20, 0x04,
+
+       0x61, 0x51, 0xE0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x52, 0xBF,
+       0x0F, 0x52, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x62, 0xBF,
+       0x1E, 0x51, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x0E, 0x61, 0x60, 0xEA,
+
+       0x32, 0x40, 0x50, 0xBD,
+       0x22, 0x40, 0x60, 0xBD,
+
+       0x12, 0x41, 0x51, 0xBD,
+       0x3A, 0x41, 0x61, 0xBD,
+
+       0xBF, 0x2F, 0x0E, 0xBD,
+       0x97, 0xE2,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x35, 0x48, 0xB1, 0xE8,
+       0x3D, 0x59, 0xB1, 0xE8,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x56, 0x31, 0x56, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x66, 0x31, 0x66, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x57, 0x39, 0x57, 0xBF,
+       0x67, 0x39, 0x67, 0xBF,
+
+       0x7B, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x35, 0x00,
+       0x3D, 0x00,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0x8D, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x75, 0xF8, 0xEC,
+       0x35, 0x20,
+       0x3D, 0x20,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x53, 0x53, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x0E, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x48, 0x35, 0x48, 0xBF,
+       0x58, 0x35, 0x58, 0xBF,
+
+       0x68, 0x35, 0x68, 0xBF,
+       0x49, 0x3D, 0x49, 0xBF,
+
+       0x59, 0x3D, 0x59, 0xBF,
+       0x69, 0x3D, 0x69, 0xBF,
+
+       0x63, 0x63, 0x2D, 0xDF,
+       0x4D, 0x7D, 0xF8, 0xEC,
+
+       0x59, 0xE3,
+       0x00, 0xE0,
+       0xB8, 0x38, 0x33, 0xBF,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x18, 0x3A, 0x41, 0xE9,
+
+       0x3F, 0x53, 0xA0, 0xE8,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x63, 0xA0, 0xE8,
+
+       0x50, 0x70, 0xF8, 0xEC,
+       0x2B, 0x50, 0x3C, 0xE9,
+
+       0x1F, 0x0F, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x59, 0x78, 0xF8, 0xEC,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x56, 0x3F, 0x56, 0xDF,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x66, 0x3D, 0x66, 0xDF,
+
+       0x1D, 0x32, 0x41, 0xE9,
+       0x67, 0x3D, 0x67, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3F, 0x57, 0xDF,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x59, 0x3F, 0x59, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x69, 0x3D, 0x69, 0xDF,
+
+       0x48, 0x37, 0x48, 0xDF,
+       0x58, 0x3F, 0x58, 0xDF,
+
+       0x68, 0x3D, 0x68, 0xDF,
+       0x49, 0x37, 0x49, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x0F, 0xCF, 0x74, 0xC2,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x0A, 0x44, 0x54, 0xB0,
+       0x02, 0x44, 0x64, 0xB0,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x34, 0x37, 0x20, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x38, 0x0F, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x54, 0xB2,
+       0x1A, 0x44, 0x64, 0xB2,
+
+       0x36, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x0F, 0xCF, 0x75, 0xC0,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x3D, 0xCF, 0x75, 0xC2,
+       0x37, 0xCF, 0x75, 0xC4,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA6, 0x0F, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA3, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x54, 0xB4,
+       0x1A, 0x44, 0x64, 0xB4,
+
+       0x0A, 0x45, 0x55, 0xB0,
+       0x02, 0x45, 0x65, 0xB0,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA0, 0x37, 0x20, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x45, 0x55, 0xB2,
+       0x1A, 0x45, 0x65, 0xB2,
+
+       0x0A, 0x45, 0x55, 0xB4,
+       0x02, 0x45, 0x65, 0xB4,
+
+       0x0F, 0xCF, 0x75, 0xC6,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA7, 0x30, 0x4F, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x31, 0x0F, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA8, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x45, 0x55, 0xB6,
+       0x1A, 0x45, 0x65, 0xB6,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x36, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x37, 0x39, 0x4F, 0xE9,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x2A, 0x46, 0x56, 0xBF,
+       0x1A, 0x46, 0x66, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA4, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA5, 0x39, 0x4F, 0xE9,
+
+       0x0A, 0x47, 0x57, 0xBF,
+       0x02, 0x47, 0x67, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA1, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA2, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x53, 0xBF,
+       0x1A, 0x43, 0x63, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x35, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x39, 0x39, 0x4F, 0xE9,
+
+       0x0A, 0x48, 0x58, 0xBF,
+       0x02, 0x48, 0x68, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x2A, 0x49, 0x59, 0xBF,
+       0x1A, 0x49, 0x69, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x82, 0x30, 0x57, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x83, 0x38, 0x57, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x84, 0x31, 0x5E, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x85, 0x39, 0x5E, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x87, 0x77, 0x57, 0xE9,
+       0x8B, 0x3E, 0xBF, 0xEA,
+
+       0x80, 0x30, 0x57, 0xE9,
+       0x81, 0x38, 0x57, 0xE9,
+
+       0x82, 0x31, 0x57, 0xE9,
+       0x86, 0x78, 0x57, 0xE9,
+
+       0x83, 0x39, 0x57, 0xE9,
+       0x87, 0x79, 0x57, 0xE9,
+
+       0x30, 0x1F, 0x5F, 0xE9,
+       0x8A, 0x34, 0x20, 0xE9,
+
+       0x8B, 0x3C, 0x20, 0xE9,
+       0x37, 0x50, 0x60, 0xBD,
+
+       0x57, 0x0D, 0x20, 0xE9,
+       0x35, 0x51, 0x61, 0xBD,
+
+       0x2B, 0x50, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x0E, 0x77,
+
+       0x24, 0x51, 0x20, 0xE9,
+       0x8D, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x0E, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x0B, 0x46, 0xA0, 0xE8,
+       0x1B, 0x56, 0xA0, 0xE8,
+
+       0x2B, 0x66, 0xA0, 0xE8,
+       0x0C, 0x47, 0xA0, 0xE8,
+
+       0x1C, 0x57, 0xA0, 0xE8,
+       0x2C, 0x67, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x57, 0x80, 0x57, 0xCF,
+
+       0x66, 0x33, 0x66, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x67, 0x3B, 0x67, 0xCF,
+
+       0x0B, 0x48, 0xA0, 0xE8,
+       0x1B, 0x58, 0xA0, 0xE8,
+
+       0x2B, 0x68, 0xA0, 0xE8,
+       0x0C, 0x49, 0xA0, 0xE8,
+
+       0x1C, 0x59, 0xA0, 0xE8,
+       0x2C, 0x69, 0xA0, 0xE8,
+
+       0x0B, 0x00,
+       0x1B, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x0C, 0x00,
+       0x1C, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x0B, 0x65,
+       0x1B, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x0C, 0x65,
+       0x1C, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x0B, 0x1B, 0x60, 0xEC,
+       0x34, 0xD7, 0x34, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x0C, 0x1C, 0x60, 0xEC,
+
+       0x3C, 0xD7, 0x3C, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x0B, 0x2B, 0xDE, 0xE8,
+       0x1B, 0x80, 0xDE, 0xE8,
+
+       0x34, 0x80, 0x34, 0xBD,
+       0x3C, 0x80, 0x3C, 0xBD,
+
+       0x33, 0xD7, 0x0B, 0xBD,
+       0x3B, 0xD7, 0x1B, 0xBD,
+
+       0x48, 0x80, 0x48, 0xCF,
+       0x59, 0x80, 0x59, 0xCF,
+
+       0x68, 0x33, 0x68, 0xCF,
+       0x49, 0x3B, 0x49, 0xCF,
+
+       0xAD, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x58, 0x33, 0x58, 0xCF,
+       0x69, 0x3B, 0x69, 0xCF,
+
+       0x6B, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgz[] = {
+
+       0x00, 0x88, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x22, 0x40, 0x48, 0xBF,
+       0x2A, 0x40, 0x50, 0xBF,
+
+       0x32, 0x41, 0x49, 0xBF,
+       0x3A, 0x41, 0x51, 0xBF,
+
+       0xC3, 0x6B,
+       0xCB, 0x6B,
+       0x00, 0x88, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x4B, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x29, 0x9F,
+       0x00, 0xE0,
+       0x49, 0x04,
+
+       0x90, 0xE2,
+       0x51, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x49, 0x41, 0xC0, 0xEC,
+       0x39, 0x57, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0x51, 0x41, 0xC0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x58, 0x80, 0x15, 0xEA,
+       0x08, 0x04,
+       0x10, 0x04,
+
+       0x51, 0x49, 0xC0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x4A, 0xBF,
+       0x27, 0x4A, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x52, 0xBF,
+       0x1E, 0x49, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x26, 0x51, 0x60, 0xEA,
+
+       0x32, 0x40, 0x48, 0xBD,
+       0x22, 0x40, 0x50, 0xBD,
+
+       0x12, 0x41, 0x49, 0xBD,
+       0x3A, 0x41, 0x51, 0xBD,
+
+       0xBF, 0x2F, 0x26, 0xBD,
+       0x00, 0xE0,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x4E, 0x31, 0x4E, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x56, 0x31, 0x56, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x4F, 0x39, 0x4F, 0xBF,
+       0x57, 0x39, 0x57, 0xBF,
+
+       0x4A, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x42, 0x73, 0xF8, 0xEC,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0xA5, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x4B, 0x4B, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x26, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x53, 0x53, 0x2D, 0xDF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xB8, 0x38, 0x33, 0xBF,
+       0x00, 0xE0,
+       0x59, 0xE3,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x3F, 0x4B, 0xA0, 0xE8,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x53, 0xA0, 0xE8,
+
+       0x48, 0x70, 0xF8, 0xEC,
+       0x2B, 0x48, 0x3C, 0xE9,
+
+       0x1F, 0x27, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x18, 0x3A, 0x41, 0xE9,
+       0x1D, 0x32, 0x41, 0xE9,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x56, 0x3D, 0x56, 0xDF,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x4E, 0x3F, 0x4E, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x4F, 0x3F, 0x4F, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3D, 0x57, 0xDF,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x34, 0x80, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x0A, 0x44, 0x4C, 0xB0,
+       0x02, 0x44, 0x54, 0xB0,
+
+       0x2A, 0x44, 0x4C, 0xB2,
+       0x1A, 0x44, 0x54, 0xB2,
+
+       0x1D, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x3D, 0xCF, 0x74, 0xC2,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x2A, 0x44, 0x4C, 0xB4,
+       0x1A, 0x44, 0x54, 0xB4,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x38, 0x3D, 0x20, 0xE9,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x2A, 0x46, 0x4E, 0xBF,
+       0x1A, 0x46, 0x56, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x0A, 0x47, 0x4F, 0xBF,
+       0x02, 0x47, 0x57, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x4B, 0xBF,
+       0x1A, 0x43, 0x53, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x36, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x37, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x37, 0x48, 0x50, 0xBD,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8B, 0x3E, 0x20, 0xE9,
+
+       0x82, 0x30, 0x57, 0xE9,
+       0x87, 0x77, 0x57, 0xE9,
+
+       0x83, 0x38, 0x57, 0xE9,
+       0x35, 0x49, 0x51, 0xBD,
+
+       0x84, 0x31, 0x5E, 0xE9,
+       0x30, 0x1F, 0x5F, 0xE9,
+
+       0x85, 0x39, 0x5E, 0xE9,
+       0x57, 0x25, 0x20, 0xE9,
+
+       0x2B, 0x48, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x26, 0x77,
+
+       0x24, 0x49, 0x20, 0xE9,
+       0xAF, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x26, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x1C, 0x46, 0xA0, 0xE8,
+       0x23, 0x4E, 0xA0, 0xE8,
+
+       0x2B, 0x56, 0xA0, 0xE8,
+       0x1D, 0x47, 0xA0, 0xE8,
+
+       0x24, 0x4F, 0xA0, 0xE8,
+       0x2C, 0x57, 0xA0, 0xE8,
+
+       0x1C, 0x00,
+       0x23, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x1D, 0x00,
+       0x24, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x1C, 0x65,
+       0x23, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x1D, 0x65,
+       0x24, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x1C, 0x23, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x1D, 0x24, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x1C, 0x2B, 0xDE, 0xE8,
+       0x23, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x1C, 0xBD,
+       0x3B, 0xD7, 0x23, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x4F, 0x80, 0x4F, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0xD6, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x4E, 0x33, 0x4E, 0xCF,
+       0x57, 0x3B, 0x57, 0xCF,
+
+       0x9D, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgza[] = {
+
+       0x00, 0x88, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x22, 0x40, 0x48, 0xBF,
+       0x2A, 0x40, 0x50, 0xBF,
+
+       0x32, 0x41, 0x49, 0xBF,
+       0x3A, 0x41, 0x51, 0xBF,
+
+       0xC3, 0x6B,
+       0xCB, 0x6B,
+       0x00, 0x88, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x4B, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x29, 0x9F,
+       0x00, 0xE0,
+       0x49, 0x04,
+
+       0x90, 0xE2,
+       0x51, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x49, 0x41, 0xC0, 0xEC,
+       0x39, 0x57, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0x51, 0x41, 0xC0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x5C, 0x80, 0x15, 0xEA,
+       0x08, 0x04,
+       0x10, 0x04,
+
+       0x51, 0x49, 0xC0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x4A, 0xBF,
+       0x27, 0x4A, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x52, 0xBF,
+       0x1E, 0x49, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x26, 0x51, 0x60, 0xEA,
+
+       0x32, 0x40, 0x48, 0xBD,
+       0x22, 0x40, 0x50, 0xBD,
+
+       0x12, 0x41, 0x49, 0xBD,
+       0x3A, 0x41, 0x51, 0xBD,
+
+       0xBF, 0x2F, 0x26, 0xBD,
+       0x00, 0xE0,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x4E, 0x31, 0x4E, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x56, 0x31, 0x56, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x4F, 0x39, 0x4F, 0xBF,
+       0x57, 0x39, 0x57, 0xBF,
+
+       0x4E, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x42, 0x73, 0xF8, 0xEC,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0xA5, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x4B, 0x4B, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x26, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x53, 0x53, 0x2D, 0xDF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xB8, 0x38, 0x33, 0xBF,
+       0x00, 0xE0,
+       0x59, 0xE3,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x3F, 0x4B, 0xA0, 0xE8,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x53, 0xA0, 0xE8,
+
+       0x48, 0x70, 0xF8, 0xEC,
+       0x2B, 0x48, 0x3C, 0xE9,
+
+       0x1F, 0x27, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x18, 0x3A, 0x41, 0xE9,
+       0x1D, 0x32, 0x41, 0xE9,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x56, 0x3D, 0x56, 0xDF,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x4E, 0x3F, 0x4E, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x4F, 0x3F, 0x4F, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3D, 0x57, 0xDF,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x34, 0x80, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x27, 0xCF, 0x74, 0xC6,
+       0x3D, 0xCF, 0x74, 0xC2,
+
+       0x0A, 0x44, 0x4C, 0xB0,
+       0x02, 0x44, 0x54, 0xB0,
+
+       0x2A, 0x44, 0x4C, 0xB2,
+       0x1A, 0x44, 0x54, 0xB2,
+
+       0x20, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x9C, 0x27, 0x20, 0xE9,
+
+       0x0A, 0x44, 0x4C, 0xB4,
+       0x02, 0x44, 0x54, 0xB4,
+
+       0x2A, 0x44, 0x4C, 0xB6,
+       0x1A, 0x44, 0x54, 0xB6,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x38, 0x3D, 0x20, 0xE9,
+
+       0x0A, 0x20,
+       0x02, 0x20,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x0A, 0x47, 0x4F, 0xBF,
+       0x02, 0x47, 0x57, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x46, 0x4E, 0xBF,
+       0x1A, 0x46, 0x56, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x36, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x37, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x4B, 0xBF,
+       0x1A, 0x43, 0x53, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x9D, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x9E, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x37, 0x48, 0x50, 0xBD,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8B, 0x3E, 0x20, 0xE9,
+
+       0x82, 0x30, 0x57, 0xE9,
+       0x87, 0x77, 0x57, 0xE9,
+
+       0x83, 0x38, 0x57, 0xE9,
+       0x35, 0x49, 0x51, 0xBD,
+
+       0x84, 0x31, 0x5E, 0xE9,
+       0x30, 0x1F, 0x5F, 0xE9,
+
+       0x85, 0x39, 0x5E, 0xE9,
+       0x57, 0x25, 0x20, 0xE9,
+
+       0x2B, 0x48, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x26, 0x77,
+
+       0x24, 0x49, 0x20, 0xE9,
+       0xAB, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x26, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x1C, 0x46, 0xA0, 0xE8,
+       0x23, 0x4E, 0xA0, 0xE8,
+
+       0x2B, 0x56, 0xA0, 0xE8,
+       0x1D, 0x47, 0xA0, 0xE8,
+
+       0x24, 0x4F, 0xA0, 0xE8,
+       0x2C, 0x57, 0xA0, 0xE8,
+
+       0x1C, 0x00,
+       0x23, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x1D, 0x00,
+       0x24, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x1C, 0x65,
+       0x23, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x1D, 0x65,
+       0x24, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x1C, 0x23, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x1D, 0x24, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x1C, 0x2B, 0xDE, 0xE8,
+       0x23, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x1C, 0xBD,
+       0x3B, 0xD7, 0x23, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x4F, 0x80, 0x4F, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0xD3, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x4E, 0x33, 0x4E, 0xCF,
+       0x57, 0x3B, 0x57, 0xCF,
+
+       0x99, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzaf[] = {
+
+       0x00, 0x88, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x22, 0x40, 0x48, 0xBF,
+       0x2A, 0x40, 0x50, 0xBF,
+
+       0x32, 0x41, 0x49, 0xBF,
+       0x3A, 0x41, 0x51, 0xBF,
+
+       0xC3, 0x6B,
+       0xCB, 0x6B,
+       0x00, 0x88, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x4B, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x29, 0x9F,
+       0x00, 0xE0,
+       0x49, 0x04,
+
+       0x90, 0xE2,
+       0x51, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x49, 0x41, 0xC0, 0xEC,
+       0x39, 0x57, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0x51, 0x41, 0xC0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x61, 0x80, 0x15, 0xEA,
+       0x08, 0x04,
+       0x10, 0x04,
+
+       0x51, 0x49, 0xC0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x4A, 0xBF,
+       0x27, 0x4A, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x52, 0xBF,
+       0x1E, 0x49, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x26, 0x51, 0x60, 0xEA,
+
+       0x32, 0x40, 0x48, 0xBD,
+       0x22, 0x40, 0x50, 0xBD,
+
+       0x12, 0x41, 0x49, 0xBD,
+       0x3A, 0x41, 0x51, 0xBD,
+
+       0xBF, 0x2F, 0x26, 0xBD,
+       0x00, 0xE0,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x4E, 0x31, 0x4E, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x56, 0x31, 0x56, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x4F, 0x39, 0x4F, 0xBF,
+       0x57, 0x39, 0x57, 0xBF,
+
+       0x53, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x42, 0x73, 0xF8, 0xEC,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0xA5, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x4B, 0x4B, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x26, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x53, 0x53, 0x2D, 0xDF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xB8, 0x38, 0x33, 0xBF,
+       0x00, 0xE0,
+       0x59, 0xE3,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x3F, 0x4B, 0xA0, 0xE8,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x53, 0xA0, 0xE8,
+
+       0x48, 0x70, 0xF8, 0xEC,
+       0x2B, 0x48, 0x3C, 0xE9,
+
+       0x1F, 0x27, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x18, 0x3A, 0x41, 0xE9,
+       0x1D, 0x32, 0x41, 0xE9,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x56, 0x3D, 0x56, 0xDF,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x4E, 0x3F, 0x4E, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x4F, 0x3F, 0x4F, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3D, 0x57, 0xDF,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x0A, 0x44, 0x4C, 0xB0,
+       0x02, 0x44, 0x54, 0xB0,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x34, 0x37, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x4C, 0xB2,
+       0x1A, 0x44, 0x54, 0xB2,
+
+       0x26, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x3D, 0xCF, 0x74, 0xC2,
+       0x27, 0xCF, 0x74, 0xC6,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x9C, 0x27, 0x20, 0xE9,
+
+       0x0A, 0x44, 0x4C, 0xB4,
+       0x02, 0x44, 0x54, 0xB4,
+
+       0x2A, 0x44, 0x4C, 0xB6,
+       0x1A, 0x44, 0x54, 0xB6,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x38, 0x3D, 0x20, 0xE9,
+
+       0x0A, 0x20,
+       0x02, 0x20,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x3D, 0xCF, 0x75, 0xC6,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x0A, 0x45, 0x4D, 0xB6,
+       0x02, 0x45, 0x55, 0xB6,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x3D, 0x20, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x2A, 0x46, 0x4E, 0xBF,
+       0x1A, 0x46, 0x56, 0xBF,
+
+       0x0A, 0x47, 0x4F, 0xBF,
+       0x02, 0x47, 0x57, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x36, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x37, 0x38, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x9D, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x9E, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x4B, 0xBF,
+       0x1A, 0x43, 0x53, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x35, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x39, 0x38, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x37, 0x48, 0x50, 0xBD,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8B, 0x3E, 0x20, 0xE9,
+
+       0x82, 0x30, 0x57, 0xE9,
+       0x87, 0x77, 0x57, 0xE9,
+
+       0x83, 0x38, 0x57, 0xE9,
+       0x35, 0x49, 0x51, 0xBD,
+
+       0x84, 0x31, 0x5E, 0xE9,
+       0x30, 0x1F, 0x5F, 0xE9,
+
+       0x85, 0x39, 0x5E, 0xE9,
+       0x57, 0x25, 0x20, 0xE9,
+
+       0x2B, 0x48, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x26, 0x77,
+
+       0x24, 0x49, 0x20, 0xE9,
+       0xA6, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x26, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x1C, 0x46, 0xA0, 0xE8,
+       0x23, 0x4E, 0xA0, 0xE8,
+
+       0x2B, 0x56, 0xA0, 0xE8,
+       0x1D, 0x47, 0xA0, 0xE8,
+
+       0x24, 0x4F, 0xA0, 0xE8,
+       0x2C, 0x57, 0xA0, 0xE8,
+
+       0x1C, 0x00,
+       0x23, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x1D, 0x00,
+       0x24, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x1C, 0x65,
+       0x23, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x1D, 0x65,
+       0x24, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x1C, 0x23, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x1D, 0x24, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x1C, 0x2B, 0xDE, 0xE8,
+       0x23, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x1C, 0xBD,
+       0x3B, 0xD7, 0x23, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x4F, 0x80, 0x4F, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0xCD, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x4E, 0x33, 0x4E, 0xCF,
+       0x57, 0x3B, 0x57, 0xCF,
+
+       0x94, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzf[] = {
+
+       0x00, 0x88, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x22, 0x40, 0x48, 0xBF,
+       0x2A, 0x40, 0x50, 0xBF,
+
+       0x32, 0x41, 0x49, 0xBF,
+       0x3A, 0x41, 0x51, 0xBF,
+
+       0xC3, 0x6B,
+       0xCB, 0x6B,
+       0x00, 0x88, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x4B, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x29, 0x9F,
+       0x00, 0xE0,
+       0x49, 0x04,
+
+       0x90, 0xE2,
+       0x51, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x49, 0x41, 0xC0, 0xEC,
+       0x39, 0x57, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0x51, 0x41, 0xC0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x5D, 0x80, 0x15, 0xEA,
+       0x08, 0x04,
+       0x10, 0x04,
+
+       0x51, 0x49, 0xC0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x4A, 0xBF,
+       0x27, 0x4A, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x52, 0xBF,
+       0x1E, 0x49, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x26, 0x51, 0x60, 0xEA,
+
+       0x32, 0x40, 0x48, 0xBD,
+       0x22, 0x40, 0x50, 0xBD,
+
+       0x12, 0x41, 0x49, 0xBD,
+       0x3A, 0x41, 0x51, 0xBD,
+
+       0xBF, 0x2F, 0x26, 0xBD,
+       0x00, 0xE0,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x4E, 0x31, 0x4E, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x56, 0x31, 0x56, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x4F, 0x39, 0x4F, 0xBF,
+       0x57, 0x39, 0x57, 0xBF,
+
+       0x4F, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x42, 0x73, 0xF8, 0xEC,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0xA5, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x4B, 0x4B, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x26, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x53, 0x53, 0x2D, 0xDF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xB8, 0x38, 0x33, 0xBF,
+       0x00, 0xE0,
+       0x59, 0xE3,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x3F, 0x4B, 0xA0, 0xE8,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x53, 0xA0, 0xE8,
+
+       0x48, 0x70, 0xF8, 0xEC,
+       0x2B, 0x48, 0x3C, 0xE9,
+
+       0x1F, 0x27, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x18, 0x3A, 0x41, 0xE9,
+       0x1D, 0x32, 0x41, 0xE9,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x56, 0x3D, 0x56, 0xDF,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x4E, 0x3F, 0x4E, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x4F, 0x3F, 0x4F, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3D, 0x57, 0xDF,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x34, 0x80, 0x20, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x27, 0xCF, 0x75, 0xC6,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x0A, 0x44, 0x4C, 0xB0,
+       0x02, 0x44, 0x54, 0xB0,
+
+       0x2A, 0x44, 0x4C, 0xB2,
+       0x1A, 0x44, 0x54, 0xB2,
+
+       0x20, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x3D, 0xCF, 0x74, 0xC2,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x31, 0x27, 0x20, 0xE9,
+
+       0x0A, 0x44, 0x4C, 0xB4,
+       0x02, 0x44, 0x54, 0xB4,
+
+       0x2A, 0x45, 0x4D, 0xB6,
+       0x1A, 0x45, 0x55, 0xB6,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x38, 0x3D, 0x20, 0xE9,
+
+       0x0A, 0x20,
+       0x02, 0x20,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x0A, 0x47, 0x4F, 0xBF,
+       0x02, 0x47, 0x57, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x46, 0x4E, 0xBF,
+       0x1A, 0x46, 0x56, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x36, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x37, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x4B, 0xBF,
+       0x1A, 0x43, 0x53, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x35, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x39, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x37, 0x48, 0x50, 0xBD,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8B, 0x3E, 0x20, 0xE9,
+
+       0x82, 0x30, 0x57, 0xE9,
+       0x87, 0x77, 0x57, 0xE9,
+
+       0x83, 0x38, 0x57, 0xE9,
+       0x35, 0x49, 0x51, 0xBD,
+
+       0x84, 0x31, 0x5E, 0xE9,
+       0x30, 0x1F, 0x5F, 0xE9,
+
+       0x85, 0x39, 0x5E, 0xE9,
+       0x57, 0x25, 0x20, 0xE9,
+
+       0x2B, 0x48, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x26, 0x77,
+
+       0x24, 0x49, 0x20, 0xE9,
+       0xAA, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x26, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x1C, 0x46, 0xA0, 0xE8,
+       0x23, 0x4E, 0xA0, 0xE8,
+
+       0x2B, 0x56, 0xA0, 0xE8,
+       0x1D, 0x47, 0xA0, 0xE8,
+
+       0x24, 0x4F, 0xA0, 0xE8,
+       0x2C, 0x57, 0xA0, 0xE8,
+
+       0x1C, 0x00,
+       0x23, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x1D, 0x00,
+       0x24, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x1C, 0x65,
+       0x23, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x1D, 0x65,
+       0x24, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x1C, 0x23, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x1D, 0x24, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x1C, 0x2B, 0xDE, 0xE8,
+       0x23, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x1C, 0xBD,
+       0x3B, 0xD7, 0x23, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x4F, 0x80, 0x4F, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0xD3, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x4E, 0x33, 0x4E, 0xCF,
+       0x57, 0x3B, 0x57, 0xCF,
+
+       0x98, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzs[] = {
+
+       0x00, 0x88, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x22, 0x40, 0x48, 0xBF,
+       0x2A, 0x40, 0x50, 0xBF,
+
+       0x32, 0x41, 0x49, 0xBF,
+       0x3A, 0x41, 0x51, 0xBF,
+
+       0xC3, 0x6B,
+       0xCB, 0x6B,
+       0x00, 0x88, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x4B, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x29, 0x9F,
+       0x00, 0xE0,
+       0x49, 0x04,
+
+       0x90, 0xE2,
+       0x51, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x49, 0x41, 0xC0, 0xEC,
+       0x39, 0x57, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0x51, 0x41, 0xC0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x65, 0x80, 0x15, 0xEA,
+       0x08, 0x04,
+       0x10, 0x04,
+
+       0x51, 0x49, 0xC0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x4A, 0xBF,
+       0x27, 0x4A, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x52, 0xBF,
+       0x1E, 0x49, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x26, 0x51, 0x60, 0xEA,
+
+       0x32, 0x40, 0x48, 0xBD,
+       0x22, 0x40, 0x50, 0xBD,
+
+       0x12, 0x41, 0x49, 0xBD,
+       0x3A, 0x41, 0x51, 0xBD,
+
+       0xBF, 0x2F, 0x26, 0xBD,
+       0x00, 0xE0,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x4E, 0x31, 0x4E, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x56, 0x31, 0x56, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x4F, 0x39, 0x4F, 0xBF,
+       0x57, 0x39, 0x57, 0xBF,
+
+       0x57, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x42, 0x73, 0xF8, 0xEC,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0xA5, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x4B, 0x4B, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x26, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x53, 0x53, 0x2D, 0xDF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xB8, 0x38, 0x33, 0xBF,
+       0x00, 0xE0,
+       0x59, 0xE3,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x3F, 0x4B, 0xA0, 0xE8,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x53, 0xA0, 0xE8,
+
+       0x48, 0x70, 0xF8, 0xEC,
+       0x2B, 0x48, 0x3C, 0xE9,
+
+       0x1F, 0x27, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x18, 0x3A, 0x41, 0xE9,
+       0x1D, 0x32, 0x41, 0xE9,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x56, 0x3D, 0x56, 0xDF,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x4E, 0x3F, 0x4E, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x4F, 0x3F, 0x4F, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3D, 0x57, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x27, 0xCF, 0x74, 0xC2,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x0A, 0x44, 0x4C, 0xB0,
+       0x02, 0x44, 0x54, 0xB0,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x34, 0x37, 0x20, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x38, 0x27, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x4C, 0xB2,
+       0x1A, 0x44, 0x54, 0xB2,
+
+       0x29, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x27, 0xCF, 0x75, 0xC0,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x3D, 0xCF, 0x75, 0xC2,
+       0x37, 0xCF, 0x75, 0xC4,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA6, 0x27, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA3, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x4C, 0xB4,
+       0x1A, 0x44, 0x54, 0xB4,
+
+       0x0A, 0x45, 0x4D, 0xB0,
+       0x02, 0x45, 0x55, 0xB0,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA0, 0x37, 0x20, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x2A, 0x45, 0x4D, 0xB2,
+       0x1A, 0x45, 0x55, 0xB2,
+
+       0x0A, 0x45, 0x4D, 0xB4,
+       0x02, 0x45, 0x55, 0xB4,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x0A, 0x20,
+       0x02, 0x20,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x2A, 0x46, 0x4E, 0xBF,
+       0x1A, 0x46, 0x56, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x36, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x37, 0x39, 0x4F, 0xE9,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0xA7, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0xA8, 0x38, 0x4F, 0xE9,
+
+       0x0A, 0x47, 0x4F, 0xBF,
+       0x02, 0x47, 0x57, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA4, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA5, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x4B, 0xBF,
+       0x1A, 0x43, 0x53, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0xA1, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0xA2, 0x38, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x37, 0x48, 0x50, 0xBD,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8B, 0x3E, 0x20, 0xE9,
+
+       0x82, 0x30, 0x57, 0xE9,
+       0x87, 0x77, 0x57, 0xE9,
+
+       0x83, 0x38, 0x57, 0xE9,
+       0x35, 0x49, 0x51, 0xBD,
+
+       0x84, 0x31, 0x5E, 0xE9,
+       0x30, 0x1F, 0x5F, 0xE9,
+
+       0x85, 0x39, 0x5E, 0xE9,
+       0x57, 0x25, 0x20, 0xE9,
+
+       0x2B, 0x48, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x26, 0x77,
+
+       0x24, 0x49, 0x20, 0xE9,
+       0xA2, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x26, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x1C, 0x46, 0xA0, 0xE8,
+       0x23, 0x4E, 0xA0, 0xE8,
+
+       0x2B, 0x56, 0xA0, 0xE8,
+       0x1D, 0x47, 0xA0, 0xE8,
+
+       0x24, 0x4F, 0xA0, 0xE8,
+       0x2C, 0x57, 0xA0, 0xE8,
+
+       0x1C, 0x00,
+       0x23, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x1D, 0x00,
+       0x24, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x1C, 0x65,
+       0x23, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x1D, 0x65,
+       0x24, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x1C, 0x23, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x1D, 0x24, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x1C, 0x2B, 0xDE, 0xE8,
+       0x23, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x1C, 0xBD,
+       0x3B, 0xD7, 0x23, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x4F, 0x80, 0x4F, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0xCA, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x4E, 0x33, 0x4E, 0xCF,
+       0x57, 0x3B, 0x57, 0xCF,
+
+       0x90, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzsa[] = {
+
+       0x00, 0x88, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x22, 0x40, 0x48, 0xBF,
+       0x2A, 0x40, 0x50, 0xBF,
+
+       0x32, 0x41, 0x49, 0xBF,
+       0x3A, 0x41, 0x51, 0xBF,
+
+       0xC3, 0x6B,
+       0xCB, 0x6B,
+       0x00, 0x88, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x4B, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x29, 0x9F,
+       0x00, 0xE0,
+       0x49, 0x04,
+
+       0x90, 0xE2,
+       0x51, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x49, 0x41, 0xC0, 0xEC,
+       0x39, 0x57, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0x51, 0x41, 0xC0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x6A, 0x80, 0x15, 0xEA,
+       0x08, 0x04,
+       0x10, 0x04,
+
+       0x51, 0x49, 0xC0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x4A, 0xBF,
+       0x27, 0x4A, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x52, 0xBF,
+       0x1E, 0x49, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x26, 0x51, 0x60, 0xEA,
+
+       0x32, 0x40, 0x48, 0xBD,
+       0x22, 0x40, 0x50, 0xBD,
+
+       0x12, 0x41, 0x49, 0xBD,
+       0x3A, 0x41, 0x51, 0xBD,
+
+       0xBF, 0x2F, 0x26, 0xBD,
+       0x00, 0xE0,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x4E, 0x31, 0x4E, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x56, 0x31, 0x56, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x4F, 0x39, 0x4F, 0xBF,
+       0x57, 0x39, 0x57, 0xBF,
+
+       0x5C, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x42, 0x73, 0xF8, 0xEC,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0xA5, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x4B, 0x4B, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x26, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x53, 0x53, 0x2D, 0xDF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xB8, 0x38, 0x33, 0xBF,
+       0x00, 0xE0,
+       0x59, 0xE3,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x3F, 0x4B, 0xA0, 0xE8,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x53, 0xA0, 0xE8,
+
+       0x48, 0x70, 0xF8, 0xEC,
+       0x2B, 0x48, 0x3C, 0xE9,
+
+       0x1F, 0x27, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x18, 0x3A, 0x41, 0xE9,
+       0x1D, 0x32, 0x41, 0xE9,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x56, 0x3D, 0x56, 0xDF,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x4E, 0x3F, 0x4E, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x4F, 0x3F, 0x4F, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3D, 0x57, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x27, 0xCF, 0x74, 0xC2,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x0A, 0x44, 0x4C, 0xB0,
+       0x02, 0x44, 0x54, 0xB0,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x34, 0x37, 0x20, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x38, 0x27, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x4C, 0xB2,
+       0x1A, 0x44, 0x54, 0xB2,
+
+       0x2E, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x27, 0xCF, 0x75, 0xC0,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x3D, 0xCF, 0x75, 0xC2,
+       0x37, 0xCF, 0x75, 0xC4,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA6, 0x27, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA3, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x4C, 0xB4,
+       0x1A, 0x44, 0x54, 0xB4,
+
+       0x0A, 0x45, 0x4D, 0xB0,
+       0x02, 0x45, 0x55, 0xB0,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA0, 0x37, 0x20, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x45, 0x4D, 0xB2,
+       0x1A, 0x45, 0x55, 0xB2,
+
+       0x0A, 0x45, 0x4D, 0xB4,
+       0x02, 0x45, 0x55, 0xB4,
+
+       0x27, 0xCF, 0x74, 0xC6,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA7, 0x30, 0x4F, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x9C, 0x27, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA8, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x44, 0x4C, 0xB6,
+       0x1A, 0x44, 0x54, 0xB6,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x36, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x37, 0x39, 0x4F, 0xE9,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x2A, 0x46, 0x4E, 0xBF,
+       0x1A, 0x46, 0x56, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA4, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA5, 0x39, 0x4F, 0xE9,
+
+       0x0A, 0x47, 0x4F, 0xBF,
+       0x02, 0x47, 0x57, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA1, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA2, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x4B, 0xBF,
+       0x1A, 0x43, 0x53, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x9D, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x9E, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x37, 0x48, 0x50, 0xBD,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8B, 0x3E, 0x20, 0xE9,
+
+       0x82, 0x30, 0x57, 0xE9,
+       0x87, 0x77, 0x57, 0xE9,
+
+       0x83, 0x38, 0x57, 0xE9,
+       0x35, 0x49, 0x51, 0xBD,
+
+       0x84, 0x31, 0x5E, 0xE9,
+       0x30, 0x1F, 0x5F, 0xE9,
+
+       0x85, 0x39, 0x5E, 0xE9,
+       0x57, 0x25, 0x20, 0xE9,
+
+       0x2B, 0x48, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x26, 0x77,
+
+       0x24, 0x49, 0x20, 0xE9,
+       0x9D, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x26, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x1C, 0x46, 0xA0, 0xE8,
+       0x23, 0x4E, 0xA0, 0xE8,
+
+       0x2B, 0x56, 0xA0, 0xE8,
+       0x1D, 0x47, 0xA0, 0xE8,
+
+       0x24, 0x4F, 0xA0, 0xE8,
+       0x2C, 0x57, 0xA0, 0xE8,
+
+       0x1C, 0x00,
+       0x23, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x1D, 0x00,
+       0x24, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x1C, 0x65,
+       0x23, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x1D, 0x65,
+       0x24, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x1C, 0x23, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x1D, 0x24, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x1C, 0x2B, 0xDE, 0xE8,
+       0x23, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x1C, 0xBD,
+       0x3B, 0xD7, 0x23, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x4F, 0x80, 0x4F, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0xC5, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x4E, 0x33, 0x4E, 0xCF,
+       0x57, 0x3B, 0x57, 0xCF,
+
+       0x8B, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzsaf[] = {
+
+       0x00, 0x88, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x22, 0x40, 0x48, 0xBF,
+       0x2A, 0x40, 0x50, 0xBF,
+
+       0x32, 0x41, 0x49, 0xBF,
+       0x3A, 0x41, 0x51, 0xBF,
+
+       0xC3, 0x6B,
+       0xCB, 0x6B,
+       0x00, 0x88, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x4B, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x29, 0x9F,
+       0x00, 0xE0,
+       0x49, 0x04,
+
+       0x90, 0xE2,
+       0x51, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x49, 0x41, 0xC0, 0xEC,
+       0x39, 0x57, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0x51, 0x41, 0xC0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x6E, 0x80, 0x15, 0xEA,
+       0x08, 0x04,
+       0x10, 0x04,
+
+       0x51, 0x49, 0xC0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x4A, 0xBF,
+       0x27, 0x4A, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x52, 0xBF,
+       0x1E, 0x49, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x26, 0x51, 0x60, 0xEA,
+
+       0x32, 0x40, 0x48, 0xBD,
+       0x22, 0x40, 0x50, 0xBD,
+
+       0x12, 0x41, 0x49, 0xBD,
+       0x3A, 0x41, 0x51, 0xBD,
+
+       0xBF, 0x2F, 0x26, 0xBD,
+       0x00, 0xE0,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x4E, 0x31, 0x4E, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x56, 0x31, 0x56, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x4F, 0x39, 0x4F, 0xBF,
+       0x57, 0x39, 0x57, 0xBF,
+
+       0x60, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x42, 0x73, 0xF8, 0xEC,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0xA5, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x4B, 0x4B, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x26, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x53, 0x53, 0x2D, 0xDF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xB8, 0x38, 0x33, 0xBF,
+       0x00, 0xE0,
+       0x59, 0xE3,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x3F, 0x4B, 0xA0, 0xE8,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x53, 0xA0, 0xE8,
+
+       0x48, 0x70, 0xF8, 0xEC,
+       0x2B, 0x48, 0x3C, 0xE9,
+
+       0x1F, 0x27, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x18, 0x3A, 0x41, 0xE9,
+       0x1D, 0x32, 0x41, 0xE9,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x56, 0x3D, 0x56, 0xDF,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x4E, 0x3F, 0x4E, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x4F, 0x3F, 0x4F, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3D, 0x57, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x27, 0xCF, 0x74, 0xC2,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x0A, 0x44, 0x4C, 0xB0,
+       0x02, 0x44, 0x54, 0xB0,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x34, 0x37, 0x20, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x38, 0x27, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x4C, 0xB2,
+       0x1A, 0x44, 0x54, 0xB2,
+
+       0x32, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x27, 0xCF, 0x75, 0xC0,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x3D, 0xCF, 0x75, 0xC2,
+       0x37, 0xCF, 0x75, 0xC4,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA6, 0x27, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA3, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x4C, 0xB4,
+       0x1A, 0x44, 0x54, 0xB4,
+
+       0x0A, 0x45, 0x4D, 0xB0,
+       0x02, 0x45, 0x55, 0xB0,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA0, 0x37, 0x20, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x45, 0x4D, 0xB2,
+       0x1A, 0x45, 0x55, 0xB2,
+
+       0x0A, 0x45, 0x4D, 0xB4,
+       0x02, 0x45, 0x55, 0xB4,
+
+       0x27, 0xCF, 0x74, 0xC6,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA7, 0x30, 0x4F, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x9C, 0x27, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA8, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x44, 0x4C, 0xB6,
+       0x1A, 0x44, 0x54, 0xB6,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x36, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x37, 0x39, 0x4F, 0xE9,
+
+       0x0A, 0x45, 0x4D, 0xB6,
+       0x02, 0x45, 0x55, 0xB6,
+
+       0x3D, 0xCF, 0x75, 0xC6,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x2A, 0x46, 0x4E, 0xBF,
+       0x1A, 0x46, 0x56, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA4, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA5, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x3D, 0x20, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x0A, 0x47, 0x4F, 0xBF,
+       0x02, 0x47, 0x57, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0xA1, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0xA2, 0x38, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x9D, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x9E, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x4B, 0xBF,
+       0x1A, 0x43, 0x53, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x35, 0x30, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x39, 0x38, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x37, 0x48, 0x50, 0xBD,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8B, 0x3E, 0x20, 0xE9,
+
+       0x82, 0x30, 0x57, 0xE9,
+       0x87, 0x77, 0x57, 0xE9,
+
+       0x83, 0x38, 0x57, 0xE9,
+       0x35, 0x49, 0x51, 0xBD,
+
+       0x84, 0x31, 0x5E, 0xE9,
+       0x30, 0x1F, 0x5F, 0xE9,
+
+       0x85, 0x39, 0x5E, 0xE9,
+       0x57, 0x25, 0x20, 0xE9,
+
+       0x2B, 0x48, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x26, 0x77,
+
+       0x24, 0x49, 0x20, 0xE9,
+       0x99, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x26, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x1C, 0x46, 0xA0, 0xE8,
+       0x23, 0x4E, 0xA0, 0xE8,
+
+       0x2B, 0x56, 0xA0, 0xE8,
+       0x1D, 0x47, 0xA0, 0xE8,
+
+       0x24, 0x4F, 0xA0, 0xE8,
+       0x2C, 0x57, 0xA0, 0xE8,
+
+       0x1C, 0x00,
+       0x23, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x1D, 0x00,
+       0x24, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x1C, 0x65,
+       0x23, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x1D, 0x65,
+       0x24, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x1C, 0x23, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x1D, 0x24, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x1C, 0x2B, 0xDE, 0xE8,
+       0x23, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x1C, 0xBD,
+       0x3B, 0xD7, 0x23, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x4F, 0x80, 0x4F, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0xC1, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x4E, 0x33, 0x4E, 0xCF,
+       0x57, 0x3B, 0x57, 0xCF,
+
+       0x87, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
+
+static unsigned char warp_g400_tgzsf[] = {
+
+       0x00, 0x88, 0x98, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+       0xFF, 0x80, 0xC0, 0xE9,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x22, 0x40, 0x48, 0xBF,
+       0x2A, 0x40, 0x50, 0xBF,
+
+       0x32, 0x41, 0x49, 0xBF,
+       0x3A, 0x41, 0x51, 0xBF,
+
+       0xC3, 0x6B,
+       0xCB, 0x6B,
+       0x00, 0x88, 0x98, 0xE9,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x96, 0xE2,
+       0x41, 0x04,
+
+       0x7B, 0x43, 0xA0, 0xE8,
+       0x73, 0x4B, 0xA0, 0xE8,
+
+       0xAD, 0xEE, 0x29, 0x9F,
+       0x00, 0xE0,
+       0x49, 0x04,
+
+       0x90, 0xE2,
+       0x51, 0x04,
+       0x31, 0x46, 0xB1, 0xE8,
+
+       0x49, 0x41, 0xC0, 0xEC,
+       0x39, 0x57, 0xB1, 0xE8,
+
+       0x00, 0x04,
+       0x46, 0xE2,
+       0x73, 0x53, 0xA0, 0xE8,
+
+       0x51, 0x41, 0xC0, 0xEC,
+       0x31, 0x00,
+       0x39, 0x00,
+
+       0x6A, 0x80, 0x15, 0xEA,
+       0x08, 0x04,
+       0x10, 0x04,
+
+       0x51, 0x49, 0xC0, 0xEC,
+       0x2F, 0x41, 0x60, 0xEA,
+
+       0x31, 0x20,
+       0x39, 0x20,
+       0x1F, 0x42, 0xA0, 0xE8,
+
+       0x2A, 0x42, 0x4A, 0xBF,
+       0x27, 0x4A, 0xA0, 0xE8,
+
+       0x1A, 0x42, 0x52, 0xBF,
+       0x1E, 0x49, 0x60, 0xEA,
+
+       0x73, 0x7B, 0xC8, 0xEC,
+       0x26, 0x51, 0x60, 0xEA,
+
+       0x32, 0x40, 0x48, 0xBD,
+       0x22, 0x40, 0x50, 0xBD,
+
+       0x12, 0x41, 0x49, 0xBD,
+       0x3A, 0x41, 0x51, 0xBD,
+
+       0xBF, 0x2F, 0x26, 0xBD,
+       0x00, 0xE0,
+       0x7B, 0x72,
+
+       0x32, 0x20,
+       0x22, 0x20,
+       0x12, 0x20,
+       0x3A, 0x20,
+
+       0x46, 0x31, 0x46, 0xBF,
+       0x4E, 0x31, 0x4E, 0xBF,
+
+       0xB3, 0xE2, 0x2D, 0x9F,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x56, 0x31, 0x56, 0xBF,
+       0x47, 0x39, 0x47, 0xBF,
+
+       0x4F, 0x39, 0x4F, 0xBF,
+       0x57, 0x39, 0x57, 0xBF,
+
+       0x5C, 0x80, 0x07, 0xEA,
+       0x24, 0x41, 0x20, 0xE9,
+
+       0x42, 0x73, 0xF8, 0xEC,
+       0x00, 0xE0,
+       0x2D, 0x73,
+
+       0x33, 0x72,
+       0x0C, 0xE3,
+       0xA5, 0x2F, 0x1E, 0xBD,
+
+       0x43, 0x43, 0x2D, 0xDF,
+       0x4B, 0x4B, 0x2D, 0xDF,
+
+       0xAE, 0x1E, 0x26, 0xBD,
+       0x58, 0xE3,
+       0x33, 0x66,
+
+       0x53, 0x53, 0x2D, 0xDF,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0xB8, 0x38, 0x33, 0xBF,
+       0x00, 0xE0,
+       0x59, 0xE3,
+
+       0x1E, 0x12, 0x41, 0xE9,
+       0x1A, 0x22, 0x41, 0xE9,
+
+       0x2B, 0x40, 0x3D, 0xE9,
+       0x3F, 0x4B, 0xA0, 0xE8,
+
+       0x2D, 0x73,
+       0x30, 0x76,
+       0x05, 0x80, 0x3D, 0xEA,
+
+       0x37, 0x43, 0xA0, 0xE8,
+       0x3D, 0x53, 0xA0, 0xE8,
+
+       0x48, 0x70, 0xF8, 0xEC,
+       0x2B, 0x48, 0x3C, 0xE9,
+
+       0x1F, 0x27, 0xBC, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x15, 0xC0, 0x20, 0xE9,
+       0x15, 0xC0, 0x20, 0xE9,
+
+       0x18, 0x3A, 0x41, 0xE9,
+       0x1D, 0x32, 0x41, 0xE9,
+
+       0x2A, 0x40, 0x20, 0xE9,
+       0x56, 0x3D, 0x56, 0xDF,
+
+       0x46, 0x37, 0x46, 0xDF,
+       0x4E, 0x3F, 0x4E, 0xDF,
+
+       0x16, 0x30, 0x20, 0xE9,
+       0x4F, 0x3F, 0x4F, 0xDF,
+
+       0x47, 0x37, 0x47, 0xDF,
+       0x57, 0x3D, 0x57, 0xDF,
+
+       0x32, 0x32, 0x2D, 0xDF,
+       0x22, 0x22, 0x2D, 0xDF,
+
+       0x12, 0x12, 0x2D, 0xDF,
+       0x3A, 0x3A, 0x2D, 0xDF,
+
+       0x27, 0xCF, 0x74, 0xC2,
+       0x37, 0xCF, 0x74, 0xC4,
+
+       0x0A, 0x44, 0x4C, 0xB0,
+       0x02, 0x44, 0x54, 0xB0,
+
+       0x3D, 0xCF, 0x74, 0xC0,
+       0x34, 0x37, 0x20, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x38, 0x27, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3C, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x4C, 0xB2,
+       0x1A, 0x44, 0x54, 0xB2,
+
+       0x2E, 0x80, 0x3A, 0xEA,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x27, 0xCF, 0x75, 0xC0,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x32, 0x31, 0x5F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x33, 0x39, 0x5F, 0xE9,
+
+       0x3D, 0xCF, 0x75, 0xC2,
+       0x37, 0xCF, 0x75, 0xC4,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA6, 0x27, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA3, 0x3D, 0x20, 0xE9,
+
+       0x2A, 0x44, 0x4C, 0xB4,
+       0x1A, 0x44, 0x54, 0xB4,
+
+       0x0A, 0x45, 0x4D, 0xB0,
+       0x02, 0x45, 0x55, 0xB0,
+
+       0x88, 0x73, 0x5E, 0xE9,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA0, 0x37, 0x20, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x3E, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x3F, 0x38, 0x4F, 0xE9,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x3A, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x3B, 0x39, 0x4F, 0xE9,
+
+       0x2A, 0x45, 0x4D, 0xB2,
+       0x1A, 0x45, 0x55, 0xB2,
+
+       0x0A, 0x45, 0x4D, 0xB4,
+       0x02, 0x45, 0x55, 0xB4,
+
+       0x27, 0xCF, 0x75, 0xC6,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0xA7, 0x30, 0x4F, 0xE9,
+       0x0A, 0x20,
+       0x02, 0x20,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x31, 0x27, 0x20, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA8, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x45, 0x4D, 0xB6,
+       0x1A, 0x45, 0x55, 0xB6,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x36, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x37, 0x39, 0x4F, 0xE9,
+
+       0x00, 0x80, 0x00, 0xE8,
+       0x2A, 0x20,
+       0x1A, 0x20,
+
+       0x2A, 0x46, 0x4E, 0xBF,
+       0x1A, 0x46, 0x56, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA4, 0x31, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA5, 0x39, 0x4F, 0xE9,
+
+       0x0A, 0x47, 0x4F, 0xBF,
+       0x02, 0x47, 0x57, 0xBF,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0xA1, 0x30, 0x4F, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0xA2, 0x38, 0x4F, 0xE9,
+
+       0x2A, 0x43, 0x4B, 0xBF,
+       0x1A, 0x43, 0x53, 0xBF,
+
+       0x30, 0x50, 0x2E, 0x9F,
+       0x35, 0x31, 0x4F, 0xE9,
+
+       0x38, 0x21, 0x2C, 0x9F,
+       0x39, 0x39, 0x4F, 0xE9,
+
+       0x31, 0x53, 0x2F, 0x9F,
+       0x80, 0x31, 0x57, 0xE9,
+
+       0x39, 0xE5, 0x2C, 0x9F,
+       0x81, 0x39, 0x57, 0xE9,
+
+       0x37, 0x48, 0x50, 0xBD,
+       0x8A, 0x36, 0x20, 0xE9,
+
+       0x86, 0x76, 0x57, 0xE9,
+       0x8B, 0x3E, 0x20, 0xE9,
+
+       0x82, 0x30, 0x57, 0xE9,
+       0x87, 0x77, 0x57, 0xE9,
+
+       0x83, 0x38, 0x57, 0xE9,
+       0x35, 0x49, 0x51, 0xBD,
+
+       0x84, 0x31, 0x5E, 0xE9,
+       0x30, 0x1F, 0x5F, 0xE9,
+
+       0x85, 0x39, 0x5E, 0xE9,
+       0x57, 0x25, 0x20, 0xE9,
+
+       0x2B, 0x48, 0x20, 0xE9,
+       0x1D, 0x37, 0xE1, 0xEA,
+
+       0x1E, 0x35, 0xE1, 0xEA,
+       0x00, 0xE0,
+       0x26, 0x77,
+
+       0x24, 0x49, 0x20, 0xE9,
+       0x9D, 0xFF, 0x20, 0xEA,
+
+       0x16, 0x26, 0x20, 0xE9,
+       0x57, 0x2E, 0xBF, 0xEA,
+
+       0x1C, 0x46, 0xA0, 0xE8,
+       0x23, 0x4E, 0xA0, 0xE8,
+
+       0x2B, 0x56, 0xA0, 0xE8,
+       0x1D, 0x47, 0xA0, 0xE8,
+
+       0x24, 0x4F, 0xA0, 0xE8,
+       0x2C, 0x57, 0xA0, 0xE8,
+
+       0x1C, 0x00,
+       0x23, 0x00,
+       0x2B, 0x00,
+       0x00, 0xE0,
+
+       0x1D, 0x00,
+       0x24, 0x00,
+       0x2C, 0x00,
+       0x00, 0xE0,
+
+       0x1C, 0x65,
+       0x23, 0x65,
+       0x2B, 0x65,
+       0x00, 0xE0,
+
+       0x1D, 0x65,
+       0x24, 0x65,
+       0x2C, 0x65,
+       0x00, 0xE0,
+
+       0x1C, 0x23, 0x60, 0xEC,
+       0x36, 0xD7, 0x36, 0xAD,
+
+       0x2B, 0x80, 0x60, 0xEC,
+       0x1D, 0x24, 0x60, 0xEC,
+
+       0x3E, 0xD7, 0x3E, 0xAD,
+       0x2C, 0x80, 0x60, 0xEC,
+
+       0x1C, 0x2B, 0xDE, 0xE8,
+       0x23, 0x80, 0xDE, 0xE8,
+
+       0x36, 0x80, 0x36, 0xBD,
+       0x3E, 0x80, 0x3E, 0xBD,
+
+       0x33, 0xD7, 0x1C, 0xBD,
+       0x3B, 0xD7, 0x23, 0xBD,
+
+       0x46, 0x80, 0x46, 0xCF,
+       0x4F, 0x80, 0x4F, 0xCF,
+
+       0x56, 0x33, 0x56, 0xCF,
+       0x47, 0x3B, 0x47, 0xCF,
+
+       0xC5, 0xFF, 0x20, 0xEA,
+       0x00, 0x80, 0x00, 0xE8,
+
+       0x4E, 0x33, 0x4E, 0xCF,
+       0x57, 0x3B, 0x57, 0xCF,
+
+       0x8B, 0xFF, 0x20, 0xEA,
+       0x57, 0xC0, 0xBF, 0xEA,
+
+       0x00, 0x80, 0xA0, 0xE9,
+       0x00, 0x00, 0xD8, 0xEC,
+
+};
diff --git a/drivers/gpu/drm/mga/mga_warp.c b/drivers/gpu/drm/mga/mga_warp.c
new file mode 100644 (file)
index 0000000..651b93c
--- /dev/null
@@ -0,0 +1,193 @@
+/* mga_warp.c -- Matrox G200/G400 WARP engine management -*- linux-c -*-
+ * Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com
+ *
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "mga_drm.h"
+#include "mga_drv.h"
+#include "mga_ucode.h"
+
+#define MGA_WARP_CODE_ALIGN            256     /* in bytes */
+
+#define WARP_UCODE_SIZE( which )                                       \
+       ((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN)
+
+#define WARP_UCODE_INSTALL( which, where )                             \
+do {                                                                   \
+       DRM_DEBUG( " pcbase = 0x%08lx  vcbase = %p\n", pcbase, vcbase );\
+       dev_priv->warp_pipe_phys[where] = pcbase;                       \
+       memcpy( vcbase, which, sizeof(which) );                         \
+       pcbase += WARP_UCODE_SIZE( which );                             \
+       vcbase += WARP_UCODE_SIZE( which );                             \
+} while (0)
+
+static const unsigned int mga_warp_g400_microcode_size =
+    (WARP_UCODE_SIZE(warp_g400_tgz) +
+     WARP_UCODE_SIZE(warp_g400_tgza) +
+     WARP_UCODE_SIZE(warp_g400_tgzaf) +
+     WARP_UCODE_SIZE(warp_g400_tgzf) +
+     WARP_UCODE_SIZE(warp_g400_tgzs) +
+     WARP_UCODE_SIZE(warp_g400_tgzsa) +
+     WARP_UCODE_SIZE(warp_g400_tgzsaf) +
+     WARP_UCODE_SIZE(warp_g400_tgzsf) +
+     WARP_UCODE_SIZE(warp_g400_t2gz) +
+     WARP_UCODE_SIZE(warp_g400_t2gza) +
+     WARP_UCODE_SIZE(warp_g400_t2gzaf) +
+     WARP_UCODE_SIZE(warp_g400_t2gzf) +
+     WARP_UCODE_SIZE(warp_g400_t2gzs) +
+     WARP_UCODE_SIZE(warp_g400_t2gzsa) +
+     WARP_UCODE_SIZE(warp_g400_t2gzsaf) + WARP_UCODE_SIZE(warp_g400_t2gzsf));
+
+static const unsigned int mga_warp_g200_microcode_size =
+    (WARP_UCODE_SIZE(warp_g200_tgz) +
+     WARP_UCODE_SIZE(warp_g200_tgza) +
+     WARP_UCODE_SIZE(warp_g200_tgzaf) +
+     WARP_UCODE_SIZE(warp_g200_tgzf) +
+     WARP_UCODE_SIZE(warp_g200_tgzs) +
+     WARP_UCODE_SIZE(warp_g200_tgzsa) +
+     WARP_UCODE_SIZE(warp_g200_tgzsaf) + WARP_UCODE_SIZE(warp_g200_tgzsf));
+
+unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv)
+{
+       switch (dev_priv->chipset) {
+       case MGA_CARD_TYPE_G400:
+       case MGA_CARD_TYPE_G550:
+               return PAGE_ALIGN(mga_warp_g400_microcode_size);
+       case MGA_CARD_TYPE_G200:
+               return PAGE_ALIGN(mga_warp_g200_microcode_size);
+       default:
+               return 0;
+       }
+}
+
+static int mga_warp_install_g400_microcode(drm_mga_private_t * dev_priv)
+{
+       unsigned char *vcbase = dev_priv->warp->handle;
+       unsigned long pcbase = dev_priv->warp->offset;
+
+       memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+
+       WARP_UCODE_INSTALL(warp_g400_tgz, MGA_WARP_TGZ);
+       WARP_UCODE_INSTALL(warp_g400_tgzf, MGA_WARP_TGZF);
+       WARP_UCODE_INSTALL(warp_g400_tgza, MGA_WARP_TGZA);
+       WARP_UCODE_INSTALL(warp_g400_tgzaf, MGA_WARP_TGZAF);
+       WARP_UCODE_INSTALL(warp_g400_tgzs, MGA_WARP_TGZS);
+       WARP_UCODE_INSTALL(warp_g400_tgzsf, MGA_WARP_TGZSF);
+       WARP_UCODE_INSTALL(warp_g400_tgzsa, MGA_WARP_TGZSA);
+       WARP_UCODE_INSTALL(warp_g400_tgzsaf, MGA_WARP_TGZSAF);
+
+       WARP_UCODE_INSTALL(warp_g400_t2gz, MGA_WARP_T2GZ);
+       WARP_UCODE_INSTALL(warp_g400_t2gzf, MGA_WARP_T2GZF);
+       WARP_UCODE_INSTALL(warp_g400_t2gza, MGA_WARP_T2GZA);
+       WARP_UCODE_INSTALL(warp_g400_t2gzaf, MGA_WARP_T2GZAF);
+       WARP_UCODE_INSTALL(warp_g400_t2gzs, MGA_WARP_T2GZS);
+       WARP_UCODE_INSTALL(warp_g400_t2gzsf, MGA_WARP_T2GZSF);
+       WARP_UCODE_INSTALL(warp_g400_t2gzsa, MGA_WARP_T2GZSA);
+       WARP_UCODE_INSTALL(warp_g400_t2gzsaf, MGA_WARP_T2GZSAF);
+
+       return 0;
+}
+
+static int mga_warp_install_g200_microcode(drm_mga_private_t * dev_priv)
+{
+       unsigned char *vcbase = dev_priv->warp->handle;
+       unsigned long pcbase = dev_priv->warp->offset;
+
+       memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+
+       WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ);
+       WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF);
+       WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA);
+       WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF);
+       WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS);
+       WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF);
+       WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA);
+       WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF);
+
+       return 0;
+}
+
+int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
+{
+       const unsigned int size = mga_warp_microcode_size(dev_priv);
+
+       DRM_DEBUG("MGA ucode size = %d bytes\n", size);
+       if (size > dev_priv->warp->size) {
+               DRM_ERROR("microcode too large! (%u > %lu)\n",
+                         size, dev_priv->warp->size);
+               return -ENOMEM;
+       }
+
+       switch (dev_priv->chipset) {
+       case MGA_CARD_TYPE_G400:
+       case MGA_CARD_TYPE_G550:
+               return mga_warp_install_g400_microcode(dev_priv);
+       case MGA_CARD_TYPE_G200:
+               return mga_warp_install_g200_microcode(dev_priv);
+       default:
+               return -EINVAL;
+       }
+}
+
+#define WMISC_EXPECTED         (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
+
+int mga_warp_init(drm_mga_private_t * dev_priv)
+{
+       u32 wmisc;
+
+       /* FIXME: Get rid of these damned magic numbers...
+        */
+       switch (dev_priv->chipset) {
+       case MGA_CARD_TYPE_G400:
+       case MGA_CARD_TYPE_G550:
+               MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND);
+               MGA_WRITE(MGA_WGETMSB, 0x00000E00);
+               MGA_WRITE(MGA_WVRTXSZ, 0x00001807);
+               MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000);
+               break;
+       case MGA_CARD_TYPE_G200:
+               MGA_WRITE(MGA_WIADDR, MGA_WMODE_SUSPEND);
+               MGA_WRITE(MGA_WGETMSB, 0x1606);
+               MGA_WRITE(MGA_WVRTXSZ, 7);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
+                             MGA_WMASTER_ENABLE | MGA_WCACHEFLUSH_ENABLE));
+       wmisc = MGA_READ(MGA_WMISC);
+       if (wmisc != WMISC_EXPECTED) {
+               DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n",
+                         wmisc, WMISC_EXPECTED);
+               return -EINVAL;
+       }
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/r128/Makefile b/drivers/gpu/drm/r128/Makefile
new file mode 100644 (file)
index 0000000..1cc72ae
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+r128-y   := r128_drv.o r128_cce.o r128_state.o r128_irq.o
+
+r128-$(CONFIG_COMPAT)   += r128_ioc32.o
+
+obj-$(CONFIG_DRM_R128) += r128.o
diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c
new file mode 100644 (file)
index 0000000..c31afbd
--- /dev/null
@@ -0,0 +1,935 @@
+/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-
+ * Created: Wed Apr  5 19:24:19 2000 by kevin@precisioninsight.com
+ */
+/*
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
+#include "r128_drv.h"
+
+#define R128_FIFO_DEBUG                0
+
+/* CCE microcode (from ATI) */
+static u32 r128_cce_microcode[] = {
+       0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0,
+       1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0,
+       599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1,
+       11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11,
+       262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28,
+       1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9,
+       30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656,
+       1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1,
+       15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071,
+       12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2,
+       46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1,
+       459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1,
+       18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1,
+       15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2,
+       268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1,
+       15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82,
+       1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729,
+       3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008,
+       1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0,
+       15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1,
+       180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1,
+       114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0,
+       33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370,
+       1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1,
+       14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793,
+       1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1,
+       198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1,
+       114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1,
+       1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1,
+       1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894,
+       16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14,
+       174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1,
+       33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1,
+       33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1,
+       409611, 9, 188, 0, 10240, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static int R128_READ_PLL(struct drm_device * dev, int addr)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+
+       R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
+       return R128_READ(R128_CLOCK_CNTL_DATA);
+}
+
+#if R128_FIFO_DEBUG
+static void r128_status(drm_r128_private_t * dev_priv)
+{
+       printk("GUI_STAT           = 0x%08x\n",
+              (unsigned int)R128_READ(R128_GUI_STAT));
+       printk("PM4_STAT           = 0x%08x\n",
+              (unsigned int)R128_READ(R128_PM4_STAT));
+       printk("PM4_BUFFER_DL_WPTR = 0x%08x\n",
+              (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR));
+       printk("PM4_BUFFER_DL_RPTR = 0x%08x\n",
+              (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR));
+       printk("PM4_MICRO_CNTL     = 0x%08x\n",
+              (unsigned int)R128_READ(R128_PM4_MICRO_CNTL));
+       printk("PM4_BUFFER_CNTL    = 0x%08x\n",
+              (unsigned int)R128_READ(R128_PM4_BUFFER_CNTL));
+}
+#endif
+
+/* ================================================================
+ * Engine, FIFO control
+ */
+
+static int r128_do_pixcache_flush(drm_r128_private_t * dev_priv)
+{
+       u32 tmp;
+       int i;
+
+       tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL;
+       R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp);
+
+       for (i = 0; i < dev_priv->usec_timeout; i++) {
+               if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) {
+                       return 0;
+               }
+               DRM_UDELAY(1);
+       }
+
+#if R128_FIFO_DEBUG
+       DRM_ERROR("failed!\n");
+#endif
+       return -EBUSY;
+}
+
+static int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries)
+{
+       int i;
+
+       for (i = 0; i < dev_priv->usec_timeout; i++) {
+               int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
+               if (slots >= entries)
+                       return 0;
+               DRM_UDELAY(1);
+       }
+
+#if R128_FIFO_DEBUG
+       DRM_ERROR("failed!\n");
+#endif
+       return -EBUSY;
+}
+
+static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv)
+{
+       int i, ret;
+
+       ret = r128_do_wait_for_fifo(dev_priv, 64);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < dev_priv->usec_timeout; i++) {
+               if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
+                       r128_do_pixcache_flush(dev_priv);
+                       return 0;
+               }
+               DRM_UDELAY(1);
+       }
+
+#if R128_FIFO_DEBUG
+       DRM_ERROR("failed!\n");
+#endif
+       return -EBUSY;
+}
+
+/* ================================================================
+ * CCE control, initialization
+ */
+
+/* Load the microcode for the CCE */
+static void r128_cce_load_microcode(drm_r128_private_t * dev_priv)
+{
+       int i;
+
+       DRM_DEBUG("\n");
+
+       r128_do_wait_for_idle(dev_priv);
+
+       R128_WRITE(R128_PM4_MICROCODE_ADDR, 0);
+       for (i = 0; i < 256; i++) {
+               R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]);
+               R128_WRITE(R128_PM4_MICROCODE_DATAL,
+                          r128_cce_microcode[i * 2 + 1]);
+       }
+}
+
+/* Flush any pending commands to the CCE.  This should only be used just
+ * prior to a wait for idle, as it informs the engine that the command
+ * stream is ending.
+ */
+static void r128_do_cce_flush(drm_r128_private_t * dev_priv)
+{
+       u32 tmp;
+
+       tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR) | R128_PM4_BUFFER_DL_DONE;
+       R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp);
+}
+
+/* Wait for the CCE to go idle.
+ */
+int r128_do_cce_idle(drm_r128_private_t * dev_priv)
+{
+       int i;
+
+       for (i = 0; i < dev_priv->usec_timeout; i++) {
+               if (GET_RING_HEAD(dev_priv) == dev_priv->ring.tail) {
+                       int pm4stat = R128_READ(R128_PM4_STAT);
+                       if (((pm4stat & R128_PM4_FIFOCNT_MASK) >=
+                            dev_priv->cce_fifo_size) &&
+                           !(pm4stat & (R128_PM4_BUSY |
+                                        R128_PM4_GUI_ACTIVE))) {
+                               return r128_do_pixcache_flush(dev_priv);
+                       }
+               }
+               DRM_UDELAY(1);
+       }
+
+#if R128_FIFO_DEBUG
+       DRM_ERROR("failed!\n");
+       r128_status(dev_priv);
+#endif
+       return -EBUSY;
+}
+
+/* Start the Concurrent Command Engine.
+ */
+static void r128_do_cce_start(drm_r128_private_t * dev_priv)
+{
+       r128_do_wait_for_idle(dev_priv);
+
+       R128_WRITE(R128_PM4_BUFFER_CNTL,
+                  dev_priv->cce_mode | dev_priv->ring.size_l2qw
+                  | R128_PM4_BUFFER_CNTL_NOUPDATE);
+       R128_READ(R128_PM4_BUFFER_ADDR);        /* as per the sample code */
+       R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN);
+
+       dev_priv->cce_running = 1;
+}
+
+/* Reset the Concurrent Command Engine.  This will not flush any pending
+ * commands, so you must wait for the CCE command stream to complete
+ * before calling this routine.
+ */
+static void r128_do_cce_reset(drm_r128_private_t * dev_priv)
+{
+       R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
+       R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
+       dev_priv->ring.tail = 0;
+}
+
+/* Stop the Concurrent Command Engine.  This will not flush any pending
+ * commands, so you must flush the command stream and wait for the CCE
+ * to go idle before calling this routine.
+ */
+static void r128_do_cce_stop(drm_r128_private_t * dev_priv)
+{
+       R128_WRITE(R128_PM4_MICRO_CNTL, 0);
+       R128_WRITE(R128_PM4_BUFFER_CNTL,
+                  R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE);
+
+       dev_priv->cce_running = 0;
+}
+
+/* Reset the engine.  This will stop the CCE if it is running.
+ */
+static int r128_do_engine_reset(struct drm_device * dev)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
+
+       r128_do_pixcache_flush(dev_priv);
+
+       clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX);
+       mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL);
+
+       R128_WRITE_PLL(R128_MCLK_CNTL,
+                      mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP);
+
+       gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL);
+
+       /* Taken from the sample code - do not change */
+       R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI);
+       R128_READ(R128_GEN_RESET_CNTL);
+       R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI);
+       R128_READ(R128_GEN_RESET_CNTL);
+
+       R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl);
+       R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
+       R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl);
+
+       /* Reset the CCE ring */
+       r128_do_cce_reset(dev_priv);
+
+       /* The CCE is no longer running after an engine reset */
+       dev_priv->cce_running = 0;
+
+       /* Reset any pending vertex, indirect buffers */
+       r128_freelist_reset(dev);
+
+       return 0;
+}
+
+static void r128_cce_init_ring_buffer(struct drm_device * dev,
+                                     drm_r128_private_t * dev_priv)
+{
+       u32 ring_start;
+       u32 tmp;
+
+       DRM_DEBUG("\n");
+
+       /* The manual (p. 2) says this address is in "VM space".  This
+        * means it's an offset from the start of AGP space.
+        */
+#if __OS_HAS_AGP
+       if (!dev_priv->is_pci)
+               ring_start = dev_priv->cce_ring->offset - dev->agp->base;
+       else
+#endif
+               ring_start = dev_priv->cce_ring->offset -
+                   (unsigned long)dev->sg->virtual;
+
+       R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET);
+
+       R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
+       R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
+
+       /* Set watermark control */
+       R128_WRITE(R128_PM4_BUFFER_WM_CNTL,
+                  ((R128_WATERMARK_L / 4) << R128_WMA_SHIFT)
+                  | ((R128_WATERMARK_M / 4) << R128_WMB_SHIFT)
+                  | ((R128_WATERMARK_N / 4) << R128_WMC_SHIFT)
+                  | ((R128_WATERMARK_K / 64) << R128_WB_WM_SHIFT));
+
+       /* Force read.  Why?  Because it's in the examples... */
+       R128_READ(R128_PM4_BUFFER_ADDR);
+
+       /* Turn on bus mastering */
+       tmp = R128_READ(R128_BUS_CNTL) & ~R128_BUS_MASTER_DIS;
+       R128_WRITE(R128_BUS_CNTL, tmp);
+}
+
+static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
+{
+       drm_r128_private_t *dev_priv;
+
+       DRM_DEBUG("\n");
+
+       dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       memset(dev_priv, 0, sizeof(drm_r128_private_t));
+
+       dev_priv->is_pci = init->is_pci;
+
+       if (dev_priv->is_pci && !dev->sg) {
+               DRM_ERROR("PCI GART memory not allocated!\n");
+               dev->dev_private = (void *)dev_priv;
+               r128_do_cleanup_cce(dev);
+               return -EINVAL;
+       }
+
+       dev_priv->usec_timeout = init->usec_timeout;
+       if (dev_priv->usec_timeout < 1 ||
+           dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) {
+               DRM_DEBUG("TIMEOUT problem!\n");
+               dev->dev_private = (void *)dev_priv;
+               r128_do_cleanup_cce(dev);
+               return -EINVAL;
+       }
+
+       dev_priv->cce_mode = init->cce_mode;
+
+       /* GH: Simple idle check.
+        */
+       atomic_set(&dev_priv->idle_count, 0);
+
+       /* We don't support anything other than bus-mastering ring mode,
+        * but the ring can be in either AGP or PCI space for the ring
+        * read pointer.
+        */
+       if ((init->cce_mode != R128_PM4_192BM) &&
+           (init->cce_mode != R128_PM4_128BM_64INDBM) &&
+           (init->cce_mode != R128_PM4_64BM_128INDBM) &&
+           (init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM)) {
+               DRM_DEBUG("Bad cce_mode!\n");
+               dev->dev_private = (void *)dev_priv;
+               r128_do_cleanup_cce(dev);
+               return -EINVAL;
+       }
+
+       switch (init->cce_mode) {
+       case R128_PM4_NONPM4:
+               dev_priv->cce_fifo_size = 0;
+               break;
+       case R128_PM4_192PIO:
+       case R128_PM4_192BM:
+               dev_priv->cce_fifo_size = 192;
+               break;
+       case R128_PM4_128PIO_64INDBM:
+       case R128_PM4_128BM_64INDBM:
+               dev_priv->cce_fifo_size = 128;
+               break;
+       case R128_PM4_64PIO_128INDBM:
+       case R128_PM4_64BM_128INDBM:
+       case R128_PM4_64PIO_64VCBM_64INDBM:
+       case R128_PM4_64BM_64VCBM_64INDBM:
+       case R128_PM4_64PIO_64VCPIO_64INDPIO:
+               dev_priv->cce_fifo_size = 64;
+               break;
+       }
+
+       switch (init->fb_bpp) {
+       case 16:
+               dev_priv->color_fmt = R128_DATATYPE_RGB565;
+               break;
+       case 32:
+       default:
+               dev_priv->color_fmt = R128_DATATYPE_ARGB8888;
+               break;
+       }
+       dev_priv->front_offset = init->front_offset;
+       dev_priv->front_pitch = init->front_pitch;
+       dev_priv->back_offset = init->back_offset;
+       dev_priv->back_pitch = init->back_pitch;
+
+       switch (init->depth_bpp) {
+       case 16:
+               dev_priv->depth_fmt = R128_DATATYPE_RGB565;
+               break;
+       case 24:
+       case 32:
+       default:
+               dev_priv->depth_fmt = R128_DATATYPE_ARGB8888;
+               break;
+       }
+       dev_priv->depth_offset = init->depth_offset;
+       dev_priv->depth_pitch = init->depth_pitch;
+       dev_priv->span_offset = init->span_offset;
+
+       dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch / 8) << 21) |
+                                         (dev_priv->front_offset >> 5));
+       dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch / 8) << 21) |
+                                        (dev_priv->back_offset >> 5));
+       dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
+                                         (dev_priv->depth_offset >> 5) |
+                                         R128_DST_TILE);
+       dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
+                                        (dev_priv->span_offset >> 5));
+
+       dev_priv->sarea = drm_getsarea(dev);
+       if (!dev_priv->sarea) {
+               DRM_ERROR("could not find sarea!\n");
+               dev->dev_private = (void *)dev_priv;
+               r128_do_cleanup_cce(dev);
+               return -EINVAL;
+       }
+
+       dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+       if (!dev_priv->mmio) {
+               DRM_ERROR("could not find mmio region!\n");
+               dev->dev_private = (void *)dev_priv;
+               r128_do_cleanup_cce(dev);
+               return -EINVAL;
+       }
+       dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset);
+       if (!dev_priv->cce_ring) {
+               DRM_ERROR("could not find cce ring region!\n");
+               dev->dev_private = (void *)dev_priv;
+               r128_do_cleanup_cce(dev);
+               return -EINVAL;
+       }
+       dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
+       if (!dev_priv->ring_rptr) {
+               DRM_ERROR("could not find ring read pointer!\n");
+               dev->dev_private = (void *)dev_priv;
+               r128_do_cleanup_cce(dev);
+               return -EINVAL;
+       }
+       dev->agp_buffer_token = init->buffers_offset;
+       dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+       if (!dev->agp_buffer_map) {
+               DRM_ERROR("could not find dma buffer region!\n");
+               dev->dev_private = (void *)dev_priv;
+               r128_do_cleanup_cce(dev);
+               return -EINVAL;
+       }
+
+       if (!dev_priv->is_pci) {
+               dev_priv->agp_textures =
+                   drm_core_findmap(dev, init->agp_textures_offset);
+               if (!dev_priv->agp_textures) {
+                       DRM_ERROR("could not find agp texture region!\n");
+                       dev->dev_private = (void *)dev_priv;
+                       r128_do_cleanup_cce(dev);
+                       return -EINVAL;
+               }
+       }
+
+       dev_priv->sarea_priv =
+           (drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+                                 init->sarea_priv_offset);
+
+#if __OS_HAS_AGP
+       if (!dev_priv->is_pci) {
+               drm_core_ioremap(dev_priv->cce_ring, dev);
+               drm_core_ioremap(dev_priv->ring_rptr, dev);
+               drm_core_ioremap(dev->agp_buffer_map, dev);
+               if (!dev_priv->cce_ring->handle ||
+                   !dev_priv->ring_rptr->handle ||
+                   !dev->agp_buffer_map->handle) {
+                       DRM_ERROR("Could not ioremap agp regions!\n");
+                       dev->dev_private = (void *)dev_priv;
+                       r128_do_cleanup_cce(dev);
+                       return -ENOMEM;
+               }
+       } else
+#endif
+       {
+               dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset;
+               dev_priv->ring_rptr->handle =
+                   (void *)dev_priv->ring_rptr->offset;
+               dev->agp_buffer_map->handle =
+                   (void *)dev->agp_buffer_map->offset;
+       }
+
+#if __OS_HAS_AGP
+       if (!dev_priv->is_pci)
+               dev_priv->cce_buffers_offset = dev->agp->base;
+       else
+#endif
+               dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual;
+
+       dev_priv->ring.start = (u32 *) dev_priv->cce_ring->handle;
+       dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle
+                             + init->ring_size / sizeof(u32));
+       dev_priv->ring.size = init->ring_size;
+       dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
+
+       dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
+
+       dev_priv->ring.high_mark = 128;
+
+       dev_priv->sarea_priv->last_frame = 0;
+       R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
+
+       dev_priv->sarea_priv->last_dispatch = 0;
+       R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch);
+
+#if __OS_HAS_AGP
+       if (dev_priv->is_pci) {
+#endif
+               dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
+               dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
+               dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE;
+               dev_priv->gart_info.addr = NULL;
+               dev_priv->gart_info.bus_addr = 0;
+               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
+               if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
+                       DRM_ERROR("failed to init PCI GART!\n");
+                       dev->dev_private = (void *)dev_priv;
+                       r128_do_cleanup_cce(dev);
+                       return -ENOMEM;
+               }
+               R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);
+#if __OS_HAS_AGP
+       }
+#endif
+
+       r128_cce_init_ring_buffer(dev, dev_priv);
+       r128_cce_load_microcode(dev_priv);
+
+       dev->dev_private = (void *)dev_priv;
+
+       r128_do_engine_reset(dev);
+
+       return 0;
+}
+
+int r128_do_cleanup_cce(struct drm_device * dev)
+{
+
+       /* Make sure interrupts are disabled here because the uninstall ioctl
+        * may not have been called from userspace and after dev_private
+        * is freed, it's too late.
+        */
+       if (dev->irq_enabled)
+               drm_irq_uninstall(dev);
+
+       if (dev->dev_private) {
+               drm_r128_private_t *dev_priv = dev->dev_private;
+
+#if __OS_HAS_AGP
+               if (!dev_priv->is_pci) {
+                       if (dev_priv->cce_ring != NULL)
+                               drm_core_ioremapfree(dev_priv->cce_ring, dev);
+                       if (dev_priv->ring_rptr != NULL)
+                               drm_core_ioremapfree(dev_priv->ring_rptr, dev);
+                       if (dev->agp_buffer_map != NULL) {
+                               drm_core_ioremapfree(dev->agp_buffer_map, dev);
+                               dev->agp_buffer_map = NULL;
+                       }
+               } else
+#endif
+               {
+                       if (dev_priv->gart_info.bus_addr)
+                               if (!drm_ati_pcigart_cleanup(dev,
+                                                       &dev_priv->gart_info))
+                                       DRM_ERROR
+                                           ("failed to cleanup PCI GART!\n");
+               }
+
+               drm_free(dev->dev_private, sizeof(drm_r128_private_t),
+                        DRM_MEM_DRIVER);
+               dev->dev_private = NULL;
+       }
+
+       return 0;
+}
+
+int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_init_t *init = data;
+
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       switch (init->func) {
+       case R128_INIT_CCE:
+               return r128_do_init_cce(dev, init);
+       case R128_CLEANUP_CCE:
+               return r128_do_cleanup_cce(dev);
+       }
+
+       return -EINVAL;
+}
+
+int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
+               DRM_DEBUG("while CCE running\n");
+               return 0;
+       }
+
+       r128_do_cce_start(dev_priv);
+
+       return 0;
+}
+
+/* Stop the CCE.  The engine must have been idled before calling this
+ * routine.
+ */
+int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_cce_stop_t *stop = data;
+       int ret;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       /* Flush any pending CCE commands.  This ensures any outstanding
+        * commands are exectuted by the engine before we turn it off.
+        */
+       if (stop->flush) {
+               r128_do_cce_flush(dev_priv);
+       }
+
+       /* If we fail to make the engine go idle, we return an error
+        * code so that the DRM ioctl wrapper can try again.
+        */
+       if (stop->idle) {
+               ret = r128_do_cce_idle(dev_priv);
+               if (ret)
+                       return ret;
+       }
+
+       /* Finally, we can turn off the CCE.  If the engine isn't idle,
+        * we will get some dropped triangles as they won't be fully
+        * rendered before the CCE is shut down.
+        */
+       r128_do_cce_stop(dev_priv);
+
+       /* Reset the engine */
+       r128_do_engine_reset(dev);
+
+       return 0;
+}
+
+/* Just reset the CCE ring.  Called as part of an X Server engine reset.
+ */
+int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (!dev_priv) {
+               DRM_DEBUG("called before init done\n");
+               return -EINVAL;
+       }
+
+       r128_do_cce_reset(dev_priv);
+
+       /* The CCE is no longer running after an engine reset */
+       dev_priv->cce_running = 0;
+
+       return 0;
+}
+
+int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (dev_priv->cce_running) {
+               r128_do_cce_flush(dev_priv);
+       }
+
+       return r128_do_cce_idle(dev_priv);
+}
+
+int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       return r128_do_engine_reset(dev);
+}
+
+int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       return -EINVAL;
+}
+
+/* ================================================================
+ * Freelist management
+ */
+#define R128_BUFFER_USED       0xffffffff
+#define R128_BUFFER_FREE       0
+
+#if 0
+static int r128_freelist_init(struct drm_device * dev)
+{
+       struct drm_device_dma *dma = dev->dma;
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       struct drm_buf *buf;
+       drm_r128_buf_priv_t *buf_priv;
+       drm_r128_freelist_t *entry;
+       int i;
+
+       dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
+       if (dev_priv->head == NULL)
+               return -ENOMEM;
+
+       memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t));
+       dev_priv->head->age = R128_BUFFER_USED;
+
+       for (i = 0; i < dma->buf_count; i++) {
+               buf = dma->buflist[i];
+               buf_priv = buf->dev_private;
+
+               entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER);
+               if (!entry)
+                       return -ENOMEM;
+
+               entry->age = R128_BUFFER_FREE;
+               entry->buf = buf;
+               entry->prev = dev_priv->head;
+               entry->next = dev_priv->head->next;
+               if (!entry->next)
+                       dev_priv->tail = entry;
+
+               buf_priv->discard = 0;
+               buf_priv->dispatched = 0;
+               buf_priv->list_entry = entry;
+
+               dev_priv->head->next = entry;
+
+               if (dev_priv->head->next)
+                       dev_priv->head->next->prev = entry;
+       }
+
+       return 0;
+
+}
+#endif
+
+static struct drm_buf *r128_freelist_get(struct drm_device * dev)
+{
+       struct drm_device_dma *dma = dev->dma;
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_buf_priv_t *buf_priv;
+       struct drm_buf *buf;
+       int i, t;
+
+       /* FIXME: Optimize -- use freelist code */
+
+       for (i = 0; i < dma->buf_count; i++) {
+               buf = dma->buflist[i];
+               buf_priv = buf->dev_private;
+               if (!buf->file_priv)
+                       return buf;
+       }
+
+       for (t = 0; t < dev_priv->usec_timeout; t++) {
+               u32 done_age = R128_READ(R128_LAST_DISPATCH_REG);
+
+               for (i = 0; i < dma->buf_count; i++) {
+                       buf = dma->buflist[i];
+                       buf_priv = buf->dev_private;
+                       if (buf->pending && buf_priv->age <= done_age) {
+                               /* The buffer has been processed, so it
+                                * can now be used.
+                                */
+                               buf->pending = 0;
+                               return buf;
+                       }
+               }
+               DRM_UDELAY(1);
+       }
+
+       DRM_DEBUG("returning NULL!\n");
+       return NULL;
+}
+
+void r128_freelist_reset(struct drm_device * dev)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int i;
+
+       for (i = 0; i < dma->buf_count; i++) {
+               struct drm_buf *buf = dma->buflist[i];
+               drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+               buf_priv->age = 0;
+       }
+}
+
+/* ================================================================
+ * CCE command submission
+ */
+
+int r128_wait_ring(drm_r128_private_t * dev_priv, int n)
+{
+       drm_r128_ring_buffer_t *ring = &dev_priv->ring;
+       int i;
+
+       for (i = 0; i < dev_priv->usec_timeout; i++) {
+               r128_update_ring_snapshot(dev_priv);
+               if (ring->space >= n)
+                       return 0;
+               DRM_UDELAY(1);
+       }
+
+       /* FIXME: This is being ignored... */
+       DRM_ERROR("failed!\n");
+       return -EBUSY;
+}
+
+static int r128_cce_get_buffers(struct drm_device * dev,
+                               struct drm_file *file_priv,
+                               struct drm_dma * d)
+{
+       int i;
+       struct drm_buf *buf;
+
+       for (i = d->granted_count; i < d->request_count; i++) {
+               buf = r128_freelist_get(dev);
+               if (!buf)
+                       return -EAGAIN;
+
+               buf->file_priv = file_priv;
+
+               if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
+                                    sizeof(buf->idx)))
+                       return -EFAULT;
+               if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
+                                    sizeof(buf->total)))
+                       return -EFAULT;
+
+               d->granted_count++;
+       }
+       return 0;
+}
+
+int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int ret = 0;
+       struct drm_dma *d = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       /* Please don't send us buffers.
+        */
+       if (d->send_count != 0) {
+               DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+                         DRM_CURRENTPID, d->send_count);
+               return -EINVAL;
+       }
+
+       /* We'll send you buffers.
+        */
+       if (d->request_count < 0 || d->request_count > dma->buf_count) {
+               DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+                         DRM_CURRENTPID, d->request_count, dma->buf_count);
+               return -EINVAL;
+       }
+
+       d->granted_count = 0;
+
+       if (d->request_count) {
+               ret = r128_cce_get_buffers(dev, file_priv, d);
+       }
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c
new file mode 100644 (file)
index 0000000..6108e75
--- /dev/null
@@ -0,0 +1,103 @@
+/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*-
+ * Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
+#include "r128_drv.h"
+
+#include "drm_pciids.h"
+
+static struct pci_device_id pciidlist[] = {
+       r128_PCI_IDS
+};
+
+static struct drm_driver driver = {
+       .driver_features =
+           DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
+           DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
+           DRIVER_IRQ_VBL,
+       .dev_priv_size = sizeof(drm_r128_buf_priv_t),
+       .preclose = r128_driver_preclose,
+       .lastclose = r128_driver_lastclose,
+       .vblank_wait = r128_driver_vblank_wait,
+       .irq_preinstall = r128_driver_irq_preinstall,
+       .irq_postinstall = r128_driver_irq_postinstall,
+       .irq_uninstall = r128_driver_irq_uninstall,
+       .irq_handler = r128_driver_irq_handler,
+       .reclaim_buffers = drm_core_reclaim_buffers,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .ioctls = r128_ioctls,
+       .dma_ioctl = r128_cce_buffers,
+       .fops = {
+                .owner = THIS_MODULE,
+                .open = drm_open,
+                .release = drm_release,
+                .ioctl = drm_ioctl,
+                .mmap = drm_mmap,
+                .poll = drm_poll,
+                .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+                .compat_ioctl = r128_compat_ioctl,
+#endif
+       },
+
+       .pci_driver = {
+                .name = DRIVER_NAME,
+                .id_table = pciidlist,
+       },
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int __init r128_init(void)
+{
+       driver.num_ioctls = r128_max_ioctl;
+       return drm_init(&driver);
+}
+
+static void __exit r128_exit(void)
+{
+       drm_exit(&driver);
+}
+
+module_init(r128_init);
+module_exit(r128_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h
new file mode 100644 (file)
index 0000000..011105e
--- /dev/null
@@ -0,0 +1,522 @@
+/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-
+ * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com
+ */
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Michel Dänzer <daenzerm@student.ethz.ch>
+ */
+
+#ifndef __R128_DRV_H__
+#define __R128_DRV_H__
+
+/* General customization:
+ */
+#define DRIVER_AUTHOR          "Gareth Hughes, VA Linux Systems Inc."
+
+#define DRIVER_NAME            "r128"
+#define DRIVER_DESC            "ATI Rage 128"
+#define DRIVER_DATE            "20030725"
+
+/* Interface history:
+ *
+ * ??  - ??
+ * 2.4 - Add support for ycbcr textures (no new ioctls)
+ * 2.5 - Add FLIP ioctl, disable FULLSCREEN.
+ */
+#define DRIVER_MAJOR           2
+#define DRIVER_MINOR           5
+#define DRIVER_PATCHLEVEL      0
+
+#define GET_RING_HEAD(dev_priv)                R128_READ( R128_PM4_BUFFER_DL_RPTR )
+
+typedef struct drm_r128_freelist {
+       unsigned int age;
+       struct drm_buf *buf;
+       struct drm_r128_freelist *next;
+       struct drm_r128_freelist *prev;
+} drm_r128_freelist_t;
+
+typedef struct drm_r128_ring_buffer {
+       u32 *start;
+       u32 *end;
+       int size;
+       int size_l2qw;
+
+       u32 tail;
+       u32 tail_mask;
+       int space;
+
+       int high_mark;
+} drm_r128_ring_buffer_t;
+
+typedef struct drm_r128_private {
+       drm_r128_ring_buffer_t ring;
+       drm_r128_sarea_t *sarea_priv;
+
+       int cce_mode;
+       int cce_fifo_size;
+       int cce_running;
+
+       drm_r128_freelist_t *head;
+       drm_r128_freelist_t *tail;
+
+       int usec_timeout;
+       int is_pci;
+       unsigned long cce_buffers_offset;
+
+       atomic_t idle_count;
+
+       int page_flipping;
+       int current_page;
+       u32 crtc_offset;
+       u32 crtc_offset_cntl;
+
+       u32 color_fmt;
+       unsigned int front_offset;
+       unsigned int front_pitch;
+       unsigned int back_offset;
+       unsigned int back_pitch;
+
+       u32 depth_fmt;
+       unsigned int depth_offset;
+       unsigned int depth_pitch;
+       unsigned int span_offset;
+
+       u32 front_pitch_offset_c;
+       u32 back_pitch_offset_c;
+       u32 depth_pitch_offset_c;
+       u32 span_pitch_offset_c;
+
+       drm_local_map_t *sarea;
+       drm_local_map_t *mmio;
+       drm_local_map_t *cce_ring;
+       drm_local_map_t *ring_rptr;
+       drm_local_map_t *agp_textures;
+       struct drm_ati_pcigart_info gart_info;
+} drm_r128_private_t;
+
+typedef struct drm_r128_buf_priv {
+       u32 age;
+       int prim;
+       int discard;
+       int dispatched;
+       drm_r128_freelist_t *list_entry;
+} drm_r128_buf_priv_t;
+
+extern struct drm_ioctl_desc r128_ioctls[];
+extern int r128_max_ioctl;
+
+                               /* r128_cce.c */
+extern int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
+
+extern void r128_freelist_reset(struct drm_device * dev);
+
+extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
+
+extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
+extern int r128_do_cleanup_cce(struct drm_device * dev);
+
+extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+
+extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
+extern void r128_driver_irq_preinstall(struct drm_device * dev);
+extern void r128_driver_irq_postinstall(struct drm_device * dev);
+extern void r128_driver_irq_uninstall(struct drm_device * dev);
+extern void r128_driver_lastclose(struct drm_device * dev);
+extern void r128_driver_preclose(struct drm_device * dev,
+                                struct drm_file *file_priv);
+
+extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
+                             unsigned long arg);
+
+/* Register definitions, register access macros and drmAddMap constants
+ * for Rage 128 kernel driver.
+ */
+
+#define R128_AUX_SC_CNTL               0x1660
+#      define R128_AUX1_SC_EN                  (1 << 0)
+#      define R128_AUX1_SC_MODE_OR             (0 << 1)
+#      define R128_AUX1_SC_MODE_NAND           (1 << 1)
+#      define R128_AUX2_SC_EN                  (1 << 2)
+#      define R128_AUX2_SC_MODE_OR             (0 << 3)
+#      define R128_AUX2_SC_MODE_NAND           (1 << 3)
+#      define R128_AUX3_SC_EN                  (1 << 4)
+#      define R128_AUX3_SC_MODE_OR             (0 << 5)
+#      define R128_AUX3_SC_MODE_NAND           (1 << 5)
+#define R128_AUX1_SC_LEFT              0x1664
+#define R128_AUX1_SC_RIGHT             0x1668
+#define R128_AUX1_SC_TOP               0x166c
+#define R128_AUX1_SC_BOTTOM            0x1670
+#define R128_AUX2_SC_LEFT              0x1674
+#define R128_AUX2_SC_RIGHT             0x1678
+#define R128_AUX2_SC_TOP               0x167c
+#define R128_AUX2_SC_BOTTOM            0x1680
+#define R128_AUX3_SC_LEFT              0x1684
+#define R128_AUX3_SC_RIGHT             0x1688
+#define R128_AUX3_SC_TOP               0x168c
+#define R128_AUX3_SC_BOTTOM            0x1690
+
+#define R128_BRUSH_DATA0               0x1480
+#define R128_BUS_CNTL                  0x0030
+#      define R128_BUS_MASTER_DIS              (1 << 6)
+
+#define R128_CLOCK_CNTL_INDEX          0x0008
+#define R128_CLOCK_CNTL_DATA           0x000c
+#      define R128_PLL_WR_EN                   (1 << 7)
+#define R128_CONSTANT_COLOR_C          0x1d34
+#define R128_CRTC_OFFSET               0x0224
+#define R128_CRTC_OFFSET_CNTL          0x0228
+#      define R128_CRTC_OFFSET_FLIP_CNTL       (1 << 16)
+
+#define R128_DP_GUI_MASTER_CNTL                0x146c
+#       define R128_GMC_SRC_PITCH_OFFSET_CNTL  (1    <<  0)
+#       define R128_GMC_DST_PITCH_OFFSET_CNTL  (1    <<  1)
+#      define R128_GMC_BRUSH_SOLID_COLOR       (13   <<  4)
+#      define R128_GMC_BRUSH_NONE              (15   <<  4)
+#      define R128_GMC_DST_16BPP               (4    <<  8)
+#      define R128_GMC_DST_24BPP               (5    <<  8)
+#      define R128_GMC_DST_32BPP               (6    <<  8)
+#       define R128_GMC_DST_DATATYPE_SHIFT     8
+#      define R128_GMC_SRC_DATATYPE_COLOR      (3    << 12)
+#      define R128_DP_SRC_SOURCE_MEMORY        (2    << 24)
+#      define R128_DP_SRC_SOURCE_HOST_DATA     (3    << 24)
+#      define R128_GMC_CLR_CMP_CNTL_DIS        (1    << 28)
+#      define R128_GMC_AUX_CLIP_DIS            (1    << 29)
+#      define R128_GMC_WR_MSK_DIS              (1    << 30)
+#      define R128_ROP3_S                      0x00cc0000
+#      define R128_ROP3_P                      0x00f00000
+#define R128_DP_WRITE_MASK             0x16cc
+#define R128_DST_PITCH_OFFSET_C                0x1c80
+#      define R128_DST_TILE                    (1 << 31)
+
+#define R128_GEN_INT_CNTL              0x0040
+#      define R128_CRTC_VBLANK_INT_EN          (1 <<  0)
+#define R128_GEN_INT_STATUS            0x0044
+#      define R128_CRTC_VBLANK_INT             (1 <<  0)
+#      define R128_CRTC_VBLANK_INT_AK          (1 <<  0)
+#define R128_GEN_RESET_CNTL            0x00f0
+#      define R128_SOFT_RESET_GUI              (1 <<  0)
+
+#define R128_GUI_SCRATCH_REG0          0x15e0
+#define R128_GUI_SCRATCH_REG1          0x15e4
+#define R128_GUI_SCRATCH_REG2          0x15e8
+#define R128_GUI_SCRATCH_REG3          0x15ec
+#define R128_GUI_SCRATCH_REG4          0x15f0
+#define R128_GUI_SCRATCH_REG5          0x15f4
+
+#define R128_GUI_STAT                  0x1740
+#      define R128_GUI_FIFOCNT_MASK            0x0fff
+#      define R128_GUI_ACTIVE                  (1 << 31)
+
+#define R128_MCLK_CNTL                 0x000f
+#      define R128_FORCE_GCP                   (1 << 16)
+#      define R128_FORCE_PIPE3D_CP             (1 << 17)
+#      define R128_FORCE_RCP                   (1 << 18)
+
+#define R128_PC_GUI_CTLSTAT            0x1748
+#define R128_PC_NGUI_CTLSTAT           0x0184
+#      define R128_PC_FLUSH_GUI                (3 << 0)
+#      define R128_PC_RI_GUI                   (1 << 2)
+#      define R128_PC_FLUSH_ALL                0x00ff
+#      define R128_PC_BUSY                     (1 << 31)
+
+#define R128_PCI_GART_PAGE             0x017c
+#define R128_PRIM_TEX_CNTL_C           0x1cb0
+
+#define R128_SCALE_3D_CNTL             0x1a00
+#define R128_SEC_TEX_CNTL_C            0x1d00
+#define R128_SEC_TEXTURE_BORDER_COLOR_C        0x1d3c
+#define R128_SETUP_CNTL                        0x1bc4
+#define R128_STEN_REF_MASK_C           0x1d40
+
+#define R128_TEX_CNTL_C                        0x1c9c
+#      define R128_TEX_CACHE_FLUSH             (1 << 23)
+
+#define R128_WAIT_UNTIL                        0x1720
+#      define R128_EVENT_CRTC_OFFSET           (1 << 0)
+#define R128_WINDOW_XY_OFFSET          0x1bcc
+
+/* CCE registers
+ */
+#define R128_PM4_BUFFER_OFFSET         0x0700
+#define R128_PM4_BUFFER_CNTL           0x0704
+#      define R128_PM4_MASK                    (15 << 28)
+#      define R128_PM4_NONPM4                  (0  << 28)
+#      define R128_PM4_192PIO                  (1  << 28)
+#      define R128_PM4_192BM                   (2  << 28)
+#      define R128_PM4_128PIO_64INDBM          (3  << 28)
+#      define R128_PM4_128BM_64INDBM           (4  << 28)
+#      define R128_PM4_64PIO_128INDBM          (5  << 28)
+#      define R128_PM4_64BM_128INDBM           (6  << 28)
+#      define R128_PM4_64PIO_64VCBM_64INDBM    (7  << 28)
+#      define R128_PM4_64BM_64VCBM_64INDBM     (8  << 28)
+#      define R128_PM4_64PIO_64VCPIO_64INDPIO  (15 << 28)
+#      define R128_PM4_BUFFER_CNTL_NOUPDATE    (1  << 27)
+
+#define R128_PM4_BUFFER_WM_CNTL                0x0708
+#      define R128_WMA_SHIFT                   0
+#      define R128_WMB_SHIFT                   8
+#      define R128_WMC_SHIFT                   16
+#      define R128_WB_WM_SHIFT                 24
+
+#define R128_PM4_BUFFER_DL_RPTR_ADDR   0x070c
+#define R128_PM4_BUFFER_DL_RPTR                0x0710
+#define R128_PM4_BUFFER_DL_WPTR                0x0714
+#      define R128_PM4_BUFFER_DL_DONE          (1 << 31)
+
+#define R128_PM4_VC_FPU_SETUP          0x071c
+
+#define R128_PM4_IW_INDOFF             0x0738
+#define R128_PM4_IW_INDSIZE            0x073c
+
+#define R128_PM4_STAT                  0x07b8
+#      define R128_PM4_FIFOCNT_MASK            0x0fff
+#      define R128_PM4_BUSY                    (1 << 16)
+#      define R128_PM4_GUI_ACTIVE              (1 << 31)
+
+#define R128_PM4_MICROCODE_ADDR                0x07d4
+#define R128_PM4_MICROCODE_RADDR       0x07d8
+#define R128_PM4_MICROCODE_DATAH       0x07dc
+#define R128_PM4_MICROCODE_DATAL       0x07e0
+
+#define R128_PM4_BUFFER_ADDR           0x07f0
+#define R128_PM4_MICRO_CNTL            0x07fc
+#      define R128_PM4_MICRO_FREERUN           (1 << 30)
+
+#define R128_PM4_FIFO_DATA_EVEN                0x1000
+#define R128_PM4_FIFO_DATA_ODD         0x1004
+
+/* CCE command packets
+ */
+#define R128_CCE_PACKET0               0x00000000
+#define R128_CCE_PACKET1               0x40000000
+#define R128_CCE_PACKET2               0x80000000
+#define R128_CCE_PACKET3               0xC0000000
+#      define R128_CNTL_HOSTDATA_BLT           0x00009400
+#      define R128_CNTL_PAINT_MULTI            0x00009A00
+#      define R128_CNTL_BITBLT_MULTI           0x00009B00
+#      define R128_3D_RNDR_GEN_INDX_PRIM       0x00002300
+
+#define R128_CCE_PACKET_MASK           0xC0000000
+#define R128_CCE_PACKET_COUNT_MASK     0x3fff0000
+#define R128_CCE_PACKET0_REG_MASK      0x000007ff
+#define R128_CCE_PACKET1_REG0_MASK     0x000007ff
+#define R128_CCE_PACKET1_REG1_MASK     0x003ff800
+
+#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE                0x00000000
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT       0x00000001
+#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE                0x00000002
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE   0x00000003
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST    0x00000004
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN     0x00000005
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP   0x00000006
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2   0x00000007
+#define R128_CCE_VC_CNTL_PRIM_WALK_IND         0x00000010
+#define R128_CCE_VC_CNTL_PRIM_WALK_LIST                0x00000020
+#define R128_CCE_VC_CNTL_PRIM_WALK_RING                0x00000030
+#define R128_CCE_VC_CNTL_NUM_SHIFT             16
+
+#define R128_DATATYPE_VQ               0
+#define R128_DATATYPE_CI4              1
+#define R128_DATATYPE_CI8              2
+#define R128_DATATYPE_ARGB1555         3
+#define R128_DATATYPE_RGB565           4
+#define R128_DATATYPE_RGB888           5
+#define R128_DATATYPE_ARGB8888         6
+#define R128_DATATYPE_RGB332           7
+#define R128_DATATYPE_Y8               8
+#define R128_DATATYPE_RGB8             9
+#define R128_DATATYPE_CI16             10
+#define R128_DATATYPE_YVYU422          11
+#define R128_DATATYPE_VYUY422          12
+#define R128_DATATYPE_AYUV444          14
+#define R128_DATATYPE_ARGB4444         15
+
+/* Constants */
+#define R128_AGP_OFFSET                        0x02000000
+
+#define R128_WATERMARK_L               16
+#define R128_WATERMARK_M               8
+#define R128_WATERMARK_N               8
+#define R128_WATERMARK_K               128
+
+#define R128_MAX_USEC_TIMEOUT          100000  /* 100 ms */
+
+#define R128_LAST_FRAME_REG            R128_GUI_SCRATCH_REG0
+#define R128_LAST_DISPATCH_REG         R128_GUI_SCRATCH_REG1
+#define R128_MAX_VB_AGE                        0x7fffffff
+#define R128_MAX_VB_VERTS              (0xffff)
+
+#define R128_RING_HIGH_MARK            128
+
+#define R128_PERFORMANCE_BOXES         0
+
+#define R128_PCIGART_TABLE_SIZE         32768
+
+#define R128_READ(reg)         DRM_READ32(  dev_priv->mmio, (reg) )
+#define R128_WRITE(reg,val)    DRM_WRITE32( dev_priv->mmio, (reg), (val) )
+#define R128_READ8(reg)                DRM_READ8(   dev_priv->mmio, (reg) )
+#define R128_WRITE8(reg,val)   DRM_WRITE8(  dev_priv->mmio, (reg), (val) )
+
+#define R128_WRITE_PLL(addr,val)                                       \
+do {                                                                   \
+       R128_WRITE8(R128_CLOCK_CNTL_INDEX,                              \
+                   ((addr) & 0x1f) | R128_PLL_WR_EN);                  \
+       R128_WRITE(R128_CLOCK_CNTL_DATA, (val));                        \
+} while (0)
+
+#define CCE_PACKET0( reg, n )          (R128_CCE_PACKET0 |             \
+                                        ((n) << 16) | ((reg) >> 2))
+#define CCE_PACKET1( reg0, reg1 )      (R128_CCE_PACKET1 |             \
+                                        (((reg1) >> 2) << 11) | ((reg0) >> 2))
+#define CCE_PACKET2()                  (R128_CCE_PACKET2)
+#define CCE_PACKET3( pkt, n )          (R128_CCE_PACKET3 |             \
+                                        (pkt) | ((n) << 16))
+
+static __inline__ void r128_update_ring_snapshot(drm_r128_private_t * dev_priv)
+{
+       drm_r128_ring_buffer_t *ring = &dev_priv->ring;
+       ring->space = (GET_RING_HEAD(dev_priv) - ring->tail) * sizeof(u32);
+       if (ring->space <= 0)
+               ring->space += ring->size;
+}
+
+/* ================================================================
+ * Misc helper macros
+ */
+
+#define RING_SPACE_TEST_WITH_RETURN( dev_priv )                                \
+do {                                                                   \
+       drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i;          \
+       if ( ring->space < ring->high_mark ) {                          \
+               for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {      \
+                       r128_update_ring_snapshot( dev_priv );          \
+                       if ( ring->space >= ring->high_mark )           \
+                               goto __ring_space_done;                 \
+                       DRM_UDELAY(1);                          \
+               }                                                       \
+               DRM_ERROR( "ring space check failed!\n" );              \
+               return -EBUSY;                          \
+       }                                                               \
+ __ring_space_done:                                                    \
+       ;                                                               \
+} while (0)
+
+#define VB_AGE_TEST_WITH_RETURN( dev_priv )                            \
+do {                                                                   \
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;            \
+       if ( sarea_priv->last_dispatch >= R128_MAX_VB_AGE ) {           \
+               int __ret = r128_do_cce_idle( dev_priv );               \
+               if ( __ret ) return __ret;                              \
+               sarea_priv->last_dispatch = 0;                          \
+               r128_freelist_reset( dev );                             \
+       }                                                               \
+} while (0)
+
+#define R128_WAIT_UNTIL_PAGE_FLIPPED() do {                            \
+       OUT_RING( CCE_PACKET0( R128_WAIT_UNTIL, 0 ) );                  \
+       OUT_RING( R128_EVENT_CRTC_OFFSET );                             \
+} while (0)
+
+/* ================================================================
+ * Ring control
+ */
+
+#define R128_VERBOSE   0
+
+#define RING_LOCALS                                                    \
+       int write, _nr; unsigned int tail_mask; volatile u32 *ring;
+
+#define BEGIN_RING( n ) do {                                           \
+       if ( R128_VERBOSE ) {                                           \
+               DRM_INFO( "BEGIN_RING( %d )\n", (n));                   \
+       }                                                               \
+       if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {              \
+               COMMIT_RING();                                          \
+               r128_wait_ring( dev_priv, (n) * sizeof(u32) );          \
+       }                                                               \
+       _nr = n; dev_priv->ring.space -= (n) * sizeof(u32);             \
+       ring = dev_priv->ring.start;                                    \
+       write = dev_priv->ring.tail;                                    \
+       tail_mask = dev_priv->ring.tail_mask;                           \
+} while (0)
+
+/* You can set this to zero if you want.  If the card locks up, you'll
+ * need to keep this set.  It works around a bug in early revs of the
+ * Rage 128 chipset, where the CCE would read 32 dwords past the end of
+ * the ring buffer before wrapping around.
+ */
+#define R128_BROKEN_CCE        1
+
+#define ADVANCE_RING() do {                                            \
+       if ( R128_VERBOSE ) {                                           \
+               DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",     \
+                         write, dev_priv->ring.tail );                 \
+       }                                                               \
+       if ( R128_BROKEN_CCE && write < 32 ) {                          \
+               memcpy( dev_priv->ring.end,                             \
+                       dev_priv->ring.start,                           \
+                       write * sizeof(u32) );                          \
+       }                                                               \
+       if (((dev_priv->ring.tail + _nr) & tail_mask) != write) {       \
+               DRM_ERROR(                                              \
+                       "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n",        \
+                       ((dev_priv->ring.tail + _nr) & tail_mask),      \
+                       write, __LINE__);                               \
+       } else                                                          \
+               dev_priv->ring.tail = write;                            \
+} while (0)
+
+#define COMMIT_RING() do {                                             \
+       if ( R128_VERBOSE ) {                                           \
+               DRM_INFO( "COMMIT_RING() tail=0x%06x\n",                \
+                       dev_priv->ring.tail );                          \
+       }                                                               \
+       DRM_MEMORYBARRIER();                                            \
+       R128_WRITE( R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail );     \
+       R128_READ( R128_PM4_BUFFER_DL_WPTR );                           \
+} while (0)
+
+#define OUT_RING( x ) do {                                             \
+       if ( R128_VERBOSE ) {                                           \
+               DRM_INFO( "   OUT_RING( 0x%08x ) at 0x%x\n",            \
+                          (unsigned int)(x), write );                  \
+       }                                                               \
+       ring[write++] = cpu_to_le32( x );                               \
+       write &= tail_mask;                                             \
+} while (0)
+
+#endif                         /* __R128_DRV_H__ */
diff --git a/drivers/gpu/drm/r128/r128_ioc32.c b/drivers/gpu/drm/r128/r128_ioc32.c
new file mode 100644 (file)
index 0000000..d3cb676
--- /dev/null
@@ -0,0 +1,221 @@
+/**
+ * \file r128_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the R128 DRM.
+ *
+ * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich
+ *
+ * Copyright (C) Paul Mackerras 2005
+ * Copyright (C) Egbert Eich 2003,2004
+ * Copyright (C) Dave Airlie 2005
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <linux/compat.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
+
+typedef struct drm_r128_init32 {
+       int func;
+       unsigned int sarea_priv_offset;
+       int is_pci;
+       int cce_mode;
+       int cce_secure;
+       int ring_size;
+       int usec_timeout;
+
+       unsigned int fb_bpp;
+       unsigned int front_offset, front_pitch;
+       unsigned int back_offset, back_pitch;
+       unsigned int depth_bpp;
+       unsigned int depth_offset, depth_pitch;
+       unsigned int span_offset;
+
+       unsigned int fb_offset;
+       unsigned int mmio_offset;
+       unsigned int ring_offset;
+       unsigned int ring_rptr_offset;
+       unsigned int buffers_offset;
+       unsigned int agp_textures_offset;
+} drm_r128_init32_t;
+
+static int compat_r128_init(struct file *file, unsigned int cmd,
+                           unsigned long arg)
+{
+       drm_r128_init32_t init32;
+       drm_r128_init_t __user *init;
+
+       if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
+               return -EFAULT;
+
+       init = compat_alloc_user_space(sizeof(*init));
+       if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
+           || __put_user(init32.func, &init->func)
+           || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
+           || __put_user(init32.is_pci, &init->is_pci)
+           || __put_user(init32.cce_mode, &init->cce_mode)
+           || __put_user(init32.cce_secure, &init->cce_secure)
+           || __put_user(init32.ring_size, &init->ring_size)
+           || __put_user(init32.usec_timeout, &init->usec_timeout)
+           || __put_user(init32.fb_bpp, &init->fb_bpp)
+           || __put_user(init32.front_offset, &init->front_offset)
+           || __put_user(init32.front_pitch, &init->front_pitch)
+           || __put_user(init32.back_offset, &init->back_offset)
+           || __put_user(init32.back_pitch, &init->back_pitch)
+           || __put_user(init32.depth_bpp, &init->depth_bpp)
+           || __put_user(init32.depth_offset, &init->depth_offset)
+           || __put_user(init32.depth_pitch, &init->depth_pitch)
+           || __put_user(init32.span_offset, &init->span_offset)
+           || __put_user(init32.fb_offset, &init->fb_offset)
+           || __put_user(init32.mmio_offset, &init->mmio_offset)
+           || __put_user(init32.ring_offset, &init->ring_offset)
+           || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
+           || __put_user(init32.buffers_offset, &init->buffers_offset)
+           || __put_user(init32.agp_textures_offset,
+                         &init->agp_textures_offset))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_R128_INIT, (unsigned long)init);
+}
+
+typedef struct drm_r128_depth32 {
+       int func;
+       int n;
+       u32 x;
+       u32 y;
+       u32 buffer;
+       u32 mask;
+} drm_r128_depth32_t;
+
+static int compat_r128_depth(struct file *file, unsigned int cmd,
+                            unsigned long arg)
+{
+       drm_r128_depth32_t depth32;
+       drm_r128_depth_t __user *depth;
+
+       if (copy_from_user(&depth32, (void __user *)arg, sizeof(depth32)))
+               return -EFAULT;
+
+       depth = compat_alloc_user_space(sizeof(*depth));
+       if (!access_ok(VERIFY_WRITE, depth, sizeof(*depth))
+           || __put_user(depth32.func, &depth->func)
+           || __put_user(depth32.n, &depth->n)
+           || __put_user((int __user *)(unsigned long)depth32.x, &depth->x)
+           || __put_user((int __user *)(unsigned long)depth32.y, &depth->y)
+           || __put_user((unsigned int __user *)(unsigned long)depth32.buffer,
+                         &depth->buffer)
+           || __put_user((unsigned char __user *)(unsigned long)depth32.mask,
+                         &depth->mask))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
+
+}
+
+typedef struct drm_r128_stipple32 {
+       u32 mask;
+} drm_r128_stipple32_t;
+
+static int compat_r128_stipple(struct file *file, unsigned int cmd,
+                              unsigned long arg)
+{
+       drm_r128_stipple32_t stipple32;
+       drm_r128_stipple_t __user *stipple;
+
+       if (copy_from_user(&stipple32, (void __user *)arg, sizeof(stipple32)))
+               return -EFAULT;
+
+       stipple = compat_alloc_user_space(sizeof(*stipple));
+       if (!access_ok(VERIFY_WRITE, stipple, sizeof(*stipple))
+           || __put_user((unsigned int __user *)(unsigned long)stipple32.mask,
+                         &stipple->mask))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
+}
+
+typedef struct drm_r128_getparam32 {
+       int param;
+       u32 value;
+} drm_r128_getparam32_t;
+
+static int compat_r128_getparam(struct file *file, unsigned int cmd,
+                               unsigned long arg)
+{
+       drm_r128_getparam32_t getparam32;
+       drm_r128_getparam_t __user *getparam;
+
+       if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
+               return -EFAULT;
+
+       getparam = compat_alloc_user_space(sizeof(*getparam));
+       if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
+           || __put_user(getparam32.param, &getparam->param)
+           || __put_user((void __user *)(unsigned long)getparam32.value,
+                         &getparam->value))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
+}
+
+drm_ioctl_compat_t *r128_compat_ioctls[] = {
+       [DRM_R128_INIT] = compat_r128_init,
+       [DRM_R128_DEPTH] = compat_r128_depth,
+       [DRM_R128_STIPPLE] = compat_r128_stipple,
+       [DRM_R128_GETPARAM] = compat_r128_getparam,
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/dri/card<n>.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       unsigned int nr = DRM_IOCTL_NR(cmd);
+       drm_ioctl_compat_t *fn = NULL;
+       int ret;
+
+       if (nr < DRM_COMMAND_BASE)
+               return drm_compat_ioctl(filp, cmd, arg);
+
+       if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(r128_compat_ioctls))
+               fn = r128_compat_ioctls[nr - DRM_COMMAND_BASE];
+
+       lock_kernel();          /* XXX for now */
+       if (fn != NULL)
+               ret = (*fn) (filp, cmd, arg);
+       else
+               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
+       unlock_kernel();
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c
new file mode 100644 (file)
index 0000000..c76fdca
--- /dev/null
@@ -0,0 +1,101 @@
+/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- */
+/*
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Eric Anholt <anholt@FreeBSD.org>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
+#include "r128_drv.h"
+
+irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+       int status;
+
+       status = R128_READ(R128_GEN_INT_STATUS);
+
+       /* VBLANK interrupt */
+       if (status & R128_CRTC_VBLANK_INT) {
+               R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
+               atomic_inc(&dev->vbl_received);
+               DRM_WAKEUP(&dev->vbl_queue);
+               drm_vbl_send_signals(dev);
+               return IRQ_HANDLED;
+       }
+       return IRQ_NONE;
+}
+
+int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+{
+       unsigned int cur_vblank;
+       int ret = 0;
+
+       /* Assume that the user has missed the current sequence number
+        * by about a day rather than she wants to wait for years
+        * using vertical blanks...
+        */
+       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+                   (((cur_vblank = atomic_read(&dev->vbl_received))
+                     - *sequence) <= (1 << 23)));
+
+       *sequence = cur_vblank;
+
+       return ret;
+}
+
+void r128_driver_irq_preinstall(struct drm_device * dev)
+{
+       drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+
+       /* Disable *all* interrupts */
+       R128_WRITE(R128_GEN_INT_CNTL, 0);
+       /* Clear vblank bit if it's already high */
+       R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
+}
+
+void r128_driver_irq_postinstall(struct drm_device * dev)
+{
+       drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+
+       /* Turn on VBL interrupt */
+       R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
+}
+
+void r128_driver_irq_uninstall(struct drm_device * dev)
+{
+       drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
+       if (!dev_priv)
+               return;
+
+       /* Disable *all* interrupts */
+       R128_WRITE(R128_GEN_INT_CNTL, 0);
+}
diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c
new file mode 100644 (file)
index 0000000..51a9afc
--- /dev/null
@@ -0,0 +1,1681 @@
+/* r128_state.c -- State support for r128 -*- linux-c -*-
+ * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
+ */
+/*
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "r128_drm.h"
+#include "r128_drv.h"
+
+/* ================================================================
+ * CCE hardware state programming functions
+ */
+
+static void r128_emit_clip_rects(drm_r128_private_t * dev_priv,
+                                struct drm_clip_rect * boxes, int count)
+{
+       u32 aux_sc_cntl = 0x00000000;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_RING((count < 3 ? count : 3) * 5 + 2);
+
+       if (count >= 1) {
+               OUT_RING(CCE_PACKET0(R128_AUX1_SC_LEFT, 3));
+               OUT_RING(boxes[0].x1);
+               OUT_RING(boxes[0].x2 - 1);
+               OUT_RING(boxes[0].y1);
+               OUT_RING(boxes[0].y2 - 1);
+
+               aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
+       }
+       if (count >= 2) {
+               OUT_RING(CCE_PACKET0(R128_AUX2_SC_LEFT, 3));
+               OUT_RING(boxes[1].x1);
+               OUT_RING(boxes[1].x2 - 1);
+               OUT_RING(boxes[1].y1);
+               OUT_RING(boxes[1].y2 - 1);
+
+               aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
+       }
+       if (count >= 3) {
+               OUT_RING(CCE_PACKET0(R128_AUX3_SC_LEFT, 3));
+               OUT_RING(boxes[2].x1);
+               OUT_RING(boxes[2].x2 - 1);
+               OUT_RING(boxes[2].y1);
+               OUT_RING(boxes[2].y2 - 1);
+
+               aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
+       }
+
+       OUT_RING(CCE_PACKET0(R128_AUX_SC_CNTL, 0));
+       OUT_RING(aux_sc_cntl);
+
+       ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_core(drm_r128_private_t * dev_priv)
+{
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_RING(2);
+
+       OUT_RING(CCE_PACKET0(R128_SCALE_3D_CNTL, 0));
+       OUT_RING(ctx->scale_3d_cntl);
+
+       ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_context(drm_r128_private_t * dev_priv)
+{
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_RING(13);
+
+       OUT_RING(CCE_PACKET0(R128_DST_PITCH_OFFSET_C, 11));
+       OUT_RING(ctx->dst_pitch_offset_c);
+       OUT_RING(ctx->dp_gui_master_cntl_c);
+       OUT_RING(ctx->sc_top_left_c);
+       OUT_RING(ctx->sc_bottom_right_c);
+       OUT_RING(ctx->z_offset_c);
+       OUT_RING(ctx->z_pitch_c);
+       OUT_RING(ctx->z_sten_cntl_c);
+       OUT_RING(ctx->tex_cntl_c);
+       OUT_RING(ctx->misc_3d_state_cntl_reg);
+       OUT_RING(ctx->texture_clr_cmp_clr_c);
+       OUT_RING(ctx->texture_clr_cmp_msk_c);
+       OUT_RING(ctx->fog_color_c);
+
+       ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_setup(drm_r128_private_t * dev_priv)
+{
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_RING(3);
+
+       OUT_RING(CCE_PACKET1(R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP));
+       OUT_RING(ctx->setup_cntl);
+       OUT_RING(ctx->pm4_vc_fpu_setup);
+
+       ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_masks(drm_r128_private_t * dev_priv)
+{
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_RING(5);
+
+       OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
+       OUT_RING(ctx->dp_write_mask);
+
+       OUT_RING(CCE_PACKET0(R128_STEN_REF_MASK_C, 1));
+       OUT_RING(ctx->sten_ref_mask_c);
+       OUT_RING(ctx->plane_3d_mask_c);
+
+       ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_window(drm_r128_private_t * dev_priv)
+{
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_RING(2);
+
+       OUT_RING(CCE_PACKET0(R128_WINDOW_XY_OFFSET, 0));
+       OUT_RING(ctx->window_xy_offset);
+
+       ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_tex0(drm_r128_private_t * dev_priv)
+{
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
+       drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
+       int i;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS);
+
+       OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C,
+                            2 + R128_MAX_TEXTURE_LEVELS));
+       OUT_RING(tex->tex_cntl);
+       OUT_RING(tex->tex_combine_cntl);
+       OUT_RING(ctx->tex_size_pitch_c);
+       for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
+               OUT_RING(tex->tex_offset[i]);
+       }
+
+       OUT_RING(CCE_PACKET0(R128_CONSTANT_COLOR_C, 1));
+       OUT_RING(ctx->constant_color_c);
+       OUT_RING(tex->tex_border_color);
+
+       ADVANCE_RING();
+}
+
+static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv)
+{
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
+       int i;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS);
+
+       OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS));
+       OUT_RING(tex->tex_cntl);
+       OUT_RING(tex->tex_combine_cntl);
+       for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) {
+               OUT_RING(tex->tex_offset[i]);
+       }
+
+       OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0));
+       OUT_RING(tex->tex_border_color);
+
+       ADVANCE_RING();
+}
+
+static void r128_emit_state(drm_r128_private_t * dev_priv)
+{
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       unsigned int dirty = sarea_priv->dirty;
+
+       DRM_DEBUG("dirty=0x%08x\n", dirty);
+
+       if (dirty & R128_UPLOAD_CORE) {
+               r128_emit_core(dev_priv);
+               sarea_priv->dirty &= ~R128_UPLOAD_CORE;
+       }
+
+       if (dirty & R128_UPLOAD_CONTEXT) {
+               r128_emit_context(dev_priv);
+               sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
+       }
+
+       if (dirty & R128_UPLOAD_SETUP) {
+               r128_emit_setup(dev_priv);
+               sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
+       }
+
+       if (dirty & R128_UPLOAD_MASKS) {
+               r128_emit_masks(dev_priv);
+               sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
+       }
+
+       if (dirty & R128_UPLOAD_WINDOW) {
+               r128_emit_window(dev_priv);
+               sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
+       }
+
+       if (dirty & R128_UPLOAD_TEX0) {
+               r128_emit_tex0(dev_priv);
+               sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
+       }
+
+       if (dirty & R128_UPLOAD_TEX1) {
+               r128_emit_tex1(dev_priv);
+               sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
+       }
+
+       /* Turn off the texture cache flushing */
+       sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
+
+       sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
+}
+
+#if R128_PERFORMANCE_BOXES
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void r128_clear_box(drm_r128_private_t * dev_priv,
+                          int x, int y, int w, int h, int r, int g, int b)
+{
+       u32 pitch, offset;
+       u32 fb_bpp, color;
+       RING_LOCALS;
+
+       switch (dev_priv->fb_bpp) {
+       case 16:
+               fb_bpp = R128_GMC_DST_16BPP;
+               color = (((r & 0xf8) << 8) |
+                        ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
+               break;
+       case 24:
+               fb_bpp = R128_GMC_DST_24BPP;
+               color = ((r << 16) | (g << 8) | b);
+               break;
+       case 32:
+               fb_bpp = R128_GMC_DST_32BPP;
+               color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+               break;
+       default:
+               return;
+       }
+
+       offset = dev_priv->back_offset;
+       pitch = dev_priv->back_pitch >> 3;
+
+       BEGIN_RING(6);
+
+       OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+       OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+                R128_GMC_BRUSH_SOLID_COLOR |
+                fb_bpp |
+                R128_GMC_SRC_DATATYPE_COLOR |
+                R128_ROP3_P |
+                R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS);
+
+       OUT_RING((pitch << 21) | (offset >> 5));
+       OUT_RING(color);
+
+       OUT_RING((x << 16) | y);
+       OUT_RING((w << 16) | h);
+
+       ADVANCE_RING();
+}
+
+static void r128_cce_performance_boxes(drm_r128_private_t * dev_priv)
+{
+       if (atomic_read(&dev_priv->idle_count) == 0) {
+               r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
+       } else {
+               atomic_set(&dev_priv->idle_count, 0);
+       }
+}
+
+#endif
+
+/* ================================================================
+ * CCE command dispatch functions
+ */
+
+static void r128_print_dirty(const char *msg, unsigned int flags)
+{
+       DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
+                msg,
+                flags,
+                (flags & R128_UPLOAD_CORE) ? "core, " : "",
+                (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
+                (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
+                (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
+                (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
+                (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
+                (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
+                (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
+                (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
+}
+
+static void r128_cce_dispatch_clear(struct drm_device * dev,
+                                   drm_r128_clear_t * clear)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
+       unsigned int flags = clear->flags;
+       int i;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       if (dev_priv->page_flipping && dev_priv->current_page == 1) {
+               unsigned int tmp = flags;
+
+               flags &= ~(R128_FRONT | R128_BACK);
+               if (tmp & R128_FRONT)
+                       flags |= R128_BACK;
+               if (tmp & R128_BACK)
+                       flags |= R128_FRONT;
+       }
+
+       for (i = 0; i < nbox; i++) {
+               int x = pbox[i].x1;
+               int y = pbox[i].y1;
+               int w = pbox[i].x2 - x;
+               int h = pbox[i].y2 - y;
+
+               DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
+                         pbox[i].x1, pbox[i].y1, pbox[i].x2,
+                         pbox[i].y2, flags);
+
+               if (flags & (R128_FRONT | R128_BACK)) {
+                       BEGIN_RING(2);
+
+                       OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
+                       OUT_RING(clear->color_mask);
+
+                       ADVANCE_RING();
+               }
+
+               if (flags & R128_FRONT) {
+                       BEGIN_RING(6);
+
+                       OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+                       OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+                                R128_GMC_BRUSH_SOLID_COLOR |
+                                (dev_priv->color_fmt << 8) |
+                                R128_GMC_SRC_DATATYPE_COLOR |
+                                R128_ROP3_P |
+                                R128_GMC_CLR_CMP_CNTL_DIS |
+                                R128_GMC_AUX_CLIP_DIS);
+
+                       OUT_RING(dev_priv->front_pitch_offset_c);
+                       OUT_RING(clear->clear_color);
+
+                       OUT_RING((x << 16) | y);
+                       OUT_RING((w << 16) | h);
+
+                       ADVANCE_RING();
+               }
+
+               if (flags & R128_BACK) {
+                       BEGIN_RING(6);
+
+                       OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+                       OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+                                R128_GMC_BRUSH_SOLID_COLOR |
+                                (dev_priv->color_fmt << 8) |
+                                R128_GMC_SRC_DATATYPE_COLOR |
+                                R128_ROP3_P |
+                                R128_GMC_CLR_CMP_CNTL_DIS |
+                                R128_GMC_AUX_CLIP_DIS);
+
+                       OUT_RING(dev_priv->back_pitch_offset_c);
+                       OUT_RING(clear->clear_color);
+
+                       OUT_RING((x << 16) | y);
+                       OUT_RING((w << 16) | h);
+
+                       ADVANCE_RING();
+               }
+
+               if (flags & R128_DEPTH) {
+                       BEGIN_RING(6);
+
+                       OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+                       OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+                                R128_GMC_BRUSH_SOLID_COLOR |
+                                (dev_priv->depth_fmt << 8) |
+                                R128_GMC_SRC_DATATYPE_COLOR |
+                                R128_ROP3_P |
+                                R128_GMC_CLR_CMP_CNTL_DIS |
+                                R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
+
+                       OUT_RING(dev_priv->depth_pitch_offset_c);
+                       OUT_RING(clear->clear_depth);
+
+                       OUT_RING((x << 16) | y);
+                       OUT_RING((w << 16) | h);
+
+                       ADVANCE_RING();
+               }
+       }
+}
+
+static void r128_cce_dispatch_swap(struct drm_device * dev)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
+       int i;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+#if R128_PERFORMANCE_BOXES
+       /* Do some trivial performance monitoring...
+        */
+       r128_cce_performance_boxes(dev_priv);
+#endif
+
+       for (i = 0; i < nbox; i++) {
+               int x = pbox[i].x1;
+               int y = pbox[i].y1;
+               int w = pbox[i].x2 - x;
+               int h = pbox[i].y2 - y;
+
+               BEGIN_RING(7);
+
+               OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
+               OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
+                        R128_GMC_DST_PITCH_OFFSET_CNTL |
+                        R128_GMC_BRUSH_NONE |
+                        (dev_priv->color_fmt << 8) |
+                        R128_GMC_SRC_DATATYPE_COLOR |
+                        R128_ROP3_S |
+                        R128_DP_SRC_SOURCE_MEMORY |
+                        R128_GMC_CLR_CMP_CNTL_DIS |
+                        R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
+
+               /* Make this work even if front & back are flipped:
+                */
+               if (dev_priv->current_page == 0) {
+                       OUT_RING(dev_priv->back_pitch_offset_c);
+                       OUT_RING(dev_priv->front_pitch_offset_c);
+               } else {
+                       OUT_RING(dev_priv->front_pitch_offset_c);
+                       OUT_RING(dev_priv->back_pitch_offset_c);
+               }
+
+               OUT_RING((x << 16) | y);
+               OUT_RING((x << 16) | y);
+               OUT_RING((w << 16) | h);
+
+               ADVANCE_RING();
+       }
+
+       /* Increment the frame counter.  The client-side 3D driver must
+        * throttle the framerate by waiting for this value before
+        * performing the swapbuffer ioctl.
+        */
+       dev_priv->sarea_priv->last_frame++;
+
+       BEGIN_RING(2);
+
+       OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
+       OUT_RING(dev_priv->sarea_priv->last_frame);
+
+       ADVANCE_RING();
+}
+
+static void r128_cce_dispatch_flip(struct drm_device * dev)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+       DRM_DEBUG("page=%d pfCurrentPage=%d\n",
+                 dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
+
+#if R128_PERFORMANCE_BOXES
+       /* Do some trivial performance monitoring...
+        */
+       r128_cce_performance_boxes(dev_priv);
+#endif
+
+       BEGIN_RING(4);
+
+       R128_WAIT_UNTIL_PAGE_FLIPPED();
+       OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0));
+
+       if (dev_priv->current_page == 0) {
+               OUT_RING(dev_priv->back_offset);
+       } else {
+               OUT_RING(dev_priv->front_offset);
+       }
+
+       ADVANCE_RING();
+
+       /* Increment the frame counter.  The client-side 3D driver must
+        * throttle the framerate by waiting for this value before
+        * performing the swapbuffer ioctl.
+        */
+       dev_priv->sarea_priv->last_frame++;
+       dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
+           1 - dev_priv->current_page;
+
+       BEGIN_RING(2);
+
+       OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
+       OUT_RING(dev_priv->sarea_priv->last_frame);
+
+       ADVANCE_RING();
+}
+
+static void r128_cce_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int format = sarea_priv->vc_format;
+       int offset = buf->bus_address;
+       int size = buf->used;
+       int prim = buf_priv->prim;
+       int i = 0;
+       RING_LOCALS;
+       DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox);
+
+       if (0)
+               r128_print_dirty("dispatch_vertex", sarea_priv->dirty);
+
+       if (buf->used) {
+               buf_priv->dispatched = 1;
+
+               if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
+                       r128_emit_state(dev_priv);
+               }
+
+               do {
+                       /* Emit the next set of up to three cliprects */
+                       if (i < sarea_priv->nbox) {
+                               r128_emit_clip_rects(dev_priv,
+                                                    &sarea_priv->boxes[i],
+                                                    sarea_priv->nbox - i);
+                       }
+
+                       /* Emit the vertex buffer rendering commands */
+                       BEGIN_RING(5);
+
+                       OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3));
+                       OUT_RING(offset);
+                       OUT_RING(size);
+                       OUT_RING(format);
+                       OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
+                                (size << R128_CCE_VC_CNTL_NUM_SHIFT));
+
+                       ADVANCE_RING();
+
+                       i += 3;
+               } while (i < sarea_priv->nbox);
+       }
+
+       if (buf_priv->discard) {
+               buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+               /* Emit the vertex buffer age */
+               BEGIN_RING(2);
+
+               OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
+               OUT_RING(buf_priv->age);
+
+               ADVANCE_RING();
+
+               buf->pending = 1;
+               buf->used = 0;
+               /* FIXME: Check dispatched field */
+               buf_priv->dispatched = 0;
+       }
+
+       dev_priv->sarea_priv->last_dispatch++;
+
+       sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
+       sarea_priv->nbox = 0;
+}
+
+static void r128_cce_dispatch_indirect(struct drm_device * dev,
+                                      struct drm_buf * buf, int start, int end)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+       RING_LOCALS;
+       DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
+
+       if (start != end) {
+               int offset = buf->bus_address + start;
+               int dwords = (end - start + 3) / sizeof(u32);
+
+               /* Indirect buffer data must be an even number of
+                * dwords, so if we've been given an odd number we must
+                * pad the data with a Type-2 CCE packet.
+                */
+               if (dwords & 1) {
+                       u32 *data = (u32 *)
+                           ((char *)dev->agp_buffer_map->handle
+                            + buf->offset + start);
+                       data[dwords++] = cpu_to_le32(R128_CCE_PACKET2);
+               }
+
+               buf_priv->dispatched = 1;
+
+               /* Fire off the indirect buffer */
+               BEGIN_RING(3);
+
+               OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1));
+               OUT_RING(offset);
+               OUT_RING(dwords);
+
+               ADVANCE_RING();
+       }
+
+       if (buf_priv->discard) {
+               buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+               /* Emit the indirect buffer age */
+               BEGIN_RING(2);
+
+               OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
+               OUT_RING(buf_priv->age);
+
+               ADVANCE_RING();
+
+               buf->pending = 1;
+               buf->used = 0;
+               /* FIXME: Check dispatched field */
+               buf_priv->dispatched = 0;
+       }
+
+       dev_priv->sarea_priv->last_dispatch++;
+}
+
+static void r128_cce_dispatch_indices(struct drm_device * dev,
+                                     struct drm_buf * buf,
+                                     int start, int end, int count)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_buf_priv_t *buf_priv = buf->dev_private;
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int format = sarea_priv->vc_format;
+       int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset;
+       int prim = buf_priv->prim;
+       u32 *data;
+       int dwords;
+       int i = 0;
+       RING_LOCALS;
+       DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count);
+
+       if (0)
+               r128_print_dirty("dispatch_indices", sarea_priv->dirty);
+
+       if (start != end) {
+               buf_priv->dispatched = 1;
+
+               if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) {
+                       r128_emit_state(dev_priv);
+               }
+
+               dwords = (end - start + 3) / sizeof(u32);
+
+               data = (u32 *) ((char *)dev->agp_buffer_map->handle
+                               + buf->offset + start);
+
+               data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM,
+                                                 dwords - 2));
+
+               data[1] = cpu_to_le32(offset);
+               data[2] = cpu_to_le32(R128_MAX_VB_VERTS);
+               data[3] = cpu_to_le32(format);
+               data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
+                                      (count << 16)));
+
+               if (count & 0x1) {
+#ifdef __LITTLE_ENDIAN
+                       data[dwords - 1] &= 0x0000ffff;
+#else
+                       data[dwords - 1] &= 0xffff0000;
+#endif
+               }
+
+               do {
+                       /* Emit the next set of up to three cliprects */
+                       if (i < sarea_priv->nbox) {
+                               r128_emit_clip_rects(dev_priv,
+                                                    &sarea_priv->boxes[i],
+                                                    sarea_priv->nbox - i);
+                       }
+
+                       r128_cce_dispatch_indirect(dev, buf, start, end);
+
+                       i += 3;
+               } while (i < sarea_priv->nbox);
+       }
+
+       if (buf_priv->discard) {
+               buf_priv->age = dev_priv->sarea_priv->last_dispatch;
+
+               /* Emit the vertex buffer age */
+               BEGIN_RING(2);
+
+               OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
+               OUT_RING(buf_priv->age);
+
+               ADVANCE_RING();
+
+               buf->pending = 1;
+               /* FIXME: Check dispatched field */
+               buf_priv->dispatched = 0;
+       }
+
+       dev_priv->sarea_priv->last_dispatch++;
+
+       sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
+       sarea_priv->nbox = 0;
+}
+
+static int r128_cce_dispatch_blit(struct drm_device * dev,
+                                 struct drm_file *file_priv,
+                                 drm_r128_blit_t * blit)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_r128_buf_priv_t *buf_priv;
+       u32 *data;
+       int dword_shift, dwords;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       /* The compiler won't optimize away a division by a variable,
+        * even if the only legal values are powers of two.  Thus, we'll
+        * use a shift instead.
+        */
+       switch (blit->format) {
+       case R128_DATATYPE_ARGB8888:
+               dword_shift = 0;
+               break;
+       case R128_DATATYPE_ARGB1555:
+       case R128_DATATYPE_RGB565:
+       case R128_DATATYPE_ARGB4444:
+       case R128_DATATYPE_YVYU422:
+       case R128_DATATYPE_VYUY422:
+               dword_shift = 1;
+               break;
+       case R128_DATATYPE_CI8:
+       case R128_DATATYPE_RGB8:
+               dword_shift = 2;
+               break;
+       default:
+               DRM_ERROR("invalid blit format %d\n", blit->format);
+               return -EINVAL;
+       }
+
+       /* Flush the pixel cache, and mark the contents as Read Invalid.
+        * This ensures no pixel data gets mixed up with the texture
+        * data from the host data blit, otherwise part of the texture
+        * image may be corrupted.
+        */
+       BEGIN_RING(2);
+
+       OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
+       OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI);
+
+       ADVANCE_RING();
+
+       /* Dispatch the indirect buffer.
+        */
+       buf = dma->buflist[blit->idx];
+       buf_priv = buf->dev_private;
+
+       if (buf->file_priv != file_priv) {
+               DRM_ERROR("process %d using buffer owned by %p\n",
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
+       }
+       if (buf->pending) {
+               DRM_ERROR("sending pending buffer %d\n", blit->idx);
+               return -EINVAL;
+       }
+
+       buf_priv->discard = 1;
+
+       dwords = (blit->width * blit->height) >> dword_shift;
+
+       data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
+
+       data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6));
+       data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL |
+                              R128_GMC_BRUSH_NONE |
+                              (blit->format << 8) |
+                              R128_GMC_SRC_DATATYPE_COLOR |
+                              R128_ROP3_S |
+                              R128_DP_SRC_SOURCE_HOST_DATA |
+                              R128_GMC_CLR_CMP_CNTL_DIS |
+                              R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS));
+
+       data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5));
+       data[3] = cpu_to_le32(0xffffffff);
+       data[4] = cpu_to_le32(0xffffffff);
+       data[5] = cpu_to_le32((blit->y << 16) | blit->x);
+       data[6] = cpu_to_le32((blit->height << 16) | blit->width);
+       data[7] = cpu_to_le32(dwords);
+
+       buf->used = (dwords + 8) * sizeof(u32);
+
+       r128_cce_dispatch_indirect(dev, buf, 0, buf->used);
+
+       /* Flush the pixel cache after the blit completes.  This ensures
+        * the texture data is written out to memory before rendering
+        * continues.
+        */
+       BEGIN_RING(2);
+
+       OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
+       OUT_RING(R128_PC_FLUSH_GUI);
+
+       ADVANCE_RING();
+
+       return 0;
+}
+
+/* ================================================================
+ * Tiled depth buffer management
+ *
+ * FIXME: These should all set the destination write mask for when we
+ * have hardware stencil support.
+ */
+
+static int r128_cce_dispatch_write_span(struct drm_device * dev,
+                                       drm_r128_depth_t * depth)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       int count, x, y;
+       u32 *buffer;
+       u8 *mask;
+       int i, buffer_size, mask_size;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       count = depth->n;
+       if (count > 4096 || count <= 0)
+               return -EMSGSIZE;
+
+       if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
+               return -EFAULT;
+       }
+       if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
+               return -EFAULT;
+       }
+
+       buffer_size = depth->n * sizeof(u32);
+       buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
+       if (buffer == NULL)
+               return -ENOMEM;
+       if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
+               drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+               return -EFAULT;
+       }
+
+       mask_size = depth->n * sizeof(u8);
+       if (depth->mask) {
+               mask = drm_alloc(mask_size, DRM_MEM_BUFS);
+               if (mask == NULL) {
+                       drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+                       return -ENOMEM;
+               }
+               if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
+                       drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+                       drm_free(mask, mask_size, DRM_MEM_BUFS);
+                       return -EFAULT;
+               }
+
+               for (i = 0; i < count; i++, x++) {
+                       if (mask[i]) {
+                               BEGIN_RING(6);
+
+                               OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+                               OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+                                        R128_GMC_BRUSH_SOLID_COLOR |
+                                        (dev_priv->depth_fmt << 8) |
+                                        R128_GMC_SRC_DATATYPE_COLOR |
+                                        R128_ROP3_P |
+                                        R128_GMC_CLR_CMP_CNTL_DIS |
+                                        R128_GMC_WR_MSK_DIS);
+
+                               OUT_RING(dev_priv->depth_pitch_offset_c);
+                               OUT_RING(buffer[i]);
+
+                               OUT_RING((x << 16) | y);
+                               OUT_RING((1 << 16) | 1);
+
+                               ADVANCE_RING();
+                       }
+               }
+
+               drm_free(mask, mask_size, DRM_MEM_BUFS);
+       } else {
+               for (i = 0; i < count; i++, x++) {
+                       BEGIN_RING(6);
+
+                       OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+                       OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+                                R128_GMC_BRUSH_SOLID_COLOR |
+                                (dev_priv->depth_fmt << 8) |
+                                R128_GMC_SRC_DATATYPE_COLOR |
+                                R128_ROP3_P |
+                                R128_GMC_CLR_CMP_CNTL_DIS |
+                                R128_GMC_WR_MSK_DIS);
+
+                       OUT_RING(dev_priv->depth_pitch_offset_c);
+                       OUT_RING(buffer[i]);
+
+                       OUT_RING((x << 16) | y);
+                       OUT_RING((1 << 16) | 1);
+
+                       ADVANCE_RING();
+               }
+       }
+
+       drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+
+       return 0;
+}
+
+static int r128_cce_dispatch_write_pixels(struct drm_device * dev,
+                                         drm_r128_depth_t * depth)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       int count, *x, *y;
+       u32 *buffer;
+       u8 *mask;
+       int i, xbuf_size, ybuf_size, buffer_size, mask_size;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       count = depth->n;
+       if (count > 4096 || count <= 0)
+               return -EMSGSIZE;
+
+       xbuf_size = count * sizeof(*x);
+       ybuf_size = count * sizeof(*y);
+       x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
+       if (x == NULL) {
+               return -ENOMEM;
+       }
+       y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
+       if (y == NULL) {
+               drm_free(x, xbuf_size, DRM_MEM_BUFS);
+               return -ENOMEM;
+       }
+       if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
+               drm_free(x, xbuf_size, DRM_MEM_BUFS);
+               drm_free(y, ybuf_size, DRM_MEM_BUFS);
+               return -EFAULT;
+       }
+       if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) {
+               drm_free(x, xbuf_size, DRM_MEM_BUFS);
+               drm_free(y, ybuf_size, DRM_MEM_BUFS);
+               return -EFAULT;
+       }
+
+       buffer_size = depth->n * sizeof(u32);
+       buffer = drm_alloc(buffer_size, DRM_MEM_BUFS);
+       if (buffer == NULL) {
+               drm_free(x, xbuf_size, DRM_MEM_BUFS);
+               drm_free(y, ybuf_size, DRM_MEM_BUFS);
+               return -ENOMEM;
+       }
+       if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) {
+               drm_free(x, xbuf_size, DRM_MEM_BUFS);
+               drm_free(y, ybuf_size, DRM_MEM_BUFS);
+               drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+               return -EFAULT;
+       }
+
+       if (depth->mask) {
+               mask_size = depth->n * sizeof(u8);
+               mask = drm_alloc(mask_size, DRM_MEM_BUFS);
+               if (mask == NULL) {
+                       drm_free(x, xbuf_size, DRM_MEM_BUFS);
+                       drm_free(y, ybuf_size, DRM_MEM_BUFS);
+                       drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+                       return -ENOMEM;
+               }
+               if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) {
+                       drm_free(x, xbuf_size, DRM_MEM_BUFS);
+                       drm_free(y, ybuf_size, DRM_MEM_BUFS);
+                       drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+                       drm_free(mask, mask_size, DRM_MEM_BUFS);
+                       return -EFAULT;
+               }
+
+               for (i = 0; i < count; i++) {
+                       if (mask[i]) {
+                               BEGIN_RING(6);
+
+                               OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+                               OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+                                        R128_GMC_BRUSH_SOLID_COLOR |
+                                        (dev_priv->depth_fmt << 8) |
+                                        R128_GMC_SRC_DATATYPE_COLOR |
+                                        R128_ROP3_P |
+                                        R128_GMC_CLR_CMP_CNTL_DIS |
+                                        R128_GMC_WR_MSK_DIS);
+
+                               OUT_RING(dev_priv->depth_pitch_offset_c);
+                               OUT_RING(buffer[i]);
+
+                               OUT_RING((x[i] << 16) | y[i]);
+                               OUT_RING((1 << 16) | 1);
+
+                               ADVANCE_RING();
+                       }
+               }
+
+               drm_free(mask, mask_size, DRM_MEM_BUFS);
+       } else {
+               for (i = 0; i < count; i++) {
+                       BEGIN_RING(6);
+
+                       OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
+                       OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
+                                R128_GMC_BRUSH_SOLID_COLOR |
+                                (dev_priv->depth_fmt << 8) |
+                                R128_GMC_SRC_DATATYPE_COLOR |
+                                R128_ROP3_P |
+                                R128_GMC_CLR_CMP_CNTL_DIS |
+                                R128_GMC_WR_MSK_DIS);
+
+                       OUT_RING(dev_priv->depth_pitch_offset_c);
+                       OUT_RING(buffer[i]);
+
+                       OUT_RING((x[i] << 16) | y[i]);
+                       OUT_RING((1 << 16) | 1);
+
+                       ADVANCE_RING();
+               }
+       }
+
+       drm_free(x, xbuf_size, DRM_MEM_BUFS);
+       drm_free(y, ybuf_size, DRM_MEM_BUFS);
+       drm_free(buffer, buffer_size, DRM_MEM_BUFS);
+
+       return 0;
+}
+
+static int r128_cce_dispatch_read_span(struct drm_device * dev,
+                                      drm_r128_depth_t * depth)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       int count, x, y;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       count = depth->n;
+       if (count > 4096 || count <= 0)
+               return -EMSGSIZE;
+
+       if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) {
+               return -EFAULT;
+       }
+       if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) {
+               return -EFAULT;
+       }
+
+       BEGIN_RING(7);
+
+       OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
+       OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
+                R128_GMC_DST_PITCH_OFFSET_CNTL |
+                R128_GMC_BRUSH_NONE |
+                (dev_priv->depth_fmt << 8) |
+                R128_GMC_SRC_DATATYPE_COLOR |
+                R128_ROP3_S |
+                R128_DP_SRC_SOURCE_MEMORY |
+                R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
+
+       OUT_RING(dev_priv->depth_pitch_offset_c);
+       OUT_RING(dev_priv->span_pitch_offset_c);
+
+       OUT_RING((x << 16) | y);
+       OUT_RING((0 << 16) | 0);
+       OUT_RING((count << 16) | 1);
+
+       ADVANCE_RING();
+
+       return 0;
+}
+
+static int r128_cce_dispatch_read_pixels(struct drm_device * dev,
+                                        drm_r128_depth_t * depth)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       int count, *x, *y;
+       int i, xbuf_size, ybuf_size;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       count = depth->n;
+       if (count > 4096 || count <= 0)
+               return -EMSGSIZE;
+
+       if (count > dev_priv->depth_pitch) {
+               count = dev_priv->depth_pitch;
+       }
+
+       xbuf_size = count * sizeof(*x);
+       ybuf_size = count * sizeof(*y);
+       x = drm_alloc(xbuf_size, DRM_MEM_BUFS);
+       if (x == NULL) {
+               return -ENOMEM;
+       }
+       y = drm_alloc(ybuf_size, DRM_MEM_BUFS);
+       if (y == NULL) {
+               drm_free(x, xbuf_size, DRM_MEM_BUFS);
+               return -ENOMEM;
+       }
+       if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) {
+               drm_free(x, xbuf_size, DRM_MEM_BUFS);
+               drm_free(y, ybuf_size, DRM_MEM_BUFS);
+               return -EFAULT;
+       }
+       if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) {
+               drm_free(x, xbuf_size, DRM_MEM_BUFS);
+               drm_free(y, ybuf_size, DRM_MEM_BUFS);
+               return -EFAULT;
+       }
+
+       for (i = 0; i < count; i++) {
+               BEGIN_RING(7);
+
+               OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
+               OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
+                        R128_GMC_DST_PITCH_OFFSET_CNTL |
+                        R128_GMC_BRUSH_NONE |
+                        (dev_priv->depth_fmt << 8) |
+                        R128_GMC_SRC_DATATYPE_COLOR |
+                        R128_ROP3_S |
+                        R128_DP_SRC_SOURCE_MEMORY |
+                        R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
+
+               OUT_RING(dev_priv->depth_pitch_offset_c);
+               OUT_RING(dev_priv->span_pitch_offset_c);
+
+               OUT_RING((x[i] << 16) | y[i]);
+               OUT_RING((i << 16) | 0);
+               OUT_RING((1 << 16) | 1);
+
+               ADVANCE_RING();
+       }
+
+       drm_free(x, xbuf_size, DRM_MEM_BUFS);
+       drm_free(y, ybuf_size, DRM_MEM_BUFS);
+
+       return 0;
+}
+
+/* ================================================================
+ * Polygon stipple
+ */
+
+static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       int i;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_RING(33);
+
+       OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31));
+       for (i = 0; i < 32; i++) {
+               OUT_RING(stipple[i]);
+       }
+
+       ADVANCE_RING();
+}
+
+/* ================================================================
+ * IOCTL functions
+ */
+
+static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_r128_clear_t *clear = data;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+       if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
+               sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
+
+       r128_cce_dispatch_clear(dev, clear);
+       COMMIT_RING();
+
+       /* Make sure we restore the 3D state next time.
+        */
+       dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
+
+       return 0;
+}
+
+static int r128_do_init_pageflip(struct drm_device * dev)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG("\n");
+
+       dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET);
+       dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL);
+
+       R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset);
+       R128_WRITE(R128_CRTC_OFFSET_CNTL,
+                  dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL);
+
+       dev_priv->page_flipping = 1;
+       dev_priv->current_page = 0;
+       dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
+
+       return 0;
+}
+
+static int r128_do_cleanup_pageflip(struct drm_device * dev)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG("\n");
+
+       R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset);
+       R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl);
+
+       if (dev_priv->current_page != 0) {
+               r128_cce_dispatch_flip(dev);
+               COMMIT_RING();
+       }
+
+       dev_priv->page_flipping = 0;
+       return 0;
+}
+
+/* Swapping and flipping are different operations, need different ioctls.
+ * They can & should be intermixed to support multiple 3d windows.
+ */
+
+static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+       if (!dev_priv->page_flipping)
+               r128_do_init_pageflip(dev);
+
+       r128_cce_dispatch_flip(dev);
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+       if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
+               sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
+
+       r128_cce_dispatch_swap(dev);
+       dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
+                                       R128_UPLOAD_MASKS);
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_r128_buf_priv_t *buf_priv;
+       drm_r128_vertex_t *vertex = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
+                 DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
+
+       if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
+               DRM_ERROR("buffer index %d (of %d max)\n",
+                         vertex->idx, dma->buf_count - 1);
+               return -EINVAL;
+       }
+       if (vertex->prim < 0 ||
+           vertex->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
+               DRM_ERROR("buffer prim %d\n", vertex->prim);
+               return -EINVAL;
+       }
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+       VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+       buf = dma->buflist[vertex->idx];
+       buf_priv = buf->dev_private;
+
+       if (buf->file_priv != file_priv) {
+               DRM_ERROR("process %d using buffer owned by %p\n",
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
+       }
+       if (buf->pending) {
+               DRM_ERROR("sending pending buffer %d\n", vertex->idx);
+               return -EINVAL;
+       }
+
+       buf->used = vertex->count;
+       buf_priv->prim = vertex->prim;
+       buf_priv->discard = vertex->discard;
+
+       r128_cce_dispatch_vertex(dev, buf);
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_r128_buf_priv_t *buf_priv;
+       drm_r128_indices_t *elts = data;
+       int count;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
+                 elts->idx, elts->start, elts->end, elts->discard);
+
+       if (elts->idx < 0 || elts->idx >= dma->buf_count) {
+               DRM_ERROR("buffer index %d (of %d max)\n",
+                         elts->idx, dma->buf_count - 1);
+               return -EINVAL;
+       }
+       if (elts->prim < 0 ||
+           elts->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
+               DRM_ERROR("buffer prim %d\n", elts->prim);
+               return -EINVAL;
+       }
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+       VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+       buf = dma->buflist[elts->idx];
+       buf_priv = buf->dev_private;
+
+       if (buf->file_priv != file_priv) {
+               DRM_ERROR("process %d using buffer owned by %p\n",
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
+       }
+       if (buf->pending) {
+               DRM_ERROR("sending pending buffer %d\n", elts->idx);
+               return -EINVAL;
+       }
+
+       count = (elts->end - elts->start) / sizeof(u16);
+       elts->start -= R128_INDEX_PRIM_OFFSET;
+
+       if (elts->start & 0x7) {
+               DRM_ERROR("misaligned buffer 0x%x\n", elts->start);
+               return -EINVAL;
+       }
+       if (elts->start < buf->used) {
+               DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);
+               return -EINVAL;
+       }
+
+       buf->used = elts->end;
+       buf_priv->prim = elts->prim;
+       buf_priv->discard = elts->discard;
+
+       r128_cce_dispatch_indices(dev, buf, elts->start, elts->end, count);
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_blit_t *blit = data;
+       int ret;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx);
+
+       if (blit->idx < 0 || blit->idx >= dma->buf_count) {
+               DRM_ERROR("buffer index %d (of %d max)\n",
+                         blit->idx, dma->buf_count - 1);
+               return -EINVAL;
+       }
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+       VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+       ret = r128_cce_dispatch_blit(dev, file_priv, blit);
+
+       COMMIT_RING();
+       return ret;
+}
+
+static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_depth_t *depth = data;
+       int ret;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+       ret = -EINVAL;
+       switch (depth->func) {
+       case R128_WRITE_SPAN:
+               ret = r128_cce_dispatch_write_span(dev, depth);
+               break;
+       case R128_WRITE_PIXELS:
+               ret = r128_cce_dispatch_write_pixels(dev, depth);
+               break;
+       case R128_READ_SPAN:
+               ret = r128_cce_dispatch_read_span(dev, depth);
+               break;
+       case R128_READ_PIXELS:
+               ret = r128_cce_dispatch_read_pixels(dev, depth);
+               break;
+       }
+
+       COMMIT_RING();
+       return ret;
+}
+
+static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_stipple_t *stipple = data;
+       u32 mask[32];
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
+               return -EFAULT;
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+       r128_cce_dispatch_stipple(dev, mask);
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_r128_buf_priv_t *buf_priv;
+       drm_r128_indirect_t *indirect = data;
+#if 0
+       RING_LOCALS;
+#endif
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
+                 indirect->idx, indirect->start, indirect->end,
+                 indirect->discard);
+
+       if (indirect->idx < 0 || indirect->idx >= dma->buf_count) {
+               DRM_ERROR("buffer index %d (of %d max)\n",
+                         indirect->idx, dma->buf_count - 1);
+               return -EINVAL;
+       }
+
+       buf = dma->buflist[indirect->idx];
+       buf_priv = buf->dev_private;
+
+       if (buf->file_priv != file_priv) {
+               DRM_ERROR("process %d using buffer owned by %p\n",
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
+       }
+       if (buf->pending) {
+               DRM_ERROR("sending pending buffer %d\n", indirect->idx);
+               return -EINVAL;
+       }
+
+       if (indirect->start < buf->used) {
+               DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
+                         indirect->start, buf->used);
+               return -EINVAL;
+       }
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+       VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+       buf->used = indirect->end;
+       buf_priv->discard = indirect->discard;
+
+#if 0
+       /* Wait for the 3D stream to idle before the indirect buffer
+        * containing 2D acceleration commands is processed.
+        */
+       BEGIN_RING(2);
+       RADEON_WAIT_UNTIL_3D_IDLE();
+       ADVANCE_RING();
+#endif
+
+       /* Dispatch the indirect buffer full of commands from the
+        * X server.  This is insecure and is thus only available to
+        * privileged clients.
+        */
+       r128_cce_dispatch_indirect(dev, buf, indirect->start, indirect->end);
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_r128_private_t *dev_priv = dev->dev_private;
+       drm_r128_getparam_t *param = data;
+       int value;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+       switch (param->param) {
+       case R128_PARAM_IRQ_NR:
+               value = dev->irq;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
+               DRM_ERROR("copy_to_user\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+void r128_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
+{
+       if (dev->dev_private) {
+               drm_r128_private_t *dev_priv = dev->dev_private;
+               if (dev_priv->page_flipping) {
+                       r128_do_cleanup_pageflip(dev);
+               }
+       }
+}
+
+void r128_driver_lastclose(struct drm_device * dev)
+{
+       r128_do_cleanup_cce(dev);
+}
+
+struct drm_ioctl_desc r128_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_R128_CCE_IDLE, r128_cce_idle, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_RESET, r128_engine_reset, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_FULLSCREEN, r128_fullscreen, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_SWAP, r128_cce_swap, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_FLIP, r128_cce_flip, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_CLEAR, r128_cce_clear, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_VERTEX, r128_cce_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_INDICES, r128_cce_indices, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_BLIT, r128_cce_blit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_DEPTH, r128_cce_depth, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_STIPPLE, r128_cce_stipple, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_R128_GETPARAM, r128_getparam, DRM_AUTH),
+};
+
+int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
new file mode 100644 (file)
index 0000000..feb521e
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o
+
+radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
+
+obj-$(CONFIG_DRM_RADEON)+= radeon.o
diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c
new file mode 100644 (file)
index 0000000..702df45
--- /dev/null
@@ -0,0 +1,1071 @@
+/* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*-
+ *
+ * Copyright (C) The Weather Channel, Inc.  2002.
+ * Copyright (C) 2004 Nicolai Haehnle.
+ * All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Nicolai Haehnle <prefect_@gmx.net>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+#include "r300_reg.h"
+
+#define R300_SIMULTANEOUS_CLIPRECTS            4
+
+/* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects
+ */
+static const int r300_cliprect_cntl[4] = {
+       0xAAAA,
+       0xEEEE,
+       0xFEFE,
+       0xFFFE
+};
+
+/**
+ * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
+ * buffer, starting with index n.
+ */
+static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
+                              drm_radeon_kcmd_buffer_t *cmdbuf, int n)
+{
+       struct drm_clip_rect box;
+       int nr;
+       int i;
+       RING_LOCALS;
+
+       nr = cmdbuf->nbox - n;
+       if (nr > R300_SIMULTANEOUS_CLIPRECTS)
+               nr = R300_SIMULTANEOUS_CLIPRECTS;
+
+       DRM_DEBUG("%i cliprects\n", nr);
+
+       if (nr) {
+               BEGIN_RING(6 + nr * 2);
+               OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1));
+
+               for (i = 0; i < nr; ++i) {
+                       if (DRM_COPY_FROM_USER_UNCHECKED
+                           (&box, &cmdbuf->boxes[n + i], sizeof(box))) {
+                               DRM_ERROR("copy cliprect faulted\n");
+                               return -EFAULT;
+                       }
+
+                       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
+                               box.x1 = (box.x1) &
+                                       R300_CLIPRECT_MASK;
+                               box.y1 = (box.y1) &
+                                       R300_CLIPRECT_MASK;
+                               box.x2 = (box.x2) &
+                                       R300_CLIPRECT_MASK;
+                               box.y2 = (box.y2) &
+                                       R300_CLIPRECT_MASK;
+                       } else {
+                               box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) &
+                                       R300_CLIPRECT_MASK;
+                               box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) &
+                                       R300_CLIPRECT_MASK;
+                               box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) &
+                                       R300_CLIPRECT_MASK;
+                               box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) &
+                                       R300_CLIPRECT_MASK;
+
+                       }
+                       OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
+                                (box.y1 << R300_CLIPRECT_Y_SHIFT));
+                       OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
+                                (box.y2 << R300_CLIPRECT_Y_SHIFT));
+
+               }
+
+               OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]);
+
+               /* TODO/SECURITY: Force scissors to a safe value, otherwise the
+                * client might be able to trample over memory.
+                * The impact should be very limited, but I'd rather be safe than
+                * sorry.
+                */
+               OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1));
+               OUT_RING(0);
+               OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK);
+               ADVANCE_RING();
+       } else {
+               /* Why we allow zero cliprect rendering:
+                * There are some commands in a command buffer that must be submitted
+                * even when there are no cliprects, e.g. DMA buffer discard
+                * or state setting (though state setting could be avoided by
+                * simulating a loss of context).
+                *
+                * Now since the cmdbuf interface is so chaotic right now (and is
+                * bound to remain that way for a bit until things settle down),
+                * it is basically impossible to filter out the commands that are
+                * necessary and those that aren't.
+                *
+                * So I choose the safe way and don't do any filtering at all;
+                * instead, I simply set up the engine so that all rendering
+                * can't produce any fragments.
+                */
+               BEGIN_RING(2);
+               OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0);
+               ADVANCE_RING();
+       }
+
+       return 0;
+}
+
+static u8 r300_reg_flags[0x10000 >> 2];
+
+void r300_init_reg_flags(struct drm_device *dev)
+{
+       int i;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+
+       memset(r300_reg_flags, 0, 0x10000 >> 2);
+#define ADD_RANGE_MARK(reg, count,mark) \
+               for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\
+                       r300_reg_flags[i]|=(mark);
+
+#define MARK_SAFE              1
+#define MARK_CHECK_OFFSET      2
+
+#define ADD_RANGE(reg, count)  ADD_RANGE_MARK(reg, count, MARK_SAFE)
+
+       /* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */
+       ADD_RANGE(R300_SE_VPORT_XSCALE, 6);
+       ADD_RANGE(R300_VAP_CNTL, 1);
+       ADD_RANGE(R300_SE_VTE_CNTL, 2);
+       ADD_RANGE(0x2134, 2);
+       ADD_RANGE(R300_VAP_CNTL_STATUS, 1);
+       ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2);
+       ADD_RANGE(0x21DC, 1);
+       ADD_RANGE(R300_VAP_UNKNOWN_221C, 1);
+       ADD_RANGE(R300_VAP_CLIP_X_0, 4);
+       ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1);
+       ADD_RANGE(R300_VAP_UNKNOWN_2288, 1);
+       ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2);
+       ADD_RANGE(R300_VAP_PVS_CNTL_1, 3);
+       ADD_RANGE(R300_GB_ENABLE, 1);
+       ADD_RANGE(R300_GB_MSPOS0, 5);
+       ADD_RANGE(R300_TX_CNTL, 1);
+       ADD_RANGE(R300_TX_ENABLE, 1);
+       ADD_RANGE(0x4200, 4);
+       ADD_RANGE(0x4214, 1);
+       ADD_RANGE(R300_RE_POINTSIZE, 1);
+       ADD_RANGE(0x4230, 3);
+       ADD_RANGE(R300_RE_LINE_CNT, 1);
+       ADD_RANGE(R300_RE_UNK4238, 1);
+       ADD_RANGE(0x4260, 3);
+       ADD_RANGE(R300_RE_SHADE, 4);
+       ADD_RANGE(R300_RE_POLYGON_MODE, 5);
+       ADD_RANGE(R300_RE_ZBIAS_CNTL, 1);
+       ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4);
+       ADD_RANGE(R300_RE_OCCLUSION_CNTL, 1);
+       ADD_RANGE(R300_RE_CULL_CNTL, 1);
+       ADD_RANGE(0x42C0, 2);
+       ADD_RANGE(R300_RS_CNTL_0, 2);
+
+       ADD_RANGE(R300_SC_HYPERZ, 2);
+       ADD_RANGE(0x43E8, 1);
+
+       ADD_RANGE(0x46A4, 5);
+
+       ADD_RANGE(R300_RE_FOG_STATE, 1);
+       ADD_RANGE(R300_FOG_COLOR_R, 3);
+       ADD_RANGE(R300_PP_ALPHA_TEST, 2);
+       ADD_RANGE(0x4BD8, 1);
+       ADD_RANGE(R300_PFS_PARAM_0_X, 64);
+       ADD_RANGE(0x4E00, 1);
+       ADD_RANGE(R300_RB3D_CBLEND, 2);
+       ADD_RANGE(R300_RB3D_COLORMASK, 1);
+       ADD_RANGE(R300_RB3D_BLEND_COLOR, 3);
+       ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET);   /* check offset */
+       ADD_RANGE(R300_RB3D_COLORPITCH0, 1);
+       ADD_RANGE(0x4E50, 9);
+       ADD_RANGE(0x4E88, 1);
+       ADD_RANGE(0x4EA0, 2);
+       ADD_RANGE(R300_ZB_CNTL, 3);
+       ADD_RANGE(R300_ZB_FORMAT, 4);
+       ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET);      /* check offset */
+       ADD_RANGE(R300_ZB_DEPTHPITCH, 1);
+       ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1);
+       ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13);
+
+       ADD_RANGE(R300_TX_FILTER_0, 16);
+       ADD_RANGE(R300_TX_FILTER1_0, 16);
+       ADD_RANGE(R300_TX_SIZE_0, 16);
+       ADD_RANGE(R300_TX_FORMAT_0, 16);
+       ADD_RANGE(R300_TX_PITCH_0, 16);
+       /* Texture offset is dangerous and needs more checking */
+       ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
+       ADD_RANGE(R300_TX_CHROMA_KEY_0, 16);
+       ADD_RANGE(R300_TX_BORDER_COLOR_0, 16);
+
+       /* Sporadic registers used as primitives are emitted */
+       ADD_RANGE(R300_ZB_ZCACHE_CTLSTAT, 1);
+       ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1);
+       ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8);
+       ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8);
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
+               ADD_RANGE(R500_VAP_INDEX_OFFSET, 1);
+               ADD_RANGE(R500_US_CONFIG, 2);
+               ADD_RANGE(R500_US_CODE_ADDR, 3);
+               ADD_RANGE(R500_US_FC_CTRL, 1);
+               ADD_RANGE(R500_RS_IP_0, 16);
+               ADD_RANGE(R500_RS_INST_0, 16);
+               ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2);
+               ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2);
+               ADD_RANGE(R500_ZB_FIFO_SIZE, 2);
+       } else {
+               ADD_RANGE(R300_PFS_CNTL_0, 3);
+               ADD_RANGE(R300_PFS_NODE_0, 4);
+               ADD_RANGE(R300_PFS_TEXI_0, 64);
+               ADD_RANGE(R300_PFS_INSTR0_0, 64);
+               ADD_RANGE(R300_PFS_INSTR1_0, 64);
+               ADD_RANGE(R300_PFS_INSTR2_0, 64);
+               ADD_RANGE(R300_PFS_INSTR3_0, 64);
+               ADD_RANGE(R300_RS_INTERP_0, 8);
+               ADD_RANGE(R300_RS_ROUTE_0, 8);
+
+       }
+}
+
+static __inline__ int r300_check_range(unsigned reg, int count)
+{
+       int i;
+       if (reg & ~0xffff)
+               return -1;
+       for (i = (reg >> 2); i < (reg >> 2) + count; i++)
+               if (r300_reg_flags[i] != MARK_SAFE)
+                       return 1;
+       return 0;
+}
+
+static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
+                                                         dev_priv,
+                                                         drm_radeon_kcmd_buffer_t
+                                                         * cmdbuf,
+                                                         drm_r300_cmd_header_t
+                                                         header)
+{
+       int reg;
+       int sz;
+       int i;
+       int values[64];
+       RING_LOCALS;
+
+       sz = header.packet0.count;
+       reg = (header.packet0.reghi << 8) | header.packet0.reglo;
+
+       if ((sz > 64) || (sz < 0)) {
+               DRM_ERROR
+                   ("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n",
+                    reg, sz);
+               return -EINVAL;
+       }
+       for (i = 0; i < sz; i++) {
+               values[i] = ((int *)cmdbuf->buf)[i];
+               switch (r300_reg_flags[(reg >> 2) + i]) {
+               case MARK_SAFE:
+                       break;
+               case MARK_CHECK_OFFSET:
+                       if (!radeon_check_offset(dev_priv, (u32) values[i])) {
+                               DRM_ERROR
+                                   ("Offset failed range check (reg=%04x sz=%d)\n",
+                                    reg, sz);
+                               return -EINVAL;
+                       }
+                       break;
+               default:
+                       DRM_ERROR("Register %04x failed check as flag=%02x\n",
+                                 reg + i * 4, r300_reg_flags[(reg >> 2) + i]);
+                       return -EINVAL;
+               }
+       }
+
+       BEGIN_RING(1 + sz);
+       OUT_RING(CP_PACKET0(reg, sz - 1));
+       OUT_RING_TABLE(values, sz);
+       ADVANCE_RING();
+
+       cmdbuf->buf += sz * 4;
+       cmdbuf->bufsz -= sz * 4;
+
+       return 0;
+}
+
+/**
+ * Emits a packet0 setting arbitrary registers.
+ * Called by r300_do_cp_cmdbuf.
+ *
+ * Note that checks are performed on contents and addresses of the registers
+ */
+static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
+                                       drm_radeon_kcmd_buffer_t *cmdbuf,
+                                       drm_r300_cmd_header_t header)
+{
+       int reg;
+       int sz;
+       RING_LOCALS;
+
+       sz = header.packet0.count;
+       reg = (header.packet0.reghi << 8) | header.packet0.reglo;
+
+       if (!sz)
+               return 0;
+
+       if (sz * 4 > cmdbuf->bufsz)
+               return -EINVAL;
+
+       if (reg + sz * 4 >= 0x10000) {
+               DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg,
+                         sz);
+               return -EINVAL;
+       }
+
+       if (r300_check_range(reg, sz)) {
+               /* go and check everything */
+               return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf,
+                                                          header);
+       }
+       /* the rest of the data is safe to emit, whatever the values the user passed */
+
+       BEGIN_RING(1 + sz);
+       OUT_RING(CP_PACKET0(reg, sz - 1));
+       OUT_RING_TABLE((int *)cmdbuf->buf, sz);
+       ADVANCE_RING();
+
+       cmdbuf->buf += sz * 4;
+       cmdbuf->bufsz -= sz * 4;
+
+       return 0;
+}
+
+/**
+ * Uploads user-supplied vertex program instructions or parameters onto
+ * the graphics card.
+ * Called by r300_do_cp_cmdbuf.
+ */
+static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
+                                   drm_radeon_kcmd_buffer_t *cmdbuf,
+                                   drm_r300_cmd_header_t header)
+{
+       int sz;
+       int addr;
+       RING_LOCALS;
+
+       sz = header.vpu.count;
+       addr = (header.vpu.adrhi << 8) | header.vpu.adrlo;
+
+       if (!sz)
+               return 0;
+       if (sz * 16 > cmdbuf->bufsz)
+               return -EINVAL;
+
+       BEGIN_RING(5 + sz * 4);
+       /* Wait for VAP to come to senses.. */
+       /* there is no need to emit it multiple times, (only once before VAP is programmed,
+          but this optimization is for later */
+       OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0);
+       OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr);
+       OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1));
+       OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4);
+
+       ADVANCE_RING();
+
+       cmdbuf->buf += sz * 16;
+       cmdbuf->bufsz -= sz * 16;
+
+       return 0;
+}
+
+/**
+ * Emit a clear packet from userspace.
+ * Called by r300_emit_packet3.
+ */
+static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
+                                     drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       RING_LOCALS;
+
+       if (8 * 4 > cmdbuf->bufsz)
+               return -EINVAL;
+
+       BEGIN_RING(10);
+       OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8));
+       OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
+                (1 << R300_PRIM_NUM_VERTICES_SHIFT));
+       OUT_RING_TABLE((int *)cmdbuf->buf, 8);
+       ADVANCE_RING();
+
+       cmdbuf->buf += 8 * 4;
+       cmdbuf->bufsz -= 8 * 4;
+
+       return 0;
+}
+
+static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
+                                              drm_radeon_kcmd_buffer_t *cmdbuf,
+                                              u32 header)
+{
+       int count, i, k;
+#define MAX_ARRAY_PACKET  64
+       u32 payload[MAX_ARRAY_PACKET];
+       u32 narrays;
+       RING_LOCALS;
+
+       count = (header >> 16) & 0x3fff;
+
+       if ((count + 1) > MAX_ARRAY_PACKET) {
+               DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
+                         count);
+               return -EINVAL;
+       }
+       memset(payload, 0, MAX_ARRAY_PACKET * 4);
+       memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4);
+
+       /* carefully check packet contents */
+
+       narrays = payload[0];
+       k = 0;
+       i = 1;
+       while ((k < narrays) && (i < (count + 1))) {
+               i++;            /* skip attribute field */
+               if (!radeon_check_offset(dev_priv, payload[i])) {
+                       DRM_ERROR
+                           ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
+                            k, i);
+                       return -EINVAL;
+               }
+               k++;
+               i++;
+               if (k == narrays)
+                       break;
+               /* have one more to process, they come in pairs */
+               if (!radeon_check_offset(dev_priv, payload[i])) {
+                       DRM_ERROR
+                           ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
+                            k, i);
+                       return -EINVAL;
+               }
+               k++;
+               i++;
+       }
+       /* do the counts match what we expect ? */
+       if ((k != narrays) || (i != (count + 1))) {
+               DRM_ERROR
+                   ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
+                    k, i, narrays, count + 1);
+               return -EINVAL;
+       }
+
+       /* all clear, output packet */
+
+       BEGIN_RING(count + 2);
+       OUT_RING(header);
+       OUT_RING_TABLE(payload, count + 1);
+       ADVANCE_RING();
+
+       cmdbuf->buf += (count + 2) * 4;
+       cmdbuf->bufsz -= (count + 2) * 4;
+
+       return 0;
+}
+
+static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
+                                            drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       u32 *cmd = (u32 *) cmdbuf->buf;
+       int count, ret;
+       RING_LOCALS;
+
+       count=(cmd[0]>>16) & 0x3fff;
+
+       if (cmd[0] & 0x8000) {
+               u32 offset;
+
+               if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+                             | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+                       offset = cmd[2] << 10;
+                       ret = !radeon_check_offset(dev_priv, offset);
+                       if (ret) {
+                               DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
+                               return -EINVAL;
+                       }
+               }
+
+               if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
+                   (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+                       offset = cmd[3] << 10;
+                       ret = !radeon_check_offset(dev_priv, offset);
+                       if (ret) {
+                               DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
+                               return -EINVAL;
+                       }
+
+               }
+       }
+
+       BEGIN_RING(count+2);
+       OUT_RING(cmd[0]);
+       OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
+       ADVANCE_RING();
+
+       cmdbuf->buf += (count+2)*4;
+       cmdbuf->bufsz -= (count+2)*4;
+
+       return 0;
+}
+
+static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
+                                            drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       u32 *cmd = (u32 *) cmdbuf->buf;
+       int count, ret;
+       RING_LOCALS;
+
+       count=(cmd[0]>>16) & 0x3fff;
+
+       if ((cmd[1] & 0x8000ffff) != 0x80000810) {
+               DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
+               return -EINVAL;
+       }
+       ret = !radeon_check_offset(dev_priv, cmd[2]);
+       if (ret) {
+               DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+               return -EINVAL;
+       }
+
+       BEGIN_RING(count+2);
+       OUT_RING(cmd[0]);
+       OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
+       ADVANCE_RING();
+
+       cmdbuf->buf += (count+2)*4;
+       cmdbuf->bufsz -= (count+2)*4;
+
+       return 0;
+}
+
+static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
+                                           drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       u32 header;
+       int count;
+       RING_LOCALS;
+
+       if (4 > cmdbuf->bufsz)
+               return -EINVAL;
+
+       /* Fixme !! This simply emits a packet without much checking.
+          We need to be smarter. */
+
+       /* obtain first word - actual packet3 header */
+       header = *(u32 *) cmdbuf->buf;
+
+       /* Is it packet 3 ? */
+       if ((header >> 30) != 0x3) {
+               DRM_ERROR("Not a packet3 header (0x%08x)\n", header);
+               return -EINVAL;
+       }
+
+       count = (header >> 16) & 0x3fff;
+
+       /* Check again now that we know how much data to expect */
+       if ((count + 2) * 4 > cmdbuf->bufsz) {
+               DRM_ERROR
+                   ("Expected packet3 of length %d but have only %d bytes left\n",
+                    (count + 2) * 4, cmdbuf->bufsz);
+               return -EINVAL;
+       }
+
+       /* Is it a packet type we know about ? */
+       switch (header & 0xff00) {
+       case RADEON_3D_LOAD_VBPNTR:     /* load vertex array pointers */
+               return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, header);
+
+       case RADEON_CNTL_BITBLT_MULTI:
+               return r300_emit_bitblt_multi(dev_priv, cmdbuf);
+
+       case RADEON_CP_INDX_BUFFER:     /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */
+               return r300_emit_indx_buffer(dev_priv, cmdbuf);
+       case RADEON_CP_3D_DRAW_IMMD_2:  /* triggers drawing using in-packet vertex data */
+       case RADEON_CP_3D_DRAW_VBUF_2:  /* triggers drawing of vertex buffers setup elsewhere */
+       case RADEON_CP_3D_DRAW_INDX_2:  /* triggers drawing using indices to vertex buffer */
+       case RADEON_WAIT_FOR_IDLE:
+       case RADEON_CP_NOP:
+               /* these packets are safe */
+               break;
+       default:
+               DRM_ERROR("Unknown packet3 header (0x%08x)\n", header);
+               return -EINVAL;
+       }
+
+       BEGIN_RING(count + 2);
+       OUT_RING(header);
+       OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1);
+       ADVANCE_RING();
+
+       cmdbuf->buf += (count + 2) * 4;
+       cmdbuf->bufsz -= (count + 2) * 4;
+
+       return 0;
+}
+
+/**
+ * Emit a rendering packet3 from userspace.
+ * Called by r300_do_cp_cmdbuf.
+ */
+static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
+                                       drm_radeon_kcmd_buffer_t *cmdbuf,
+                                       drm_r300_cmd_header_t header)
+{
+       int n;
+       int ret;
+       char *orig_buf = cmdbuf->buf;
+       int orig_bufsz = cmdbuf->bufsz;
+
+       /* This is a do-while-loop so that we run the interior at least once,
+        * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale.
+        */
+       n = 0;
+       do {
+               if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) {
+                       ret = r300_emit_cliprects(dev_priv, cmdbuf, n);
+                       if (ret)
+                               return ret;
+
+                       cmdbuf->buf = orig_buf;
+                       cmdbuf->bufsz = orig_bufsz;
+               }
+
+               switch (header.packet3.packet) {
+               case R300_CMD_PACKET3_CLEAR:
+                       DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n");
+                       ret = r300_emit_clear(dev_priv, cmdbuf);
+                       if (ret) {
+                               DRM_ERROR("r300_emit_clear failed\n");
+                               return ret;
+                       }
+                       break;
+
+               case R300_CMD_PACKET3_RAW:
+                       DRM_DEBUG("R300_CMD_PACKET3_RAW\n");
+                       ret = r300_emit_raw_packet3(dev_priv, cmdbuf);
+                       if (ret) {
+                               DRM_ERROR("r300_emit_raw_packet3 failed\n");
+                               return ret;
+                       }
+                       break;
+
+               default:
+                       DRM_ERROR("bad packet3 type %i at %p\n",
+                                 header.packet3.packet,
+                                 cmdbuf->buf - sizeof(header));
+                       return -EINVAL;
+               }
+
+               n += R300_SIMULTANEOUS_CLIPRECTS;
+       } while (n < cmdbuf->nbox);
+
+       return 0;
+}
+
+/* Some of the R300 chips seem to be extremely touchy about the two registers
+ * that are configured in r300_pacify.
+ * Among the worst offenders seems to be the R300 ND (0x4E44): When userspace
+ * sends a command buffer that contains only state setting commands and a
+ * vertex program/parameter upload sequence, this will eventually lead to a
+ * lockup, unless the sequence is bracketed by calls to r300_pacify.
+ * So we should take great care to *always* call r300_pacify before
+ * *anything* 3D related, and again afterwards. This is what the
+ * call bracket in r300_do_cp_cmdbuf is for.
+ */
+
+/**
+ * Emit the sequence to pacify R300.
+ */
+static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
+{
+       RING_LOCALS;
+
+       BEGIN_RING(6);
+       OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+       OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A);
+       OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));
+       OUT_RING(R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE|
+                R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
+       OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0));
+       OUT_RING(0x0);
+       ADVANCE_RING();
+}
+
+/**
+ * Called by r300_do_cp_cmdbuf to update the internal buffer age and state.
+ * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
+ * be careful about how this function is called.
+ */
+static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+
+       buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
+       buf->pending = 1;
+       buf->used = 0;
+}
+
+static void r300_cmd_wait(drm_radeon_private_t * dev_priv,
+                         drm_r300_cmd_header_t header)
+{
+       u32 wait_until;
+       RING_LOCALS;
+
+       if (!header.wait.flags)
+               return;
+
+       wait_until = 0;
+
+       switch(header.wait.flags) {
+       case R300_WAIT_2D:
+               wait_until = RADEON_WAIT_2D_IDLE;
+               break;
+       case R300_WAIT_3D:
+               wait_until = RADEON_WAIT_3D_IDLE;
+               break;
+       case R300_NEW_WAIT_2D_3D:
+               wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE;
+               break;
+       case R300_NEW_WAIT_2D_2D_CLEAN:
+               wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
+               break;
+       case R300_NEW_WAIT_3D_3D_CLEAN:
+               wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
+               break;
+       case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN:
+               wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
+               wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
+               break;
+       default:
+               return;
+       }
+
+       BEGIN_RING(2);
+       OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+       OUT_RING(wait_until);
+       ADVANCE_RING();
+}
+
+static int r300_scratch(drm_radeon_private_t *dev_priv,
+                       drm_radeon_kcmd_buffer_t *cmdbuf,
+                       drm_r300_cmd_header_t header)
+{
+       u32 *ref_age_base;
+       u32 i, buf_idx, h_pending;
+       RING_LOCALS;
+
+       if (cmdbuf->bufsz <
+           (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) {
+               return -EINVAL;
+       }
+
+       if (header.scratch.reg >= 5) {
+               return -EINVAL;
+       }
+
+       dev_priv->scratch_ages[header.scratch.reg]++;
+
+       ref_age_base =  (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf);
+
+       cmdbuf->buf += sizeof(u64);
+       cmdbuf->bufsz -= sizeof(u64);
+
+       for (i=0; i < header.scratch.n_bufs; i++) {
+               buf_idx = *(u32 *)cmdbuf->buf;
+               buf_idx *= 2; /* 8 bytes per buf */
+
+               if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) {
+                       return -EINVAL;
+               }
+
+               if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) {
+                       return -EINVAL;
+               }
+
+               if (h_pending == 0) {
+                       return -EINVAL;
+               }
+
+               h_pending--;
+
+               if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) {
+                       return -EINVAL;
+               }
+
+               cmdbuf->buf += sizeof(buf_idx);
+               cmdbuf->bufsz -= sizeof(buf_idx);
+       }
+
+       BEGIN_RING(2);
+       OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) );
+       OUT_RING( dev_priv->scratch_ages[header.scratch.reg] );
+       ADVANCE_RING();
+
+       return 0;
+}
+
+/**
+ * Uploads user-supplied vertex program instructions or parameters onto
+ * the graphics card.
+ * Called by r300_do_cp_cmdbuf.
+ */
+static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv,
+                                      drm_radeon_kcmd_buffer_t *cmdbuf,
+                                      drm_r300_cmd_header_t header)
+{
+       int sz;
+       int addr;
+       int type;
+       int clamp;
+       int stride;
+       RING_LOCALS;
+
+       sz = header.r500fp.count;
+       /* address is 9 bits 0 - 8, bit 1 of flags is part of address */
+       addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo;
+
+       type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE);
+       clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP);
+
+       addr |= (type << 16);
+       addr |= (clamp << 17);
+
+       stride = type ? 4 : 6;
+
+       DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type);
+       if (!sz)
+               return 0;
+       if (sz * stride * 4 > cmdbuf->bufsz)
+               return -EINVAL;
+
+       BEGIN_RING(3 + sz * stride);
+       OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr);
+       OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1));
+       OUT_RING_TABLE((int *)cmdbuf->buf, sz * stride);
+
+       ADVANCE_RING();
+
+       cmdbuf->buf += sz * stride * 4;
+       cmdbuf->bufsz -= sz * stride * 4;
+
+       return 0;
+}
+
+
+/**
+ * Parses and validates a user-supplied command buffer and emits appropriate
+ * commands on the DMA ring buffer.
+ * Called by the ioctl handler function radeon_cp_cmdbuf.
+ */
+int r300_do_cp_cmdbuf(struct drm_device *dev,
+                     struct drm_file *file_priv,
+                     drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf = NULL;
+       int emit_dispatch_age = 0;
+       int ret = 0;
+
+       DRM_DEBUG("\n");
+
+       /* See the comment above r300_emit_begin3d for why this call must be here,
+        * and what the cleanup gotos are for. */
+       r300_pacify(dev_priv);
+
+       if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) {
+               ret = r300_emit_cliprects(dev_priv, cmdbuf, 0);
+               if (ret)
+                       goto cleanup;
+       }
+
+       while (cmdbuf->bufsz >= sizeof(drm_r300_cmd_header_t)) {
+               int idx;
+               drm_r300_cmd_header_t header;
+
+               header.u = *(unsigned int *)cmdbuf->buf;
+
+               cmdbuf->buf += sizeof(header);
+               cmdbuf->bufsz -= sizeof(header);
+
+               switch (header.header.cmd_type) {
+               case R300_CMD_PACKET0:
+                       DRM_DEBUG("R300_CMD_PACKET0\n");
+                       ret = r300_emit_packet0(dev_priv, cmdbuf, header);
+                       if (ret) {
+                               DRM_ERROR("r300_emit_packet0 failed\n");
+                               goto cleanup;
+                       }
+                       break;
+
+               case R300_CMD_VPU:
+                       DRM_DEBUG("R300_CMD_VPU\n");
+                       ret = r300_emit_vpu(dev_priv, cmdbuf, header);
+                       if (ret) {
+                               DRM_ERROR("r300_emit_vpu failed\n");
+                               goto cleanup;
+                       }
+                       break;
+
+               case R300_CMD_PACKET3:
+                       DRM_DEBUG("R300_CMD_PACKET3\n");
+                       ret = r300_emit_packet3(dev_priv, cmdbuf, header);
+                       if (ret) {
+                               DRM_ERROR("r300_emit_packet3 failed\n");
+                               goto cleanup;
+                       }
+                       break;
+
+               case R300_CMD_END3D:
+                       DRM_DEBUG("R300_CMD_END3D\n");
+                       /* TODO:
+                          Ideally userspace driver should not need to issue this call,
+                          i.e. the drm driver should issue it automatically and prevent
+                          lockups.
+
+                          In practice, we do not understand why this call is needed and what
+                          it does (except for some vague guesses that it has to do with cache
+                          coherence) and so the user space driver does it.
+
+                          Once we are sure which uses prevent lockups the code could be moved
+                          into the kernel and the userspace driver will not
+                          need to use this command.
+
+                          Note that issuing this command does not hurt anything
+                          except, possibly, performance */
+                       r300_pacify(dev_priv);
+                       break;
+
+               case R300_CMD_CP_DELAY:
+                       /* simple enough, we can do it here */
+                       DRM_DEBUG("R300_CMD_CP_DELAY\n");
+                       {
+                               int i;
+                               RING_LOCALS;
+
+                               BEGIN_RING(header.delay.count);
+                               for (i = 0; i < header.delay.count; i++)
+                                       OUT_RING(RADEON_CP_PACKET2);
+                               ADVANCE_RING();
+                       }
+                       break;
+
+               case R300_CMD_DMA_DISCARD:
+                       DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
+                       idx = header.dma.buf_idx;
+                       if (idx < 0 || idx >= dma->buf_count) {
+                               DRM_ERROR("buffer index %d (of %d max)\n",
+                                         idx, dma->buf_count - 1);
+                               ret = -EINVAL;
+                               goto cleanup;
+                       }
+
+                       buf = dma->buflist[idx];
+                       if (buf->file_priv != file_priv || buf->pending) {
+                               DRM_ERROR("bad buffer %p %p %d\n",
+                                         buf->file_priv, file_priv,
+                                         buf->pending);
+                               ret = -EINVAL;
+                               goto cleanup;
+                       }
+
+                       emit_dispatch_age = 1;
+                       r300_discard_buffer(dev, buf);
+                       break;
+
+               case R300_CMD_WAIT:
+                       DRM_DEBUG("R300_CMD_WAIT\n");
+                       r300_cmd_wait(dev_priv, header);
+                       break;
+
+               case R300_CMD_SCRATCH:
+                       DRM_DEBUG("R300_CMD_SCRATCH\n");
+                       ret = r300_scratch(dev_priv, cmdbuf, header);
+                       if (ret) {
+                               DRM_ERROR("r300_scratch failed\n");
+                               goto cleanup;
+                       }
+                       break;
+
+               case R300_CMD_R500FP:
+                       if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) {
+                               DRM_ERROR("Calling r500 command on r300 card\n");
+                               ret = -EINVAL;
+                               goto cleanup;
+                       }
+                       DRM_DEBUG("R300_CMD_R500FP\n");
+                       ret = r300_emit_r500fp(dev_priv, cmdbuf, header);
+                       if (ret) {
+                               DRM_ERROR("r300_emit_r500fp failed\n");
+                               goto cleanup;
+                       }
+                       break;
+               default:
+                       DRM_ERROR("bad cmd_type %i at %p\n",
+                                 header.header.cmd_type,
+                                 cmdbuf->buf - sizeof(header));
+                       ret = -EINVAL;
+                       goto cleanup;
+               }
+       }
+
+       DRM_DEBUG("END\n");
+
+      cleanup:
+       r300_pacify(dev_priv);
+
+       /* We emit the vertex buffer age here, outside the pacifier "brackets"
+        * for two reasons:
+        *  (1) This may coalesce multiple age emissions into a single one and
+        *  (2) more importantly, some chips lock up hard when scratch registers
+        *      are written inside the pacifier bracket.
+        */
+       if (emit_dispatch_age) {
+               RING_LOCALS;
+
+               /* Emit the vertex buffer age */
+               BEGIN_RING(2);
+               RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch);
+               ADVANCE_RING();
+       }
+
+       COMMIT_RING();
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/radeon/r300_reg.h b/drivers/gpu/drm/radeon/r300_reg.h
new file mode 100644 (file)
index 0000000..a6802f2
--- /dev/null
@@ -0,0 +1,1772 @@
+/**************************************************************************
+
+Copyright (C) 2004-2005 Nicolai Haehnle et al.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef _R300_REG_H
+#define _R300_REG_H
+
+#define R300_MC_INIT_MISC_LAT_TIMER    0x180
+#      define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT      0
+#      define R300_MC_MISC__MC_VF_INIT_LAT_SHIFT       4
+#      define R300_MC_MISC__MC_DISP0R_INIT_LAT_SHIFT   8
+#      define R300_MC_MISC__MC_DISP1R_INIT_LAT_SHIFT   12
+#      define R300_MC_MISC__MC_FIXED_INIT_LAT_SHIFT    16
+#      define R300_MC_MISC__MC_E2R_INIT_LAT_SHIFT      20
+#      define R300_MC_MISC__MC_SAME_PAGE_PRIO_SHIFT    24
+#      define R300_MC_MISC__MC_GLOBW_INIT_LAT_SHIFT    28
+
+#define R300_MC_INIT_GFX_LAT_TIMER     0x154
+#      define R300_MC_MISC__MC_G3D0R_INIT_LAT_SHIFT    0
+#      define R300_MC_MISC__MC_G3D1R_INIT_LAT_SHIFT    4
+#      define R300_MC_MISC__MC_G3D2R_INIT_LAT_SHIFT    8
+#      define R300_MC_MISC__MC_G3D3R_INIT_LAT_SHIFT    12
+#      define R300_MC_MISC__MC_TX0R_INIT_LAT_SHIFT     16
+#      define R300_MC_MISC__MC_TX1R_INIT_LAT_SHIFT     20
+#      define R300_MC_MISC__MC_GLOBR_INIT_LAT_SHIFT    24
+#      define R300_MC_MISC__MC_GLOBW_FULL_LAT_SHIFT    28
+
+/*
+ * This file contains registers and constants for the R300. They have been
+ * found mostly by examining command buffers captured using glxtest, as well
+ * as by extrapolating some known registers and constants from the R200.
+ * I am fairly certain that they are correct unless stated otherwise
+ * in comments.
+ */
+
+#define R300_SE_VPORT_XSCALE                0x1D98
+#define R300_SE_VPORT_XOFFSET               0x1D9C
+#define R300_SE_VPORT_YSCALE                0x1DA0
+#define R300_SE_VPORT_YOFFSET               0x1DA4
+#define R300_SE_VPORT_ZSCALE                0x1DA8
+#define R300_SE_VPORT_ZOFFSET               0x1DAC
+
+
+/*
+ * Vertex Array Processing (VAP) Control
+ * Stolen from r200 code from Christoph Brill (It's a guess!)
+ */
+#define R300_VAP_CNTL  0x2080
+
+/* This register is written directly and also starts data section
+ * in many 3d CP_PACKET3's
+ */
+#define R300_VAP_VF_CNTL       0x2084
+#      define  R300_VAP_VF_CNTL__PRIM_TYPE__SHIFT              0
+#      define  R300_VAP_VF_CNTL__PRIM_NONE                     (0<<0)
+#      define  R300_VAP_VF_CNTL__PRIM_POINTS                   (1<<0)
+#      define  R300_VAP_VF_CNTL__PRIM_LINES                    (2<<0)
+#      define  R300_VAP_VF_CNTL__PRIM_LINE_STRIP               (3<<0)
+#      define  R300_VAP_VF_CNTL__PRIM_TRIANGLES                (4<<0)
+#      define  R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN             (5<<0)
+#      define  R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP           (6<<0)
+#      define  R300_VAP_VF_CNTL__PRIM_LINE_LOOP                (12<<0)
+#      define  R300_VAP_VF_CNTL__PRIM_QUADS                    (13<<0)
+#      define  R300_VAP_VF_CNTL__PRIM_QUAD_STRIP               (14<<0)
+#      define  R300_VAP_VF_CNTL__PRIM_POLYGON                  (15<<0)
+
+#      define  R300_VAP_VF_CNTL__PRIM_WALK__SHIFT              4
+       /* State based - direct writes to registers trigger vertex
+           generation */
+#      define  R300_VAP_VF_CNTL__PRIM_WALK_STATE_BASED         (0<<4)
+#      define  R300_VAP_VF_CNTL__PRIM_WALK_INDICES             (1<<4)
+#      define  R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST         (2<<4)
+#      define  R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED     (3<<4)
+
+       /* I don't think I saw these three used.. */
+#      define  R300_VAP_VF_CNTL__COLOR_ORDER__SHIFT            6
+#      define  R300_VAP_VF_CNTL__TCL_OUTPUT_CTL_ENA__SHIFT     9
+#      define  R300_VAP_VF_CNTL__PROG_STREAM_ENA__SHIFT        10
+
+       /* index size - when not set the indices are assumed to be 16 bit */
+#      define  R300_VAP_VF_CNTL__INDEX_SIZE_32bit              (1<<11)
+       /* number of vertices */
+#      define  R300_VAP_VF_CNTL__NUM_VERTICES__SHIFT           16
+
+/* BEGIN: Wild guesses */
+#define R300_VAP_OUTPUT_VTX_FMT_0           0x2090
+#       define R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT     (1<<0)
+#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT   (1<<1)
+#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT (1<<2)  /* GUESS */
+#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT (1<<3)  /* GUESS */
+#       define R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT (1<<4)  /* GUESS */
+#       define R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT (1<<16) /* GUESS */
+
+#define R300_VAP_OUTPUT_VTX_FMT_1           0x2094
+       /* each of the following is 3 bits wide, specifies number
+          of components */
+#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT 0
+#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT 3
+#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT 6
+#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT 9
+#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT 12
+#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT 15
+#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT 18
+#       define R300_VAP_OUTPUT_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT 21
+/* END: Wild guesses */
+
+#define R300_SE_VTE_CNTL                  0x20b0
+#      define     R300_VPORT_X_SCALE_ENA                0x00000001
+#      define     R300_VPORT_X_OFFSET_ENA               0x00000002
+#      define     R300_VPORT_Y_SCALE_ENA                0x00000004
+#      define     R300_VPORT_Y_OFFSET_ENA               0x00000008
+#      define     R300_VPORT_Z_SCALE_ENA                0x00000010
+#      define     R300_VPORT_Z_OFFSET_ENA               0x00000020
+#      define     R300_VTX_XY_FMT                       0x00000100
+#      define     R300_VTX_Z_FMT                        0x00000200
+#      define     R300_VTX_W0_FMT                       0x00000400
+#      define     R300_VTX_W0_NORMALIZE                 0x00000800
+#      define     R300_VTX_ST_DENORMALIZED              0x00001000
+
+/* BEGIN: Vertex data assembly - lots of uncertainties */
+
+/* gap */
+
+#define R300_VAP_CNTL_STATUS              0x2140
+#      define R300_VC_NO_SWAP                  (0 << 0)
+#      define R300_VC_16BIT_SWAP               (1 << 0)
+#      define R300_VC_32BIT_SWAP               (2 << 0)
+#      define R300_VAP_TCL_BYPASS              (1 << 8)
+
+/* gap */
+
+/* Where do we get our vertex data?
+ *
+ * Vertex data either comes either from immediate mode registers or from
+ * vertex arrays.
+ * There appears to be no mixed mode (though we can force the pitch of
+ * vertex arrays to 0, effectively reusing the same element over and over
+ * again).
+ *
+ * Immediate mode is controlled by the INPUT_CNTL registers. I am not sure
+ * if these registers influence vertex array processing.
+ *
+ * Vertex arrays are controlled via the 3D_LOAD_VBPNTR packet3.
+ *
+ * In both cases, vertex attributes are then passed through INPUT_ROUTE.
+ *
+ * Beginning with INPUT_ROUTE_0_0 is a list of WORDs that route vertex data
+ * into the vertex processor's input registers.
+ * The first word routes the first input, the second word the second, etc.
+ * The corresponding input is routed into the register with the given index.
+ * The list is ended by a word with INPUT_ROUTE_END set.
+ *
+ * Always set COMPONENTS_4 in immediate mode.
+ */
+
+#define R300_VAP_INPUT_ROUTE_0_0            0x2150
+#       define R300_INPUT_ROUTE_COMPONENTS_1     (0 << 0)
+#       define R300_INPUT_ROUTE_COMPONENTS_2     (1 << 0)
+#       define R300_INPUT_ROUTE_COMPONENTS_3     (2 << 0)
+#       define R300_INPUT_ROUTE_COMPONENTS_4     (3 << 0)
+#       define R300_INPUT_ROUTE_COMPONENTS_RGBA  (4 << 0) /* GUESS */
+#       define R300_VAP_INPUT_ROUTE_IDX_SHIFT    8
+#       define R300_VAP_INPUT_ROUTE_IDX_MASK     (31 << 8) /* GUESS */
+#       define R300_VAP_INPUT_ROUTE_END          (1 << 13)
+#       define R300_INPUT_ROUTE_IMMEDIATE_MODE   (0 << 14) /* GUESS */
+#       define R300_INPUT_ROUTE_FLOAT            (1 << 14) /* GUESS */
+#       define R300_INPUT_ROUTE_UNSIGNED_BYTE    (2 << 14) /* GUESS */
+#       define R300_INPUT_ROUTE_FLOAT_COLOR      (3 << 14) /* GUESS */
+#define R300_VAP_INPUT_ROUTE_0_1            0x2154
+#define R300_VAP_INPUT_ROUTE_0_2            0x2158
+#define R300_VAP_INPUT_ROUTE_0_3            0x215C
+#define R300_VAP_INPUT_ROUTE_0_4            0x2160
+#define R300_VAP_INPUT_ROUTE_0_5            0x2164
+#define R300_VAP_INPUT_ROUTE_0_6            0x2168
+#define R300_VAP_INPUT_ROUTE_0_7            0x216C
+
+/* gap */
+
+/* Notes:
+ *  - always set up to produce at least two attributes:
+ *    if vertex program uses only position, fglrx will set normal, too
+ *  - INPUT_CNTL_0_COLOR and INPUT_CNTL_COLOR bits are always equal.
+ */
+#define R300_VAP_INPUT_CNTL_0               0x2180
+#       define R300_INPUT_CNTL_0_COLOR           0x00000001
+#define R300_VAP_INPUT_CNTL_1               0x2184
+#       define R300_INPUT_CNTL_POS               0x00000001
+#       define R300_INPUT_CNTL_NORMAL            0x00000002
+#       define R300_INPUT_CNTL_COLOR             0x00000004
+#       define R300_INPUT_CNTL_TC0               0x00000400
+#       define R300_INPUT_CNTL_TC1               0x00000800
+#       define R300_INPUT_CNTL_TC2               0x00001000 /* GUESS */
+#       define R300_INPUT_CNTL_TC3               0x00002000 /* GUESS */
+#       define R300_INPUT_CNTL_TC4               0x00004000 /* GUESS */
+#       define R300_INPUT_CNTL_TC5               0x00008000 /* GUESS */
+#       define R300_INPUT_CNTL_TC6               0x00010000 /* GUESS */
+#       define R300_INPUT_CNTL_TC7               0x00020000 /* GUESS */
+
+/* gap */
+
+/* Words parallel to INPUT_ROUTE_0; All words that are active in INPUT_ROUTE_0
+ * are set to a swizzling bit pattern, other words are 0.
+ *
+ * In immediate mode, the pattern is always set to xyzw. In vertex array
+ * mode, the swizzling pattern is e.g. used to set zw components in texture
+ * coordinates with only tweo components.
+ */
+#define R300_VAP_INPUT_ROUTE_1_0            0x21E0
+#       define R300_INPUT_ROUTE_SELECT_X    0
+#       define R300_INPUT_ROUTE_SELECT_Y    1
+#       define R300_INPUT_ROUTE_SELECT_Z    2
+#       define R300_INPUT_ROUTE_SELECT_W    3
+#       define R300_INPUT_ROUTE_SELECT_ZERO 4
+#       define R300_INPUT_ROUTE_SELECT_ONE  5
+#       define R300_INPUT_ROUTE_SELECT_MASK 7
+#       define R300_INPUT_ROUTE_X_SHIFT     0
+#       define R300_INPUT_ROUTE_Y_SHIFT     3
+#       define R300_INPUT_ROUTE_Z_SHIFT     6
+#       define R300_INPUT_ROUTE_W_SHIFT     9
+#       define R300_INPUT_ROUTE_ENABLE      (15 << 12)
+#define R300_VAP_INPUT_ROUTE_1_1            0x21E4
+#define R300_VAP_INPUT_ROUTE_1_2            0x21E8
+#define R300_VAP_INPUT_ROUTE_1_3            0x21EC
+#define R300_VAP_INPUT_ROUTE_1_4            0x21F0
+#define R300_VAP_INPUT_ROUTE_1_5            0x21F4
+#define R300_VAP_INPUT_ROUTE_1_6            0x21F8
+#define R300_VAP_INPUT_ROUTE_1_7            0x21FC
+
+/* END: Vertex data assembly */
+
+/* gap */
+
+/* BEGIN: Upload vertex program and data */
+
+/*
+ * The programmable vertex shader unit has a memory bank of unknown size
+ * that can be written to in 16 byte units by writing the address into
+ * UPLOAD_ADDRESS, followed by data in UPLOAD_DATA (multiples of 4 DWORDs).
+ *
+ * Pointers into the memory bank are always in multiples of 16 bytes.
+ *
+ * The memory bank is divided into areas with fixed meaning.
+ *
+ * Starting at address UPLOAD_PROGRAM: Vertex program instructions.
+ * Native limits reported by drivers from ATI suggest size 256 (i.e. 4KB),
+ * whereas the difference between known addresses suggests size 512.
+ *
+ * Starting at address UPLOAD_PARAMETERS: Vertex program parameters.
+ * Native reported limits and the VPI layout suggest size 256, whereas
+ * difference between known addresses suggests size 512.
+ *
+ * At address UPLOAD_POINTSIZE is a vector (0, 0, ps, 0), where ps is the
+ * floating point pointsize. The exact purpose of this state is uncertain,
+ * as there is also the R300_RE_POINTSIZE register.
+ *
+ * Multiple vertex programs and parameter sets can be loaded at once,
+ * which could explain the size discrepancy.
+ */
+#define R300_VAP_PVS_UPLOAD_ADDRESS         0x2200
+#       define R300_PVS_UPLOAD_PROGRAM           0x00000000
+#       define R300_PVS_UPLOAD_PARAMETERS        0x00000200
+#       define R300_PVS_UPLOAD_POINTSIZE         0x00000406
+
+/* gap */
+
+#define R300_VAP_PVS_UPLOAD_DATA            0x2208
+
+/* END: Upload vertex program and data */
+
+/* gap */
+
+/* I do not know the purpose of this register. However, I do know that
+ * it is set to 221C_CLEAR for clear operations and to 221C_NORMAL
+ * for normal rendering.
+ */
+#define R300_VAP_UNKNOWN_221C               0x221C
+#       define R300_221C_NORMAL                  0x00000000
+#       define R300_221C_CLEAR                   0x0001C000
+
+/* These seem to be per-pixel and per-vertex X and Y clipping planes. The first
+ * plane is per-pixel and the second plane is per-vertex.
+ *
+ * This was determined by experimentation alone but I believe it is correct.
+ *
+ * These registers are called X_QUAD0_1_FL to X_QUAD0_4_FL by glxtest.
+ */
+#define R300_VAP_CLIP_X_0                   0x2220
+#define R300_VAP_CLIP_X_1                   0x2224
+#define R300_VAP_CLIP_Y_0                   0x2228
+#define R300_VAP_CLIP_Y_1                   0x2230
+
+/* gap */
+
+/* Sometimes, END_OF_PKT and 0x2284=0 are the only commands sent between
+ * rendering commands and overwriting vertex program parameters.
+ * Therefore, I suspect writing zero to 0x2284 synchronizes the engine and
+ * avoids bugs caused by still running shaders reading bad data from memory.
+ */
+#define R300_VAP_PVS_WAITIDLE               0x2284 /* GUESS */
+
+/* Absolutely no clue what this register is about. */
+#define R300_VAP_UNKNOWN_2288               0x2288
+#       define R300_2288_R300                    0x00750000 /* -- nh */
+#       define R300_2288_RV350                   0x0000FFFF /* -- Vladimir */
+
+/* gap */
+
+/* Addresses are relative to the vertex program instruction area of the
+ * memory bank. PROGRAM_END points to the last instruction of the active
+ * program
+ *
+ * The meaning of the two UNKNOWN fields is obviously not known. However,
+ * experiments so far have shown that both *must* point to an instruction
+ * inside the vertex program, otherwise the GPU locks up.
+ *
+ * fglrx usually sets CNTL_3_UNKNOWN to the end of the program and
+ * R300_PVS_CNTL_1_POS_END_SHIFT points to instruction where last write to
+ * position takes place.
+ *
+ * Most likely this is used to ignore rest of the program in cases
+ * where group of verts arent visible. For some reason this "section"
+ * is sometimes accepted other instruction that have no relationship with
+ * position calculations.
+ */
+#define R300_VAP_PVS_CNTL_1                 0x22D0
+#       define R300_PVS_CNTL_1_PROGRAM_START_SHIFT   0
+#       define R300_PVS_CNTL_1_POS_END_SHIFT         10
+#       define R300_PVS_CNTL_1_PROGRAM_END_SHIFT     20
+/* Addresses are relative the the vertex program parameters area. */
+#define R300_VAP_PVS_CNTL_2                 0x22D4
+#       define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0
+#       define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT  16
+#define R300_VAP_PVS_CNTL_3               0x22D8
+#       define R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT 10
+#       define R300_PVS_CNTL_3_PROGRAM_UNKNOWN2_SHIFT 0
+
+/* The entire range from 0x2300 to 0x2AC inclusive seems to be used for
+ * immediate vertices
+ */
+#define R300_VAP_VTX_COLOR_R                0x2464
+#define R300_VAP_VTX_COLOR_G                0x2468
+#define R300_VAP_VTX_COLOR_B                0x246C
+#define R300_VAP_VTX_POS_0_X_1              0x2490 /* used for glVertex2*() */
+#define R300_VAP_VTX_POS_0_Y_1              0x2494
+#define R300_VAP_VTX_COLOR_PKD              0x249C /* RGBA */
+#define R300_VAP_VTX_POS_0_X_2              0x24A0 /* used for glVertex3*() */
+#define R300_VAP_VTX_POS_0_Y_2              0x24A4
+#define R300_VAP_VTX_POS_0_Z_2              0x24A8
+/* write 0 to indicate end of packet? */
+#define R300_VAP_VTX_END_OF_PKT             0x24AC
+
+/* gap */
+
+/* These are values from r300_reg/r300_reg.h - they are known to be correct
+ * and are here so we can use one register file instead of several
+ * - Vladimir
+ */
+#define R300_GB_VAP_RASTER_VTX_FMT_0   0x4000
+#      define R300_GB_VAP_RASTER_VTX_FMT_0__POS_PRESENT        (1<<0)
+#      define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_0_PRESENT    (1<<1)
+#      define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_1_PRESENT    (1<<2)
+#      define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_2_PRESENT    (1<<3)
+#      define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_3_PRESENT    (1<<4)
+#      define R300_GB_VAP_RASTER_VTX_FMT_0__COLOR_SPACE        (0xf<<5)
+#      define R300_GB_VAP_RASTER_VTX_FMT_0__PT_SIZE_PRESENT    (0x1<<16)
+
+#define R300_GB_VAP_RASTER_VTX_FMT_1   0x4004
+       /* each of the following is 3 bits wide, specifies number
+          of components */
+#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_0_COMP_CNT_SHIFT       0
+#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_1_COMP_CNT_SHIFT       3
+#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_2_COMP_CNT_SHIFT       6
+#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_3_COMP_CNT_SHIFT       9
+#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_4_COMP_CNT_SHIFT       12
+#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_5_COMP_CNT_SHIFT       15
+#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_6_COMP_CNT_SHIFT       18
+#      define R300_GB_VAP_RASTER_VTX_FMT_1__TEX_7_COMP_CNT_SHIFT       21
+
+/* UNK30 seems to enables point to quad transformation on textures
+ * (or something closely related to that).
+ * This bit is rather fatal at the time being due to lackings at pixel
+ * shader side
+ */
+#define R300_GB_ENABLE 0x4008
+#      define R300_GB_POINT_STUFF_ENABLE       (1<<0)
+#      define R300_GB_LINE_STUFF_ENABLE        (1<<1)
+#      define R300_GB_TRIANGLE_STUFF_ENABLE    (1<<2)
+#      define R300_GB_STENCIL_AUTO_ENABLE      (1<<4)
+#      define R300_GB_UNK31                    (1<<31)
+       /* each of the following is 2 bits wide */
+#define R300_GB_TEX_REPLICATE  0
+#define R300_GB_TEX_ST         1
+#define R300_GB_TEX_STR                2
+#      define R300_GB_TEX0_SOURCE_SHIFT        16
+#      define R300_GB_TEX1_SOURCE_SHIFT        18
+#      define R300_GB_TEX2_SOURCE_SHIFT        20
+#      define R300_GB_TEX3_SOURCE_SHIFT        22
+#      define R300_GB_TEX4_SOURCE_SHIFT        24
+#      define R300_GB_TEX5_SOURCE_SHIFT        26
+#      define R300_GB_TEX6_SOURCE_SHIFT        28
+#      define R300_GB_TEX7_SOURCE_SHIFT        30
+
+/* MSPOS - positions for multisample antialiasing (?) */
+#define R300_GB_MSPOS0 0x4010
+       /* shifts - each of the fields is 4 bits */
+#      define R300_GB_MSPOS0__MS_X0_SHIFT      0
+#      define R300_GB_MSPOS0__MS_Y0_SHIFT      4
+#      define R300_GB_MSPOS0__MS_X1_SHIFT      8
+#      define R300_GB_MSPOS0__MS_Y1_SHIFT      12
+#      define R300_GB_MSPOS0__MS_X2_SHIFT      16
+#      define R300_GB_MSPOS0__MS_Y2_SHIFT      20
+#      define R300_GB_MSPOS0__MSBD0_Y          24
+#      define R300_GB_MSPOS0__MSBD0_X          28
+
+#define R300_GB_MSPOS1 0x4014
+#      define R300_GB_MSPOS1__MS_X3_SHIFT      0
+#      define R300_GB_MSPOS1__MS_Y3_SHIFT      4
+#      define R300_GB_MSPOS1__MS_X4_SHIFT      8
+#      define R300_GB_MSPOS1__MS_Y4_SHIFT      12
+#      define R300_GB_MSPOS1__MS_X5_SHIFT      16
+#      define R300_GB_MSPOS1__MS_Y5_SHIFT      20
+#      define R300_GB_MSPOS1__MSBD1            24
+
+
+#define R300_GB_TILE_CONFIG    0x4018
+#      define R300_GB_TILE_ENABLE      (1<<0)
+#      define R300_GB_TILE_PIPE_COUNT_RV300    0
+#      define R300_GB_TILE_PIPE_COUNT_R300     (3<<1)
+#      define R300_GB_TILE_PIPE_COUNT_R420     (7<<1)
+#      define R300_GB_TILE_PIPE_COUNT_RV410    (3<<1)
+#      define R300_GB_TILE_SIZE_8              0
+#      define R300_GB_TILE_SIZE_16             (1<<4)
+#      define R300_GB_TILE_SIZE_32             (2<<4)
+#      define R300_GB_SUPER_SIZE_1             (0<<6)
+#      define R300_GB_SUPER_SIZE_2             (1<<6)
+#      define R300_GB_SUPER_SIZE_4             (2<<6)
+#      define R300_GB_SUPER_SIZE_8             (3<<6)
+#      define R300_GB_SUPER_SIZE_16            (4<<6)
+#      define R300_GB_SUPER_SIZE_32            (5<<6)
+#      define R300_GB_SUPER_SIZE_64            (6<<6)
+#      define R300_GB_SUPER_SIZE_128           (7<<6)
+#      define R300_GB_SUPER_X_SHIFT            9       /* 3 bits wide */
+#      define R300_GB_SUPER_Y_SHIFT            12      /* 3 bits wide */
+#      define R300_GB_SUPER_TILE_A             0
+#      define R300_GB_SUPER_TILE_B             (1<<15)
+#      define R300_GB_SUBPIXEL_1_12            0
+#      define R300_GB_SUBPIXEL_1_16            (1<<16)
+
+#define R300_GB_FIFO_SIZE      0x4024
+       /* each of the following is 2 bits wide */
+#define R300_GB_FIFO_SIZE_32   0
+#define R300_GB_FIFO_SIZE_64   1
+#define R300_GB_FIFO_SIZE_128  2
+#define R300_GB_FIFO_SIZE_256  3
+#      define R300_SC_IFIFO_SIZE_SHIFT 0
+#      define R300_SC_TZFIFO_SIZE_SHIFT        2
+#      define R300_SC_BFIFO_SIZE_SHIFT 4
+
+#      define R300_US_OFIFO_SIZE_SHIFT 12
+#      define R300_US_WFIFO_SIZE_SHIFT 14
+       /* the following use the same constants as above, but meaning is
+          is times 2 (i.e. instead of 32 words it means 64 */
+#      define R300_RS_TFIFO_SIZE_SHIFT 6
+#      define R300_RS_CFIFO_SIZE_SHIFT 8
+#      define R300_US_RAM_SIZE_SHIFT           10
+       /* watermarks, 3 bits wide */
+#      define R300_RS_HIGHWATER_COL_SHIFT      16
+#      define R300_RS_HIGHWATER_TEX_SHIFT      19
+#      define R300_OFIFO_HIGHWATER_SHIFT       22      /* two bits only */
+#      define R300_CUBE_FIFO_HIGHWATER_COL_SHIFT       24
+
+#define R300_GB_SELECT 0x401C
+#      define R300_GB_FOG_SELECT_C0A           0
+#      define R300_GB_FOG_SELECT_C1A           1
+#      define R300_GB_FOG_SELECT_C2A           2
+#      define R300_GB_FOG_SELECT_C3A           3
+#      define R300_GB_FOG_SELECT_1_1_W 4
+#      define R300_GB_FOG_SELECT_Z             5
+#      define R300_GB_DEPTH_SELECT_Z           0
+#      define R300_GB_DEPTH_SELECT_1_1_W       (1<<3)
+#      define R300_GB_W_SELECT_1_W             0
+#      define R300_GB_W_SELECT_1               (1<<4)
+
+#define R300_GB_AA_CONFIG              0x4020
+#      define R300_AA_DISABLE                  0x00
+#      define R300_AA_ENABLE                   0x01
+#      define R300_AA_SUBSAMPLES_2             0
+#      define R300_AA_SUBSAMPLES_3             (1<<1)
+#      define R300_AA_SUBSAMPLES_4             (2<<1)
+#      define R300_AA_SUBSAMPLES_6             (3<<1)
+
+/* gap */
+
+/* Zero to flush caches. */
+#define R300_TX_CNTL                        0x4100
+#define R300_TX_FLUSH                       0x0
+
+/* The upper enable bits are guessed, based on fglrx reported limits. */
+#define R300_TX_ENABLE                      0x4104
+#       define R300_TX_ENABLE_0                  (1 << 0)
+#       define R300_TX_ENABLE_1                  (1 << 1)
+#       define R300_TX_ENABLE_2                  (1 << 2)
+#       define R300_TX_ENABLE_3                  (1 << 3)
+#       define R300_TX_ENABLE_4                  (1 << 4)
+#       define R300_TX_ENABLE_5                  (1 << 5)
+#       define R300_TX_ENABLE_6                  (1 << 6)
+#       define R300_TX_ENABLE_7                  (1 << 7)
+#       define R300_TX_ENABLE_8                  (1 << 8)
+#       define R300_TX_ENABLE_9                  (1 << 9)
+#       define R300_TX_ENABLE_10                 (1 << 10)
+#       define R300_TX_ENABLE_11                 (1 << 11)
+#       define R300_TX_ENABLE_12                 (1 << 12)
+#       define R300_TX_ENABLE_13                 (1 << 13)
+#       define R300_TX_ENABLE_14                 (1 << 14)
+#       define R300_TX_ENABLE_15                 (1 << 15)
+
+/* The pointsize is given in multiples of 6. The pointsize can be
+ * enormous: Clear() renders a single point that fills the entire
+ * framebuffer.
+ */
+#define R300_RE_POINTSIZE                   0x421C
+#       define R300_POINTSIZE_Y_SHIFT            0
+#       define R300_POINTSIZE_Y_MASK             (0xFFFF << 0) /* GUESS */
+#       define R300_POINTSIZE_X_SHIFT            16
+#       define R300_POINTSIZE_X_MASK             (0xFFFF << 16) /* GUESS */
+#       define R300_POINTSIZE_MAX             (R300_POINTSIZE_Y_MASK / 6)
+
+/* The line width is given in multiples of 6.
+ * In default mode lines are classified as vertical lines.
+ * HO: horizontal
+ * VE: vertical or horizontal
+ * HO & VE: no classification
+ */
+#define R300_RE_LINE_CNT                      0x4234
+#       define R300_LINESIZE_SHIFT            0
+#       define R300_LINESIZE_MASK             (0xFFFF << 0) /* GUESS */
+#       define R300_LINESIZE_MAX             (R300_LINESIZE_MASK / 6)
+#       define R300_LINE_CNT_HO               (1 << 16)
+#       define R300_LINE_CNT_VE               (1 << 17)
+
+/* Some sort of scale or clamp value for texcoordless textures. */
+#define R300_RE_UNK4238                       0x4238
+
+/* Something shade related */
+#define R300_RE_SHADE                         0x4274
+
+#define R300_RE_SHADE_MODEL                   0x4278
+#      define R300_RE_SHADE_MODEL_SMOOTH     0x3aaaa
+#      define R300_RE_SHADE_MODEL_FLAT       0x39595
+
+/* Dangerous */
+#define R300_RE_POLYGON_MODE                  0x4288
+#      define R300_PM_ENABLED                (1 << 0)
+#      define R300_PM_FRONT_POINT            (0 << 0)
+#      define R300_PM_BACK_POINT             (0 << 0)
+#      define R300_PM_FRONT_LINE             (1 << 4)
+#      define R300_PM_FRONT_FILL             (1 << 5)
+#      define R300_PM_BACK_LINE              (1 << 7)
+#      define R300_PM_BACK_FILL              (1 << 8)
+
+/* Fog parameters */
+#define R300_RE_FOG_SCALE                     0x4294
+#define R300_RE_FOG_START                     0x4298
+
+/* Not sure why there are duplicate of factor and constant values.
+ * My best guess so far is that there are separate zbiases for test and write.
+ * Ordering might be wrong.
+ * Some of the tests indicate that fgl has a fallback implementation of zbias
+ * via pixel shaders.
+ */
+#define R300_RE_ZBIAS_CNTL                    0x42A0 /* GUESS */
+#define R300_RE_ZBIAS_T_FACTOR                0x42A4
+#define R300_RE_ZBIAS_T_CONSTANT              0x42A8
+#define R300_RE_ZBIAS_W_FACTOR                0x42AC
+#define R300_RE_ZBIAS_W_CONSTANT              0x42B0
+
+/* This register needs to be set to (1<<1) for RV350 to correctly
+ * perform depth test (see --vb-triangles in r300_demo)
+ * Don't know about other chips. - Vladimir
+ * This is set to 3 when GL_POLYGON_OFFSET_FILL is on.
+ * My guess is that there are two bits for each zbias primitive
+ * (FILL, LINE, POINT).
+ *  One to enable depth test and one for depth write.
+ * Yet this doesnt explain why depth writes work ...
+ */
+#define R300_RE_OCCLUSION_CNTL             0x42B4
+#      define R300_OCCLUSION_ON                (1<<1)
+
+#define R300_RE_CULL_CNTL                   0x42B8
+#       define R300_CULL_FRONT                   (1 << 0)
+#       define R300_CULL_BACK                    (1 << 1)
+#       define R300_FRONT_FACE_CCW               (0 << 2)
+#       define R300_FRONT_FACE_CW                (1 << 2)
+
+
+/* BEGIN: Rasterization / Interpolators - many guesses */
+
+/* 0_UNKNOWN_18 has always been set except for clear operations.
+ * TC_CNT is the number of incoming texture coordinate sets (i.e. it depends
+ * on the vertex program, *not* the fragment program)
+ */
+#define R300_RS_CNTL_0                      0x4300
+#       define R300_RS_CNTL_TC_CNT_SHIFT         2
+#       define R300_RS_CNTL_TC_CNT_MASK          (7 << 2)
+       /* number of color interpolators used */
+#      define R300_RS_CNTL_CI_CNT_SHIFT         7
+#       define R300_RS_CNTL_0_UNKNOWN_18         (1 << 18)
+       /* Guess: RS_CNTL_1 holds the index of the highest used RS_ROUTE_n
+          register. */
+#define R300_RS_CNTL_1                      0x4304
+
+/* gap */
+
+/* Only used for texture coordinates.
+ * Use the source field to route texture coordinate input from the
+ * vertex program to the desired interpolator. Note that the source
+ * field is relative to the outputs the vertex program *actually*
+ * writes. If a vertex program only writes texcoord[1], this will
+ * be source index 0.
+ * Set INTERP_USED on all interpolators that produce data used by
+ * the fragment program. INTERP_USED looks like a swizzling mask,
+ * but I haven't seen it used that way.
+ *
+ * Note: The _UNKNOWN constants are always set in their respective
+ * register. I don't know if this is necessary.
+ */
+#define R300_RS_INTERP_0                    0x4310
+#define R300_RS_INTERP_1                    0x4314
+#       define R300_RS_INTERP_1_UNKNOWN          0x40
+#define R300_RS_INTERP_2                    0x4318
+#       define R300_RS_INTERP_2_UNKNOWN          0x80
+#define R300_RS_INTERP_3                    0x431C
+#       define R300_RS_INTERP_3_UNKNOWN          0xC0
+#define R300_RS_INTERP_4                    0x4320
+#define R300_RS_INTERP_5                    0x4324
+#define R300_RS_INTERP_6                    0x4328
+#define R300_RS_INTERP_7                    0x432C
+#       define R300_RS_INTERP_SRC_SHIFT          2
+#       define R300_RS_INTERP_SRC_MASK           (7 << 2)
+#       define R300_RS_INTERP_USED               0x00D10000
+
+/* These DWORDs control how vertex data is routed into fragment program
+ * registers, after interpolators.
+ */
+#define R300_RS_ROUTE_0                     0x4330
+#define R300_RS_ROUTE_1                     0x4334
+#define R300_RS_ROUTE_2                     0x4338
+#define R300_RS_ROUTE_3                     0x433C /* GUESS */
+#define R300_RS_ROUTE_4                     0x4340 /* GUESS */
+#define R300_RS_ROUTE_5                     0x4344 /* GUESS */
+#define R300_RS_ROUTE_6                     0x4348 /* GUESS */
+#define R300_RS_ROUTE_7                     0x434C /* GUESS */
+#       define R300_RS_ROUTE_SOURCE_INTERP_0     0
+#       define R300_RS_ROUTE_SOURCE_INTERP_1     1
+#       define R300_RS_ROUTE_SOURCE_INTERP_2     2
+#       define R300_RS_ROUTE_SOURCE_INTERP_3     3
+#       define R300_RS_ROUTE_SOURCE_INTERP_4     4
+#       define R300_RS_ROUTE_SOURCE_INTERP_5     5 /* GUESS */
+#       define R300_RS_ROUTE_SOURCE_INTERP_6     6 /* GUESS */
+#       define R300_RS_ROUTE_SOURCE_INTERP_7     7 /* GUESS */
+#       define R300_RS_ROUTE_ENABLE              (1 << 3) /* GUESS */
+#       define R300_RS_ROUTE_DEST_SHIFT          6
+#       define R300_RS_ROUTE_DEST_MASK           (31 << 6) /* GUESS */
+
+/* Special handling for color: When the fragment program uses color,
+ * the ROUTE_0_COLOR bit is set and ROUTE_0_COLOR_DEST contains the
+ * color register index.
+ *
+ * Apperently you may set the R300_RS_ROUTE_0_COLOR bit, but not provide any
+ * R300_RS_ROUTE_0_COLOR_DEST value; this setup is used for clearing the state.
+ * See r300_ioctl.c:r300EmitClearState. I'm not sure if this setup is strictly
+ * correct or not. - Oliver.
+ */
+#       define R300_RS_ROUTE_0_COLOR             (1 << 14)
+#       define R300_RS_ROUTE_0_COLOR_DEST_SHIFT  17
+#       define R300_RS_ROUTE_0_COLOR_DEST_MASK   (31 << 17) /* GUESS */
+/* As above, but for secondary color */
+#              define R300_RS_ROUTE_1_COLOR1            (1 << 14)
+#              define R300_RS_ROUTE_1_COLOR1_DEST_SHIFT 17
+#              define R300_RS_ROUTE_1_COLOR1_DEST_MASK  (31 << 17)
+#              define R300_RS_ROUTE_1_UNKNOWN11         (1 << 11)
+/* END: Rasterization / Interpolators - many guesses */
+
+/* Hierarchical Z Enable */
+#define R300_SC_HYPERZ                   0x43a4
+#      define R300_SC_HYPERZ_DISABLE     (0 << 0)
+#      define R300_SC_HYPERZ_ENABLE      (1 << 0)
+#      define R300_SC_HYPERZ_MIN         (0 << 1)
+#      define R300_SC_HYPERZ_MAX         (1 << 1)
+#      define R300_SC_HYPERZ_ADJ_256     (0 << 2)
+#      define R300_SC_HYPERZ_ADJ_128     (1 << 2)
+#      define R300_SC_HYPERZ_ADJ_64      (2 << 2)
+#      define R300_SC_HYPERZ_ADJ_32      (3 << 2)
+#      define R300_SC_HYPERZ_ADJ_16      (4 << 2)
+#      define R300_SC_HYPERZ_ADJ_8       (5 << 2)
+#      define R300_SC_HYPERZ_ADJ_4       (6 << 2)
+#      define R300_SC_HYPERZ_ADJ_2       (7 << 2)
+#      define R300_SC_HYPERZ_HZ_Z0MIN_NO (0 << 5)
+#      define R300_SC_HYPERZ_HZ_Z0MIN    (1 << 5)
+#      define R300_SC_HYPERZ_HZ_Z0MAX_NO (0 << 6)
+#      define R300_SC_HYPERZ_HZ_Z0MAX    (1 << 6)
+
+#define R300_SC_EDGERULE                 0x43a8
+
+/* BEGIN: Scissors and cliprects */
+
+/* There are four clipping rectangles. Their corner coordinates are inclusive.
+ * Every pixel is assigned a number from 0 and 15 by setting bits 0-3 depending
+ * on whether the pixel is inside cliprects 0-3, respectively. For example,
+ * if a pixel is inside cliprects 0 and 1, but outside 2 and 3, it is assigned
+ * the number 3 (binary 0011).
+ * Iff the bit corresponding to the pixel's number in RE_CLIPRECT_CNTL is set,
+ * the pixel is rasterized.
+ *
+ * In addition to this, there is a scissors rectangle. Only pixels inside the
+ * scissors rectangle are drawn. (coordinates are inclusive)
+ *
+ * For some reason, the top-left corner of the framebuffer is at (1440, 1440)
+ * for the purpose of clipping and scissors.
+ */
+#define R300_RE_CLIPRECT_TL_0               0x43B0
+#define R300_RE_CLIPRECT_BR_0               0x43B4
+#define R300_RE_CLIPRECT_TL_1               0x43B8
+#define R300_RE_CLIPRECT_BR_1               0x43BC
+#define R300_RE_CLIPRECT_TL_2               0x43C0
+#define R300_RE_CLIPRECT_BR_2               0x43C4
+#define R300_RE_CLIPRECT_TL_3               0x43C8
+#define R300_RE_CLIPRECT_BR_3               0x43CC
+#       define R300_CLIPRECT_OFFSET              1440
+#       define R300_CLIPRECT_MASK                0x1FFF
+#       define R300_CLIPRECT_X_SHIFT             0
+#       define R300_CLIPRECT_X_MASK              (0x1FFF << 0)
+#       define R300_CLIPRECT_Y_SHIFT             13
+#       define R300_CLIPRECT_Y_MASK              (0x1FFF << 13)
+#define R300_RE_CLIPRECT_CNTL               0x43D0
+#       define R300_CLIP_OUT                     (1 << 0)
+#       define R300_CLIP_0                       (1 << 1)
+#       define R300_CLIP_1                       (1 << 2)
+#       define R300_CLIP_10                      (1 << 3)
+#       define R300_CLIP_2                       (1 << 4)
+#       define R300_CLIP_20                      (1 << 5)
+#       define R300_CLIP_21                      (1 << 6)
+#       define R300_CLIP_210                     (1 << 7)
+#       define R300_CLIP_3                       (1 << 8)
+#       define R300_CLIP_30                      (1 << 9)
+#       define R300_CLIP_31                      (1 << 10)
+#       define R300_CLIP_310                     (1 << 11)
+#       define R300_CLIP_32                      (1 << 12)
+#       define R300_CLIP_320                     (1 << 13)
+#       define R300_CLIP_321                     (1 << 14)
+#       define R300_CLIP_3210                    (1 << 15)
+
+/* gap */
+
+#define R300_RE_SCISSORS_TL                 0x43E0
+#define R300_RE_SCISSORS_BR                 0x43E4
+#       define R300_SCISSORS_OFFSET              1440
+#       define R300_SCISSORS_X_SHIFT             0
+#       define R300_SCISSORS_X_MASK              (0x1FFF << 0)
+#       define R300_SCISSORS_Y_SHIFT             13
+#       define R300_SCISSORS_Y_MASK              (0x1FFF << 13)
+/* END: Scissors and cliprects */
+
+/* BEGIN: Texture specification */
+
+/*
+ * The texture specification dwords are grouped by meaning and not by texture
+ * unit. This means that e.g. the offset for texture image unit N is found in
+ * register TX_OFFSET_0 + (4*N)
+ */
+#define R300_TX_FILTER_0                    0x4400
+#       define R300_TX_REPEAT                    0
+#       define R300_TX_MIRRORED                  1
+#       define R300_TX_CLAMP                     4
+#       define R300_TX_CLAMP_TO_EDGE             2
+#       define R300_TX_CLAMP_TO_BORDER           6
+#       define R300_TX_WRAP_S_SHIFT              0
+#       define R300_TX_WRAP_S_MASK               (7 << 0)
+#       define R300_TX_WRAP_T_SHIFT              3
+#       define R300_TX_WRAP_T_MASK               (7 << 3)
+#       define R300_TX_WRAP_Q_SHIFT              6
+#       define R300_TX_WRAP_Q_MASK               (7 << 6)
+#       define R300_TX_MAG_FILTER_NEAREST        (1 << 9)
+#       define R300_TX_MAG_FILTER_LINEAR         (2 << 9)
+#       define R300_TX_MAG_FILTER_MASK           (3 << 9)
+#       define R300_TX_MIN_FILTER_NEAREST        (1 << 11)
+#       define R300_TX_MIN_FILTER_LINEAR         (2 << 11)
+#      define R300_TX_MIN_FILTER_NEAREST_MIP_NEAREST       (5  <<  11)
+#      define R300_TX_MIN_FILTER_NEAREST_MIP_LINEAR        (9  <<  11)
+#      define R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST        (6  <<  11)
+#      define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR         (10 <<  11)
+
+/* NOTE: NEAREST doesnt seem to exist.
+ * Im not seting MAG_FILTER_MASK and (3 << 11) on for all
+ * anisotropy modes because that would void selected mag filter
+ */
+#      define R300_TX_MIN_FILTER_ANISO_NEAREST             (0 << 13)
+#      define R300_TX_MIN_FILTER_ANISO_LINEAR              (0 << 13)
+#      define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (1 << 13)
+#      define R300_TX_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR  (2 << 13)
+#       define R300_TX_MIN_FILTER_MASK   ( (15 << 11) | (3 << 13) )
+#      define R300_TX_MAX_ANISO_1_TO_1  (0 << 21)
+#      define R300_TX_MAX_ANISO_2_TO_1  (2 << 21)
+#      define R300_TX_MAX_ANISO_4_TO_1  (4 << 21)
+#      define R300_TX_MAX_ANISO_8_TO_1  (6 << 21)
+#      define R300_TX_MAX_ANISO_16_TO_1 (8 << 21)
+#      define R300_TX_MAX_ANISO_MASK    (14 << 21)
+
+#define R300_TX_FILTER1_0                      0x4440
+#      define R300_CHROMA_KEY_MODE_DISABLE    0
+#      define R300_CHROMA_KEY_FORCE           1
+#      define R300_CHROMA_KEY_BLEND           2
+#      define R300_MC_ROUND_NORMAL            (0<<2)
+#      define R300_MC_ROUND_MPEG4             (1<<2)
+#      define R300_LOD_BIAS_MASK           0x1fff
+#      define R300_EDGE_ANISO_EDGE_DIAG       (0<<13)
+#      define R300_EDGE_ANISO_EDGE_ONLY       (1<<13)
+#      define R300_MC_COORD_TRUNCATE_DISABLE  (0<<14)
+#      define R300_MC_COORD_TRUNCATE_MPEG     (1<<14)
+#      define R300_TX_TRI_PERF_0_8            (0<<15)
+#      define R300_TX_TRI_PERF_1_8            (1<<15)
+#      define R300_TX_TRI_PERF_1_4            (2<<15)
+#      define R300_TX_TRI_PERF_3_8            (3<<15)
+#      define R300_ANISO_THRESHOLD_MASK       (7<<17)
+
+#define R300_TX_SIZE_0                      0x4480
+#       define R300_TX_WIDTHMASK_SHIFT           0
+#       define R300_TX_WIDTHMASK_MASK            (2047 << 0)
+#       define R300_TX_HEIGHTMASK_SHIFT          11
+#       define R300_TX_HEIGHTMASK_MASK           (2047 << 11)
+#       define R300_TX_UNK23                     (1 << 23)
+#       define R300_TX_MAX_MIP_LEVEL_SHIFT       26
+#       define R300_TX_MAX_MIP_LEVEL_MASK        (0xf << 26)
+#       define R300_TX_SIZE_PROJECTED            (1<<30)
+#       define R300_TX_SIZE_TXPITCH_EN           (1<<31)
+#define R300_TX_FORMAT_0                    0x44C0
+       /* The interpretation of the format word by Wladimir van der Laan */
+       /* The X, Y, Z and W refer to the layout of the components.
+          They are given meanings as R, G, B and Alpha by the swizzle
+          specification */
+#      define R300_TX_FORMAT_X8                    0x0
+#      define R300_TX_FORMAT_X16                   0x1
+#      define R300_TX_FORMAT_Y4X4                  0x2
+#      define R300_TX_FORMAT_Y8X8                  0x3
+#      define R300_TX_FORMAT_Y16X16                0x4
+#      define R300_TX_FORMAT_Z3Y3X2                0x5
+#      define R300_TX_FORMAT_Z5Y6X5                0x6
+#      define R300_TX_FORMAT_Z6Y5X5                0x7
+#      define R300_TX_FORMAT_Z11Y11X10             0x8
+#      define R300_TX_FORMAT_Z10Y11X11             0x9
+#      define R300_TX_FORMAT_W4Z4Y4X4              0xA
+#      define R300_TX_FORMAT_W1Z5Y5X5              0xB
+#      define R300_TX_FORMAT_W8Z8Y8X8              0xC
+#      define R300_TX_FORMAT_W2Z10Y10X10           0xD
+#      define R300_TX_FORMAT_W16Z16Y16X16          0xE
+#      define R300_TX_FORMAT_DXT1                  0xF
+#      define R300_TX_FORMAT_DXT3                  0x10
+#      define R300_TX_FORMAT_DXT5                  0x11
+#      define R300_TX_FORMAT_D3DMFT_CxV8U8         0x12     /* no swizzle */
+#      define R300_TX_FORMAT_A8R8G8B8              0x13     /* no swizzle */
+#      define R300_TX_FORMAT_B8G8_B8G8             0x14     /* no swizzle */
+#      define R300_TX_FORMAT_G8R8_G8B8             0x15     /* no swizzle */
+       /* 0x16 - some 16 bit green format.. ?? */
+#      define R300_TX_FORMAT_UNK25                (1 << 25) /* no swizzle */
+#      define R300_TX_FORMAT_CUBIC_MAP            (1 << 26)
+
+       /* gap */
+       /* Floating point formats */
+       /* Note - hardware supports both 16 and 32 bit floating point */
+#      define R300_TX_FORMAT_FL_I16                0x18
+#      define R300_TX_FORMAT_FL_I16A16             0x19
+#      define R300_TX_FORMAT_FL_R16G16B16A16       0x1A
+#      define R300_TX_FORMAT_FL_I32                0x1B
+#      define R300_TX_FORMAT_FL_I32A32             0x1C
+#      define R300_TX_FORMAT_FL_R32G32B32A32       0x1D
+       /* alpha modes, convenience mostly */
+       /* if you have alpha, pick constant appropriate to the
+          number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */
+#      define R300_TX_FORMAT_ALPHA_1CH             0x000
+#      define R300_TX_FORMAT_ALPHA_2CH             0x200
+#      define R300_TX_FORMAT_ALPHA_4CH             0x600
+#      define R300_TX_FORMAT_ALPHA_NONE            0xA00
+       /* Swizzling */
+       /* constants */
+#      define R300_TX_FORMAT_X         0
+#      define R300_TX_FORMAT_Y         1
+#      define R300_TX_FORMAT_Z         2
+#      define R300_TX_FORMAT_W         3
+#      define R300_TX_FORMAT_ZERO      4
+#      define R300_TX_FORMAT_ONE       5
+       /* 2.0*Z, everything above 1.0 is set to 0.0 */
+#      define R300_TX_FORMAT_CUT_Z     6
+       /* 2.0*W, everything above 1.0 is set to 0.0 */
+#      define R300_TX_FORMAT_CUT_W     7
+
+#      define R300_TX_FORMAT_B_SHIFT   18
+#      define R300_TX_FORMAT_G_SHIFT   15
+#      define R300_TX_FORMAT_R_SHIFT   12
+#      define R300_TX_FORMAT_A_SHIFT   9
+       /* Convenience macro to take care of layout and swizzling */
+#      define R300_EASY_TX_FORMAT(B, G, R, A, FMT)     (               \
+               ((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT)          \
+               | ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT)        \
+               | ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT)        \
+               | ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT)        \
+               | (R300_TX_FORMAT_##FMT)                                \
+               )
+       /* These can be ORed with result of R300_EASY_TX_FORMAT()
+          We don't really know what they do. Take values from a
+           constant color ? */
+#      define R300_TX_FORMAT_CONST_X           (1<<5)
+#      define R300_TX_FORMAT_CONST_Y           (2<<5)
+#      define R300_TX_FORMAT_CONST_Z           (4<<5)
+#      define R300_TX_FORMAT_CONST_W           (8<<5)
+
+#      define R300_TX_FORMAT_YUV_MODE          0x00800000
+
+#define R300_TX_PITCH_0                            0x4500 /* obvious missing in gap */
+#define R300_TX_OFFSET_0                    0x4540
+       /* BEGIN: Guess from R200 */
+#       define R300_TXO_ENDIAN_NO_SWAP           (0 << 0)
+#       define R300_TXO_ENDIAN_BYTE_SWAP         (1 << 0)
+#       define R300_TXO_ENDIAN_WORD_SWAP         (2 << 0)
+#       define R300_TXO_ENDIAN_HALFDW_SWAP       (3 << 0)
+#       define R300_TXO_MACRO_TILE               (1 << 2)
+#       define R300_TXO_MICRO_TILE               (1 << 3)
+#       define R300_TXO_OFFSET_MASK              0xffffffe0
+#       define R300_TXO_OFFSET_SHIFT             5
+       /* END: Guess from R200 */
+
+/* 32 bit chroma key */
+#define R300_TX_CHROMA_KEY_0                      0x4580
+/* ff00ff00 == { 0, 1.0, 0, 1.0 } */
+#define R300_TX_BORDER_COLOR_0              0x45C0
+
+/* END: Texture specification */
+
+/* BEGIN: Fragment program instruction set */
+
+/* Fragment programs are written directly into register space.
+ * There are separate instruction streams for texture instructions and ALU
+ * instructions.
+ * In order to synchronize these streams, the program is divided into up
+ * to 4 nodes. Each node begins with a number of TEX operations, followed
+ * by a number of ALU operations.
+ * The first node can have zero TEX ops, all subsequent nodes must have at
+ * least
+ * one TEX ops.
+ * All nodes must have at least one ALU op.
+ *
+ * The index of the last node is stored in PFS_CNTL_0: A value of 0 means
+ * 1 node, a value of 3 means 4 nodes.
+ * The total amount of instructions is defined in PFS_CNTL_2. The offsets are
+ * offsets into the respective instruction streams, while *_END points to the
+ * last instruction relative to this offset.
+ */
+#define R300_PFS_CNTL_0                     0x4600
+#       define R300_PFS_CNTL_LAST_NODES_SHIFT    0
+#       define R300_PFS_CNTL_LAST_NODES_MASK     (3 << 0)
+#       define R300_PFS_CNTL_FIRST_NODE_HAS_TEX  (1 << 3)
+#define R300_PFS_CNTL_1                     0x4604
+/* There is an unshifted value here which has so far always been equal to the
+ * index of the highest used temporary register.
+ */
+#define R300_PFS_CNTL_2                     0x4608
+#       define R300_PFS_CNTL_ALU_OFFSET_SHIFT    0
+#       define R300_PFS_CNTL_ALU_OFFSET_MASK     (63 << 0)
+#       define R300_PFS_CNTL_ALU_END_SHIFT       6
+#       define R300_PFS_CNTL_ALU_END_MASK        (63 << 6)
+#       define R300_PFS_CNTL_TEX_OFFSET_SHIFT    12
+#       define R300_PFS_CNTL_TEX_OFFSET_MASK     (31 << 12) /* GUESS */
+#       define R300_PFS_CNTL_TEX_END_SHIFT       18
+#       define R300_PFS_CNTL_TEX_END_MASK        (31 << 18) /* GUESS */
+
+/* gap */
+
+/* Nodes are stored backwards. The last active node is always stored in
+ * PFS_NODE_3.
+ * Example: In a 2-node program, NODE_0 and NODE_1 are set to 0. The
+ * first node is stored in NODE_2, the second node is stored in NODE_3.
+ *
+ * Offsets are relative to the master offset from PFS_CNTL_2.
+ */
+#define R300_PFS_NODE_0                     0x4610
+#define R300_PFS_NODE_1                     0x4614
+#define R300_PFS_NODE_2                     0x4618
+#define R300_PFS_NODE_3                     0x461C
+#       define R300_PFS_NODE_ALU_OFFSET_SHIFT    0
+#       define R300_PFS_NODE_ALU_OFFSET_MASK     (63 << 0)
+#       define R300_PFS_NODE_ALU_END_SHIFT       6
+#       define R300_PFS_NODE_ALU_END_MASK        (63 << 6)
+#       define R300_PFS_NODE_TEX_OFFSET_SHIFT    12
+#       define R300_PFS_NODE_TEX_OFFSET_MASK     (31 << 12)
+#       define R300_PFS_NODE_TEX_END_SHIFT       17
+#       define R300_PFS_NODE_TEX_END_MASK        (31 << 17)
+#              define R300_PFS_NODE_OUTPUT_COLOR        (1 << 22)
+#              define R300_PFS_NODE_OUTPUT_DEPTH        (1 << 23)
+
+/* TEX
+ * As far as I can tell, texture instructions cannot write into output
+ * registers directly. A subsequent ALU instruction is always necessary,
+ * even if it's just MAD o0, r0, 1, 0
+ */
+#define R300_PFS_TEXI_0                     0x4620
+#      define R300_FPITX_SRC_SHIFT              0
+#      define R300_FPITX_SRC_MASK               (31 << 0)
+       /* GUESS */
+#      define R300_FPITX_SRC_CONST              (1 << 5)
+#      define R300_FPITX_DST_SHIFT              6
+#      define R300_FPITX_DST_MASK               (31 << 6)
+#      define R300_FPITX_IMAGE_SHIFT            11
+       /* GUESS based on layout and native limits */
+#       define R300_FPITX_IMAGE_MASK             (15 << 11)
+/* Unsure if these are opcodes, or some kind of bitfield, but this is how
+ * they were set when I checked
+ */
+#      define R300_FPITX_OPCODE_SHIFT          15
+#              define R300_FPITX_OP_TEX        1
+#              define R300_FPITX_OP_KIL        2
+#              define R300_FPITX_OP_TXP        3
+#              define R300_FPITX_OP_TXB        4
+#      define R300_FPITX_OPCODE_MASK           (7 << 15)
+
+/* ALU
+ * The ALU instructions register blocks are enumerated according to the order
+ * in which fglrx. I assume there is space for 64 instructions, since
+ * each block has space for a maximum of 64 DWORDs, and this matches reported
+ * native limits.
+ *
+ * The basic functional block seems to be one MAD for each color and alpha,
+ * and an adder that adds all components after the MUL.
+ *  - ADD, MUL, MAD etc.: use MAD with appropriate neutral operands
+ *  - DP4: Use OUTC_DP4, OUTA_DP4
+ *  - DP3: Use OUTC_DP3, OUTA_DP4, appropriate alpha operands
+ *  - DPH: Use OUTC_DP4, OUTA_DP4, appropriate alpha operands
+ *  - CMPH: If ARG2 > 0.5, return ARG0, else return ARG1
+ *  - CMP: If ARG2 < 0, return ARG1, else return ARG0
+ *  - FLR: use FRC+MAD
+ *  - XPD: use MAD+MAD
+ *  - SGE, SLT: use MAD+CMP
+ *  - RSQ: use ABS modifier for argument
+ *  - Use OUTC_REPL_ALPHA to write results of an alpha-only operation
+ *    (e.g. RCP) into color register
+ *  - apparently, there's no quick DST operation
+ *  - fglrx set FPI2_UNKNOWN_31 on a "MAD fragment.color, tmp0, tmp1, tmp2"
+ *  - fglrx set FPI2_UNKNOWN_31 on a "MAX r2, r1, c0"
+ *  - fglrx once set FPI0_UNKNOWN_31 on a "FRC r1, r1"
+ *
+ * Operand selection
+ * First stage selects three sources from the available registers and
+ * constant parameters. This is defined in INSTR1 (color) and INSTR3 (alpha).
+ * fglrx sorts the three source fields: Registers before constants,
+ * lower indices before higher indices; I do not know whether this is
+ * necessary.
+ *
+ * fglrx fills unused sources with "read constant 0"
+ * According to specs, you cannot select more than two different constants.
+ *
+ * Second stage selects the operands from the sources. This is defined in
+ * INSTR0 (color) and INSTR2 (alpha). You can also select the special constants
+ * zero and one.
+ * Swizzling and negation happens in this stage, as well.
+ *
+ * Important: Color and alpha seem to be mostly separate, i.e. their sources
+ * selection appears to be fully independent (the register storage is probably
+ * physically split into a color and an alpha section).
+ * However (because of the apparent physical split), there is some interaction
+ * WRT swizzling. If, for example, you want to load an R component into an
+ * Alpha operand, this R component is taken from a *color* source, not from
+ * an alpha source. The corresponding register doesn't even have to appear in
+ * the alpha sources list. (I hope this all makes sense to you)
+ *
+ * Destination selection
+ * The destination register index is in FPI1 (color) and FPI3 (alpha)
+ * together with enable bits.
+ * There are separate enable bits for writing into temporary registers
+ * (DSTC_REG_* /DSTA_REG) and and program output registers (DSTC_OUTPUT_*
+ * /DSTA_OUTPUT). You can write to both at once, or not write at all (the
+ * same index must be used for both).
+ *
+ * Note: There is a special form for LRP
+ *  - Argument order is the same as in ARB_fragment_program.
+ *  - Operation is MAD
+ *  - ARG1 is set to ARGC_SRC1C_LRP/ARGC_SRC1A_LRP
+ *  - Set FPI0/FPI2_SPECIAL_LRP
+ * Arbitrary LRP (including support for swizzling) requires vanilla MAD+MAD
+ */
+#define R300_PFS_INSTR1_0                   0x46C0
+#       define R300_FPI1_SRC0C_SHIFT             0
+#       define R300_FPI1_SRC0C_MASK              (31 << 0)
+#       define R300_FPI1_SRC0C_CONST             (1 << 5)
+#       define R300_FPI1_SRC1C_SHIFT             6
+#       define R300_FPI1_SRC1C_MASK              (31 << 6)
+#       define R300_FPI1_SRC1C_CONST             (1 << 11)
+#       define R300_FPI1_SRC2C_SHIFT             12
+#       define R300_FPI1_SRC2C_MASK              (31 << 12)
+#       define R300_FPI1_SRC2C_CONST             (1 << 17)
+#       define R300_FPI1_SRC_MASK                0x0003ffff
+#       define R300_FPI1_DSTC_SHIFT              18
+#       define R300_FPI1_DSTC_MASK               (31 << 18)
+#              define R300_FPI1_DSTC_REG_MASK_SHIFT     23
+#       define R300_FPI1_DSTC_REG_X              (1 << 23)
+#       define R300_FPI1_DSTC_REG_Y              (1 << 24)
+#       define R300_FPI1_DSTC_REG_Z              (1 << 25)
+#              define R300_FPI1_DSTC_OUTPUT_MASK_SHIFT  26
+#       define R300_FPI1_DSTC_OUTPUT_X           (1 << 26)
+#       define R300_FPI1_DSTC_OUTPUT_Y           (1 << 27)
+#       define R300_FPI1_DSTC_OUTPUT_Z           (1 << 28)
+
+#define R300_PFS_INSTR3_0                   0x47C0
+#       define R300_FPI3_SRC0A_SHIFT             0
+#       define R300_FPI3_SRC0A_MASK              (31 << 0)
+#       define R300_FPI3_SRC0A_CONST             (1 << 5)
+#       define R300_FPI3_SRC1A_SHIFT             6
+#       define R300_FPI3_SRC1A_MASK              (31 << 6)
+#       define R300_FPI3_SRC1A_CONST             (1 << 11)
+#       define R300_FPI3_SRC2A_SHIFT             12
+#       define R300_FPI3_SRC2A_MASK              (31 << 12)
+#       define R300_FPI3_SRC2A_CONST             (1 << 17)
+#       define R300_FPI3_SRC_MASK                0x0003ffff
+#       define R300_FPI3_DSTA_SHIFT              18
+#       define R300_FPI3_DSTA_MASK               (31 << 18)
+#       define R300_FPI3_DSTA_REG                (1 << 23)
+#       define R300_FPI3_DSTA_OUTPUT             (1 << 24)
+#              define R300_FPI3_DSTA_DEPTH              (1 << 27)
+
+#define R300_PFS_INSTR0_0                   0x48C0
+#       define R300_FPI0_ARGC_SRC0C_XYZ          0
+#       define R300_FPI0_ARGC_SRC0C_XXX          1
+#       define R300_FPI0_ARGC_SRC0C_YYY          2
+#       define R300_FPI0_ARGC_SRC0C_ZZZ          3
+#       define R300_FPI0_ARGC_SRC1C_XYZ          4
+#       define R300_FPI0_ARGC_SRC1C_XXX          5
+#       define R300_FPI0_ARGC_SRC1C_YYY          6
+#       define R300_FPI0_ARGC_SRC1C_ZZZ          7
+#       define R300_FPI0_ARGC_SRC2C_XYZ          8
+#       define R300_FPI0_ARGC_SRC2C_XXX          9
+#       define R300_FPI0_ARGC_SRC2C_YYY          10
+#       define R300_FPI0_ARGC_SRC2C_ZZZ          11
+#       define R300_FPI0_ARGC_SRC0A              12
+#       define R300_FPI0_ARGC_SRC1A              13
+#       define R300_FPI0_ARGC_SRC2A              14
+#       define R300_FPI0_ARGC_SRC1C_LRP          15
+#       define R300_FPI0_ARGC_ZERO               20
+#       define R300_FPI0_ARGC_ONE                21
+       /* GUESS */
+#       define R300_FPI0_ARGC_HALF               22
+#       define R300_FPI0_ARGC_SRC0C_YZX          23
+#       define R300_FPI0_ARGC_SRC1C_YZX          24
+#       define R300_FPI0_ARGC_SRC2C_YZX          25
+#       define R300_FPI0_ARGC_SRC0C_ZXY          26
+#       define R300_FPI0_ARGC_SRC1C_ZXY          27
+#       define R300_FPI0_ARGC_SRC2C_ZXY          28
+#       define R300_FPI0_ARGC_SRC0CA_WZY         29
+#       define R300_FPI0_ARGC_SRC1CA_WZY         30
+#       define R300_FPI0_ARGC_SRC2CA_WZY         31
+
+#       define R300_FPI0_ARG0C_SHIFT             0
+#       define R300_FPI0_ARG0C_MASK              (31 << 0)
+#       define R300_FPI0_ARG0C_NEG               (1 << 5)
+#       define R300_FPI0_ARG0C_ABS               (1 << 6)
+#       define R300_FPI0_ARG1C_SHIFT             7
+#       define R300_FPI0_ARG1C_MASK              (31 << 7)
+#       define R300_FPI0_ARG1C_NEG               (1 << 12)
+#       define R300_FPI0_ARG1C_ABS               (1 << 13)
+#       define R300_FPI0_ARG2C_SHIFT             14
+#       define R300_FPI0_ARG2C_MASK              (31 << 14)
+#       define R300_FPI0_ARG2C_NEG               (1 << 19)
+#       define R300_FPI0_ARG2C_ABS               (1 << 20)
+#       define R300_FPI0_SPECIAL_LRP             (1 << 21)
+#       define R300_FPI0_OUTC_MAD                (0 << 23)
+#       define R300_FPI0_OUTC_DP3                (1 << 23)
+#       define R300_FPI0_OUTC_DP4                (2 << 23)
+#       define R300_FPI0_OUTC_MIN                (4 << 23)
+#       define R300_FPI0_OUTC_MAX                (5 << 23)
+#       define R300_FPI0_OUTC_CMPH               (7 << 23)
+#       define R300_FPI0_OUTC_CMP                (8 << 23)
+#       define R300_FPI0_OUTC_FRC                (9 << 23)
+#       define R300_FPI0_OUTC_REPL_ALPHA         (10 << 23)
+#       define R300_FPI0_OUTC_SAT                (1 << 30)
+#       define R300_FPI0_INSERT_NOP              (1 << 31)
+
+#define R300_PFS_INSTR2_0                   0x49C0
+#       define R300_FPI2_ARGA_SRC0C_X            0
+#       define R300_FPI2_ARGA_SRC0C_Y            1
+#       define R300_FPI2_ARGA_SRC0C_Z            2
+#       define R300_FPI2_ARGA_SRC1C_X            3
+#       define R300_FPI2_ARGA_SRC1C_Y            4
+#       define R300_FPI2_ARGA_SRC1C_Z            5
+#       define R300_FPI2_ARGA_SRC2C_X            6
+#       define R300_FPI2_ARGA_SRC2C_Y            7
+#       define R300_FPI2_ARGA_SRC2C_Z            8
+#       define R300_FPI2_ARGA_SRC0A              9
+#       define R300_FPI2_ARGA_SRC1A              10
+#       define R300_FPI2_ARGA_SRC2A              11
+#       define R300_FPI2_ARGA_SRC1A_LRP          15
+#       define R300_FPI2_ARGA_ZERO               16
+#       define R300_FPI2_ARGA_ONE                17
+       /* GUESS */
+#       define R300_FPI2_ARGA_HALF               18
+#       define R300_FPI2_ARG0A_SHIFT             0
+#       define R300_FPI2_ARG0A_MASK              (31 << 0)
+#       define R300_FPI2_ARG0A_NEG               (1 << 5)
+       /* GUESS */
+#      define R300_FPI2_ARG0A_ABS               (1 << 6)
+#       define R300_FPI2_ARG1A_SHIFT             7
+#       define R300_FPI2_ARG1A_MASK              (31 << 7)
+#       define R300_FPI2_ARG1A_NEG               (1 << 12)
+       /* GUESS */
+#      define R300_FPI2_ARG1A_ABS               (1 << 13)
+#       define R300_FPI2_ARG2A_SHIFT             14
+#       define R300_FPI2_ARG2A_MASK              (31 << 14)
+#       define R300_FPI2_ARG2A_NEG               (1 << 19)
+       /* GUESS */
+#      define R300_FPI2_ARG2A_ABS               (1 << 20)
+#       define R300_FPI2_SPECIAL_LRP             (1 << 21)
+#       define R300_FPI2_OUTA_MAD                (0 << 23)
+#       define R300_FPI2_OUTA_DP4                (1 << 23)
+#       define R300_FPI2_OUTA_MIN                (2 << 23)
+#       define R300_FPI2_OUTA_MAX                (3 << 23)
+#       define R300_FPI2_OUTA_CMP                (6 << 23)
+#       define R300_FPI2_OUTA_FRC                (7 << 23)
+#       define R300_FPI2_OUTA_EX2                (8 << 23)
+#       define R300_FPI2_OUTA_LG2                (9 << 23)
+#       define R300_FPI2_OUTA_RCP                (10 << 23)
+#       define R300_FPI2_OUTA_RSQ                (11 << 23)
+#       define R300_FPI2_OUTA_SAT                (1 << 30)
+#       define R300_FPI2_UNKNOWN_31              (1 << 31)
+/* END: Fragment program instruction set */
+
+/* Fog state and color */
+#define R300_RE_FOG_STATE                   0x4BC0
+#       define R300_FOG_ENABLE                   (1 << 0)
+#      define R300_FOG_MODE_LINEAR              (0 << 1)
+#      define R300_FOG_MODE_EXP                 (1 << 1)
+#      define R300_FOG_MODE_EXP2                (2 << 1)
+#      define R300_FOG_MODE_MASK                (3 << 1)
+#define R300_FOG_COLOR_R                    0x4BC8
+#define R300_FOG_COLOR_G                    0x4BCC
+#define R300_FOG_COLOR_B                    0x4BD0
+
+#define R300_PP_ALPHA_TEST                  0x4BD4
+#       define R300_REF_ALPHA_MASK               0x000000ff
+#       define R300_ALPHA_TEST_FAIL              (0 << 8)
+#       define R300_ALPHA_TEST_LESS              (1 << 8)
+#       define R300_ALPHA_TEST_LEQUAL            (3 << 8)
+#       define R300_ALPHA_TEST_EQUAL             (2 << 8)
+#       define R300_ALPHA_TEST_GEQUAL            (6 << 8)
+#       define R300_ALPHA_TEST_GREATER           (4 << 8)
+#       define R300_ALPHA_TEST_NEQUAL            (5 << 8)
+#       define R300_ALPHA_TEST_PASS              (7 << 8)
+#       define R300_ALPHA_TEST_OP_MASK           (7 << 8)
+#       define R300_ALPHA_TEST_ENABLE            (1 << 11)
+
+/* gap */
+
+/* Fragment program parameters in 7.16 floating point */
+#define R300_PFS_PARAM_0_X                  0x4C00
+#define R300_PFS_PARAM_0_Y                  0x4C04
+#define R300_PFS_PARAM_0_Z                  0x4C08
+#define R300_PFS_PARAM_0_W                  0x4C0C
+/* GUESS: PARAM_31 is last, based on native limits reported by fglrx */
+#define R300_PFS_PARAM_31_X                 0x4DF0
+#define R300_PFS_PARAM_31_Y                 0x4DF4
+#define R300_PFS_PARAM_31_Z                 0x4DF8
+#define R300_PFS_PARAM_31_W                 0x4DFC
+
+/* Notes:
+ * - AFAIK fglrx always sets BLEND_UNKNOWN when blending is used in
+ *   the application
+ * - AFAIK fglrx always sets BLEND_NO_SEPARATE when CBLEND and ABLEND
+ *    are set to the same
+ *   function (both registers are always set up completely in any case)
+ * - Most blend flags are simply copied from R200 and not tested yet
+ */
+#define R300_RB3D_CBLEND                    0x4E04
+#define R300_RB3D_ABLEND                    0x4E08
+/* the following only appear in CBLEND */
+#       define R300_BLEND_ENABLE                     (1 << 0)
+#       define R300_BLEND_UNKNOWN                    (3 << 1)
+#       define R300_BLEND_NO_SEPARATE                (1 << 3)
+/* the following are shared between CBLEND and ABLEND */
+#       define R300_FCN_MASK                         (3  << 12)
+#       define R300_COMB_FCN_ADD_CLAMP               (0  << 12)
+#       define R300_COMB_FCN_ADD_NOCLAMP             (1  << 12)
+#       define R300_COMB_FCN_SUB_CLAMP               (2  << 12)
+#       define R300_COMB_FCN_SUB_NOCLAMP             (3  << 12)
+#       define R300_COMB_FCN_MIN                     (4  << 12)
+#       define R300_COMB_FCN_MAX                     (5  << 12)
+#       define R300_COMB_FCN_RSUB_CLAMP              (6  << 12)
+#       define R300_COMB_FCN_RSUB_NOCLAMP            (7  << 12)
+#       define R300_BLEND_GL_ZERO                    (32)
+#       define R300_BLEND_GL_ONE                     (33)
+#       define R300_BLEND_GL_SRC_COLOR               (34)
+#       define R300_BLEND_GL_ONE_MINUS_SRC_COLOR     (35)
+#       define R300_BLEND_GL_DST_COLOR               (36)
+#       define R300_BLEND_GL_ONE_MINUS_DST_COLOR     (37)
+#       define R300_BLEND_GL_SRC_ALPHA               (38)
+#       define R300_BLEND_GL_ONE_MINUS_SRC_ALPHA     (39)
+#       define R300_BLEND_GL_DST_ALPHA               (40)
+#       define R300_BLEND_GL_ONE_MINUS_DST_ALPHA     (41)
+#       define R300_BLEND_GL_SRC_ALPHA_SATURATE      (42)
+#       define R300_BLEND_GL_CONST_COLOR             (43)
+#       define R300_BLEND_GL_ONE_MINUS_CONST_COLOR   (44)
+#       define R300_BLEND_GL_CONST_ALPHA             (45)
+#       define R300_BLEND_GL_ONE_MINUS_CONST_ALPHA   (46)
+#       define R300_BLEND_MASK                       (63)
+#       define R300_SRC_BLEND_SHIFT                  (16)
+#       define R300_DST_BLEND_SHIFT                  (24)
+#define R300_RB3D_BLEND_COLOR               0x4E10
+#define R300_RB3D_COLORMASK                 0x4E0C
+#       define R300_COLORMASK0_B                 (1<<0)
+#       define R300_COLORMASK0_G                 (1<<1)
+#       define R300_COLORMASK0_R                 (1<<2)
+#       define R300_COLORMASK0_A                 (1<<3)
+
+/* gap */
+
+#define R300_RB3D_COLOROFFSET0              0x4E28
+#       define R300_COLOROFFSET_MASK             0xFFFFFFF0 /* GUESS */
+#define R300_RB3D_COLOROFFSET1              0x4E2C /* GUESS */
+#define R300_RB3D_COLOROFFSET2              0x4E30 /* GUESS */
+#define R300_RB3D_COLOROFFSET3              0x4E34 /* GUESS */
+
+/* gap */
+
+/* Bit 16: Larger tiles
+ * Bit 17: 4x2 tiles
+ * Bit 18: Extremely weird tile like, but some pixels duplicated?
+ */
+#define R300_RB3D_COLORPITCH0               0x4E38
+#       define R300_COLORPITCH_MASK              0x00001FF8 /* GUESS */
+#       define R300_COLOR_TILE_ENABLE            (1 << 16) /* GUESS */
+#       define R300_COLOR_MICROTILE_ENABLE       (1 << 17) /* GUESS */
+#       define R300_COLOR_ENDIAN_NO_SWAP         (0 << 18) /* GUESS */
+#       define R300_COLOR_ENDIAN_WORD_SWAP       (1 << 18) /* GUESS */
+#       define R300_COLOR_ENDIAN_DWORD_SWAP      (2 << 18) /* GUESS */
+#       define R300_COLOR_FORMAT_RGB565          (2 << 22)
+#       define R300_COLOR_FORMAT_ARGB8888        (3 << 22)
+#define R300_RB3D_COLORPITCH1               0x4E3C /* GUESS */
+#define R300_RB3D_COLORPITCH2               0x4E40 /* GUESS */
+#define R300_RB3D_COLORPITCH3               0x4E44 /* GUESS */
+
+/* gap */
+
+/* Guess by Vladimir.
+ * Set to 0A before 3D operations, set to 02 afterwards.
+ */
+/*#define R300_RB3D_DSTCACHE_CTLSTAT          0x4E4C*/
+#       define R300_RB3D_DSTCACHE_UNKNOWN_02             0x00000002
+#       define R300_RB3D_DSTCACHE_UNKNOWN_0A             0x0000000A
+
+/* gap */
+/* There seems to be no "write only" setting, so use Z-test = ALWAYS
+ * for this.
+ * Bit (1<<8) is the "test" bit. so plain write is 6  - vd
+ */
+#define R300_ZB_CNTL                             0x4F00
+#      define R300_STENCIL_ENABLE               (1 << 0)
+#      define R300_Z_ENABLE                     (1 << 1)
+#      define R300_Z_WRITE_ENABLE               (1 << 2)
+#      define R300_Z_SIGNED_COMPARE             (1 << 3)
+#      define R300_STENCIL_FRONT_BACK           (1 << 4)
+
+#define R300_ZB_ZSTENCILCNTL                   0x4f04
+       /* functions */
+#      define R300_ZS_NEVER                    0
+#      define R300_ZS_LESS                     1
+#      define R300_ZS_LEQUAL                   2
+#      define R300_ZS_EQUAL                    3
+#      define R300_ZS_GEQUAL                   4
+#      define R300_ZS_GREATER                  5
+#      define R300_ZS_NOTEQUAL                 6
+#      define R300_ZS_ALWAYS                   7
+#       define R300_ZS_MASK                     7
+       /* operations */
+#      define R300_ZS_KEEP                     0
+#      define R300_ZS_ZERO                     1
+#      define R300_ZS_REPLACE                  2
+#      define R300_ZS_INCR                     3
+#      define R300_ZS_DECR                     4
+#      define R300_ZS_INVERT                   5
+#      define R300_ZS_INCR_WRAP                6
+#      define R300_ZS_DECR_WRAP                7
+#      define R300_Z_FUNC_SHIFT                0
+       /* front and back refer to operations done for front
+          and back faces, i.e. separate stencil function support */
+#      define R300_S_FRONT_FUNC_SHIFT          3
+#      define R300_S_FRONT_SFAIL_OP_SHIFT      6
+#      define R300_S_FRONT_ZPASS_OP_SHIFT      9
+#      define R300_S_FRONT_ZFAIL_OP_SHIFT      12
+#      define R300_S_BACK_FUNC_SHIFT           15
+#      define R300_S_BACK_SFAIL_OP_SHIFT       18
+#      define R300_S_BACK_ZPASS_OP_SHIFT       21
+#      define R300_S_BACK_ZFAIL_OP_SHIFT       24
+
+#define R300_ZB_STENCILREFMASK                        0x4f08
+#      define R300_STENCILREF_SHIFT       0
+#      define R300_STENCILREF_MASK        0x000000ff
+#      define R300_STENCILMASK_SHIFT      8
+#      define R300_STENCILMASK_MASK       0x0000ff00
+#      define R300_STENCILWRITEMASK_SHIFT 16
+#      define R300_STENCILWRITEMASK_MASK  0x00ff0000
+
+/* gap */
+
+#define R300_ZB_FORMAT                             0x4f10
+#      define R300_DEPTHFORMAT_16BIT_INT_Z   (0 << 0)
+#      define R300_DEPTHFORMAT_16BIT_13E3    (1 << 0)
+#      define R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL   (2 << 0)
+/* reserved up to (15 << 0) */
+#      define R300_INVERT_13E3_LEADING_ONES  (0 << 4)
+#      define R300_INVERT_13E3_LEADING_ZEROS (1 << 4)
+
+#define R300_ZB_ZTOP                             0x4F14
+#      define R300_ZTOP_DISABLE                 (0 << 0)
+#      define R300_ZTOP_ENABLE                  (1 << 0)
+
+/* gap */
+
+#define R300_ZB_ZCACHE_CTLSTAT            0x4f18
+#       define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_NO_EFFECT      (0 << 0)
+#       define R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE (1 << 0)
+#       define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_NO_EFFECT       (0 << 1)
+#       define R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE            (1 << 1)
+#       define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_IDLE            (0 << 31)
+#       define R300_ZB_ZCACHE_CTLSTAT_ZC_BUSY_BUSY            (1 << 31)
+
+#define R300_ZB_BW_CNTL                     0x4f1c
+#      define R300_HIZ_DISABLE                              (0 << 0)
+#      define R300_HIZ_ENABLE                               (1 << 0)
+#      define R300_HIZ_MIN                                  (0 << 1)
+#      define R300_HIZ_MAX                                  (1 << 1)
+#      define R300_FAST_FILL_DISABLE                        (0 << 2)
+#      define R300_FAST_FILL_ENABLE                         (1 << 2)
+#      define R300_RD_COMP_DISABLE                          (0 << 3)
+#      define R300_RD_COMP_ENABLE                           (1 << 3)
+#      define R300_WR_COMP_DISABLE                          (0 << 4)
+#      define R300_WR_COMP_ENABLE                           (1 << 4)
+#      define R300_ZB_CB_CLEAR_RMW                          (0 << 5)
+#      define R300_ZB_CB_CLEAR_CACHE_LINEAR                 (1 << 5)
+#      define R300_FORCE_COMPRESSED_STENCIL_VALUE_DISABLE   (0 << 6)
+#      define R300_FORCE_COMPRESSED_STENCIL_VALUE_ENABLE    (1 << 6)
+
+#      define R500_ZEQUAL_OPTIMIZE_ENABLE                   (0 << 7)
+#      define R500_ZEQUAL_OPTIMIZE_DISABLE                  (1 << 7)
+#      define R500_SEQUAL_OPTIMIZE_ENABLE                   (0 << 8)
+#      define R500_SEQUAL_OPTIMIZE_DISABLE                  (1 << 8)
+
+#      define R500_BMASK_ENABLE                             (0 << 10)
+#      define R500_BMASK_DISABLE                            (1 << 10)
+#      define R500_HIZ_EQUAL_REJECT_DISABLE                 (0 << 11)
+#      define R500_HIZ_EQUAL_REJECT_ENABLE                  (1 << 11)
+#      define R500_HIZ_FP_EXP_BITS_DISABLE                  (0 << 12)
+#      define R500_HIZ_FP_EXP_BITS_1                        (1 << 12)
+#      define R500_HIZ_FP_EXP_BITS_2                        (2 << 12)
+#      define R500_HIZ_FP_EXP_BITS_3                        (3 << 12)
+#      define R500_HIZ_FP_EXP_BITS_4                        (4 << 12)
+#      define R500_HIZ_FP_EXP_BITS_5                        (5 << 12)
+#      define R500_HIZ_FP_INVERT_LEADING_ONES               (0 << 15)
+#      define R500_HIZ_FP_INVERT_LEADING_ZEROS              (1 << 15)
+#      define R500_TILE_OVERWRITE_RECOMPRESSION_ENABLE      (0 << 16)
+#      define R500_TILE_OVERWRITE_RECOMPRESSION_DISABLE     (1 << 16)
+#      define R500_CONTIGUOUS_6XAA_SAMPLES_ENABLE           (0 << 17)
+#      define R500_CONTIGUOUS_6XAA_SAMPLES_DISABLE          (1 << 17)
+#      define R500_PEQ_PACKING_DISABLE                      (0 << 18)
+#      define R500_PEQ_PACKING_ENABLE                       (1 << 18)
+#      define R500_COVERED_PTR_MASKING_DISABLE              (0 << 18)
+#      define R500_COVERED_PTR_MASKING_ENABLE               (1 << 18)
+
+
+/* gap */
+
+/* Z Buffer Address Offset.
+ * Bits 31 to 5 are used for aligned Z buffer address offset for macro tiles.
+ */
+#define R300_ZB_DEPTHOFFSET               0x4f20
+
+/* Z Buffer Pitch and Endian Control */
+#define R300_ZB_DEPTHPITCH                0x4f24
+#       define R300_DEPTHPITCH_MASK              0x00003FFC
+#       define R300_DEPTHMACROTILE_DISABLE      (0 << 16)
+#       define R300_DEPTHMACROTILE_ENABLE       (1 << 16)
+#       define R300_DEPTHMICROTILE_LINEAR       (0 << 17)
+#       define R300_DEPTHMICROTILE_TILED        (1 << 17)
+#       define R300_DEPTHMICROTILE_TILED_SQUARE (2 << 17)
+#       define R300_DEPTHENDIAN_NO_SWAP         (0 << 18)
+#       define R300_DEPTHENDIAN_WORD_SWAP       (1 << 18)
+#       define R300_DEPTHENDIAN_DWORD_SWAP      (2 << 18)
+#       define R300_DEPTHENDIAN_HALF_DWORD_SWAP (3 << 18)
+
+/* Z Buffer Clear Value */
+#define R300_ZB_DEPTHCLEARVALUE                  0x4f28
+
+#define R300_ZB_ZMASK_OFFSET                    0x4f30
+#define R300_ZB_ZMASK_PITCH                     0x4f34
+#define R300_ZB_ZMASK_WRINDEX                   0x4f38
+#define R300_ZB_ZMASK_DWORD                     0x4f3c
+#define R300_ZB_ZMASK_RDINDEX                   0x4f40
+
+/* Hierarchical Z Memory Offset */
+#define R300_ZB_HIZ_OFFSET                       0x4f44
+
+/* Hierarchical Z Write Index */
+#define R300_ZB_HIZ_WRINDEX                      0x4f48
+
+/* Hierarchical Z Data */
+#define R300_ZB_HIZ_DWORD                        0x4f4c
+
+/* Hierarchical Z Read Index */
+#define R300_ZB_HIZ_RDINDEX                      0x4f50
+
+/* Hierarchical Z Pitch */
+#define R300_ZB_HIZ_PITCH                        0x4f54
+
+/* Z Buffer Z Pass Counter Data */
+#define R300_ZB_ZPASS_DATA                       0x4f58
+
+/* Z Buffer Z Pass Counter Address */
+#define R300_ZB_ZPASS_ADDR                       0x4f5c
+
+/* Depth buffer X and Y coordinate offset */
+#define R300_ZB_DEPTHXY_OFFSET                   0x4f60
+#      define R300_DEPTHX_OFFSET_SHIFT  1
+#      define R300_DEPTHX_OFFSET_MASK   0x000007FE
+#      define R300_DEPTHY_OFFSET_SHIFT  17
+#      define R300_DEPTHY_OFFSET_MASK   0x07FE0000
+
+/* Sets the fifo sizes */
+#define R500_ZB_FIFO_SIZE                        0x4fd0
+#      define R500_OP_FIFO_SIZE_FULL   (0 << 0)
+#      define R500_OP_FIFO_SIZE_HALF   (1 << 0)
+#      define R500_OP_FIFO_SIZE_QUATER (2 << 0)
+#      define R500_OP_FIFO_SIZE_EIGTHS (4 << 0)
+
+/* Stencil Reference Value and Mask for backfacing quads */
+/* R300_ZB_STENCILREFMASK handles front face */
+#define R500_ZB_STENCILREFMASK_BF                0x4fd4
+#      define R500_STENCILREF_SHIFT       0
+#      define R500_STENCILREF_MASK        0x000000ff
+#      define R500_STENCILMASK_SHIFT      8
+#      define R500_STENCILMASK_MASK       0x0000ff00
+#      define R500_STENCILWRITEMASK_SHIFT 16
+#      define R500_STENCILWRITEMASK_MASK  0x00ff0000
+
+/* BEGIN: Vertex program instruction set */
+
+/* Every instruction is four dwords long:
+ *  DWORD 0: output and opcode
+ *  DWORD 1: first argument
+ *  DWORD 2: second argument
+ *  DWORD 3: third argument
+ *
+ * Notes:
+ *  - ABS r, a is implemented as MAX r, a, -a
+ *  - MOV is implemented as ADD to zero
+ *  - XPD is implemented as MUL + MAD
+ *  - FLR is implemented as FRC + ADD
+ *  - apparently, fglrx tries to schedule instructions so that there is at
+ *    least one instruction between the write to a temporary and the first
+ *    read from said temporary; however, violations of this scheduling are
+ *    allowed
+ *  - register indices seem to be unrelated with OpenGL aliasing to
+ *    conventional state
+ *  - only one attribute and one parameter can be loaded at a time; however,
+ *    the same attribute/parameter can be used for more than one argument
+ *  - the second software argument for POW is the third hardware argument
+ *    (no idea why)
+ *  - MAD with only temporaries as input seems to use VPI_OUT_SELECT_MAD_2
+ *
+ * There is some magic surrounding LIT:
+ *   The single argument is replicated across all three inputs, but swizzled:
+ *     First argument: xyzy
+ *     Second argument: xyzx
+ *     Third argument: xyzw
+ *   Whenever the result is used later in the fragment program, fglrx forces
+ *   x and w to be 1.0 in the input selection; I don't know whether this is
+ *   strictly necessary
+ */
+#define R300_VPI_OUT_OP_DOT                     (1 << 0)
+#define R300_VPI_OUT_OP_MUL                     (2 << 0)
+#define R300_VPI_OUT_OP_ADD                     (3 << 0)
+#define R300_VPI_OUT_OP_MAD                     (4 << 0)
+#define R300_VPI_OUT_OP_DST                     (5 << 0)
+#define R300_VPI_OUT_OP_FRC                     (6 << 0)
+#define R300_VPI_OUT_OP_MAX                     (7 << 0)
+#define R300_VPI_OUT_OP_MIN                     (8 << 0)
+#define R300_VPI_OUT_OP_SGE                     (9 << 0)
+#define R300_VPI_OUT_OP_SLT                     (10 << 0)
+       /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, vector(scalar, vector) */
+#define R300_VPI_OUT_OP_UNK12                   (12 << 0)
+#define R300_VPI_OUT_OP_ARL                     (13 << 0)
+#define R300_VPI_OUT_OP_EXP                     (65 << 0)
+#define R300_VPI_OUT_OP_LOG                     (66 << 0)
+       /* Used in fog computations, scalar(scalar) */
+#define R300_VPI_OUT_OP_UNK67                   (67 << 0)
+#define R300_VPI_OUT_OP_LIT                     (68 << 0)
+#define R300_VPI_OUT_OP_POW                     (69 << 0)
+#define R300_VPI_OUT_OP_RCP                     (70 << 0)
+#define R300_VPI_OUT_OP_RSQ                     (72 << 0)
+       /* Used in GL_POINT_DISTANCE_ATTENUATION_ARB, scalar(scalar) */
+#define R300_VPI_OUT_OP_UNK73                   (73 << 0)
+#define R300_VPI_OUT_OP_EX2                     (75 << 0)
+#define R300_VPI_OUT_OP_LG2                     (76 << 0)
+#define R300_VPI_OUT_OP_MAD_2                   (128 << 0)
+       /* all temps, vector(scalar, vector, vector) */
+#define R300_VPI_OUT_OP_UNK129                  (129 << 0)
+
+#define R300_VPI_OUT_REG_CLASS_TEMPORARY        (0 << 8)
+#define R300_VPI_OUT_REG_CLASS_ADDR             (1 << 8)
+#define R300_VPI_OUT_REG_CLASS_RESULT           (2 << 8)
+#define R300_VPI_OUT_REG_CLASS_MASK             (31 << 8)
+
+#define R300_VPI_OUT_REG_INDEX_SHIFT            13
+       /* GUESS based on fglrx native limits */
+#define R300_VPI_OUT_REG_INDEX_MASK             (31 << 13)
+
+#define R300_VPI_OUT_WRITE_X                    (1 << 20)
+#define R300_VPI_OUT_WRITE_Y                    (1 << 21)
+#define R300_VPI_OUT_WRITE_Z                    (1 << 22)
+#define R300_VPI_OUT_WRITE_W                    (1 << 23)
+
+#define R300_VPI_IN_REG_CLASS_TEMPORARY         (0 << 0)
+#define R300_VPI_IN_REG_CLASS_ATTRIBUTE         (1 << 0)
+#define R300_VPI_IN_REG_CLASS_PARAMETER         (2 << 0)
+#define R300_VPI_IN_REG_CLASS_NONE              (9 << 0)
+#define R300_VPI_IN_REG_CLASS_MASK              (31 << 0)
+
+#define R300_VPI_IN_REG_INDEX_SHIFT             5
+       /* GUESS based on fglrx native limits */
+#define R300_VPI_IN_REG_INDEX_MASK              (255 << 5)
+
+/* The R300 can select components from the input register arbitrarily.
+ * Use the following constants, shifted by the component shift you
+ * want to select
+ */
+#define R300_VPI_IN_SELECT_X    0
+#define R300_VPI_IN_SELECT_Y    1
+#define R300_VPI_IN_SELECT_Z    2
+#define R300_VPI_IN_SELECT_W    3
+#define R300_VPI_IN_SELECT_ZERO 4
+#define R300_VPI_IN_SELECT_ONE  5
+#define R300_VPI_IN_SELECT_MASK 7
+
+#define R300_VPI_IN_X_SHIFT                     13
+#define R300_VPI_IN_Y_SHIFT                     16
+#define R300_VPI_IN_Z_SHIFT                     19
+#define R300_VPI_IN_W_SHIFT                     22
+
+#define R300_VPI_IN_NEG_X                       (1 << 25)
+#define R300_VPI_IN_NEG_Y                       (1 << 26)
+#define R300_VPI_IN_NEG_Z                       (1 << 27)
+#define R300_VPI_IN_NEG_W                       (1 << 28)
+/* END: Vertex program instruction set */
+
+/* BEGIN: Packet 3 commands */
+
+/* A primitive emission dword. */
+#define R300_PRIM_TYPE_NONE                     (0 << 0)
+#define R300_PRIM_TYPE_POINT                    (1 << 0)
+#define R300_PRIM_TYPE_LINE                     (2 << 0)
+#define R300_PRIM_TYPE_LINE_STRIP               (3 << 0)
+#define R300_PRIM_TYPE_TRI_LIST                 (4 << 0)
+#define R300_PRIM_TYPE_TRI_FAN                  (5 << 0)
+#define R300_PRIM_TYPE_TRI_STRIP                (6 << 0)
+#define R300_PRIM_TYPE_TRI_TYPE2                (7 << 0)
+#define R300_PRIM_TYPE_RECT_LIST                (8 << 0)
+#define R300_PRIM_TYPE_3VRT_POINT_LIST          (9 << 0)
+#define R300_PRIM_TYPE_3VRT_LINE_LIST           (10 << 0)
+       /* GUESS (based on r200) */
+#define R300_PRIM_TYPE_POINT_SPRITES            (11 << 0)
+#define R300_PRIM_TYPE_LINE_LOOP                (12 << 0)
+#define R300_PRIM_TYPE_QUADS                    (13 << 0)
+#define R300_PRIM_TYPE_QUAD_STRIP               (14 << 0)
+#define R300_PRIM_TYPE_POLYGON                  (15 << 0)
+#define R300_PRIM_TYPE_MASK                     0xF
+#define R300_PRIM_WALK_IND                      (1 << 4)
+#define R300_PRIM_WALK_LIST                     (2 << 4)
+#define R300_PRIM_WALK_RING                     (3 << 4)
+#define R300_PRIM_WALK_MASK                     (3 << 4)
+       /* GUESS (based on r200) */
+#define R300_PRIM_COLOR_ORDER_BGRA              (0 << 6)
+#define R300_PRIM_COLOR_ORDER_RGBA              (1 << 6)
+#define R300_PRIM_NUM_VERTICES_SHIFT            16
+#define R300_PRIM_NUM_VERTICES_MASK             0xffff
+
+/* Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR.
+ * Two parameter dwords:
+ * 0. The first parameter appears to be always 0
+ * 1. The second parameter is a standard primitive emission dword.
+ */
+#define R300_PACKET3_3D_DRAW_VBUF           0x00002800
+
+/* Specify the full set of vertex arrays as (address, stride).
+ * The first parameter is the number of vertex arrays specified.
+ * The rest of the command is a variable length list of blocks, where
+ * each block is three dwords long and specifies two arrays.
+ * The first dword of a block is split into two words, the lower significant
+ * word refers to the first array, the more significant word to the second
+ * array in the block.
+ * The low byte of each word contains the size of an array entry in dwords,
+ * the high byte contains the stride of the array.
+ * The second dword of a block contains the pointer to the first array,
+ * the third dword of a block contains the pointer to the second array.
+ * Note that if the total number of arrays is odd, the third dword of
+ * the last block is omitted.
+ */
+#define R300_PACKET3_3D_LOAD_VBPNTR         0x00002F00
+
+#define R300_PACKET3_INDX_BUFFER            0x00003300
+#    define R300_EB_UNK1_SHIFT                      24
+#    define R300_EB_UNK1                    (0x80<<24)
+#    define R300_EB_UNK2                        0x0810
+#define R300_PACKET3_3D_DRAW_VBUF_2         0x00003400
+#define R300_PACKET3_3D_DRAW_INDX_2         0x00003600
+
+/* END: Packet 3 commands */
+
+
+/* Color formats for 2d packets
+ */
+#define R300_CP_COLOR_FORMAT_CI8       2
+#define R300_CP_COLOR_FORMAT_ARGB1555  3
+#define R300_CP_COLOR_FORMAT_RGB565    4
+#define R300_CP_COLOR_FORMAT_ARGB8888  6
+#define R300_CP_COLOR_FORMAT_RGB332    7
+#define R300_CP_COLOR_FORMAT_RGB8      9
+#define R300_CP_COLOR_FORMAT_ARGB4444  15
+
+/*
+ * CP type-3 packets
+ */
+#define R300_CP_CMD_BITBLT_MULTI       0xC0009B00
+
+#define R500_VAP_INDEX_OFFSET          0x208c
+
+#define R500_GA_US_VECTOR_INDEX         0x4250
+#define R500_GA_US_VECTOR_DATA          0x4254
+
+#define R500_RS_IP_0                    0x4074
+#define R500_RS_INST_0                  0x4320
+
+#define R500_US_CONFIG                  0x4600
+
+#define R500_US_FC_CTRL                        0x4624
+#define R500_US_CODE_ADDR              0x4630
+
+#define R500_RB3D_COLOR_CLEAR_VALUE_AR  0x46c0
+#define R500_RB3D_CONSTANT_COLOR_AR     0x4ef8
+
+#endif /* _R300_REG_H */
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
new file mode 100644 (file)
index 0000000..e53158f
--- /dev/null
@@ -0,0 +1,1773 @@
+/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */
+/*
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * Copyright 2007 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+#include "r300_reg.h"
+
+#include "radeon_microcode.h"
+
+#define RADEON_FIFO_DEBUG      0
+
+static int radeon_do_cleanup_cp(struct drm_device * dev);
+
+static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+{
+       u32 ret;
+       RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff));
+       ret = RADEON_READ(R520_MC_IND_DATA);
+       RADEON_WRITE(R520_MC_IND_INDEX, 0);
+       return ret;
+}
+
+static u32 RS480_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+{
+       u32 ret;
+       RADEON_WRITE(RS480_NB_MC_INDEX, addr & 0xff);
+       ret = RADEON_READ(RS480_NB_MC_DATA);
+       RADEON_WRITE(RS480_NB_MC_INDEX, 0xff);
+       return ret;
+}
+
+static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+{
+       u32 ret;
+       RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK));
+       ret = RADEON_READ(RS690_MC_DATA);
+       RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_MASK);
+       return ret;
+}
+
+static u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+{
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+               return RS690_READ_MCIND(dev_priv, addr);
+       else
+               return RS480_READ_MCIND(dev_priv, addr);
+}
+
+u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv)
+{
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
+               return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+               return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
+               return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION);
+       else
+               return RADEON_READ(RADEON_MC_FB_LOCATION);
+}
+
+static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc)
+{
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
+               R500_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+               RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
+               R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc);
+       else
+               RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc);
+}
+
+static void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc)
+{
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
+               R500_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+               RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
+               R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc);
+       else
+               RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc);
+}
+
+static void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base)
+{
+       u32 agp_base_hi = upper_32_bits(agp_base);
+       u32 agp_base_lo = agp_base & 0xffffffff;
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) {
+               R500_WRITE_MCIND(RV515_MC_AGP_BASE, agp_base_lo);
+               R500_WRITE_MCIND(RV515_MC_AGP_BASE_2, agp_base_hi);
+       } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
+               RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo);
+               RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi);
+       } else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) {
+               R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo);
+               R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi);
+       } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480) {
+               RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
+               RADEON_WRITE(RS480_AGP_BASE_2, 0);
+       } else {
+               RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo);
+               if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200)
+                       RADEON_WRITE(RADEON_AGP_BASE_2, agp_base_hi);
+       }
+}
+
+static int RADEON_READ_PLL(struct drm_device * dev, int addr)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+
+       RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
+       return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
+}
+
+static u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
+{
+       RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
+       return RADEON_READ(RADEON_PCIE_DATA);
+}
+
+#if RADEON_FIFO_DEBUG
+static void radeon_status(drm_radeon_private_t * dev_priv)
+{
+       printk("%s:\n", __func__);
+       printk("RBBM_STATUS = 0x%08x\n",
+              (unsigned int)RADEON_READ(RADEON_RBBM_STATUS));
+       printk("CP_RB_RTPR = 0x%08x\n",
+              (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR));
+       printk("CP_RB_WTPR = 0x%08x\n",
+              (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR));
+       printk("AIC_CNTL = 0x%08x\n",
+              (unsigned int)RADEON_READ(RADEON_AIC_CNTL));
+       printk("AIC_STAT = 0x%08x\n",
+              (unsigned int)RADEON_READ(RADEON_AIC_STAT));
+       printk("AIC_PT_BASE = 0x%08x\n",
+              (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE));
+       printk("TLB_ADDR = 0x%08x\n",
+              (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR));
+       printk("TLB_DATA = 0x%08x\n",
+              (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA));
+}
+#endif
+
+/* ================================================================
+ * Engine, FIFO control
+ */
+
+static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
+{
+       u32 tmp;
+       int i;
+
+       dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {
+               tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
+               tmp |= RADEON_RB3D_DC_FLUSH_ALL;
+               RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
+
+               for (i = 0; i < dev_priv->usec_timeout; i++) {
+                       if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT)
+                             & RADEON_RB3D_DC_BUSY)) {
+                               return 0;
+                       }
+                       DRM_UDELAY(1);
+               }
+       } else {
+               /* 3D */
+               tmp = RADEON_READ(R300_RB3D_DSTCACHE_CTLSTAT);
+               tmp |= RADEON_RB3D_DC_FLUSH_ALL;
+               RADEON_WRITE(R300_RB3D_DSTCACHE_CTLSTAT, tmp);
+
+               /* 2D */
+               tmp = RADEON_READ(R300_DSTCACHE_CTLSTAT);
+               tmp |= RADEON_RB3D_DC_FLUSH_ALL;
+               RADEON_WRITE(R300_DSTCACHE_CTLSTAT, tmp);
+
+               for (i = 0; i < dev_priv->usec_timeout; i++) {
+                       if (!(RADEON_READ(R300_DSTCACHE_CTLSTAT)
+                         & RADEON_RB3D_DC_BUSY)) {
+                               return 0;
+                       }
+                       DRM_UDELAY(1);
+               }
+       }
+
+#if RADEON_FIFO_DEBUG
+       DRM_ERROR("failed!\n");
+       radeon_status(dev_priv);
+#endif
+       return -EBUSY;
+}
+
+static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries)
+{
+       int i;
+
+       dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+       for (i = 0; i < dev_priv->usec_timeout; i++) {
+               int slots = (RADEON_READ(RADEON_RBBM_STATUS)
+                            & RADEON_RBBM_FIFOCNT_MASK);
+               if (slots >= entries)
+                       return 0;
+               DRM_UDELAY(1);
+       }
+
+#if RADEON_FIFO_DEBUG
+       DRM_ERROR("failed!\n");
+       radeon_status(dev_priv);
+#endif
+       return -EBUSY;
+}
+
+static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
+{
+       int i, ret;
+
+       dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+       ret = radeon_do_wait_for_fifo(dev_priv, 64);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < dev_priv->usec_timeout; i++) {
+               if (!(RADEON_READ(RADEON_RBBM_STATUS)
+                     & RADEON_RBBM_ACTIVE)) {
+                       radeon_do_pixcache_flush(dev_priv);
+                       return 0;
+               }
+               DRM_UDELAY(1);
+       }
+
+#if RADEON_FIFO_DEBUG
+       DRM_ERROR("failed!\n");
+       radeon_status(dev_priv);
+#endif
+       return -EBUSY;
+}
+
+static void radeon_init_pipes(drm_radeon_private_t *dev_priv)
+{
+       uint32_t gb_tile_config, gb_pipe_sel = 0;
+
+       /* RS4xx/RS6xx/R4xx/R5xx */
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) {
+               gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT);
+               dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
+       } else {
+               /* R3xx */
+               if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
+                   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350)) {
+                       dev_priv->num_gb_pipes = 2;
+               } else {
+                       /* R3Vxx */
+                       dev_priv->num_gb_pipes = 1;
+               }
+       }
+       DRM_INFO("Num pipes: %d\n", dev_priv->num_gb_pipes);
+
+       gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 /*| R300_SUBPIXEL_1_16*/);
+
+       switch (dev_priv->num_gb_pipes) {
+       case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break;
+       case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break;
+       case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break;
+       default:
+       case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
+       }
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
+               RADEON_WRITE_PLL(R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
+               RADEON_WRITE(R500_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1));
+       }
+       RADEON_WRITE(R300_GB_TILE_CONFIG, gb_tile_config);
+       radeon_do_wait_for_idle(dev_priv);
+       RADEON_WRITE(R300_DST_PIPE_CONFIG, RADEON_READ(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG);
+       RADEON_WRITE(R300_RB2D_DSTCACHE_MODE, (RADEON_READ(R300_RB2D_DSTCACHE_MODE) |
+                                              R300_DC_AUTOFLUSH_ENABLE |
+                                              R300_DC_DC_DISABLE_IGNORE_PE));
+
+
+}
+
+/* ================================================================
+ * CP control, initialization
+ */
+
+/* Load the microcode for the CP */
+static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
+{
+       int i;
+       DRM_DEBUG("\n");
+
+       radeon_do_wait_for_idle(dev_priv);
+
+       RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
+       if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) {
+               DRM_INFO("Loading R100 Microcode\n");
+               for (i = 0; i < 256; i++) {
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+                                    R100_cp_microcode[i][1]);
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+                                    R100_cp_microcode[i][0]);
+               }
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) {
+               DRM_INFO("Loading R200 Microcode\n");
+               for (i = 0; i < 256; i++) {
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+                                    R200_cp_microcode[i][1]);
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+                                    R200_cp_microcode[i][0]);
+               }
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
+               DRM_INFO("Loading R300 Microcode\n");
+               for (i = 0; i < 256; i++) {
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+                                    R300_cp_microcode[i][1]);
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+                                    R300_cp_microcode[i][0]);
+               }
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) {
+               DRM_INFO("Loading R400 Microcode\n");
+               for (i = 0; i < 256; i++) {
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+                                    R420_cp_microcode[i][1]);
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+                                    R420_cp_microcode[i][0]);
+               }
+       } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
+               DRM_INFO("Loading RS690 Microcode\n");
+               for (i = 0; i < 256; i++) {
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+                                    RS690_cp_microcode[i][1]);
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+                                    RS690_cp_microcode[i][0]);
+               }
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R580) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) {
+               DRM_INFO("Loading R500 Microcode\n");
+               for (i = 0; i < 256; i++) {
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+                                    R520_cp_microcode[i][1]);
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+                                    R520_cp_microcode[i][0]);
+               }
+       }
+}
+
+/* Flush any pending commands to the CP.  This should only be used just
+ * prior to a wait for idle, as it informs the engine that the command
+ * stream is ending.
+ */
+static void radeon_do_cp_flush(drm_radeon_private_t * dev_priv)
+{
+       DRM_DEBUG("\n");
+#if 0
+       u32 tmp;
+
+       tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31);
+       RADEON_WRITE(RADEON_CP_RB_WPTR, tmp);
+#endif
+}
+
+/* Wait for the CP to go idle.
+ */
+int radeon_do_cp_idle(drm_radeon_private_t * dev_priv)
+{
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_RING(6);
+
+       RADEON_PURGE_CACHE();
+       RADEON_PURGE_ZCACHE();
+       RADEON_WAIT_UNTIL_IDLE();
+
+       ADVANCE_RING();
+       COMMIT_RING();
+
+       return radeon_do_wait_for_idle(dev_priv);
+}
+
+/* Start the Command Processor.
+ */
+static void radeon_do_cp_start(drm_radeon_private_t * dev_priv)
+{
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       radeon_do_wait_for_idle(dev_priv);
+
+       RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode);
+
+       dev_priv->cp_running = 1;
+
+       BEGIN_RING(6);
+
+       RADEON_PURGE_CACHE();
+       RADEON_PURGE_ZCACHE();
+       RADEON_WAIT_UNTIL_IDLE();
+
+       ADVANCE_RING();
+       COMMIT_RING();
+}
+
+/* Reset the Command Processor.  This will not flush any pending
+ * commands, so you must wait for the CP command stream to complete
+ * before calling this routine.
+ */
+static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv)
+{
+       u32 cur_read_ptr;
+       DRM_DEBUG("\n");
+
+       cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
+       RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
+       SET_RING_HEAD(dev_priv, cur_read_ptr);
+       dev_priv->ring.tail = cur_read_ptr;
+}
+
+/* Stop the Command Processor.  This will not flush any pending
+ * commands, so you must flush the command stream and wait for the CP
+ * to go idle before calling this routine.
+ */
+static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
+{
+       DRM_DEBUG("\n");
+
+       RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
+
+       dev_priv->cp_running = 0;
+}
+
+/* Reset the engine.  This will stop the CP if it is running.
+ */
+static int radeon_do_engine_reset(struct drm_device * dev)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       u32 clock_cntl_index = 0, mclk_cntl = 0, rbbm_soft_reset;
+       DRM_DEBUG("\n");
+
+       radeon_do_pixcache_flush(dev_priv);
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
+               /* may need something similar for newer chips */
+               clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
+               mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
+
+               RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
+                                                   RADEON_FORCEON_MCLKA |
+                                                   RADEON_FORCEON_MCLKB |
+                                                   RADEON_FORCEON_YCLKA |
+                                                   RADEON_FORCEON_YCLKB |
+                                                   RADEON_FORCEON_MC |
+                                                   RADEON_FORCEON_AIC));
+       }
+
+       rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
+
+       RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
+                                             RADEON_SOFT_RESET_CP |
+                                             RADEON_SOFT_RESET_HI |
+                                             RADEON_SOFT_RESET_SE |
+                                             RADEON_SOFT_RESET_RE |
+                                             RADEON_SOFT_RESET_PP |
+                                             RADEON_SOFT_RESET_E2 |
+                                             RADEON_SOFT_RESET_RB));
+       RADEON_READ(RADEON_RBBM_SOFT_RESET);
+       RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
+                                             ~(RADEON_SOFT_RESET_CP |
+                                               RADEON_SOFT_RESET_HI |
+                                               RADEON_SOFT_RESET_SE |
+                                               RADEON_SOFT_RESET_RE |
+                                               RADEON_SOFT_RESET_PP |
+                                               RADEON_SOFT_RESET_E2 |
+                                               RADEON_SOFT_RESET_RB)));
+       RADEON_READ(RADEON_RBBM_SOFT_RESET);
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
+               RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
+               RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
+               RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
+       }
+
+       /* setup the raster pipes */
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300)
+           radeon_init_pipes(dev_priv);
+
+       /* Reset the CP ring */
+       radeon_do_cp_reset(dev_priv);
+
+       /* The CP is no longer running after an engine reset */
+       dev_priv->cp_running = 0;
+
+       /* Reset any pending vertex, indirect buffers */
+       radeon_freelist_reset(dev);
+
+       return 0;
+}
+
+static void radeon_cp_init_ring_buffer(struct drm_device * dev,
+                                      drm_radeon_private_t * dev_priv)
+{
+       u32 ring_start, cur_read_ptr;
+       u32 tmp;
+
+       /* Initialize the memory controller. With new memory map, the fb location
+        * is not changed, it should have been properly initialized already. Part
+        * of the problem is that the code below is bogus, assuming the GART is
+        * always appended to the fb which is not necessarily the case
+        */
+       if (!dev_priv->new_memmap)
+               radeon_write_fb_location(dev_priv,
+                            ((dev_priv->gart_vm_start - 1) & 0xffff0000)
+                            | (dev_priv->fb_location >> 16));
+
+#if __OS_HAS_AGP
+       if (dev_priv->flags & RADEON_IS_AGP) {
+               radeon_write_agp_base(dev_priv, dev->agp->base);
+
+               radeon_write_agp_location(dev_priv,
+                            (((dev_priv->gart_vm_start - 1 +
+                               dev_priv->gart_size) & 0xffff0000) |
+                             (dev_priv->gart_vm_start >> 16)));
+
+               ring_start = (dev_priv->cp_ring->offset
+                             - dev->agp->base
+                             + dev_priv->gart_vm_start);
+       } else
+#endif
+               ring_start = (dev_priv->cp_ring->offset
+                             - (unsigned long)dev->sg->virtual
+                             + dev_priv->gart_vm_start);
+
+       RADEON_WRITE(RADEON_CP_RB_BASE, ring_start);
+
+       /* Set the write pointer delay */
+       RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0);
+
+       /* Initialize the ring buffer's read and write pointers */
+       cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);
+       RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);
+       SET_RING_HEAD(dev_priv, cur_read_ptr);
+       dev_priv->ring.tail = cur_read_ptr;
+
+#if __OS_HAS_AGP
+       if (dev_priv->flags & RADEON_IS_AGP) {
+               RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
+                            dev_priv->ring_rptr->offset
+                            - dev->agp->base + dev_priv->gart_vm_start);
+       } else
+#endif
+       {
+               struct drm_sg_mem *entry = dev->sg;
+               unsigned long tmp_ofs, page_ofs;
+
+               tmp_ofs = dev_priv->ring_rptr->offset -
+                               (unsigned long)dev->sg->virtual;
+               page_ofs = tmp_ofs >> PAGE_SHIFT;
+
+               RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]);
+               DRM_DEBUG("ring rptr: offset=0x%08lx handle=0x%08lx\n",
+                         (unsigned long)entry->busaddr[page_ofs],
+                         entry->handle + tmp_ofs);
+       }
+
+       /* Set ring buffer size */
+#ifdef __BIG_ENDIAN
+       RADEON_WRITE(RADEON_CP_RB_CNTL,
+                    RADEON_BUF_SWAP_32BIT |
+                    (dev_priv->ring.fetch_size_l2ow << 18) |
+                    (dev_priv->ring.rptr_update_l2qw << 8) |
+                    dev_priv->ring.size_l2qw);
+#else
+       RADEON_WRITE(RADEON_CP_RB_CNTL,
+                    (dev_priv->ring.fetch_size_l2ow << 18) |
+                    (dev_priv->ring.rptr_update_l2qw << 8) |
+                    dev_priv->ring.size_l2qw);
+#endif
+
+       /* Start with assuming that writeback doesn't work */
+       dev_priv->writeback_works = 0;
+
+       /* Initialize the scratch register pointer.  This will cause
+        * the scratch register values to be written out to memory
+        * whenever they are updated.
+        *
+        * We simply put this behind the ring read pointer, this works
+        * with PCI GART as well as (whatever kind of) AGP GART
+        */
+       RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)
+                    + RADEON_SCRATCH_REG_OFFSET);
+
+       dev_priv->scratch = ((__volatile__ u32 *)
+                            dev_priv->ring_rptr->handle +
+                            (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
+
+       RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
+
+       /* Turn on bus mastering */
+       tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
+       RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+
+       dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
+       RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
+
+       dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
+       RADEON_WRITE(RADEON_LAST_DISPATCH_REG,
+                    dev_priv->sarea_priv->last_dispatch);
+
+       dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
+       RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
+
+       radeon_do_wait_for_idle(dev_priv);
+
+       /* Sync everything up */
+       RADEON_WRITE(RADEON_ISYNC_CNTL,
+                    (RADEON_ISYNC_ANY2D_IDLE3D |
+                     RADEON_ISYNC_ANY3D_IDLE2D |
+                     RADEON_ISYNC_WAIT_IDLEGUI |
+                     RADEON_ISYNC_CPSCRATCH_IDLEGUI));
+
+}
+
+static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
+{
+       u32 tmp;
+
+       /* Writeback doesn't seem to work everywhere, test it here and possibly
+        * enable it if it appears to work
+        */
+       DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);
+       RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
+
+       for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
+               if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==
+                   0xdeadbeef)
+                       break;
+               DRM_UDELAY(1);
+       }
+
+       if (tmp < dev_priv->usec_timeout) {
+               dev_priv->writeback_works = 1;
+               DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
+       } else {
+               dev_priv->writeback_works = 0;
+               DRM_INFO("writeback test failed\n");
+       }
+       if (radeon_no_wb == 1) {
+               dev_priv->writeback_works = 0;
+               DRM_INFO("writeback forced off\n");
+       }
+
+       if (!dev_priv->writeback_works) {
+               /* Disable writeback to avoid unnecessary bus master transfer */
+               RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) |
+                            RADEON_RB_NO_UPDATE);
+               RADEON_WRITE(RADEON_SCRATCH_UMSK, 0);
+       }
+}
+
+/* Enable or disable IGP GART on the chip */
+static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
+{
+       u32 temp;
+
+       if (on) {
+               DRM_DEBUG("programming igp gart %08X %08lX %08X\n",
+                         dev_priv->gart_vm_start,
+                         (long)dev_priv->gart_info.bus_addr,
+                         dev_priv->gart_size);
+
+               temp = IGP_READ_MCIND(dev_priv, RS480_MC_MISC_CNTL);
+               if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+                       IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, (RS480_GART_INDEX_REG_EN |
+                                                            RS690_BLOCK_GFX_D3_EN));
+               else
+                       IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN);
+
+               IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN |
+                                                              RS480_VA_SIZE_32MB));
+
+               temp = IGP_READ_MCIND(dev_priv, RS480_GART_FEATURE_ID);
+               IGP_WRITE_MCIND(RS480_GART_FEATURE_ID, (RS480_HANG_EN |
+                                                       RS480_TLB_ENABLE |
+                                                       RS480_GTW_LAC_EN |
+                                                       RS480_1LEVEL_GART));
+
+               temp = dev_priv->gart_info.bus_addr & 0xfffff000;
+               temp |= (upper_32_bits(dev_priv->gart_info.bus_addr) & 0xff) << 4;
+               IGP_WRITE_MCIND(RS480_GART_BASE, temp);
+
+               temp = IGP_READ_MCIND(dev_priv, RS480_AGP_MODE_CNTL);
+               IGP_WRITE_MCIND(RS480_AGP_MODE_CNTL, ((1 << RS480_REQ_TYPE_SNOOP_SHIFT) |
+                                                     RS480_REQ_TYPE_SNOOP_DIS));
+
+               radeon_write_agp_base(dev_priv, dev_priv->gart_vm_start);
+
+               dev_priv->gart_size = 32*1024*1024;
+               temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) &
+                        0xffff0000) | (dev_priv->gart_vm_start >> 16));
+
+               radeon_write_agp_location(dev_priv, temp);
+
+               temp = IGP_READ_MCIND(dev_priv, RS480_AGP_ADDRESS_SPACE_SIZE);
+               IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN |
+                                                              RS480_VA_SIZE_32MB));
+
+               do {
+                       temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
+                       if ((temp & RS480_GART_CACHE_INVALIDATE) == 0)
+                               break;
+                       DRM_UDELAY(1);
+               } while (1);
+
+               IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL,
+                               RS480_GART_CACHE_INVALIDATE);
+
+               do {
+                       temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
+                       if ((temp & RS480_GART_CACHE_INVALIDATE) == 0)
+                               break;
+                       DRM_UDELAY(1);
+               } while (1);
+
+               IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, 0);
+       } else {
+               IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, 0);
+       }
+}
+
+static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
+{
+       u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);
+       if (on) {
+
+               DRM_DEBUG("programming pcie %08X %08lX %08X\n",
+                         dev_priv->gart_vm_start,
+                         (long)dev_priv->gart_info.bus_addr,
+                         dev_priv->gart_size);
+               RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO,
+                                 dev_priv->gart_vm_start);
+               RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE,
+                                 dev_priv->gart_info.bus_addr);
+               RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO,
+                                 dev_priv->gart_vm_start);
+               RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO,
+                                 dev_priv->gart_vm_start +
+                                 dev_priv->gart_size - 1);
+
+               radeon_write_agp_location(dev_priv, 0xffffffc0); /* ?? */
+
+               RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
+                                 RADEON_PCIE_TX_GART_EN);
+       } else {
+               RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,
+                                 tmp & ~RADEON_PCIE_TX_GART_EN);
+       }
+}
+
+/* Enable or disable PCI GART on the chip */
+static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
+{
+       u32 tmp;
+
+       if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+           (dev_priv->flags & RADEON_IS_IGPGART)) {
+               radeon_set_igpgart(dev_priv, on);
+               return;
+       }
+
+       if (dev_priv->flags & RADEON_IS_PCIE) {
+               radeon_set_pciegart(dev_priv, on);
+               return;
+       }
+
+       tmp = RADEON_READ(RADEON_AIC_CNTL);
+
+       if (on) {
+               RADEON_WRITE(RADEON_AIC_CNTL,
+                            tmp | RADEON_PCIGART_TRANSLATE_EN);
+
+               /* set PCI GART page-table base address
+                */
+               RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr);
+
+               /* set address range for PCI address translate
+                */
+               RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start);
+               RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start
+                            + dev_priv->gart_size - 1);
+
+               /* Turn off AGP aperture -- is this required for PCI GART?
+                */
+               radeon_write_agp_location(dev_priv, 0xffffffc0);
+               RADEON_WRITE(RADEON_AGP_COMMAND, 0);    /* clear AGP_COMMAND */
+       } else {
+               RADEON_WRITE(RADEON_AIC_CNTL,
+                            tmp & ~RADEON_PCIGART_TRANSLATE_EN);
+       }
+}
+
+static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+
+       /* if we require new memory map but we don't have it fail */
+       if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
+               DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
+               radeon_do_cleanup_cp(dev);
+               return -EINVAL;
+       }
+
+       if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
+               DRM_DEBUG("Forcing AGP card to PCI mode\n");
+               dev_priv->flags &= ~RADEON_IS_AGP;
+       } else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE))
+                  && !init->is_pci) {
+               DRM_DEBUG("Restoring AGP flag\n");
+               dev_priv->flags |= RADEON_IS_AGP;
+       }
+
+       if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) {
+               DRM_ERROR("PCI GART memory not allocated!\n");
+               radeon_do_cleanup_cp(dev);
+               return -EINVAL;
+       }
+
+       dev_priv->usec_timeout = init->usec_timeout;
+       if (dev_priv->usec_timeout < 1 ||
+           dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
+               DRM_DEBUG("TIMEOUT problem!\n");
+               radeon_do_cleanup_cp(dev);
+               return -EINVAL;
+       }
+
+       /* Enable vblank on CRTC1 for older X servers
+        */
+       dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
+
+       switch(init->func) {
+       case RADEON_INIT_R200_CP:
+               dev_priv->microcode_version = UCODE_R200;
+               break;
+       case RADEON_INIT_R300_CP:
+               dev_priv->microcode_version = UCODE_R300;
+               break;
+       default:
+               dev_priv->microcode_version = UCODE_R100;
+       }
+
+       dev_priv->do_boxes = 0;
+       dev_priv->cp_mode = init->cp_mode;
+
+       /* We don't support anything other than bus-mastering ring mode,
+        * but the ring can be in either AGP or PCI space for the ring
+        * read pointer.
+        */
+       if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
+           (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
+               DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
+               radeon_do_cleanup_cp(dev);
+               return -EINVAL;
+       }
+
+       switch (init->fb_bpp) {
+       case 16:
+               dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
+               break;
+       case 32:
+       default:
+               dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
+               break;
+       }
+       dev_priv->front_offset = init->front_offset;
+       dev_priv->front_pitch = init->front_pitch;
+       dev_priv->back_offset = init->back_offset;
+       dev_priv->back_pitch = init->back_pitch;
+
+       switch (init->depth_bpp) {
+       case 16:
+               dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
+               break;
+       case 32:
+       default:
+               dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
+               break;
+       }
+       dev_priv->depth_offset = init->depth_offset;
+       dev_priv->depth_pitch = init->depth_pitch;
+
+       /* Hardware state for depth clears.  Remove this if/when we no
+        * longer clear the depth buffer with a 3D rectangle.  Hard-code
+        * all values to prevent unwanted 3D state from slipping through
+        * and screwing with the clear operation.
+        */
+       dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
+                                          (dev_priv->color_fmt << 10) |
+                                          (dev_priv->microcode_version ==
+                                           UCODE_R100 ? RADEON_ZBLOCK16 : 0));
+
+       dev_priv->depth_clear.rb3d_zstencilcntl =
+           (dev_priv->depth_fmt |
+            RADEON_Z_TEST_ALWAYS |
+            RADEON_STENCIL_TEST_ALWAYS |
+            RADEON_STENCIL_S_FAIL_REPLACE |
+            RADEON_STENCIL_ZPASS_REPLACE |
+            RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE);
+
+       dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |
+                                        RADEON_BFACE_SOLID |
+                                        RADEON_FFACE_SOLID |
+                                        RADEON_FLAT_SHADE_VTX_LAST |
+                                        RADEON_DIFFUSE_SHADE_FLAT |
+                                        RADEON_ALPHA_SHADE_FLAT |
+                                        RADEON_SPECULAR_SHADE_FLAT |
+                                        RADEON_FOG_SHADE_FLAT |
+                                        RADEON_VTX_PIX_CENTER_OGL |
+                                        RADEON_ROUND_MODE_TRUNC |
+                                        RADEON_ROUND_PREC_8TH_PIX);
+
+
+       dev_priv->ring_offset = init->ring_offset;
+       dev_priv->ring_rptr_offset = init->ring_rptr_offset;
+       dev_priv->buffers_offset = init->buffers_offset;
+       dev_priv->gart_textures_offset = init->gart_textures_offset;
+
+       dev_priv->sarea = drm_getsarea(dev);
+       if (!dev_priv->sarea) {
+               DRM_ERROR("could not find sarea!\n");
+               radeon_do_cleanup_cp(dev);
+               return -EINVAL;
+       }
+
+       dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
+       if (!dev_priv->cp_ring) {
+               DRM_ERROR("could not find cp ring region!\n");
+               radeon_do_cleanup_cp(dev);
+               return -EINVAL;
+       }
+       dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
+       if (!dev_priv->ring_rptr) {
+               DRM_ERROR("could not find ring read pointer!\n");
+               radeon_do_cleanup_cp(dev);
+               return -EINVAL;
+       }
+       dev->agp_buffer_token = init->buffers_offset;
+       dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+       if (!dev->agp_buffer_map) {
+               DRM_ERROR("could not find dma buffer region!\n");
+               radeon_do_cleanup_cp(dev);
+               return -EINVAL;
+       }
+
+       if (init->gart_textures_offset) {
+               dev_priv->gart_textures =
+                   drm_core_findmap(dev, init->gart_textures_offset);
+               if (!dev_priv->gart_textures) {
+                       DRM_ERROR("could not find GART texture region!\n");
+                       radeon_do_cleanup_cp(dev);
+                       return -EINVAL;
+               }
+       }
+
+       dev_priv->sarea_priv =
+           (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+                                   init->sarea_priv_offset);
+
+#if __OS_HAS_AGP
+       if (dev_priv->flags & RADEON_IS_AGP) {
+               drm_core_ioremap(dev_priv->cp_ring, dev);
+               drm_core_ioremap(dev_priv->ring_rptr, dev);
+               drm_core_ioremap(dev->agp_buffer_map, dev);
+               if (!dev_priv->cp_ring->handle ||
+                   !dev_priv->ring_rptr->handle ||
+                   !dev->agp_buffer_map->handle) {
+                       DRM_ERROR("could not find ioremap agp regions!\n");
+                       radeon_do_cleanup_cp(dev);
+                       return -EINVAL;
+               }
+       } else
+#endif
+       {
+               dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset;
+               dev_priv->ring_rptr->handle =
+                   (void *)dev_priv->ring_rptr->offset;
+               dev->agp_buffer_map->handle =
+                   (void *)dev->agp_buffer_map->offset;
+
+               DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
+                         dev_priv->cp_ring->handle);
+               DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
+                         dev_priv->ring_rptr->handle);
+               DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
+                         dev->agp_buffer_map->handle);
+       }
+
+       dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16;
+       dev_priv->fb_size =
+               ((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000)
+               - dev_priv->fb_location;
+
+       dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
+                                       ((dev_priv->front_offset
+                                         + dev_priv->fb_location) >> 10));
+
+       dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |
+                                      ((dev_priv->back_offset
+                                        + dev_priv->fb_location) >> 10));
+
+       dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |
+                                       ((dev_priv->depth_offset
+                                         + dev_priv->fb_location) >> 10));
+
+       dev_priv->gart_size = init->gart_size;
+
+       /* New let's set the memory map ... */
+       if (dev_priv->new_memmap) {
+               u32 base = 0;
+
+               DRM_INFO("Setting GART location based on new memory map\n");
+
+               /* If using AGP, try to locate the AGP aperture at the same
+                * location in the card and on the bus, though we have to
+                * align it down.
+                */
+#if __OS_HAS_AGP
+               if (dev_priv->flags & RADEON_IS_AGP) {
+                       base = dev->agp->base;
+                       /* Check if valid */
+                       if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location &&
+                           base < (dev_priv->fb_location + dev_priv->fb_size - 1)) {
+                               DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
+                                        dev->agp->base);
+                               base = 0;
+                       }
+               }
+#endif
+               /* If not or if AGP is at 0 (Macs), try to put it elsewhere */
+               if (base == 0) {
+                       base = dev_priv->fb_location + dev_priv->fb_size;
+                       if (base < dev_priv->fb_location ||
+                           ((base + dev_priv->gart_size) & 0xfffffffful) < base)
+                               base = dev_priv->fb_location
+                                       - dev_priv->gart_size;
+               }
+               dev_priv->gart_vm_start = base & 0xffc00000u;
+               if (dev_priv->gart_vm_start != base)
+                       DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
+                                base, dev_priv->gart_vm_start);
+       } else {
+               DRM_INFO("Setting GART location based on old memory map\n");
+               dev_priv->gart_vm_start = dev_priv->fb_location +
+                       RADEON_READ(RADEON_CONFIG_APER_SIZE);
+       }
+
+#if __OS_HAS_AGP
+       if (dev_priv->flags & RADEON_IS_AGP)
+               dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
+                                                - dev->agp->base
+                                                + dev_priv->gart_vm_start);
+       else
+#endif
+               dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
+                                       - (unsigned long)dev->sg->virtual
+                                       + dev_priv->gart_vm_start);
+
+       DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);
+       DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start);
+       DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n",
+                 dev_priv->gart_buffers_offset);
+
+       dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
+       dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
+                             + init->ring_size / sizeof(u32));
+       dev_priv->ring.size = init->ring_size;
+       dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
+
+       dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
+       dev_priv->ring.rptr_update_l2qw = drm_order( /* init->rptr_update */ 4096 / 8);
+
+       dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
+       dev_priv->ring.fetch_size_l2ow = drm_order( /* init->fetch_size */ 32 / 16);
+       dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
+
+       dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
+
+#if __OS_HAS_AGP
+       if (dev_priv->flags & RADEON_IS_AGP) {
+               /* Turn off PCI GART */
+               radeon_set_pcigart(dev_priv, 0);
+       } else
+#endif
+       {
+               dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
+               /* if we have an offset set from userspace */
+               if (dev_priv->pcigart_offset_set) {
+                       dev_priv->gart_info.bus_addr =
+                           dev_priv->pcigart_offset + dev_priv->fb_location;
+                       dev_priv->gart_info.mapping.offset =
+                           dev_priv->pcigart_offset + dev_priv->fb_aper_offset;
+                       dev_priv->gart_info.mapping.size =
+                           dev_priv->gart_info.table_size;
+
+                       drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
+                       dev_priv->gart_info.addr =
+                           dev_priv->gart_info.mapping.handle;
+
+                       if (dev_priv->flags & RADEON_IS_PCIE)
+                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;
+                       else
+                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
+                       dev_priv->gart_info.gart_table_location =
+                           DRM_ATI_GART_FB;
+
+                       DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
+                                 dev_priv->gart_info.addr,
+                                 dev_priv->pcigart_offset);
+               } else {
+                       if (dev_priv->flags & RADEON_IS_IGPGART)
+                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP;
+                       else
+                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
+                       dev_priv->gart_info.gart_table_location =
+                           DRM_ATI_GART_MAIN;
+                       dev_priv->gart_info.addr = NULL;
+                       dev_priv->gart_info.bus_addr = 0;
+                       if (dev_priv->flags & RADEON_IS_PCIE) {
+                               DRM_ERROR
+                                   ("Cannot use PCI Express without GART in FB memory\n");
+                               radeon_do_cleanup_cp(dev);
+                               return -EINVAL;
+                       }
+               }
+
+               if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
+                       DRM_ERROR("failed to init PCI GART!\n");
+                       radeon_do_cleanup_cp(dev);
+                       return -ENOMEM;
+               }
+
+               /* Turn on PCI GART */
+               radeon_set_pcigart(dev_priv, 1);
+       }
+
+       radeon_cp_load_microcode(dev_priv);
+       radeon_cp_init_ring_buffer(dev, dev_priv);
+
+       dev_priv->last_buf = 0;
+
+       radeon_do_engine_reset(dev);
+       radeon_test_writeback(dev_priv);
+
+       return 0;
+}
+
+static int radeon_do_cleanup_cp(struct drm_device * dev)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG("\n");
+
+       /* Make sure interrupts are disabled here because the uninstall ioctl
+        * may not have been called from userspace and after dev_private
+        * is freed, it's too late.
+        */
+       if (dev->irq_enabled)
+               drm_irq_uninstall(dev);
+
+#if __OS_HAS_AGP
+       if (dev_priv->flags & RADEON_IS_AGP) {
+               if (dev_priv->cp_ring != NULL) {
+                       drm_core_ioremapfree(dev_priv->cp_ring, dev);
+                       dev_priv->cp_ring = NULL;
+               }
+               if (dev_priv->ring_rptr != NULL) {
+                       drm_core_ioremapfree(dev_priv->ring_rptr, dev);
+                       dev_priv->ring_rptr = NULL;
+               }
+               if (dev->agp_buffer_map != NULL) {
+                       drm_core_ioremapfree(dev->agp_buffer_map, dev);
+                       dev->agp_buffer_map = NULL;
+               }
+       } else
+#endif
+       {
+
+               if (dev_priv->gart_info.bus_addr) {
+                       /* Turn off PCI GART */
+                       radeon_set_pcigart(dev_priv, 0);
+                       if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
+                               DRM_ERROR("failed to cleanup PCI GART!\n");
+               }
+
+               if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
+               {
+                       drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
+                       dev_priv->gart_info.addr = 0;
+               }
+       }
+       /* only clear to the start of flags */
+       memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
+
+       return 0;
+}
+
+/* This code will reinit the Radeon CP hardware after a resume from disc.
+ * AFAIK, it would be very difficult to pickle the state at suspend time, so
+ * here we make sure that all Radeon hardware initialisation is re-done without
+ * affecting running applications.
+ *
+ * Charl P. Botha <http://cpbotha.net>
+ */
+static int radeon_do_resume_cp(struct drm_device * dev)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+
+       if (!dev_priv) {
+               DRM_ERROR("Called with no initialization\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("Starting radeon_do_resume_cp()\n");
+
+#if __OS_HAS_AGP
+       if (dev_priv->flags & RADEON_IS_AGP) {
+               /* Turn off PCI GART */
+               radeon_set_pcigart(dev_priv, 0);
+       } else
+#endif
+       {
+               /* Turn on PCI GART */
+               radeon_set_pcigart(dev_priv, 1);
+       }
+
+       radeon_cp_load_microcode(dev_priv);
+       radeon_cp_init_ring_buffer(dev, dev_priv);
+
+       radeon_do_engine_reset(dev);
+       radeon_enable_interrupt(dev);
+
+       DRM_DEBUG("radeon_do_resume_cp() complete\n");
+
+       return 0;
+}
+
+int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_init_t *init = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (init->func == RADEON_INIT_R300_CP)
+               r300_init_reg_flags(dev);
+
+       switch (init->func) {
+       case RADEON_INIT_CP:
+       case RADEON_INIT_R200_CP:
+       case RADEON_INIT_R300_CP:
+               return radeon_do_init_cp(dev, init);
+       case RADEON_CLEANUP_CP:
+               return radeon_do_cleanup_cp(dev);
+       }
+
+       return -EINVAL;
+}
+
+int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (dev_priv->cp_running) {
+               DRM_DEBUG("while CP running\n");
+               return 0;
+       }
+       if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) {
+               DRM_DEBUG("called with bogus CP mode (%d)\n",
+                         dev_priv->cp_mode);
+               return 0;
+       }
+
+       radeon_do_cp_start(dev_priv);
+
+       return 0;
+}
+
+/* Stop the CP.  The engine must have been idled before calling this
+ * routine.
+ */
+int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_cp_stop_t *stop = data;
+       int ret;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (!dev_priv->cp_running)
+               return 0;
+
+       /* Flush any pending CP commands.  This ensures any outstanding
+        * commands are exectuted by the engine before we turn it off.
+        */
+       if (stop->flush) {
+               radeon_do_cp_flush(dev_priv);
+       }
+
+       /* If we fail to make the engine go idle, we return an error
+        * code so that the DRM ioctl wrapper can try again.
+        */
+       if (stop->idle) {
+               ret = radeon_do_cp_idle(dev_priv);
+               if (ret)
+                       return ret;
+       }
+
+       /* Finally, we can turn off the CP.  If the engine isn't idle,
+        * we will get some dropped triangles as they won't be fully
+        * rendered before the CP is shut down.
+        */
+       radeon_do_cp_stop(dev_priv);
+
+       /* Reset the engine */
+       radeon_do_engine_reset(dev);
+
+       return 0;
+}
+
+void radeon_do_release(struct drm_device * dev)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       int i, ret;
+
+       if (dev_priv) {
+               if (dev_priv->cp_running) {
+                       /* Stop the cp */
+                       while ((ret = radeon_do_cp_idle(dev_priv)) != 0) {
+                               DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
+#ifdef __linux__
+                               schedule();
+#else
+                               tsleep(&ret, PZERO, "rdnrel", 1);
+#endif
+                       }
+                       radeon_do_cp_stop(dev_priv);
+                       radeon_do_engine_reset(dev);
+               }
+
+               /* Disable *all* interrupts */
+               if (dev_priv->mmio)     /* remove this after permanent addmaps */
+                       RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+
+               if (dev_priv->mmio) {   /* remove all surfaces */
+                       for (i = 0; i < RADEON_MAX_SURFACES; i++) {
+                               RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0);
+                               RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND +
+                                            16 * i, 0);
+                               RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND +
+                                            16 * i, 0);
+                       }
+               }
+
+               /* Free memory heap structures */
+               radeon_mem_takedown(&(dev_priv->gart_heap));
+               radeon_mem_takedown(&(dev_priv->fb_heap));
+
+               /* deallocate kernel resources */
+               radeon_do_cleanup_cp(dev);
+       }
+}
+
+/* Just reset the CP ring.  Called as part of an X Server engine reset.
+ */
+int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (!dev_priv) {
+               DRM_DEBUG("called before init done\n");
+               return -EINVAL;
+       }
+
+       radeon_do_cp_reset(dev_priv);
+
+       /* The CP is no longer running after an engine reset */
+       dev_priv->cp_running = 0;
+
+       return 0;
+}
+
+int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       return radeon_do_cp_idle(dev_priv);
+}
+
+/* Added by Charl P. Botha to call radeon_do_resume_cp().
+ */
+int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+
+       return radeon_do_resume_cp(dev);
+}
+
+int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       return radeon_do_engine_reset(dev);
+}
+
+/* ================================================================
+ * Fullscreen mode
+ */
+
+/* KW: Deprecated to say the least:
+ */
+int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       return 0;
+}
+
+/* ================================================================
+ * Freelist management
+ */
+
+/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through
+ *   bufs until freelist code is used.  Note this hides a problem with
+ *   the scratch register * (used to keep track of last buffer
+ *   completed) being written to before * the last buffer has actually
+ *   completed rendering.
+ *
+ * KW:  It's also a good way to find free buffers quickly.
+ *
+ * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't
+ * sleep.  However, bugs in older versions of radeon_accel.c mean that
+ * we essentially have to do this, else old clients will break.
+ *
+ * However, it does leave open a potential deadlock where all the
+ * buffers are held by other clients, which can't release them because
+ * they can't get the lock.
+ */
+
+struct drm_buf *radeon_freelist_get(struct drm_device * dev)
+{
+       struct drm_device_dma *dma = dev->dma;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_buf_priv_t *buf_priv;
+       struct drm_buf *buf;
+       int i, t;
+       int start;
+
+       if (++dev_priv->last_buf >= dma->buf_count)
+               dev_priv->last_buf = 0;
+
+       start = dev_priv->last_buf;
+
+       for (t = 0; t < dev_priv->usec_timeout; t++) {
+               u32 done_age = GET_SCRATCH(1);
+               DRM_DEBUG("done_age = %d\n", done_age);
+               for (i = start; i < dma->buf_count; i++) {
+                       buf = dma->buflist[i];
+                       buf_priv = buf->dev_private;
+                       if (buf->file_priv == NULL || (buf->pending &&
+                                                      buf_priv->age <=
+                                                      done_age)) {
+                               dev_priv->stats.requested_bufs++;
+                               buf->pending = 0;
+                               return buf;
+                       }
+                       start = 0;
+               }
+
+               if (t) {
+                       DRM_UDELAY(1);
+                       dev_priv->stats.freelist_loops++;
+               }
+       }
+
+       DRM_DEBUG("returning NULL!\n");
+       return NULL;
+}
+
+#if 0
+struct drm_buf *radeon_freelist_get(struct drm_device * dev)
+{
+       struct drm_device_dma *dma = dev->dma;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_buf_priv_t *buf_priv;
+       struct drm_buf *buf;
+       int i, t;
+       int start;
+       u32 done_age = DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1));
+
+       if (++dev_priv->last_buf >= dma->buf_count)
+               dev_priv->last_buf = 0;
+
+       start = dev_priv->last_buf;
+       dev_priv->stats.freelist_loops++;
+
+       for (t = 0; t < 2; t++) {
+               for (i = start; i < dma->buf_count; i++) {
+                       buf = dma->buflist[i];
+                       buf_priv = buf->dev_private;
+                       if (buf->file_priv == 0 || (buf->pending &&
+                                                   buf_priv->age <=
+                                                   done_age)) {
+                               dev_priv->stats.requested_bufs++;
+                               buf->pending = 0;
+                               return buf;
+                       }
+               }
+               start = 0;
+       }
+
+       return NULL;
+}
+#endif
+
+void radeon_freelist_reset(struct drm_device * dev)
+{
+       struct drm_device_dma *dma = dev->dma;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       int i;
+
+       dev_priv->last_buf = 0;
+       for (i = 0; i < dma->buf_count; i++) {
+               struct drm_buf *buf = dma->buflist[i];
+               drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+               buf_priv->age = 0;
+       }
+}
+
+/* ================================================================
+ * CP command submission
+ */
+
+int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n)
+{
+       drm_radeon_ring_buffer_t *ring = &dev_priv->ring;
+       int i;
+       u32 last_head = GET_RING_HEAD(dev_priv);
+
+       for (i = 0; i < dev_priv->usec_timeout; i++) {
+               u32 head = GET_RING_HEAD(dev_priv);
+
+               ring->space = (head - ring->tail) * sizeof(u32);
+               if (ring->space <= 0)
+                       ring->space += ring->size;
+               if (ring->space > n)
+                       return 0;
+
+               dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+               if (head != last_head)
+                       i = 0;
+               last_head = head;
+
+               DRM_UDELAY(1);
+       }
+
+       /* FIXME: This return value is ignored in the BEGIN_RING macro! */
+#if RADEON_FIFO_DEBUG
+       radeon_status(dev_priv);
+       DRM_ERROR("failed!\n");
+#endif
+       return -EBUSY;
+}
+
+static int radeon_cp_get_buffers(struct drm_device *dev,
+                                struct drm_file *file_priv,
+                                struct drm_dma * d)
+{
+       int i;
+       struct drm_buf *buf;
+
+       for (i = d->granted_count; i < d->request_count; i++) {
+               buf = radeon_freelist_get(dev);
+               if (!buf)
+                       return -EBUSY;  /* NOTE: broken client */
+
+               buf->file_priv = file_priv;
+
+               if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx,
+                                    sizeof(buf->idx)))
+                       return -EFAULT;
+               if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total,
+                                    sizeof(buf->total)))
+                       return -EFAULT;
+
+               d->granted_count++;
+       }
+       return 0;
+}
+
+int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       int ret = 0;
+       struct drm_dma *d = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       /* Please don't send us buffers.
+        */
+       if (d->send_count != 0) {
+               DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+                         DRM_CURRENTPID, d->send_count);
+               return -EINVAL;
+       }
+
+       /* We'll send you buffers.
+        */
+       if (d->request_count < 0 || d->request_count > dma->buf_count) {
+               DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+                         DRM_CURRENTPID, d->request_count, dma->buf_count);
+               return -EINVAL;
+       }
+
+       d->granted_count = 0;
+
+       if (d->request_count) {
+               ret = radeon_cp_get_buffers(dev, file_priv, d);
+       }
+
+       return ret;
+}
+
+int radeon_driver_load(struct drm_device *dev, unsigned long flags)
+{
+       drm_radeon_private_t *dev_priv;
+       int ret = 0;
+
+       dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       memset(dev_priv, 0, sizeof(drm_radeon_private_t));
+       dev->dev_private = (void *)dev_priv;
+       dev_priv->flags = flags;
+
+       switch (flags & RADEON_FAMILY_MASK) {
+       case CHIP_R100:
+       case CHIP_RV200:
+       case CHIP_R200:
+       case CHIP_R300:
+       case CHIP_R350:
+       case CHIP_R420:
+       case CHIP_RV410:
+       case CHIP_RV515:
+       case CHIP_R520:
+       case CHIP_RV570:
+       case CHIP_R580:
+               dev_priv->flags |= RADEON_HAS_HIERZ;
+               break;
+       default:
+               /* all other chips have no hierarchical z buffer */
+               break;
+       }
+
+       if (drm_device_is_agp(dev))
+               dev_priv->flags |= RADEON_IS_AGP;
+       else if (drm_device_is_pcie(dev))
+               dev_priv->flags |= RADEON_IS_PCIE;
+       else
+               dev_priv->flags |= RADEON_IS_PCI;
+
+       DRM_DEBUG("%s card detected\n",
+                 ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
+       return ret;
+}
+
+/* Create mappings for registers and framebuffer so userland doesn't necessarily
+ * have to find them.
+ */
+int radeon_driver_firstopen(struct drm_device *dev)
+{
+       int ret;
+       drm_local_map_t *map;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+
+       dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
+
+       ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
+                        drm_get_resource_len(dev, 2), _DRM_REGISTERS,
+                        _DRM_READ_ONLY, &dev_priv->mmio);
+       if (ret != 0)
+               return ret;
+
+       dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0);
+       ret = drm_addmap(dev, dev_priv->fb_aper_offset,
+                        drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER,
+                        _DRM_WRITE_COMBINING, &map);
+       if (ret != 0)
+               return ret;
+
+       return 0;
+}
+
+int radeon_driver_unload(struct drm_device *dev)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+       drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+
+       dev->dev_private = NULL;
+       return 0;
+}
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
new file mode 100644 (file)
index 0000000..349ac3d
--- /dev/null
@@ -0,0 +1,126 @@
+/**
+ * \file radeon_drv.c
+ * ATI Radeon driver
+ *
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+#include "drm_pciids.h"
+
+int radeon_no_wb;
+
+MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers\n");
+module_param_named(no_wb, radeon_no_wb, int, 0444);
+
+static int dri_library_name(struct drm_device *dev, char *buf)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       int family = dev_priv->flags & RADEON_FAMILY_MASK;
+
+       return snprintf(buf, PAGE_SIZE, "%s\n",
+                       (family < CHIP_R200) ? "radeon" :
+                       ((family < CHIP_R300) ? "r200" :
+                       "r300"));
+}
+
+static struct pci_device_id pciidlist[] = {
+       radeon_PCI_IDS
+};
+
+static struct drm_driver driver = {
+       .driver_features =
+           DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
+           DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
+           DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
+       .dev_priv_size = sizeof(drm_radeon_buf_priv_t),
+       .load = radeon_driver_load,
+       .firstopen = radeon_driver_firstopen,
+       .open = radeon_driver_open,
+       .preclose = radeon_driver_preclose,
+       .postclose = radeon_driver_postclose,
+       .lastclose = radeon_driver_lastclose,
+       .unload = radeon_driver_unload,
+       .vblank_wait = radeon_driver_vblank_wait,
+       .vblank_wait2 = radeon_driver_vblank_wait2,
+       .dri_library_name = dri_library_name,
+       .irq_preinstall = radeon_driver_irq_preinstall,
+       .irq_postinstall = radeon_driver_irq_postinstall,
+       .irq_uninstall = radeon_driver_irq_uninstall,
+       .irq_handler = radeon_driver_irq_handler,
+       .reclaim_buffers = drm_core_reclaim_buffers,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .ioctls = radeon_ioctls,
+       .dma_ioctl = radeon_cp_buffers,
+       .fops = {
+                .owner = THIS_MODULE,
+                .open = drm_open,
+                .release = drm_release,
+                .ioctl = drm_ioctl,
+                .mmap = drm_mmap,
+                .poll = drm_poll,
+                .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+                .compat_ioctl = radeon_compat_ioctl,
+#endif
+       },
+
+       .pci_driver = {
+                .name = DRIVER_NAME,
+                .id_table = pciidlist,
+       },
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int __init radeon_init(void)
+{
+       driver.num_ioctls = radeon_max_ioctl;
+       return drm_init(&driver);
+}
+
+static void __exit radeon_exit(void)
+{
+       drm_exit(&driver);
+}
+
+module_init(radeon_init);
+module_exit(radeon_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
new file mode 100644 (file)
index 0000000..3f0eca9
--- /dev/null
@@ -0,0 +1,1406 @@
+/* radeon_drv.h -- Private header for radeon driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __RADEON_DRV_H__
+#define __RADEON_DRV_H__
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR          "Gareth Hughes, Keith Whitwell, others."
+
+#define DRIVER_NAME            "radeon"
+#define DRIVER_DESC            "ATI Radeon"
+#define DRIVER_DATE            "20080528"
+
+/* Interface history:
+ *
+ * 1.1 - ??
+ * 1.2 - Add vertex2 ioctl (keith)
+ *     - Add stencil capability to clear ioctl (gareth, keith)
+ *     - Increase MAX_TEXTURE_LEVELS (brian)
+ * 1.3 - Add cmdbuf ioctl (keith)
+ *     - Add support for new radeon packets (keith)
+ *     - Add getparam ioctl (keith)
+ *     - Add flip-buffers ioctl, deprecate fullscreen foo (keith).
+ * 1.4 - Add scratch registers to get_param ioctl.
+ * 1.5 - Add r200 packets to cmdbuf ioctl
+ *     - Add r200 function to init ioctl
+ *     - Add 'scalar2' instruction to cmdbuf
+ * 1.6 - Add static GART memory manager
+ *       Add irq handler (won't be turned on unless X server knows to)
+ *       Add irq ioctls and irq_active getparam.
+ *       Add wait command for cmdbuf ioctl
+ *       Add GART offset query for getparam
+ * 1.7 - Add support for cube map registers: R200_PP_CUBIC_FACES_[0..5]
+ *       and R200_PP_CUBIC_OFFSET_F1_[0..5].
+ *       Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and
+ *       R200_EMIT_PP_CUBIC_OFFSETS_[0..5].  (brian)
+ * 1.8 - Remove need to call cleanup ioctls on last client exit (keith)
+ *       Add 'GET' queries for starting additional clients on different VT's.
+ * 1.9 - Add DRM_IOCTL_RADEON_CP_RESUME ioctl.
+ *       Add texture rectangle support for r100.
+ * 1.10- Add SETPARAM ioctl; first parameter to set is FB_LOCATION, which
+ *       clients use to tell the DRM where they think the framebuffer is
+ *       located in the card's address space
+ * 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color
+ *       and GL_EXT_blend_[func|equation]_separate on r200
+ * 1.12- Add R300 CP microcode support - this just loads the CP on r300
+ *       (No 3D support yet - just microcode loading).
+ * 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters
+ *     - Add hyperz support, add hyperz flags to clear ioctl.
+ * 1.14- Add support for color tiling
+ *     - Add R100/R200 surface allocation/free support
+ * 1.15- Add support for texture micro tiling
+ *     - Add support for r100 cube maps
+ * 1.16- Add R200_EMIT_PP_TRI_PERF_CNTL packet to support brilinear
+ *       texture filtering on r200
+ * 1.17- Add initial support for R300 (3D).
+ * 1.18- Add support for GL_ATI_fragment_shader, new packets
+ *       R200_EMIT_PP_AFS_0/1, R200_EMIT_PP_TXCTLALL_0-5 (replaces
+ *       R200_EMIT_PP_TXFILTER_0-5, 2 more regs) and R200_EMIT_ATF_TFACTOR
+ *       (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6)
+ * 1.19- Add support for gart table in FB memory and PCIE r300
+ * 1.20- Add support for r300 texrect
+ * 1.21- Add support for card type getparam
+ * 1.22- Add support for texture cache flushes (R300_TX_CNTL)
+ * 1.23- Add new radeon memory map work from benh
+ * 1.24- Add general-purpose packet for manipulating scratch registers (r300)
+ * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL,
+ *       new packet type)
+ * 1.26- Add support for variable size PCI(E) gart aperture
+ * 1.27- Add support for IGP GART
+ * 1.28- Add support for VBL on CRTC2
+ * 1.29- R500 3D cmd buffer support
+ */
+#define DRIVER_MAJOR           1
+#define DRIVER_MINOR           29
+#define DRIVER_PATCHLEVEL      0
+
+/*
+ * Radeon chip families
+ */
+enum radeon_family {
+       CHIP_R100,
+       CHIP_RV100,
+       CHIP_RS100,
+       CHIP_RV200,
+       CHIP_RS200,
+       CHIP_R200,
+       CHIP_RV250,
+       CHIP_RS300,
+       CHIP_RV280,
+       CHIP_R300,
+       CHIP_R350,
+       CHIP_RV350,
+       CHIP_RV380,
+       CHIP_R420,
+       CHIP_RV410,
+       CHIP_RS480,
+       CHIP_RS690,
+       CHIP_RV515,
+       CHIP_R520,
+       CHIP_RV530,
+       CHIP_RV560,
+       CHIP_RV570,
+       CHIP_R580,
+       CHIP_LAST,
+};
+
+enum radeon_cp_microcode_version {
+       UCODE_R100,
+       UCODE_R200,
+       UCODE_R300,
+};
+
+/*
+ * Chip flags
+ */
+enum radeon_chip_flags {
+       RADEON_FAMILY_MASK = 0x0000ffffUL,
+       RADEON_FLAGS_MASK = 0xffff0000UL,
+       RADEON_IS_MOBILITY = 0x00010000UL,
+       RADEON_IS_IGP = 0x00020000UL,
+       RADEON_SINGLE_CRTC = 0x00040000UL,
+       RADEON_IS_AGP = 0x00080000UL,
+       RADEON_HAS_HIERZ = 0x00100000UL,
+       RADEON_IS_PCIE = 0x00200000UL,
+       RADEON_NEW_MEMMAP = 0x00400000UL,
+       RADEON_IS_PCI = 0x00800000UL,
+       RADEON_IS_IGPGART = 0x01000000UL,
+};
+
+#define GET_RING_HEAD(dev_priv)        (dev_priv->writeback_works ? \
+        DRM_READ32(  (dev_priv)->ring_rptr, 0 ) : RADEON_READ(RADEON_CP_RB_RPTR))
+#define SET_RING_HEAD(dev_priv,val)    DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
+
+typedef struct drm_radeon_freelist {
+       unsigned int age;
+       struct drm_buf *buf;
+       struct drm_radeon_freelist *next;
+       struct drm_radeon_freelist *prev;
+} drm_radeon_freelist_t;
+
+typedef struct drm_radeon_ring_buffer {
+       u32 *start;
+       u32 *end;
+       int size;
+       int size_l2qw;
+
+       int rptr_update; /* Double Words */
+       int rptr_update_l2qw; /* log2 Quad Words */
+
+       int fetch_size; /* Double Words */
+       int fetch_size_l2ow; /* log2 Oct Words */
+
+       u32 tail;
+       u32 tail_mask;
+       int space;
+
+       int high_mark;
+} drm_radeon_ring_buffer_t;
+
+typedef struct drm_radeon_depth_clear_t {
+       u32 rb3d_cntl;
+       u32 rb3d_zstencilcntl;
+       u32 se_cntl;
+} drm_radeon_depth_clear_t;
+
+struct drm_radeon_driver_file_fields {
+       int64_t radeon_fb_delta;
+};
+
+struct mem_block {
+       struct mem_block *next;
+       struct mem_block *prev;
+       int start;
+       int size;
+       struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */
+};
+
+struct radeon_surface {
+       int refcount;
+       u32 lower;
+       u32 upper;
+       u32 flags;
+};
+
+struct radeon_virt_surface {
+       int surface_index;
+       u32 lower;
+       u32 upper;
+       u32 flags;
+       struct drm_file *file_priv;
+};
+
+typedef struct drm_radeon_private {
+       drm_radeon_ring_buffer_t ring;
+       drm_radeon_sarea_t *sarea_priv;
+
+       u32 fb_location;
+       u32 fb_size;
+       int new_memmap;
+
+       int gart_size;
+       u32 gart_vm_start;
+       unsigned long gart_buffers_offset;
+
+       int cp_mode;
+       int cp_running;
+
+       drm_radeon_freelist_t *head;
+       drm_radeon_freelist_t *tail;
+       int last_buf;
+       volatile u32 *scratch;
+       int writeback_works;
+
+       int usec_timeout;
+
+       int microcode_version;
+
+       struct {
+               u32 boxes;
+               int freelist_timeouts;
+               int freelist_loops;
+               int requested_bufs;
+               int last_frame_reads;
+               int last_clear_reads;
+               int clears;
+               int texture_uploads;
+       } stats;
+
+       int do_boxes;
+       int page_flipping;
+
+       u32 color_fmt;
+       unsigned int front_offset;
+       unsigned int front_pitch;
+       unsigned int back_offset;
+       unsigned int back_pitch;
+
+       u32 depth_fmt;
+       unsigned int depth_offset;
+       unsigned int depth_pitch;
+
+       u32 front_pitch_offset;
+       u32 back_pitch_offset;
+       u32 depth_pitch_offset;
+
+       drm_radeon_depth_clear_t depth_clear;
+
+       unsigned long ring_offset;
+       unsigned long ring_rptr_offset;
+       unsigned long buffers_offset;
+       unsigned long gart_textures_offset;
+
+       drm_local_map_t *sarea;
+       drm_local_map_t *mmio;
+       drm_local_map_t *cp_ring;
+       drm_local_map_t *ring_rptr;
+       drm_local_map_t *gart_textures;
+
+       struct mem_block *gart_heap;
+       struct mem_block *fb_heap;
+
+       /* SW interrupt */
+       wait_queue_head_t swi_queue;
+       atomic_t swi_emitted;
+       int vblank_crtc;
+       uint32_t irq_enable_reg;
+       int irq_enabled;
+       uint32_t r500_disp_irq_reg;
+
+       struct radeon_surface surfaces[RADEON_MAX_SURFACES];
+       struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
+
+       unsigned long pcigart_offset;
+       unsigned int pcigart_offset_set;
+       struct drm_ati_pcigart_info gart_info;
+
+       u32 scratch_ages[5];
+
+       /* starting from here on, data is preserved accross an open */
+       uint32_t flags;         /* see radeon_chip_flags */
+       unsigned long fb_aper_offset;
+
+       int num_gb_pipes;
+} drm_radeon_private_t;
+
+typedef struct drm_radeon_buf_priv {
+       u32 age;
+} drm_radeon_buf_priv_t;
+
+typedef struct drm_radeon_kcmd_buffer {
+       int bufsz;
+       char *buf;
+       int nbox;
+       struct drm_clip_rect __user *boxes;
+} drm_radeon_kcmd_buffer_t;
+
+extern int radeon_no_wb;
+extern struct drm_ioctl_desc radeon_ioctls[];
+extern int radeon_max_ioctl;
+
+/* Check whether the given hardware address is inside the framebuffer or the
+ * GART area.
+ */
+static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv,
+                                         u64 off)
+{
+       u32 fb_start = dev_priv->fb_location;
+       u32 fb_end = fb_start + dev_priv->fb_size - 1;
+       u32 gart_start = dev_priv->gart_vm_start;
+       u32 gart_end = gart_start + dev_priv->gart_size - 1;
+
+       return ((off >= fb_start && off <= fb_end) ||
+               (off >= gart_start && off <= gart_end));
+}
+
+                               /* radeon_cp.c */
+extern int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv);
+
+extern void radeon_freelist_reset(struct drm_device * dev);
+extern struct drm_buf *radeon_freelist_get(struct drm_device * dev);
+
+extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n);
+
+extern int radeon_do_cp_idle(drm_radeon_private_t * dev_priv);
+
+extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags);
+extern int radeon_presetup(struct drm_device *dev);
+extern int radeon_driver_postcleanup(struct drm_device *dev);
+
+extern int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern void radeon_mem_takedown(struct mem_block **heap);
+extern void radeon_mem_release(struct drm_file *file_priv,
+                              struct mem_block *heap);
+
+                               /* radeon_irq.c */
+extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
+
+extern void radeon_do_release(struct drm_device * dev);
+extern int radeon_driver_vblank_wait(struct drm_device * dev,
+                                    unsigned int *sequence);
+extern int radeon_driver_vblank_wait2(struct drm_device * dev,
+                                     unsigned int *sequence);
+extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
+extern void radeon_driver_irq_preinstall(struct drm_device * dev);
+extern void radeon_driver_irq_postinstall(struct drm_device * dev);
+extern void radeon_driver_irq_uninstall(struct drm_device * dev);
+extern void radeon_enable_interrupt(struct drm_device *dev);
+extern int radeon_vblank_crtc_get(struct drm_device *dev);
+extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
+
+extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
+extern int radeon_driver_unload(struct drm_device *dev);
+extern int radeon_driver_firstopen(struct drm_device *dev);
+extern void radeon_driver_preclose(struct drm_device * dev, struct drm_file *file_priv);
+extern void radeon_driver_postclose(struct drm_device * dev, struct drm_file * filp);
+extern void radeon_driver_lastclose(struct drm_device * dev);
+extern int radeon_driver_open(struct drm_device * dev, struct drm_file * filp_priv);
+extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
+                               unsigned long arg);
+
+/* r300_cmdbuf.c */
+extern void r300_init_reg_flags(struct drm_device *dev);
+
+extern int r300_do_cp_cmdbuf(struct drm_device * dev,
+                            struct drm_file *file_priv,
+                            drm_radeon_kcmd_buffer_t * cmdbuf);
+
+/* Flags for stats.boxes
+ */
+#define RADEON_BOX_DMA_IDLE      0x1
+#define RADEON_BOX_RING_FULL     0x2
+#define RADEON_BOX_FLIP          0x4
+#define RADEON_BOX_WAIT_IDLE     0x8
+#define RADEON_BOX_TEXTURE_LOAD  0x10
+
+/* Register definitions, register access macros and drmAddMap constants
+ * for Radeon kernel driver.
+ */
+
+#define RADEON_AGP_COMMAND             0x0f60
+#define RADEON_AGP_COMMAND_PCI_CONFIG   0x0060 /* offset in PCI config */
+#      define RADEON_AGP_ENABLE        (1<<8)
+#define RADEON_AUX_SCISSOR_CNTL                0x26f0
+#      define RADEON_EXCLUSIVE_SCISSOR_0       (1 << 24)
+#      define RADEON_EXCLUSIVE_SCISSOR_1       (1 << 25)
+#      define RADEON_EXCLUSIVE_SCISSOR_2       (1 << 26)
+#      define RADEON_SCISSOR_0_ENABLE          (1 << 28)
+#      define RADEON_SCISSOR_1_ENABLE          (1 << 29)
+#      define RADEON_SCISSOR_2_ENABLE          (1 << 30)
+
+#define RADEON_BUS_CNTL                        0x0030
+#      define RADEON_BUS_MASTER_DIS            (1 << 6)
+
+#define RADEON_CLOCK_CNTL_DATA         0x000c
+#      define RADEON_PLL_WR_EN                 (1 << 7)
+#define RADEON_CLOCK_CNTL_INDEX                0x0008
+#define RADEON_CONFIG_APER_SIZE                0x0108
+#define RADEON_CONFIG_MEMSIZE          0x00f8
+#define RADEON_CRTC_OFFSET             0x0224
+#define RADEON_CRTC_OFFSET_CNTL                0x0228
+#      define RADEON_CRTC_TILE_EN              (1 << 15)
+#      define RADEON_CRTC_OFFSET_FLIP_CNTL     (1 << 16)
+#define RADEON_CRTC2_OFFSET            0x0324
+#define RADEON_CRTC2_OFFSET_CNTL       0x0328
+
+#define RADEON_PCIE_INDEX               0x0030
+#define RADEON_PCIE_DATA                0x0034
+#define RADEON_PCIE_TX_GART_CNTL       0x10
+#      define RADEON_PCIE_TX_GART_EN           (1 << 0)
+#      define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0 << 1)
+#      define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO  (1 << 1)
+#      define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD   (3 << 1)
+#      define RADEON_PCIE_TX_GART_MODE_32_128_CACHE    (0 << 3)
+#      define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE   (1 << 3)
+#      define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN      (1 << 5)
+#      define RADEON_PCIE_TX_GART_INVALIDATE_TLB       (1 << 8)
+#define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11
+#define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12
+#define RADEON_PCIE_TX_GART_BASE       0x13
+#define RADEON_PCIE_TX_GART_START_LO   0x14
+#define RADEON_PCIE_TX_GART_START_HI   0x15
+#define RADEON_PCIE_TX_GART_END_LO     0x16
+#define RADEON_PCIE_TX_GART_END_HI     0x17
+
+#define RS480_NB_MC_INDEX               0x168
+#      define RS480_NB_MC_IND_WR_EN    (1 << 8)
+#define RS480_NB_MC_DATA                0x16c
+
+#define RS690_MC_INDEX                  0x78
+#   define RS690_MC_INDEX_MASK          0x1ff
+#   define RS690_MC_INDEX_WR_EN         (1 << 9)
+#   define RS690_MC_INDEX_WR_ACK        0x7f
+#define RS690_MC_DATA                   0x7c
+
+/* MC indirect registers */
+#define RS480_MC_MISC_CNTL              0x18
+#      define RS480_DISABLE_GTW        (1 << 1)
+/* switch between MCIND GART and MM GART registers. 0 = mmgart, 1 = mcind gart */
+#      define RS480_GART_INDEX_REG_EN  (1 << 12)
+#      define RS690_BLOCK_GFX_D3_EN    (1 << 14)
+#define RS480_K8_FB_LOCATION            0x1e
+#define RS480_GART_FEATURE_ID           0x2b
+#      define RS480_HANG_EN            (1 << 11)
+#      define RS480_TLB_ENABLE         (1 << 18)
+#      define RS480_P2P_ENABLE         (1 << 19)
+#      define RS480_GTW_LAC_EN         (1 << 25)
+#      define RS480_2LEVEL_GART        (0 << 30)
+#      define RS480_1LEVEL_GART        (1 << 30)
+#      define RS480_PDC_EN             (1 << 31)
+#define RS480_GART_BASE                 0x2c
+#define RS480_GART_CACHE_CNTRL          0x2e
+#      define RS480_GART_CACHE_INVALIDATE (1 << 0) /* wait for it to clear */
+#define RS480_AGP_ADDRESS_SPACE_SIZE    0x38
+#      define RS480_GART_EN            (1 << 0)
+#      define RS480_VA_SIZE_32MB       (0 << 1)
+#      define RS480_VA_SIZE_64MB       (1 << 1)
+#      define RS480_VA_SIZE_128MB      (2 << 1)
+#      define RS480_VA_SIZE_256MB      (3 << 1)
+#      define RS480_VA_SIZE_512MB      (4 << 1)
+#      define RS480_VA_SIZE_1GB        (5 << 1)
+#      define RS480_VA_SIZE_2GB        (6 << 1)
+#define RS480_AGP_MODE_CNTL             0x39
+#      define RS480_POST_GART_Q_SIZE   (1 << 18)
+#      define RS480_NONGART_SNOOP      (1 << 19)
+#      define RS480_AGP_RD_BUF_SIZE    (1 << 20)
+#      define RS480_REQ_TYPE_SNOOP_SHIFT 22
+#      define RS480_REQ_TYPE_SNOOP_MASK  0x3
+#      define RS480_REQ_TYPE_SNOOP_DIS (1 << 24)
+#define RS480_MC_MISC_UMA_CNTL          0x5f
+#define RS480_MC_MCLK_CNTL              0x7a
+#define RS480_MC_UMA_DUALCH_CNTL        0x86
+
+#define RS690_MC_FB_LOCATION            0x100
+#define RS690_MC_AGP_LOCATION           0x101
+#define RS690_MC_AGP_BASE               0x102
+#define RS690_MC_AGP_BASE_2             0x103
+
+#define R520_MC_IND_INDEX 0x70
+#define R520_MC_IND_WR_EN (1 << 24)
+#define R520_MC_IND_DATA  0x74
+
+#define RV515_MC_FB_LOCATION 0x01
+#define RV515_MC_AGP_LOCATION 0x02
+#define RV515_MC_AGP_BASE     0x03
+#define RV515_MC_AGP_BASE_2   0x04
+
+#define R520_MC_FB_LOCATION 0x04
+#define R520_MC_AGP_LOCATION 0x05
+#define R520_MC_AGP_BASE     0x06
+#define R520_MC_AGP_BASE_2   0x07
+
+#define RADEON_MPP_TB_CONFIG           0x01c0
+#define RADEON_MEM_CNTL                        0x0140
+#define RADEON_MEM_SDRAM_MODE_REG      0x0158
+#define RADEON_AGP_BASE_2              0x015c /* r200+ only */
+#define RS480_AGP_BASE_2               0x0164
+#define RADEON_AGP_BASE                        0x0170
+
+/* pipe config regs */
+#define R400_GB_PIPE_SELECT             0x402c
+#define R500_DYN_SCLK_PWMEM_PIPE        0x000d /* PLL */
+#define R500_SU_REG_DEST                0x42c8
+#define R300_GB_TILE_CONFIG             0x4018
+#       define R300_ENABLE_TILING       (1 << 0)
+#       define R300_PIPE_COUNT_RV350    (0 << 1)
+#       define R300_PIPE_COUNT_R300     (3 << 1)
+#       define R300_PIPE_COUNT_R420_3P  (6 << 1)
+#       define R300_PIPE_COUNT_R420     (7 << 1)
+#       define R300_TILE_SIZE_8         (0 << 4)
+#       define R300_TILE_SIZE_16        (1 << 4)
+#       define R300_TILE_SIZE_32        (2 << 4)
+#       define R300_SUBPIXEL_1_12       (0 << 16)
+#       define R300_SUBPIXEL_1_16       (1 << 16)
+#define R300_DST_PIPE_CONFIG            0x170c
+#       define R300_PIPE_AUTO_CONFIG    (1 << 31)
+#define R300_RB2D_DSTCACHE_MODE         0x3428
+#       define R300_DC_AUTOFLUSH_ENABLE (1 << 8)
+#       define R300_DC_DC_DISABLE_IGNORE_PE (1 << 17)
+
+#define RADEON_RB3D_COLOROFFSET                0x1c40
+#define RADEON_RB3D_COLORPITCH         0x1c48
+
+#define        RADEON_SRC_X_Y                  0x1590
+
+#define RADEON_DP_GUI_MASTER_CNTL      0x146c
+#      define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0)
+#      define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1)
+#      define RADEON_GMC_BRUSH_SOLID_COLOR     (13 << 4)
+#      define RADEON_GMC_BRUSH_NONE            (15 << 4)
+#      define RADEON_GMC_DST_16BPP             (4 << 8)
+#      define RADEON_GMC_DST_24BPP             (5 << 8)
+#      define RADEON_GMC_DST_32BPP             (6 << 8)
+#      define RADEON_GMC_DST_DATATYPE_SHIFT    8
+#      define RADEON_GMC_SRC_DATATYPE_COLOR    (3 << 12)
+#      define RADEON_DP_SRC_SOURCE_MEMORY      (2 << 24)
+#      define RADEON_DP_SRC_SOURCE_HOST_DATA   (3 << 24)
+#      define RADEON_GMC_CLR_CMP_CNTL_DIS      (1 << 28)
+#      define RADEON_GMC_WR_MSK_DIS            (1 << 30)
+#      define RADEON_ROP3_S                    0x00cc0000
+#      define RADEON_ROP3_P                    0x00f00000
+#define RADEON_DP_WRITE_MASK           0x16cc
+#define RADEON_SRC_PITCH_OFFSET                0x1428
+#define RADEON_DST_PITCH_OFFSET                0x142c
+#define RADEON_DST_PITCH_OFFSET_C      0x1c80
+#      define RADEON_DST_TILE_LINEAR           (0 << 30)
+#      define RADEON_DST_TILE_MACRO            (1 << 30)
+#      define RADEON_DST_TILE_MICRO            (2 << 30)
+#      define RADEON_DST_TILE_BOTH             (3 << 30)
+
+#define RADEON_SCRATCH_REG0            0x15e0
+#define RADEON_SCRATCH_REG1            0x15e4
+#define RADEON_SCRATCH_REG2            0x15e8
+#define RADEON_SCRATCH_REG3            0x15ec
+#define RADEON_SCRATCH_REG4            0x15f0
+#define RADEON_SCRATCH_REG5            0x15f4
+#define RADEON_SCRATCH_UMSK            0x0770
+#define RADEON_SCRATCH_ADDR            0x0774
+
+#define RADEON_SCRATCHOFF( x )         (RADEON_SCRATCH_REG_OFFSET + 4*(x))
+
+#define GET_SCRATCH( x )       (dev_priv->writeback_works                      \
+                               ? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
+                               : RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
+
+#define RADEON_GEN_INT_CNTL            0x0040
+#      define RADEON_CRTC_VBLANK_MASK          (1 << 0)
+#      define RADEON_CRTC2_VBLANK_MASK         (1 << 9)
+#      define RADEON_GUI_IDLE_INT_ENABLE       (1 << 19)
+#      define RADEON_SW_INT_ENABLE             (1 << 25)
+
+#define RADEON_GEN_INT_STATUS          0x0044
+#      define RADEON_CRTC_VBLANK_STAT          (1 << 0)
+#      define RADEON_CRTC_VBLANK_STAT_ACK      (1 << 0)
+#      define RADEON_CRTC2_VBLANK_STAT         (1 << 9)
+#      define RADEON_CRTC2_VBLANK_STAT_ACK     (1 << 9)
+#      define RADEON_GUI_IDLE_INT_TEST_ACK     (1 << 19)
+#      define RADEON_SW_INT_TEST               (1 << 25)
+#      define RADEON_SW_INT_TEST_ACK           (1 << 25)
+#      define RADEON_SW_INT_FIRE               (1 << 26)
+
+#define RADEON_HOST_PATH_CNTL          0x0130
+#      define RADEON_HDP_SOFT_RESET            (1 << 26)
+#      define RADEON_HDP_WC_TIMEOUT_MASK       (7 << 28)
+#      define RADEON_HDP_WC_TIMEOUT_28BCLK     (7 << 28)
+
+#define RADEON_ISYNC_CNTL              0x1724
+#      define RADEON_ISYNC_ANY2D_IDLE3D        (1 << 0)
+#      define RADEON_ISYNC_ANY3D_IDLE2D        (1 << 1)
+#      define RADEON_ISYNC_TRIG2D_IDLE3D       (1 << 2)
+#      define RADEON_ISYNC_TRIG3D_IDLE2D       (1 << 3)
+#      define RADEON_ISYNC_WAIT_IDLEGUI        (1 << 4)
+#      define RADEON_ISYNC_CPSCRATCH_IDLEGUI   (1 << 5)
+
+#define RADEON_RBBM_GUICNTL            0x172c
+#      define RADEON_HOST_DATA_SWAP_NONE       (0 << 0)
+#      define RADEON_HOST_DATA_SWAP_16BIT      (1 << 0)
+#      define RADEON_HOST_DATA_SWAP_32BIT      (2 << 0)
+#      define RADEON_HOST_DATA_SWAP_HDW        (3 << 0)
+
+#define RADEON_MC_AGP_LOCATION         0x014c
+#define RADEON_MC_FB_LOCATION          0x0148
+#define RADEON_MCLK_CNTL               0x0012
+#      define RADEON_FORCEON_MCLKA             (1 << 16)
+#      define RADEON_FORCEON_MCLKB             (1 << 17)
+#      define RADEON_FORCEON_YCLKA             (1 << 18)
+#      define RADEON_FORCEON_YCLKB             (1 << 19)
+#      define RADEON_FORCEON_MC                (1 << 20)
+#      define RADEON_FORCEON_AIC               (1 << 21)
+
+#define RADEON_PP_BORDER_COLOR_0       0x1d40
+#define RADEON_PP_BORDER_COLOR_1       0x1d44
+#define RADEON_PP_BORDER_COLOR_2       0x1d48
+#define RADEON_PP_CNTL                 0x1c38
+#      define RADEON_SCISSOR_ENABLE            (1 <<  1)
+#define RADEON_PP_LUM_MATRIX           0x1d00
+#define RADEON_PP_MISC                 0x1c14
+#define RADEON_PP_ROT_MATRIX_0         0x1d58
+#define RADEON_PP_TXFILTER_0           0x1c54
+#define RADEON_PP_TXOFFSET_0           0x1c5c
+#define RADEON_PP_TXFILTER_1           0x1c6c
+#define RADEON_PP_TXFILTER_2           0x1c84
+
+#define R300_RB2D_DSTCACHE_CTLSTAT     0x342c /* use R300_DSTCACHE_CTLSTAT */
+#define R300_DSTCACHE_CTLSTAT          0x1714
+#      define R300_RB2D_DC_FLUSH               (3 << 0)
+#      define R300_RB2D_DC_FREE                (3 << 2)
+#      define R300_RB2D_DC_FLUSH_ALL           0xf
+#      define R300_RB2D_DC_BUSY                (1 << 31)
+#define RADEON_RB3D_CNTL               0x1c3c
+#      define RADEON_ALPHA_BLEND_ENABLE        (1 << 0)
+#      define RADEON_PLANE_MASK_ENABLE         (1 << 1)
+#      define RADEON_DITHER_ENABLE             (1 << 2)
+#      define RADEON_ROUND_ENABLE              (1 << 3)
+#      define RADEON_SCALE_DITHER_ENABLE       (1 << 4)
+#      define RADEON_DITHER_INIT               (1 << 5)
+#      define RADEON_ROP_ENABLE                (1 << 6)
+#      define RADEON_STENCIL_ENABLE            (1 << 7)
+#      define RADEON_Z_ENABLE                  (1 << 8)
+#      define RADEON_ZBLOCK16                  (1 << 15)
+#define RADEON_RB3D_DEPTHOFFSET                0x1c24
+#define RADEON_RB3D_DEPTHCLEARVALUE    0x3230
+#define RADEON_RB3D_DEPTHPITCH         0x1c28
+#define RADEON_RB3D_PLANEMASK          0x1d84
+#define RADEON_RB3D_STENCILREFMASK     0x1d7c
+#define RADEON_RB3D_ZCACHE_MODE                0x3250
+#define RADEON_RB3D_ZCACHE_CTLSTAT     0x3254
+#      define RADEON_RB3D_ZC_FLUSH             (1 << 0)
+#      define RADEON_RB3D_ZC_FREE              (1 << 2)
+#      define RADEON_RB3D_ZC_FLUSH_ALL         0x5
+#      define RADEON_RB3D_ZC_BUSY              (1 << 31)
+#define R300_ZB_ZCACHE_CTLSTAT                  0x4f18
+#      define R300_ZC_FLUSH                    (1 << 0)
+#      define R300_ZC_FREE                     (1 << 1)
+#      define R300_ZC_FLUSH_ALL                0x3
+#      define R300_ZC_BUSY                     (1 << 31)
+#define RADEON_RB3D_DSTCACHE_CTLSTAT   0x325c
+#      define RADEON_RB3D_DC_FLUSH             (3 << 0)
+#      define RADEON_RB3D_DC_FREE              (3 << 2)
+#      define RADEON_RB3D_DC_FLUSH_ALL         0xf
+#      define RADEON_RB3D_DC_BUSY              (1 << 31)
+#define R300_RB3D_DSTCACHE_CTLSTAT              0x4e4c
+#      define R300_RB3D_DC_FINISH              (1 << 4)
+#define RADEON_RB3D_ZSTENCILCNTL       0x1c2c
+#      define RADEON_Z_TEST_MASK               (7 << 4)
+#      define RADEON_Z_TEST_ALWAYS             (7 << 4)
+#      define RADEON_Z_HIERARCHY_ENABLE        (1 << 8)
+#      define RADEON_STENCIL_TEST_ALWAYS       (7 << 12)
+#      define RADEON_STENCIL_S_FAIL_REPLACE    (2 << 16)
+#      define RADEON_STENCIL_ZPASS_REPLACE     (2 << 20)
+#      define RADEON_STENCIL_ZFAIL_REPLACE     (2 << 24)
+#      define RADEON_Z_COMPRESSION_ENABLE      (1 << 28)
+#      define RADEON_FORCE_Z_DIRTY             (1 << 29)
+#      define RADEON_Z_WRITE_ENABLE            (1 << 30)
+#      define RADEON_Z_DECOMPRESSION_ENABLE    (1 << 31)
+#define RADEON_RBBM_SOFT_RESET         0x00f0
+#      define RADEON_SOFT_RESET_CP             (1 <<  0)
+#      define RADEON_SOFT_RESET_HI             (1 <<  1)
+#      define RADEON_SOFT_RESET_SE             (1 <<  2)
+#      define RADEON_SOFT_RESET_RE             (1 <<  3)
+#      define RADEON_SOFT_RESET_PP             (1 <<  4)
+#      define RADEON_SOFT_RESET_E2             (1 <<  5)
+#      define RADEON_SOFT_RESET_RB             (1 <<  6)
+#      define RADEON_SOFT_RESET_HDP            (1 <<  7)
+/*
+ *   6:0  Available slots in the FIFO
+ *   8    Host Interface active
+ *   9    CP request active
+ *   10   FIFO request active
+ *   11   Host Interface retry active
+ *   12   CP retry active
+ *   13   FIFO retry active
+ *   14   FIFO pipeline busy
+ *   15   Event engine busy
+ *   16   CP command stream busy
+ *   17   2D engine busy
+ *   18   2D portion of render backend busy
+ *   20   3D setup engine busy
+ *   26   GA engine busy
+ *   27   CBA 2D engine busy
+ *   31   2D engine busy or 3D engine busy or FIFO not empty or CP busy or
+ *           command stream queue not empty or Ring Buffer not empty
+ */
+#define RADEON_RBBM_STATUS             0x0e40
+/* Same as the previous RADEON_RBBM_STATUS; this is a mirror of that register.  */
+/* #define RADEON_RBBM_STATUS          0x1740 */
+/* bits 6:0 are dword slots available in the cmd fifo */
+#      define RADEON_RBBM_FIFOCNT_MASK         0x007f
+#      define RADEON_HIRQ_ON_RBB       (1 <<  8)
+#      define RADEON_CPRQ_ON_RBB       (1 <<  9)
+#      define RADEON_CFRQ_ON_RBB       (1 << 10)
+#      define RADEON_HIRQ_IN_RTBUF     (1 << 11)
+#      define RADEON_CPRQ_IN_RTBUF     (1 << 12)
+#      define RADEON_CFRQ_IN_RTBUF     (1 << 13)
+#      define RADEON_PIPE_BUSY         (1 << 14)
+#      define RADEON_ENG_EV_BUSY       (1 << 15)
+#      define RADEON_CP_CMDSTRM_BUSY   (1 << 16)
+#      define RADEON_E2_BUSY           (1 << 17)
+#      define RADEON_RB2D_BUSY         (1 << 18)
+#      define RADEON_RB3D_BUSY         (1 << 19) /* not used on r300 */
+#      define RADEON_VAP_BUSY          (1 << 20)
+#      define RADEON_RE_BUSY           (1 << 21) /* not used on r300 */
+#      define RADEON_TAM_BUSY          (1 << 22) /* not used on r300 */
+#      define RADEON_TDM_BUSY          (1 << 23) /* not used on r300 */
+#      define RADEON_PB_BUSY           (1 << 24) /* not used on r300 */
+#      define RADEON_TIM_BUSY          (1 << 25) /* not used on r300 */
+#      define RADEON_GA_BUSY           (1 << 26)
+#      define RADEON_CBA2D_BUSY        (1 << 27)
+#      define RADEON_RBBM_ACTIVE       (1 << 31)
+#define RADEON_RE_LINE_PATTERN         0x1cd0
+#define RADEON_RE_MISC                 0x26c4
+#define RADEON_RE_TOP_LEFT             0x26c0
+#define RADEON_RE_WIDTH_HEIGHT         0x1c44
+#define RADEON_RE_STIPPLE_ADDR         0x1cc8
+#define RADEON_RE_STIPPLE_DATA         0x1ccc
+
+#define RADEON_SCISSOR_TL_0            0x1cd8
+#define RADEON_SCISSOR_BR_0            0x1cdc
+#define RADEON_SCISSOR_TL_1            0x1ce0
+#define RADEON_SCISSOR_BR_1            0x1ce4
+#define RADEON_SCISSOR_TL_2            0x1ce8
+#define RADEON_SCISSOR_BR_2            0x1cec
+#define RADEON_SE_COORD_FMT            0x1c50
+#define RADEON_SE_CNTL                 0x1c4c
+#      define RADEON_FFACE_CULL_CW             (0 << 0)
+#      define RADEON_BFACE_SOLID               (3 << 1)
+#      define RADEON_FFACE_SOLID               (3 << 3)
+#      define RADEON_FLAT_SHADE_VTX_LAST       (3 << 6)
+#      define RADEON_DIFFUSE_SHADE_FLAT        (1 << 8)
+#      define RADEON_DIFFUSE_SHADE_GOURAUD     (2 << 8)
+#      define RADEON_ALPHA_SHADE_FLAT          (1 << 10)
+#      define RADEON_ALPHA_SHADE_GOURAUD       (2 << 10)
+#      define RADEON_SPECULAR_SHADE_FLAT       (1 << 12)
+#      define RADEON_SPECULAR_SHADE_GOURAUD    (2 << 12)
+#      define RADEON_FOG_SHADE_FLAT            (1 << 14)
+#      define RADEON_FOG_SHADE_GOURAUD         (2 << 14)
+#      define RADEON_VPORT_XY_XFORM_ENABLE     (1 << 24)
+#      define RADEON_VPORT_Z_XFORM_ENABLE      (1 << 25)
+#      define RADEON_VTX_PIX_CENTER_OGL        (1 << 27)
+#      define RADEON_ROUND_MODE_TRUNC          (0 << 28)
+#      define RADEON_ROUND_PREC_8TH_PIX        (1 << 30)
+#define RADEON_SE_CNTL_STATUS          0x2140
+#define RADEON_SE_LINE_WIDTH           0x1db8
+#define RADEON_SE_VPORT_XSCALE         0x1d98
+#define RADEON_SE_ZBIAS_FACTOR         0x1db0
+#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210
+#define RADEON_SE_TCL_OUTPUT_VTX_FMT         0x2254
+#define RADEON_SE_TCL_VECTOR_INDX_REG        0x2200
+#       define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT  16
+#       define RADEON_VEC_INDX_DWORD_COUNT_SHIFT     28
+#define RADEON_SE_TCL_VECTOR_DATA_REG       0x2204
+#define RADEON_SE_TCL_SCALAR_INDX_REG       0x2208
+#       define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT  16
+#define RADEON_SE_TCL_SCALAR_DATA_REG       0x220C
+#define RADEON_SURFACE_ACCESS_FLAGS    0x0bf8
+#define RADEON_SURFACE_ACCESS_CLR      0x0bfc
+#define RADEON_SURFACE_CNTL            0x0b00
+#      define RADEON_SURF_TRANSLATION_DIS      (1 << 8)
+#      define RADEON_NONSURF_AP0_SWP_MASK      (3 << 20)
+#      define RADEON_NONSURF_AP0_SWP_LITTLE    (0 << 20)
+#      define RADEON_NONSURF_AP0_SWP_BIG16     (1 << 20)
+#      define RADEON_NONSURF_AP0_SWP_BIG32     (2 << 20)
+#      define RADEON_NONSURF_AP1_SWP_MASK      (3 << 22)
+#      define RADEON_NONSURF_AP1_SWP_LITTLE    (0 << 22)
+#      define RADEON_NONSURF_AP1_SWP_BIG16     (1 << 22)
+#      define RADEON_NONSURF_AP1_SWP_BIG32     (2 << 22)
+#define RADEON_SURFACE0_INFO           0x0b0c
+#      define RADEON_SURF_PITCHSEL_MASK        (0x1ff << 0)
+#      define RADEON_SURF_TILE_MODE_MASK       (3 << 16)
+#      define RADEON_SURF_TILE_MODE_MACRO      (0 << 16)
+#      define RADEON_SURF_TILE_MODE_MICRO      (1 << 16)
+#      define RADEON_SURF_TILE_MODE_32BIT_Z    (2 << 16)
+#      define RADEON_SURF_TILE_MODE_16BIT_Z    (3 << 16)
+#define RADEON_SURFACE0_LOWER_BOUND    0x0b04
+#define RADEON_SURFACE0_UPPER_BOUND    0x0b08
+#      define RADEON_SURF_ADDRESS_FIXED_MASK   (0x3ff << 0)
+#define RADEON_SURFACE1_INFO           0x0b1c
+#define RADEON_SURFACE1_LOWER_BOUND    0x0b14
+#define RADEON_SURFACE1_UPPER_BOUND    0x0b18
+#define RADEON_SURFACE2_INFO           0x0b2c
+#define RADEON_SURFACE2_LOWER_BOUND    0x0b24
+#define RADEON_SURFACE2_UPPER_BOUND    0x0b28
+#define RADEON_SURFACE3_INFO           0x0b3c
+#define RADEON_SURFACE3_LOWER_BOUND    0x0b34
+#define RADEON_SURFACE3_UPPER_BOUND    0x0b38
+#define RADEON_SURFACE4_INFO           0x0b4c
+#define RADEON_SURFACE4_LOWER_BOUND    0x0b44
+#define RADEON_SURFACE4_UPPER_BOUND    0x0b48
+#define RADEON_SURFACE5_INFO           0x0b5c
+#define RADEON_SURFACE5_LOWER_BOUND    0x0b54
+#define RADEON_SURFACE5_UPPER_BOUND    0x0b58
+#define RADEON_SURFACE6_INFO           0x0b6c
+#define RADEON_SURFACE6_LOWER_BOUND    0x0b64
+#define RADEON_SURFACE6_UPPER_BOUND    0x0b68
+#define RADEON_SURFACE7_INFO           0x0b7c
+#define RADEON_SURFACE7_LOWER_BOUND    0x0b74
+#define RADEON_SURFACE7_UPPER_BOUND    0x0b78
+#define RADEON_SW_SEMAPHORE            0x013c
+
+#define RADEON_WAIT_UNTIL              0x1720
+#      define RADEON_WAIT_CRTC_PFLIP           (1 << 0)
+#      define RADEON_WAIT_2D_IDLE              (1 << 14)
+#      define RADEON_WAIT_3D_IDLE              (1 << 15)
+#      define RADEON_WAIT_2D_IDLECLEAN         (1 << 16)
+#      define RADEON_WAIT_3D_IDLECLEAN         (1 << 17)
+#      define RADEON_WAIT_HOST_IDLECLEAN       (1 << 18)
+
+#define RADEON_RB3D_ZMASKOFFSET                0x3234
+#define RADEON_RB3D_ZSTENCILCNTL       0x1c2c
+#      define RADEON_DEPTH_FORMAT_16BIT_INT_Z  (0 << 0)
+#      define RADEON_DEPTH_FORMAT_24BIT_INT_Z  (2 << 0)
+
+/* CP registers */
+#define RADEON_CP_ME_RAM_ADDR          0x07d4
+#define RADEON_CP_ME_RAM_RADDR         0x07d8
+#define RADEON_CP_ME_RAM_DATAH         0x07dc
+#define RADEON_CP_ME_RAM_DATAL         0x07e0
+
+#define RADEON_CP_RB_BASE              0x0700
+#define RADEON_CP_RB_CNTL              0x0704
+#      define RADEON_BUF_SWAP_32BIT            (2 << 16)
+#      define RADEON_RB_NO_UPDATE              (1 << 27)
+#define RADEON_CP_RB_RPTR_ADDR         0x070c
+#define RADEON_CP_RB_RPTR              0x0710
+#define RADEON_CP_RB_WPTR              0x0714
+
+#define RADEON_CP_RB_WPTR_DELAY                0x0718
+#      define RADEON_PRE_WRITE_TIMER_SHIFT     0
+#      define RADEON_PRE_WRITE_LIMIT_SHIFT     23
+
+#define RADEON_CP_IB_BASE              0x0738
+
+#define RADEON_CP_CSQ_CNTL             0x0740
+#      define RADEON_CSQ_CNT_PRIMARY_MASK      (0xff << 0)
+#      define RADEON_CSQ_PRIDIS_INDDIS         (0 << 28)
+#      define RADEON_CSQ_PRIPIO_INDDIS         (1 << 28)
+#      define RADEON_CSQ_PRIBM_INDDIS          (2 << 28)
+#      define RADEON_CSQ_PRIPIO_INDBM          (3 << 28)
+#      define RADEON_CSQ_PRIBM_INDBM           (4 << 28)
+#      define RADEON_CSQ_PRIPIO_INDPIO         (15 << 28)
+
+#define RADEON_AIC_CNTL                        0x01d0
+#      define RADEON_PCIGART_TRANSLATE_EN      (1 << 0)
+#define RADEON_AIC_STAT                        0x01d4
+#define RADEON_AIC_PT_BASE             0x01d8
+#define RADEON_AIC_LO_ADDR             0x01dc
+#define RADEON_AIC_HI_ADDR             0x01e0
+#define RADEON_AIC_TLB_ADDR            0x01e4
+#define RADEON_AIC_TLB_DATA            0x01e8
+
+/* CP command packets */
+#define RADEON_CP_PACKET0              0x00000000
+#      define RADEON_ONE_REG_WR                (1 << 15)
+#define RADEON_CP_PACKET1              0x40000000
+#define RADEON_CP_PACKET2              0x80000000
+#define RADEON_CP_PACKET3              0xC0000000
+#       define RADEON_CP_NOP                    0x00001000
+#       define RADEON_CP_NEXT_CHAR              0x00001900
+#       define RADEON_CP_PLY_NEXTSCAN           0x00001D00
+#       define RADEON_CP_SET_SCISSORS           0x00001E00
+            /* GEN_INDX_PRIM is unsupported starting with R300 */
+#      define RADEON_3D_RNDR_GEN_INDX_PRIM     0x00002300
+#      define RADEON_WAIT_FOR_IDLE             0x00002600
+#      define RADEON_3D_DRAW_VBUF              0x00002800
+#      define RADEON_3D_DRAW_IMMD              0x00002900
+#      define RADEON_3D_DRAW_INDX              0x00002A00
+#       define RADEON_CP_LOAD_PALETTE           0x00002C00
+#      define RADEON_3D_LOAD_VBPNTR            0x00002F00
+#      define RADEON_MPEG_IDCT_MACROBLOCK      0x00003000
+#      define RADEON_MPEG_IDCT_MACROBLOCK_REV  0x00003100
+#      define RADEON_3D_CLEAR_ZMASK            0x00003200
+#      define RADEON_CP_INDX_BUFFER            0x00003300
+#       define RADEON_CP_3D_DRAW_VBUF_2         0x00003400
+#       define RADEON_CP_3D_DRAW_IMMD_2         0x00003500
+#       define RADEON_CP_3D_DRAW_INDX_2         0x00003600
+#      define RADEON_3D_CLEAR_HIZ              0x00003700
+#       define RADEON_CP_3D_CLEAR_CMASK         0x00003802
+#      define RADEON_CNTL_HOSTDATA_BLT         0x00009400
+#      define RADEON_CNTL_PAINT_MULTI          0x00009A00
+#      define RADEON_CNTL_BITBLT_MULTI         0x00009B00
+#      define RADEON_CNTL_SET_SCISSORS         0xC0001E00
+
+#define RADEON_CP_PACKET_MASK          0xC0000000
+#define RADEON_CP_PACKET_COUNT_MASK    0x3fff0000
+#define RADEON_CP_PACKET0_REG_MASK     0x000007ff
+#define RADEON_CP_PACKET1_REG0_MASK    0x000007ff
+#define RADEON_CP_PACKET1_REG1_MASK    0x003ff800
+
+#define RADEON_VTX_Z_PRESENT                   (1 << 31)
+#define RADEON_VTX_PKCOLOR_PRESENT             (1 << 3)
+
+#define RADEON_PRIM_TYPE_NONE                  (0 << 0)
+#define RADEON_PRIM_TYPE_POINT                 (1 << 0)
+#define RADEON_PRIM_TYPE_LINE                  (2 << 0)
+#define RADEON_PRIM_TYPE_LINE_STRIP            (3 << 0)
+#define RADEON_PRIM_TYPE_TRI_LIST              (4 << 0)
+#define RADEON_PRIM_TYPE_TRI_FAN               (5 << 0)
+#define RADEON_PRIM_TYPE_TRI_STRIP             (6 << 0)
+#define RADEON_PRIM_TYPE_TRI_TYPE2             (7 << 0)
+#define RADEON_PRIM_TYPE_RECT_LIST             (8 << 0)
+#define RADEON_PRIM_TYPE_3VRT_POINT_LIST       (9 << 0)
+#define RADEON_PRIM_TYPE_3VRT_LINE_LIST                (10 << 0)
+#define RADEON_PRIM_TYPE_MASK                   0xf
+#define RADEON_PRIM_WALK_IND                   (1 << 4)
+#define RADEON_PRIM_WALK_LIST                  (2 << 4)
+#define RADEON_PRIM_WALK_RING                  (3 << 4)
+#define RADEON_COLOR_ORDER_BGRA                        (0 << 6)
+#define RADEON_COLOR_ORDER_RGBA                        (1 << 6)
+#define RADEON_MAOS_ENABLE                     (1 << 7)
+#define RADEON_VTX_FMT_R128_MODE               (0 << 8)
+#define RADEON_VTX_FMT_RADEON_MODE             (1 << 8)
+#define RADEON_NUM_VERTICES_SHIFT              16
+
+#define RADEON_COLOR_FORMAT_CI8                2
+#define RADEON_COLOR_FORMAT_ARGB1555   3
+#define RADEON_COLOR_FORMAT_RGB565     4
+#define RADEON_COLOR_FORMAT_ARGB8888   6
+#define RADEON_COLOR_FORMAT_RGB332     7
+#define RADEON_COLOR_FORMAT_RGB8       9
+#define RADEON_COLOR_FORMAT_ARGB4444   15
+
+#define RADEON_TXFORMAT_I8             0
+#define RADEON_TXFORMAT_AI88           1
+#define RADEON_TXFORMAT_RGB332         2
+#define RADEON_TXFORMAT_ARGB1555       3
+#define RADEON_TXFORMAT_RGB565         4
+#define RADEON_TXFORMAT_ARGB4444       5
+#define RADEON_TXFORMAT_ARGB8888       6
+#define RADEON_TXFORMAT_RGBA8888       7
+#define RADEON_TXFORMAT_Y8             8
+#define RADEON_TXFORMAT_VYUY422         10
+#define RADEON_TXFORMAT_YVYU422         11
+#define RADEON_TXFORMAT_DXT1            12
+#define RADEON_TXFORMAT_DXT23           14
+#define RADEON_TXFORMAT_DXT45           15
+
+#define R200_PP_TXCBLEND_0                0x2f00
+#define R200_PP_TXCBLEND_1                0x2f10
+#define R200_PP_TXCBLEND_2                0x2f20
+#define R200_PP_TXCBLEND_3                0x2f30
+#define R200_PP_TXCBLEND_4                0x2f40
+#define R200_PP_TXCBLEND_5                0x2f50
+#define R200_PP_TXCBLEND_6                0x2f60
+#define R200_PP_TXCBLEND_7                0x2f70
+#define R200_SE_TCL_LIGHT_MODEL_CTL_0     0x2268
+#define R200_PP_TFACTOR_0                 0x2ee0
+#define R200_SE_VTX_FMT_0                 0x2088
+#define R200_SE_VAP_CNTL                  0x2080
+#define R200_SE_TCL_MATRIX_SEL_0          0x2230
+#define R200_SE_TCL_TEX_PROC_CTL_2        0x22a8
+#define R200_SE_TCL_UCP_VERT_BLEND_CTL    0x22c0
+#define R200_PP_TXFILTER_5                0x2ca0
+#define R200_PP_TXFILTER_4                0x2c80
+#define R200_PP_TXFILTER_3                0x2c60
+#define R200_PP_TXFILTER_2                0x2c40
+#define R200_PP_TXFILTER_1                0x2c20
+#define R200_PP_TXFILTER_0                0x2c00
+#define R200_PP_TXOFFSET_5                0x2d78
+#define R200_PP_TXOFFSET_4                0x2d60
+#define R200_PP_TXOFFSET_3                0x2d48
+#define R200_PP_TXOFFSET_2                0x2d30
+#define R200_PP_TXOFFSET_1                0x2d18
+#define R200_PP_TXOFFSET_0                0x2d00
+
+#define R200_PP_CUBIC_FACES_0             0x2c18
+#define R200_PP_CUBIC_FACES_1             0x2c38
+#define R200_PP_CUBIC_FACES_2             0x2c58
+#define R200_PP_CUBIC_FACES_3             0x2c78
+#define R200_PP_CUBIC_FACES_4             0x2c98
+#define R200_PP_CUBIC_FACES_5             0x2cb8
+#define R200_PP_CUBIC_OFFSET_F1_0         0x2d04
+#define R200_PP_CUBIC_OFFSET_F2_0         0x2d08
+#define R200_PP_CUBIC_OFFSET_F3_0         0x2d0c
+#define R200_PP_CUBIC_OFFSET_F4_0         0x2d10
+#define R200_PP_CUBIC_OFFSET_F5_0         0x2d14
+#define R200_PP_CUBIC_OFFSET_F1_1         0x2d1c
+#define R200_PP_CUBIC_OFFSET_F2_1         0x2d20
+#define R200_PP_CUBIC_OFFSET_F3_1         0x2d24
+#define R200_PP_CUBIC_OFFSET_F4_1         0x2d28
+#define R200_PP_CUBIC_OFFSET_F5_1         0x2d2c
+#define R200_PP_CUBIC_OFFSET_F1_2         0x2d34
+#define R200_PP_CUBIC_OFFSET_F2_2         0x2d38
+#define R200_PP_CUBIC_OFFSET_F3_2         0x2d3c
+#define R200_PP_CUBIC_OFFSET_F4_2         0x2d40
+#define R200_PP_CUBIC_OFFSET_F5_2         0x2d44
+#define R200_PP_CUBIC_OFFSET_F1_3         0x2d4c
+#define R200_PP_CUBIC_OFFSET_F2_3         0x2d50
+#define R200_PP_CUBIC_OFFSET_F3_3         0x2d54
+#define R200_PP_CUBIC_OFFSET_F4_3         0x2d58
+#define R200_PP_CUBIC_OFFSET_F5_3         0x2d5c
+#define R200_PP_CUBIC_OFFSET_F1_4         0x2d64
+#define R200_PP_CUBIC_OFFSET_F2_4         0x2d68
+#define R200_PP_CUBIC_OFFSET_F3_4         0x2d6c
+#define R200_PP_CUBIC_OFFSET_F4_4         0x2d70
+#define R200_PP_CUBIC_OFFSET_F5_4         0x2d74
+#define R200_PP_CUBIC_OFFSET_F1_5         0x2d7c
+#define R200_PP_CUBIC_OFFSET_F2_5         0x2d80
+#define R200_PP_CUBIC_OFFSET_F3_5         0x2d84
+#define R200_PP_CUBIC_OFFSET_F4_5         0x2d88
+#define R200_PP_CUBIC_OFFSET_F5_5         0x2d8c
+
+#define R200_RE_AUX_SCISSOR_CNTL          0x26f0
+#define R200_SE_VTE_CNTL                  0x20b0
+#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL   0x2250
+#define R200_PP_TAM_DEBUG3                0x2d9c
+#define R200_PP_CNTL_X                    0x2cc4
+#define R200_SE_VAP_CNTL_STATUS           0x2140
+#define R200_RE_SCISSOR_TL_0              0x1cd8
+#define R200_RE_SCISSOR_TL_1              0x1ce0
+#define R200_RE_SCISSOR_TL_2              0x1ce8
+#define R200_RB3D_DEPTHXY_OFFSET          0x1d60
+#define R200_RE_AUX_SCISSOR_CNTL          0x26f0
+#define R200_SE_VTX_STATE_CNTL            0x2180
+#define R200_RE_POINTSIZE                 0x2648
+#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254
+
+#define RADEON_PP_TEX_SIZE_0                0x1d04     /* NPOT */
+#define RADEON_PP_TEX_SIZE_1                0x1d0c
+#define RADEON_PP_TEX_SIZE_2                0x1d14
+
+#define RADEON_PP_CUBIC_FACES_0             0x1d24
+#define RADEON_PP_CUBIC_FACES_1             0x1d28
+#define RADEON_PP_CUBIC_FACES_2             0x1d2c
+#define RADEON_PP_CUBIC_OFFSET_T0_0         0x1dd0     /* bits [31:5] */
+#define RADEON_PP_CUBIC_OFFSET_T1_0         0x1e00
+#define RADEON_PP_CUBIC_OFFSET_T2_0         0x1e14
+
+#define RADEON_SE_TCL_STATE_FLUSH           0x2284
+
+#define SE_VAP_CNTL__TCL_ENA_MASK                          0x00000001
+#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK                   0x00010000
+#define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT                 0x00000012
+#define SE_VTE_CNTL__VTX_XY_FMT_MASK                       0x00000100
+#define SE_VTE_CNTL__VTX_Z_FMT_MASK                        0x00000200
+#define SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK                  0x00000001
+#define SE_VTX_FMT_0__VTX_W0_PRESENT_MASK                  0x00000002
+#define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT               0x0000000b
+#define R200_3D_DRAW_IMMD_2      0xC0003500
+#define R200_SE_VTX_FMT_1                 0x208c
+#define R200_RE_CNTL                      0x1c50
+
+#define R200_RB3D_BLENDCOLOR              0x3218
+
+#define R200_SE_TCL_POINT_SPRITE_CNTL     0x22c4
+
+#define R200_PP_TRI_PERF 0x2cf8
+
+#define R200_PP_AFS_0                     0x2f80
+#define R200_PP_AFS_1                     0x2f00       /* same as txcblend_0 */
+
+#define R200_VAP_PVS_CNTL_1               0x22D0
+
+#define R500_D1CRTC_STATUS 0x609c
+#define R500_D2CRTC_STATUS 0x689c
+#define R500_CRTC_V_BLANK (1<<0)
+
+#define R500_D1CRTC_FRAME_COUNT 0x60a4
+#define R500_D2CRTC_FRAME_COUNT 0x68a4
+
+#define R500_D1MODE_V_COUNTER 0x6530
+#define R500_D2MODE_V_COUNTER 0x6d30
+
+#define R500_D1MODE_VBLANK_STATUS 0x6534
+#define R500_D2MODE_VBLANK_STATUS 0x6d34
+#define R500_VBLANK_OCCURED (1<<0)
+#define R500_VBLANK_ACK     (1<<4)
+#define R500_VBLANK_STAT    (1<<12)
+#define R500_VBLANK_INT     (1<<16)
+
+#define R500_DxMODE_INT_MASK 0x6540
+#define R500_D1MODE_INT_MASK (1<<0)
+#define R500_D2MODE_INT_MASK (1<<8)
+
+#define R500_DISP_INTERRUPT_STATUS 0x7edc
+#define R500_D1_VBLANK_INTERRUPT (1 << 4)
+#define R500_D2_VBLANK_INTERRUPT (1 << 5)
+
+/* Constants */
+#define RADEON_MAX_USEC_TIMEOUT                100000  /* 100 ms */
+
+#define RADEON_LAST_FRAME_REG          RADEON_SCRATCH_REG0
+#define RADEON_LAST_DISPATCH_REG       RADEON_SCRATCH_REG1
+#define RADEON_LAST_CLEAR_REG          RADEON_SCRATCH_REG2
+#define RADEON_LAST_SWI_REG            RADEON_SCRATCH_REG3
+#define RADEON_LAST_DISPATCH           1
+
+#define RADEON_MAX_VB_AGE              0x7fffffff
+#define RADEON_MAX_VB_VERTS            (0xffff)
+
+#define RADEON_RING_HIGH_MARK          128
+
+#define RADEON_PCIGART_TABLE_SIZE      (32*1024)
+
+#define RADEON_READ(reg)       DRM_READ32(  dev_priv->mmio, (reg) )
+#define RADEON_WRITE(reg,val)  DRM_WRITE32( dev_priv->mmio, (reg), (val) )
+#define RADEON_READ8(reg)      DRM_READ8(  dev_priv->mmio, (reg) )
+#define RADEON_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) )
+
+#define RADEON_WRITE_PLL(addr, val)                                    \
+do {                                                                   \
+       RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX,                          \
+                      ((addr) & 0x1f) | RADEON_PLL_WR_EN );            \
+       RADEON_WRITE(RADEON_CLOCK_CNTL_DATA, (val));                    \
+} while (0)
+
+#define RADEON_WRITE_PCIE(addr, val)                                   \
+do {                                                                   \
+       RADEON_WRITE8(RADEON_PCIE_INDEX,                                \
+                       ((addr) & 0xff));                               \
+       RADEON_WRITE(RADEON_PCIE_DATA, (val));                  \
+} while (0)
+
+#define R500_WRITE_MCIND(addr, val)                                    \
+do {                                                           \
+       RADEON_WRITE(R520_MC_IND_INDEX, 0xff0000 | ((addr) & 0xff));    \
+       RADEON_WRITE(R520_MC_IND_DATA, (val));                  \
+       RADEON_WRITE(R520_MC_IND_INDEX, 0);     \
+} while (0)
+
+#define RS480_WRITE_MCIND(addr, val)                           \
+do {                                                                   \
+       RADEON_WRITE(RS480_NB_MC_INDEX,                         \
+                       ((addr) & 0xff) | RS480_NB_MC_IND_WR_EN);       \
+       RADEON_WRITE(RS480_NB_MC_DATA, (val));                  \
+       RADEON_WRITE(RS480_NB_MC_INDEX, 0xff);                  \
+} while (0)
+
+#define RS690_WRITE_MCIND(addr, val)                                   \
+do {                                                           \
+       RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_EN | ((addr) & RS690_MC_INDEX_MASK));    \
+       RADEON_WRITE(RS690_MC_DATA, val);                       \
+       RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK);    \
+} while (0)
+
+#define IGP_WRITE_MCIND(addr, val)                             \
+do {                                                                   \
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)       \
+               RS690_WRITE_MCIND(addr, val);                           \
+       else                                                            \
+               RS480_WRITE_MCIND(addr, val);                           \
+} while (0)
+
+#define CP_PACKET0( reg, n )                                           \
+       (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET0_TABLE( reg, n )                                     \
+       (RADEON_CP_PACKET0 | RADEON_ONE_REG_WR | ((n) << 16) | ((reg) >> 2))
+#define CP_PACKET1( reg0, reg1 )                                       \
+       (RADEON_CP_PACKET1 | (((reg1) >> 2) << 15) | ((reg0) >> 2))
+#define CP_PACKET2()                                                   \
+       (RADEON_CP_PACKET2)
+#define CP_PACKET3( pkt, n )                                           \
+       (RADEON_CP_PACKET3 | (pkt) | ((n) << 16))
+
+/* ================================================================
+ * Engine control helper macros
+ */
+
+#define RADEON_WAIT_UNTIL_2D_IDLE() do {                               \
+       OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );                 \
+       OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |                           \
+                  RADEON_WAIT_HOST_IDLECLEAN) );                       \
+} while (0)
+
+#define RADEON_WAIT_UNTIL_3D_IDLE() do {                               \
+       OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );                 \
+       OUT_RING( (RADEON_WAIT_3D_IDLECLEAN |                           \
+                  RADEON_WAIT_HOST_IDLECLEAN) );                       \
+} while (0)
+
+#define RADEON_WAIT_UNTIL_IDLE() do {                                  \
+       OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );                 \
+       OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |                           \
+                  RADEON_WAIT_3D_IDLECLEAN |                           \
+                  RADEON_WAIT_HOST_IDLECLEAN) );                       \
+} while (0)
+
+#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do {                          \
+       OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) );                 \
+       OUT_RING( RADEON_WAIT_CRTC_PFLIP );                             \
+} while (0)
+
+#define RADEON_FLUSH_CACHE() do {                                      \
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {     \
+               OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0));  \
+               OUT_RING(RADEON_RB3D_DC_FLUSH);                         \
+       } else {                                                        \
+               OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));    \
+               OUT_RING(RADEON_RB3D_DC_FLUSH);                         \
+       }                                                               \
+} while (0)
+
+#define RADEON_PURGE_CACHE() do {                                      \
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {     \
+               OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0));  \
+               OUT_RING(RADEON_RB3D_DC_FLUSH_ALL);                     \
+       } else {                                                        \
+               OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));    \
+               OUT_RING(RADEON_RB3D_DC_FLUSH_ALL);                     \
+       }                                                               \
+} while (0)
+
+#define RADEON_FLUSH_ZCACHE() do {                                     \
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {     \
+               OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));    \
+               OUT_RING(RADEON_RB3D_ZC_FLUSH);                         \
+       } else {                                                        \
+               OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0));        \
+               OUT_RING(R300_ZC_FLUSH);                                \
+       }                                                               \
+} while (0)
+
+#define RADEON_PURGE_ZCACHE() do {                                     \
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {     \
+               OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0));    \
+               OUT_RING(RADEON_RB3D_ZC_FLUSH_ALL);                     \
+       } else {                                                        \
+               OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));    \
+               OUT_RING(R300_ZC_FLUSH_ALL);                            \
+       }                                                               \
+} while (0)
+
+/* ================================================================
+ * Misc helper macros
+ */
+
+/* Perfbox functionality only.
+ */
+#define RING_SPACE_TEST_WITH_RETURN( dev_priv )                                \
+do {                                                                   \
+       if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) {           \
+               u32 head = GET_RING_HEAD( dev_priv );                   \
+               if (head == dev_priv->ring.tail)                        \
+                       dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE;   \
+       }                                                               \
+} while (0)
+
+#define VB_AGE_TEST_WITH_RETURN( dev_priv )                            \
+do {                                                                   \
+       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;          \
+       if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) {         \
+               int __ret = radeon_do_cp_idle( dev_priv );              \
+               if ( __ret ) return __ret;                              \
+               sarea_priv->last_dispatch = 0;                          \
+               radeon_freelist_reset( dev );                           \
+       }                                                               \
+} while (0)
+
+#define RADEON_DISPATCH_AGE( age ) do {                                        \
+       OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) );          \
+       OUT_RING( age );                                                \
+} while (0)
+
+#define RADEON_FRAME_AGE( age ) do {                                   \
+       OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) );             \
+       OUT_RING( age );                                                \
+} while (0)
+
+#define RADEON_CLEAR_AGE( age ) do {                                   \
+       OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) );             \
+       OUT_RING( age );                                                \
+} while (0)
+
+/* ================================================================
+ * Ring control
+ */
+
+#define RADEON_VERBOSE 0
+
+#define RING_LOCALS    int write, _nr; unsigned int mask; u32 *ring;
+
+#define BEGIN_RING( n ) do {                                           \
+       if ( RADEON_VERBOSE ) {                                         \
+               DRM_INFO( "BEGIN_RING( %d )\n", (n));                   \
+       }                                                               \
+       if ( dev_priv->ring.space <= (n) * sizeof(u32) ) {              \
+                COMMIT_RING();                                         \
+               radeon_wait_ring( dev_priv, (n) * sizeof(u32) );        \
+       }                                                               \
+       _nr = n; dev_priv->ring.space -= (n) * sizeof(u32);             \
+       ring = dev_priv->ring.start;                                    \
+       write = dev_priv->ring.tail;                                    \
+       mask = dev_priv->ring.tail_mask;                                \
+} while (0)
+
+#define ADVANCE_RING() do {                                            \
+       if ( RADEON_VERBOSE ) {                                         \
+               DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n",     \
+                         write, dev_priv->ring.tail );                 \
+       }                                                               \
+       if (((dev_priv->ring.tail + _nr) & mask) != write) {            \
+               DRM_ERROR(                                              \
+                       "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n",        \
+                       ((dev_priv->ring.tail + _nr) & mask),           \
+                       write, __LINE__);                                               \
+       } else                                                          \
+               dev_priv->ring.tail = write;                            \
+} while (0)
+
+#define COMMIT_RING() do {                                             \
+       /* Flush writes to ring */                                      \
+       DRM_MEMORYBARRIER();                                            \
+       GET_RING_HEAD( dev_priv );                                      \
+       RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail );         \
+       /* read from PCI bus to ensure correct posting */               \
+       RADEON_READ( RADEON_CP_RB_RPTR );                               \
+} while (0)
+
+#define OUT_RING( x ) do {                                             \
+       if ( RADEON_VERBOSE ) {                                         \
+               DRM_INFO( "   OUT_RING( 0x%08x ) at 0x%x\n",            \
+                          (unsigned int)(x), write );                  \
+       }                                                               \
+       ring[write++] = (x);                                            \
+       write &= mask;                                                  \
+} while (0)
+
+#define OUT_RING_REG( reg, val ) do {                                  \
+       OUT_RING( CP_PACKET0( reg, 0 ) );                               \
+       OUT_RING( val );                                                \
+} while (0)
+
+#define OUT_RING_TABLE( tab, sz ) do {                                 \
+       int _size = (sz);                                       \
+       int *_tab = (int *)(tab);                               \
+                                                               \
+       if (write + _size > mask) {                             \
+               int _i = (mask+1) - write;                      \
+               _size -= _i;                                    \
+               while (_i > 0 ) {                               \
+                       *(int *)(ring + write) = *_tab++;       \
+                       write++;                                \
+                       _i--;                                   \
+               }                                               \
+               write = 0;                                      \
+               _tab += _i;                                     \
+       }                                                       \
+       while (_size > 0) {                                     \
+               *(ring + write) = *_tab++;                      \
+               write++;                                        \
+               _size--;                                        \
+       }                                                       \
+       write &= mask;                                          \
+} while (0)
+
+#endif                         /* __RADEON_DRV_H__ */
diff --git a/drivers/gpu/drm/radeon/radeon_ioc32.c b/drivers/gpu/drm/radeon/radeon_ioc32.c
new file mode 100644 (file)
index 0000000..56decda
--- /dev/null
@@ -0,0 +1,424 @@
+/**
+ * \file radeon_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the Radeon DRM.
+ *
+ * \author Paul Mackerras <paulus@samba.org>
+ *
+ * Copyright (C) Paul Mackerras 2005
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <linux/compat.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+typedef struct drm_radeon_init32 {
+       int func;
+       u32 sarea_priv_offset;
+       int is_pci;
+       int cp_mode;
+       int gart_size;
+       int ring_size;
+       int usec_timeout;
+
+       unsigned int fb_bpp;
+       unsigned int front_offset, front_pitch;
+       unsigned int back_offset, back_pitch;
+       unsigned int depth_bpp;
+       unsigned int depth_offset, depth_pitch;
+
+       u32 fb_offset;
+       u32 mmio_offset;
+       u32 ring_offset;
+       u32 ring_rptr_offset;
+       u32 buffers_offset;
+       u32 gart_textures_offset;
+} drm_radeon_init32_t;
+
+static int compat_radeon_cp_init(struct file *file, unsigned int cmd,
+                                unsigned long arg)
+{
+       drm_radeon_init32_t init32;
+       drm_radeon_init_t __user *init;
+
+       if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
+               return -EFAULT;
+
+       init = compat_alloc_user_space(sizeof(*init));
+       if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
+           || __put_user(init32.func, &init->func)
+           || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
+           || __put_user(init32.is_pci, &init->is_pci)
+           || __put_user(init32.cp_mode, &init->cp_mode)
+           || __put_user(init32.gart_size, &init->gart_size)
+           || __put_user(init32.ring_size, &init->ring_size)
+           || __put_user(init32.usec_timeout, &init->usec_timeout)
+           || __put_user(init32.fb_bpp, &init->fb_bpp)
+           || __put_user(init32.front_offset, &init->front_offset)
+           || __put_user(init32.front_pitch, &init->front_pitch)
+           || __put_user(init32.back_offset, &init->back_offset)
+           || __put_user(init32.back_pitch, &init->back_pitch)
+           || __put_user(init32.depth_bpp, &init->depth_bpp)
+           || __put_user(init32.depth_offset, &init->depth_offset)
+           || __put_user(init32.depth_pitch, &init->depth_pitch)
+           || __put_user(init32.fb_offset, &init->fb_offset)
+           || __put_user(init32.mmio_offset, &init->mmio_offset)
+           || __put_user(init32.ring_offset, &init->ring_offset)
+           || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
+           || __put_user(init32.buffers_offset, &init->buffers_offset)
+           || __put_user(init32.gart_textures_offset,
+                         &init->gart_textures_offset))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init);
+}
+
+typedef struct drm_radeon_clear32 {
+       unsigned int flags;
+       unsigned int clear_color;
+       unsigned int clear_depth;
+       unsigned int color_mask;
+       unsigned int depth_mask;        /* misnamed field:  should be stencil */
+       u32 depth_boxes;
+} drm_radeon_clear32_t;
+
+static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
+                                 unsigned long arg)
+{
+       drm_radeon_clear32_t clr32;
+       drm_radeon_clear_t __user *clr;
+
+       if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32)))
+               return -EFAULT;
+
+       clr = compat_alloc_user_space(sizeof(*clr));
+       if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr))
+           || __put_user(clr32.flags, &clr->flags)
+           || __put_user(clr32.clear_color, &clr->clear_color)
+           || __put_user(clr32.clear_depth, &clr->clear_depth)
+           || __put_user(clr32.color_mask, &clr->color_mask)
+           || __put_user(clr32.depth_mask, &clr->depth_mask)
+           || __put_user((void __user *)(unsigned long)clr32.depth_boxes,
+                         &clr->depth_boxes))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr);
+}
+
+typedef struct drm_radeon_stipple32 {
+       u32 mask;
+} drm_radeon_stipple32_t;
+
+static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
+                                   unsigned long arg)
+{
+       drm_radeon_stipple32_t __user *argp = (void __user *)arg;
+       drm_radeon_stipple_t __user *request;
+       u32 mask;
+
+       if (get_user(mask, &argp->mask))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user((unsigned int __user *)(unsigned long)mask,
+                         &request->mask))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request);
+}
+
+typedef struct drm_radeon_tex_image32 {
+       unsigned int x, y;      /* Blit coordinates */
+       unsigned int width, height;
+       u32 data;
+} drm_radeon_tex_image32_t;
+
+typedef struct drm_radeon_texture32 {
+       unsigned int offset;
+       int pitch;
+       int format;
+       int width;              /* Texture image coordinates */
+       int height;
+       u32 image;
+} drm_radeon_texture32_t;
+
+static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
+                                   unsigned long arg)
+{
+       drm_radeon_texture32_t req32;
+       drm_radeon_texture_t __user *request;
+       drm_radeon_tex_image32_t img32;
+       drm_radeon_tex_image_t __user *image;
+
+       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+               return -EFAULT;
+       if (req32.image == 0)
+               return -EINVAL;
+       if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image,
+                          sizeof(img32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request) + sizeof(*image));
+       if (!access_ok(VERIFY_WRITE, request,
+                      sizeof(*request) + sizeof(*image)))
+               return -EFAULT;
+       image = (drm_radeon_tex_image_t __user *) (request + 1);
+
+       if (__put_user(req32.offset, &request->offset)
+           || __put_user(req32.pitch, &request->pitch)
+           || __put_user(req32.format, &request->format)
+           || __put_user(req32.width, &request->width)
+           || __put_user(req32.height, &request->height)
+           || __put_user(image, &request->image)
+           || __put_user(img32.x, &image->x)
+           || __put_user(img32.y, &image->y)
+           || __put_user(img32.width, &image->width)
+           || __put_user(img32.height, &image->height)
+           || __put_user((const void __user *)(unsigned long)img32.data,
+                         &image->data))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request);
+}
+
+typedef struct drm_radeon_vertex2_32 {
+       int idx;                /* Index of vertex buffer */
+       int discard;            /* Client finished with buffer? */
+       int nr_states;
+       u32 state;
+       int nr_prims;
+       u32 prim;
+} drm_radeon_vertex2_32_t;
+
+static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
+                                   unsigned long arg)
+{
+       drm_radeon_vertex2_32_t req32;
+       drm_radeon_vertex2_t __user *request;
+
+       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user(req32.idx, &request->idx)
+           || __put_user(req32.discard, &request->discard)
+           || __put_user(req32.nr_states, &request->nr_states)
+           || __put_user((void __user *)(unsigned long)req32.state,
+                         &request->state)
+           || __put_user(req32.nr_prims, &request->nr_prims)
+           || __put_user((void __user *)(unsigned long)req32.prim,
+                         &request->prim))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request);
+}
+
+typedef struct drm_radeon_cmd_buffer32 {
+       int bufsz;
+       u32 buf;
+       int nbox;
+       u32 boxes;
+} drm_radeon_cmd_buffer32_t;
+
+static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
+                                  unsigned long arg)
+{
+       drm_radeon_cmd_buffer32_t req32;
+       drm_radeon_cmd_buffer_t __user *request;
+
+       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user(req32.bufsz, &request->bufsz)
+           || __put_user((void __user *)(unsigned long)req32.buf,
+                         &request->buf)
+           || __put_user(req32.nbox, &request->nbox)
+           || __put_user((void __user *)(unsigned long)req32.boxes,
+                         &request->boxes))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request);
+}
+
+typedef struct drm_radeon_getparam32 {
+       int param;
+       u32 value;
+} drm_radeon_getparam32_t;
+
+static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
+                                    unsigned long arg)
+{
+       drm_radeon_getparam32_t req32;
+       drm_radeon_getparam_t __user *request;
+
+       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user(req32.param, &request->param)
+           || __put_user((void __user *)(unsigned long)req32.value,
+                         &request->value))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request);
+}
+
+typedef struct drm_radeon_mem_alloc32 {
+       int region;
+       int alignment;
+       int size;
+       u32 region_offset;      /* offset from start of fb or GART */
+} drm_radeon_mem_alloc32_t;
+
+static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
+                                  unsigned long arg)
+{
+       drm_radeon_mem_alloc32_t req32;
+       drm_radeon_mem_alloc_t __user *request;
+
+       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user(req32.region, &request->region)
+           || __put_user(req32.alignment, &request->alignment)
+           || __put_user(req32.size, &request->size)
+           || __put_user((int __user *)(unsigned long)req32.region_offset,
+                         &request->region_offset))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_RADEON_ALLOC, (unsigned long)request);
+}
+
+typedef struct drm_radeon_irq_emit32 {
+       u32 irq_seq;
+} drm_radeon_irq_emit32_t;
+
+static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
+                                 unsigned long arg)
+{
+       drm_radeon_irq_emit32_t req32;
+       drm_radeon_irq_emit_t __user *request;
+
+       if (copy_from_user(&req32, (void __user *)arg, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user((int __user *)(unsigned long)req32.irq_seq,
+                         &request->irq_seq))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_path.dentry->d_inode, file,
+                        DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
+}
+
+/* The two 64-bit arches where alignof(u64)==4 in 32-bit code */
+#if defined (CONFIG_X86_64) || defined(CONFIG_IA64)
+typedef struct drm_radeon_setparam32 {
+       int param;
+       u64 value;
+} __attribute__((packed)) drm_radeon_setparam32_t;
+
+static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd,
+                                    unsigned long arg)
+{
+       drm_radeon_setparam32_t req32;
+       drm_radeon_setparam_t __user *request;
+
+       if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+               return -EFAULT;
+
+       request = compat_alloc_user_space(sizeof(*request));
+       if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+           || __put_user(req32.param, &request->param)
+           || __put_user((void __user *)(unsigned long)req32.value,
+                         &request->value))
+               return -EFAULT;
+
+       return drm_ioctl(file->f_dentry->d_inode, file,
+                        DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request);
+}
+#else
+#define compat_radeon_cp_setparam NULL
+#endif /* X86_64 || IA64 */
+
+drm_ioctl_compat_t *radeon_compat_ioctls[] = {
+       [DRM_RADEON_CP_INIT] = compat_radeon_cp_init,
+       [DRM_RADEON_CLEAR] = compat_radeon_cp_clear,
+       [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple,
+       [DRM_RADEON_TEXTURE] = compat_radeon_cp_texture,
+       [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2,
+       [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf,
+       [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam,
+       [DRM_RADEON_SETPARAM] = compat_radeon_cp_setparam,
+       [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc,
+       [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit,
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/dri/card<n>.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       unsigned int nr = DRM_IOCTL_NR(cmd);
+       drm_ioctl_compat_t *fn = NULL;
+       int ret;
+
+       if (nr < DRM_COMMAND_BASE)
+               return drm_compat_ioctl(filp, cmd, arg);
+
+       if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls))
+               fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE];
+
+       lock_kernel();          /* XXX for now */
+       if (fn != NULL)
+               ret = (*fn) (filp, cmd, arg);
+       else
+               ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
+       unlock_kernel();
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c
new file mode 100644 (file)
index 0000000..ee40d19
--- /dev/null
@@ -0,0 +1,320 @@
+/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */
+/*
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Michel Dänzer <michel@daenzer.net>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
+                                             u32 mask)
+{
+       u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
+       if (irqs)
+               RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
+       return irqs;
+}
+
+/* Interrupts - Used for device synchronization and flushing in the
+ * following circumstances:
+ *
+ * - Exclusive FB access with hw idle:
+ *    - Wait for GUI Idle (?) interrupt, then do normal flush.
+ *
+ * - Frame throttling, NV_fence:
+ *    - Drop marker irq's into command stream ahead of time.
+ *    - Wait on irq's with lock *not held*
+ *    - Check each for termination condition
+ *
+ * - Internally in cp_getbuffer, etc:
+ *    - as above, but wait with lock held???
+ *
+ * NOTE: These functions are misleadingly named -- the irq's aren't
+ * tied to dma at all, this is just a hangover from dri prehistory.
+ */
+
+irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       drm_radeon_private_t *dev_priv =
+           (drm_radeon_private_t *) dev->dev_private;
+       u32 stat;
+
+       /* Only consider the bits we're interested in - others could be used
+        * outside the DRM
+        */
+       stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+                                                 RADEON_CRTC_VBLANK_STAT |
+                                                 RADEON_CRTC2_VBLANK_STAT));
+       if (!stat)
+               return IRQ_NONE;
+
+       stat &= dev_priv->irq_enable_reg;
+
+       /* SW interrupt */
+       if (stat & RADEON_SW_INT_TEST) {
+               DRM_WAKEUP(&dev_priv->swi_queue);
+       }
+
+       /* VBLANK interrupt */
+       if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
+               int vblank_crtc = dev_priv->vblank_crtc;
+
+               if ((vblank_crtc &
+                    (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
+                   (DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
+                       if (stat & RADEON_CRTC_VBLANK_STAT)
+                               atomic_inc(&dev->vbl_received);
+                       if (stat & RADEON_CRTC2_VBLANK_STAT)
+                               atomic_inc(&dev->vbl_received2);
+               } else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
+                          (vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
+                          ((stat & RADEON_CRTC2_VBLANK_STAT) &&
+                           (vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
+                       atomic_inc(&dev->vbl_received);
+
+               DRM_WAKEUP(&dev->vbl_queue);
+               drm_vbl_send_signals(dev);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int radeon_emit_irq(struct drm_device * dev)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       unsigned int ret;
+       RING_LOCALS;
+
+       atomic_inc(&dev_priv->swi_emitted);
+       ret = atomic_read(&dev_priv->swi_emitted);
+
+       BEGIN_RING(4);
+       OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
+       OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
+       ADVANCE_RING();
+       COMMIT_RING();
+
+       return ret;
+}
+
+static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
+{
+       drm_radeon_private_t *dev_priv =
+           (drm_radeon_private_t *) dev->dev_private;
+       int ret = 0;
+
+       if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr)
+               return 0;
+
+       dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+       DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
+                   RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
+
+       return ret;
+}
+
+static int radeon_driver_vblank_do_wait(struct drm_device * dev,
+                                       unsigned int *sequence, int crtc)
+{
+       drm_radeon_private_t *dev_priv =
+           (drm_radeon_private_t *) dev->dev_private;
+       unsigned int cur_vblank;
+       int ret = 0;
+       int ack = 0;
+       atomic_t *counter;
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       if (crtc == DRM_RADEON_VBLANK_CRTC1) {
+               counter = &dev->vbl_received;
+               ack |= RADEON_CRTC_VBLANK_STAT;
+       } else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
+               counter = &dev->vbl_received2;
+               ack |= RADEON_CRTC2_VBLANK_STAT;
+       } else
+               return -EINVAL;
+
+       radeon_acknowledge_irqs(dev_priv, ack);
+
+       dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+
+       /* Assume that the user has missed the current sequence number
+        * by about a day rather than she wants to wait for years
+        * using vertical blanks...
+        */
+       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+                   (((cur_vblank = atomic_read(counter))
+                     - *sequence) <= (1 << 23)));
+
+       *sequence = cur_vblank;
+
+       return ret;
+}
+
+int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
+{
+       return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
+}
+
+int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
+{
+       return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
+}
+
+/* Needs the lock as it touches the ring.
+ */
+int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_irq_emit_t *emit = data;
+       int result;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       result = radeon_emit_irq(dev);
+
+       if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
+               DRM_ERROR("copy_to_user\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/* Doesn't need the hardware lock.
+ */
+int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_irq_wait_t *irqwait = data;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       return radeon_wait_irq(dev, irqwait->irq_seq);
+}
+
+void radeon_enable_interrupt(struct drm_device *dev)
+{
+       drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+
+       dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
+       if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
+               dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
+
+       if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
+               dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
+
+       RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+       dev_priv->irq_enabled = 1;
+}
+
+/* drm_dma.h hooks
+*/
+void radeon_driver_irq_preinstall(struct drm_device * dev)
+{
+       drm_radeon_private_t *dev_priv =
+           (drm_radeon_private_t *) dev->dev_private;
+
+       /* Disable *all* interrupts */
+       RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+
+       /* Clear bits if they're already high */
+       radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+                                          RADEON_CRTC_VBLANK_STAT |
+                                          RADEON_CRTC2_VBLANK_STAT));
+}
+
+void radeon_driver_irq_postinstall(struct drm_device * dev)
+{
+       drm_radeon_private_t *dev_priv =
+           (drm_radeon_private_t *) dev->dev_private;
+
+       atomic_set(&dev_priv->swi_emitted, 0);
+       DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
+
+       radeon_enable_interrupt(dev);
+}
+
+void radeon_driver_irq_uninstall(struct drm_device * dev)
+{
+       drm_radeon_private_t *dev_priv =
+           (drm_radeon_private_t *) dev->dev_private;
+       if (!dev_priv)
+               return;
+
+       dev_priv->irq_enabled = 0;
+
+       /* Disable *all* interrupts */
+       RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
+}
+
+
+int radeon_vblank_crtc_get(struct drm_device *dev)
+{
+       drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+       u32 flag;
+       u32 value;
+
+       flag = RADEON_READ(RADEON_GEN_INT_CNTL);
+       value = 0;
+
+       if (flag & RADEON_CRTC_VBLANK_MASK)
+               value |= DRM_RADEON_VBLANK_CRTC1;
+
+       if (flag & RADEON_CRTC2_VBLANK_MASK)
+               value |= DRM_RADEON_VBLANK_CRTC2;
+       return value;
+}
+
+int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
+{
+       drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+       if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
+               DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value);
+               return -EINVAL;
+       }
+       dev_priv->vblank_crtc = (unsigned int)value;
+       radeon_enable_interrupt(dev);
+       return 0;
+}
diff --git a/drivers/gpu/drm/radeon/radeon_mem.c b/drivers/gpu/drm/radeon/radeon_mem.c
new file mode 100644 (file)
index 0000000..4af5286
--- /dev/null
@@ -0,0 +1,302 @@
+/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- */
+/*
+ * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
+ *
+ * The Weather Channel (TM) funded Tungsten Graphics to develop the
+ * initial release of the Radeon 8500 driver under the XFree86 license.
+ * This notice must be preserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+/* Very simple allocator for GART memory, working on a static range
+ * already mapped into each client's address space.
+ */
+
+static struct mem_block *split_block(struct mem_block *p, int start, int size,
+                                    struct drm_file *file_priv)
+{
+       /* Maybe cut off the start of an existing block */
+       if (start > p->start) {
+               struct mem_block *newblock =
+                   drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
+               if (!newblock)
+                       goto out;
+               newblock->start = start;
+               newblock->size = p->size - (start - p->start);
+               newblock->file_priv = NULL;
+               newblock->next = p->next;
+               newblock->prev = p;
+               p->next->prev = newblock;
+               p->next = newblock;
+               p->size -= newblock->size;
+               p = newblock;
+       }
+
+       /* Maybe cut off the end of an existing block */
+       if (size < p->size) {
+               struct mem_block *newblock =
+                   drm_alloc(sizeof(*newblock), DRM_MEM_BUFS);
+               if (!newblock)
+                       goto out;
+               newblock->start = start + size;
+               newblock->size = p->size - size;
+               newblock->file_priv = NULL;
+               newblock->next = p->next;
+               newblock->prev = p;
+               p->next->prev = newblock;
+               p->next = newblock;
+               p->size = size;
+       }
+
+      out:
+       /* Our block is in the middle */
+       p->file_priv = file_priv;
+       return p;
+}
+
+static struct mem_block *alloc_block(struct mem_block *heap, int size,
+                                    int align2, struct drm_file *file_priv)
+{
+       struct mem_block *p;
+       int mask = (1 << align2) - 1;
+
+       list_for_each(p, heap) {
+               int start = (p->start + mask) & ~mask;
+               if (p->file_priv == NULL && start + size <= p->start + p->size)
+                       return split_block(p, start, size, file_priv);
+       }
+
+       return NULL;
+}
+
+static struct mem_block *find_block(struct mem_block *heap, int start)
+{
+       struct mem_block *p;
+
+       list_for_each(p, heap)
+           if (p->start == start)
+               return p;
+
+       return NULL;
+}
+
+static void free_block(struct mem_block *p)
+{
+       p->file_priv = NULL;
+
+       /* Assumes a single contiguous range.  Needs a special file_priv in
+        * 'heap' to stop it being subsumed.
+        */
+       if (p->next->file_priv == NULL) {
+               struct mem_block *q = p->next;
+               p->size += q->size;
+               p->next = q->next;
+               p->next->prev = p;
+               drm_free(q, sizeof(*q), DRM_MEM_BUFS);
+       }
+
+       if (p->prev->file_priv == NULL) {
+               struct mem_block *q = p->prev;
+               q->size += p->size;
+               q->next = p->next;
+               q->next->prev = q;
+               drm_free(p, sizeof(*q), DRM_MEM_BUFS);
+       }
+}
+
+/* Initialize.  How to check for an uninitialized heap?
+ */
+static int init_heap(struct mem_block **heap, int start, int size)
+{
+       struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS);
+
+       if (!blocks)
+               return -ENOMEM;
+
+       *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS);
+       if (!*heap) {
+               drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS);
+               return -ENOMEM;
+       }
+
+       blocks->start = start;
+       blocks->size = size;
+       blocks->file_priv = NULL;
+       blocks->next = blocks->prev = *heap;
+
+       memset(*heap, 0, sizeof(**heap));
+       (*heap)->file_priv = (struct drm_file *) - 1;
+       (*heap)->next = (*heap)->prev = blocks;
+       return 0;
+}
+
+/* Free all blocks associated with the releasing file.
+ */
+void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap)
+{
+       struct mem_block *p;
+
+       if (!heap || !heap->next)
+               return;
+
+       list_for_each(p, heap) {
+               if (p->file_priv == file_priv)
+                       p->file_priv = NULL;
+       }
+
+       /* Assumes a single contiguous range.  Needs a special file_priv in
+        * 'heap' to stop it being subsumed.
+        */
+       list_for_each(p, heap) {
+               while (p->file_priv == NULL && p->next->file_priv == NULL) {
+                       struct mem_block *q = p->next;
+                       p->size += q->size;
+                       p->next = q->next;
+                       p->next->prev = p;
+                       drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
+               }
+       }
+}
+
+/* Shutdown.
+ */
+void radeon_mem_takedown(struct mem_block **heap)
+{
+       struct mem_block *p;
+
+       if (!*heap)
+               return;
+
+       for (p = (*heap)->next; p != *heap;) {
+               struct mem_block *q = p;
+               p = p->next;
+               drm_free(q, sizeof(*q), DRM_MEM_DRIVER);
+       }
+
+       drm_free(*heap, sizeof(**heap), DRM_MEM_DRIVER);
+       *heap = NULL;
+}
+
+/* IOCTL HANDLERS */
+
+static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region)
+{
+       switch (region) {
+       case RADEON_MEM_REGION_GART:
+               return &dev_priv->gart_heap;
+       case RADEON_MEM_REGION_FB:
+               return &dev_priv->fb_heap;
+       default:
+               return NULL;
+       }
+}
+
+int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_mem_alloc_t *alloc = data;
+       struct mem_block *block, **heap;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       heap = get_heap(dev_priv, alloc->region);
+       if (!heap || !*heap)
+               return -EFAULT;
+
+       /* Make things easier on ourselves: all allocations at least
+        * 4k aligned.
+        */
+       if (alloc->alignment < 12)
+               alloc->alignment = 12;
+
+       block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv);
+
+       if (!block)
+               return -ENOMEM;
+
+       if (DRM_COPY_TO_USER(alloc->region_offset, &block->start,
+                            sizeof(int))) {
+               DRM_ERROR("copy_to_user\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_mem_free_t *memfree = data;
+       struct mem_block *block, **heap;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       heap = get_heap(dev_priv, memfree->region);
+       if (!heap || !*heap)
+               return -EFAULT;
+
+       block = find_block(*heap, memfree->region_offset);
+       if (!block)
+               return -EFAULT;
+
+       if (block->file_priv != file_priv)
+               return -EPERM;
+
+       free_block(block);
+       return 0;
+}
+
+int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_mem_init_heap_t *initheap = data;
+       struct mem_block **heap;
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       heap = get_heap(dev_priv, initheap->region);
+       if (!heap)
+               return -EFAULT;
+
+       if (*heap) {
+               DRM_ERROR("heap already initialized?");
+               return -EFAULT;
+       }
+
+       return init_heap(heap, initheap->start, initheap->size);
+}
diff --git a/drivers/gpu/drm/radeon/radeon_microcode.h b/drivers/gpu/drm/radeon/radeon_microcode.h
new file mode 100644 (file)
index 0000000..a348c9e
--- /dev/null
@@ -0,0 +1,1844 @@
+/*
+ * Copyright 2007 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef RADEON_MICROCODE_H
+#define RADEON_MICROCODE_H
+
+/* production radeon ucode r1xx-r6xx */
+static const u32 R100_cp_microcode[][2] = {
+    { 0x21007000, 0000000000 },
+    { 0x20007000, 0000000000 },
+    { 0x000000b4, 0x00000004 },
+    { 0x000000b8, 0x00000004 },
+    { 0x6f5b4d4c, 0000000000 },
+    { 0x4c4c427f, 0000000000 },
+    { 0x5b568a92, 0000000000 },
+    { 0x4ca09c6d, 0000000000 },
+    { 0xad4c4c4c, 0000000000 },
+    { 0x4ce1af3d, 0000000000 },
+    { 0xd8afafaf, 0000000000 },
+    { 0xd64c4cdc, 0000000000 },
+    { 0x4cd10d10, 0000000000 },
+    { 0x000f0000, 0x00000016 },
+    { 0x362f242d, 0000000000 },
+    { 0x00000012, 0x00000004 },
+    { 0x000f0000, 0x00000016 },
+    { 0x362f282d, 0000000000 },
+    { 0x000380e7, 0x00000002 },
+    { 0x04002c97, 0x00000002 },
+    { 0x000f0001, 0x00000016 },
+    { 0x333a3730, 0000000000 },
+    { 0x000077ef, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x00000021, 0x0000001a },
+    { 0x00004000, 0x0000001e },
+    { 0x00061000, 0x00000002 },
+    { 0x00000021, 0x0000001a },
+    { 0x00004000, 0x0000001e },
+    { 0x00061000, 0x00000002 },
+    { 0x00000021, 0x0000001a },
+    { 0x00004000, 0x0000001e },
+    { 0x00000017, 0x00000004 },
+    { 0x0003802b, 0x00000002 },
+    { 0x040067e0, 0x00000002 },
+    { 0x00000017, 0x00000004 },
+    { 0x000077e0, 0x00000002 },
+    { 0x00065000, 0x00000002 },
+    { 0x000037e1, 0x00000002 },
+    { 0x040067e1, 0x00000006 },
+    { 0x000077e0, 0x00000002 },
+    { 0x000077e1, 0x00000002 },
+    { 0x000077e1, 0x00000006 },
+    { 0xffffffff, 0000000000 },
+    { 0x10000000, 0000000000 },
+    { 0x0003802b, 0x00000002 },
+    { 0x040067e0, 0x00000006 },
+    { 0x00007675, 0x00000002 },
+    { 0x00007676, 0x00000002 },
+    { 0x00007677, 0x00000002 },
+    { 0x00007678, 0x00000006 },
+    { 0x0003802c, 0x00000002 },
+    { 0x04002676, 0x00000002 },
+    { 0x00007677, 0x00000002 },
+    { 0x00007678, 0x00000006 },
+    { 0x0000002f, 0x00000018 },
+    { 0x0000002f, 0x00000018 },
+    { 0000000000, 0x00000006 },
+    { 0x00000030, 0x00000018 },
+    { 0x00000030, 0x00000018 },
+    { 0000000000, 0x00000006 },
+    { 0x01605000, 0x00000002 },
+    { 0x00065000, 0x00000002 },
+    { 0x00098000, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x64c0603e, 0x00000004 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00080000, 0x00000016 },
+    { 0000000000, 0000000000 },
+    { 0x0400251d, 0x00000002 },
+    { 0x00007580, 0x00000002 },
+    { 0x00067581, 0x00000002 },
+    { 0x04002580, 0x00000002 },
+    { 0x00067581, 0x00000002 },
+    { 0x00000049, 0x00000004 },
+    { 0x00005000, 0000000000 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x0000750e, 0x00000002 },
+    { 0x00019000, 0x00000002 },
+    { 0x00011055, 0x00000014 },
+    { 0x00000055, 0x00000012 },
+    { 0x0400250f, 0x00000002 },
+    { 0x0000504f, 0x00000004 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00007565, 0x00000002 },
+    { 0x00007566, 0x00000002 },
+    { 0x00000058, 0x00000004 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x01e655b4, 0x00000002 },
+    { 0x4401b0e4, 0x00000002 },
+    { 0x01c110e4, 0x00000002 },
+    { 0x26667066, 0x00000018 },
+    { 0x040c2565, 0x00000002 },
+    { 0x00000066, 0x00000018 },
+    { 0x04002564, 0x00000002 },
+    { 0x00007566, 0x00000002 },
+    { 0x0000005d, 0x00000004 },
+    { 0x00401069, 0x00000008 },
+    { 0x00101000, 0x00000002 },
+    { 0x000d80ff, 0x00000002 },
+    { 0x0080006c, 0x00000008 },
+    { 0x000f9000, 0x00000002 },
+    { 0x000e00ff, 0x00000002 },
+    { 0000000000, 0x00000006 },
+    { 0x0000008f, 0x00000018 },
+    { 0x0000005b, 0x00000004 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00007576, 0x00000002 },
+    { 0x00065000, 0x00000002 },
+    { 0x00009000, 0x00000002 },
+    { 0x00041000, 0x00000002 },
+    { 0x0c00350e, 0x00000002 },
+    { 0x00049000, 0x00000002 },
+    { 0x00051000, 0x00000002 },
+    { 0x01e785f8, 0x00000002 },
+    { 0x00200000, 0x00000002 },
+    { 0x0060007e, 0x0000000c },
+    { 0x00007563, 0x00000002 },
+    { 0x006075f0, 0x00000021 },
+    { 0x20007073, 0x00000004 },
+    { 0x00005073, 0x00000004 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00007576, 0x00000002 },
+    { 0x00007577, 0x00000002 },
+    { 0x0000750e, 0x00000002 },
+    { 0x0000750f, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x00600083, 0x0000000c },
+    { 0x006075f0, 0x00000021 },
+    { 0x000075f8, 0x00000002 },
+    { 0x00000083, 0x00000004 },
+    { 0x000a750e, 0x00000002 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x0020750f, 0x00000002 },
+    { 0x00600086, 0x00000004 },
+    { 0x00007570, 0x00000002 },
+    { 0x00007571, 0x00000002 },
+    { 0x00007572, 0x00000006 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00005000, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x00007568, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x00000095, 0x0000000c },
+    { 0x00058000, 0x00000002 },
+    { 0x0c607562, 0x00000002 },
+    { 0x00000097, 0x00000004 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x00600096, 0x00000004 },
+    { 0x400070e5, 0000000000 },
+    { 0x000380e6, 0x00000002 },
+    { 0x040025c5, 0x00000002 },
+    { 0x000380e5, 0x00000002 },
+    { 0x000000a8, 0x0000001c },
+    { 0x000650aa, 0x00000018 },
+    { 0x040025bb, 0x00000002 },
+    { 0x000610ab, 0x00000018 },
+    { 0x040075bc, 0000000000 },
+    { 0x000075bb, 0x00000002 },
+    { 0x000075bc, 0000000000 },
+    { 0x00090000, 0x00000006 },
+    { 0x00090000, 0x00000002 },
+    { 0x000d8002, 0x00000006 },
+    { 0x00007832, 0x00000002 },
+    { 0x00005000, 0x00000002 },
+    { 0x000380e7, 0x00000002 },
+    { 0x04002c97, 0x00000002 },
+    { 0x00007820, 0x00000002 },
+    { 0x00007821, 0x00000002 },
+    { 0x00007800, 0000000000 },
+    { 0x01200000, 0x00000002 },
+    { 0x20077000, 0x00000002 },
+    { 0x01200000, 0x00000002 },
+    { 0x20007000, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x0120751b, 0x00000002 },
+    { 0x8040750a, 0x00000002 },
+    { 0x8040750b, 0x00000002 },
+    { 0x00110000, 0x00000002 },
+    { 0x000380e5, 0x00000002 },
+    { 0x000000c6, 0x0000001c },
+    { 0x000610ab, 0x00000018 },
+    { 0x844075bd, 0x00000002 },
+    { 0x000610aa, 0x00000018 },
+    { 0x840075bb, 0x00000002 },
+    { 0x000610ab, 0x00000018 },
+    { 0x844075bc, 0x00000002 },
+    { 0x000000c9, 0x00000004 },
+    { 0x804075bd, 0x00000002 },
+    { 0x800075bb, 0x00000002 },
+    { 0x804075bc, 0x00000002 },
+    { 0x00108000, 0x00000002 },
+    { 0x01400000, 0x00000002 },
+    { 0x006000cd, 0x0000000c },
+    { 0x20c07000, 0x00000020 },
+    { 0x000000cf, 0x00000012 },
+    { 0x00800000, 0x00000006 },
+    { 0x0080751d, 0x00000006 },
+    { 0000000000, 0000000000 },
+    { 0x0000775c, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x00661000, 0x00000002 },
+    { 0x0460275d, 0x00000020 },
+    { 0x00004000, 0000000000 },
+    { 0x01e00830, 0x00000002 },
+    { 0x21007000, 0000000000 },
+    { 0x6464614d, 0000000000 },
+    { 0x69687420, 0000000000 },
+    { 0x00000073, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x00005000, 0x00000002 },
+    { 0x000380d0, 0x00000002 },
+    { 0x040025e0, 0x00000002 },
+    { 0x000075e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000380e0, 0x00000002 },
+    { 0x04002394, 0x00000002 },
+    { 0x00005000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x00000008, 0000000000 },
+    { 0x00000004, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+static const u32 R200_cp_microcode[][2] = {
+    { 0x21007000, 0000000000 },
+    { 0x20007000, 0000000000 },
+    { 0x000000bf, 0x00000004 },
+    { 0x000000c3, 0x00000004 },
+    { 0x7a685e5d, 0000000000 },
+    { 0x5d5d5588, 0000000000 },
+    { 0x68659197, 0000000000 },
+    { 0x5da19f78, 0000000000 },
+    { 0x5d5d5d5d, 0000000000 },
+    { 0x5dee5d50, 0000000000 },
+    { 0xf2acacac, 0000000000 },
+    { 0xe75df9e9, 0000000000 },
+    { 0xb1dd0e11, 0000000000 },
+    { 0xe2afafaf, 0000000000 },
+    { 0x000f0000, 0x00000016 },
+    { 0x452f232d, 0000000000 },
+    { 0x00000013, 0x00000004 },
+    { 0x000f0000, 0x00000016 },
+    { 0x452f272d, 0000000000 },
+    { 0x000f0001, 0x00000016 },
+    { 0x3e4d4a37, 0000000000 },
+    { 0x000077ef, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x00000020, 0x0000001a },
+    { 0x00004000, 0x0000001e },
+    { 0x00061000, 0x00000002 },
+    { 0x00000020, 0x0000001a },
+    { 0x00004000, 0x0000001e },
+    { 0x00061000, 0x00000002 },
+    { 0x00000020, 0x0000001a },
+    { 0x00004000, 0x0000001e },
+    { 0x00000016, 0x00000004 },
+    { 0x0003802a, 0x00000002 },
+    { 0x040067e0, 0x00000002 },
+    { 0x00000016, 0x00000004 },
+    { 0x000077e0, 0x00000002 },
+    { 0x00065000, 0x00000002 },
+    { 0x000037e1, 0x00000002 },
+    { 0x040067e1, 0x00000006 },
+    { 0x000077e0, 0x00000002 },
+    { 0x000077e1, 0x00000002 },
+    { 0x000077e1, 0x00000006 },
+    { 0xffffffff, 0000000000 },
+    { 0x10000000, 0000000000 },
+    { 0x07f007f0, 0000000000 },
+    { 0x0003802a, 0x00000002 },
+    { 0x040067e0, 0x00000006 },
+    { 0x0003802c, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002743, 0x00000002 },
+    { 0x00007675, 0x00000002 },
+    { 0x00007676, 0x00000002 },
+    { 0x00007677, 0x00000002 },
+    { 0x00007678, 0x00000006 },
+    { 0x0003802c, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002743, 0x00000002 },
+    { 0x00007676, 0x00000002 },
+    { 0x00007677, 0x00000002 },
+    { 0x00007678, 0x00000006 },
+    { 0x0003802b, 0x00000002 },
+    { 0x04002676, 0x00000002 },
+    { 0x00007677, 0x00000002 },
+    { 0x0003802c, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002743, 0x00000002 },
+    { 0x00007678, 0x00000006 },
+    { 0x0003802c, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002741, 0x00000002 },
+    { 0x04002743, 0x00000002 },
+    { 0x00007678, 0x00000006 },
+    { 0x0000002f, 0x00000018 },
+    { 0x0000002f, 0x00000018 },
+    { 0000000000, 0x00000006 },
+    { 0x00000037, 0x00000018 },
+    { 0x00000037, 0x00000018 },
+    { 0000000000, 0x00000006 },
+    { 0x01605000, 0x00000002 },
+    { 0x00065000, 0x00000002 },
+    { 0x00098000, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x64c06051, 0x00000004 },
+    { 0x00080000, 0x00000016 },
+    { 0000000000, 0000000000 },
+    { 0x0400251d, 0x00000002 },
+    { 0x00007580, 0x00000002 },
+    { 0x00067581, 0x00000002 },
+    { 0x04002580, 0x00000002 },
+    { 0x00067581, 0x00000002 },
+    { 0x0000005a, 0x00000004 },
+    { 0x00005000, 0000000000 },
+    { 0x00061000, 0x00000002 },
+    { 0x0000750e, 0x00000002 },
+    { 0x00019000, 0x00000002 },
+    { 0x00011064, 0x00000014 },
+    { 0x00000064, 0x00000012 },
+    { 0x0400250f, 0x00000002 },
+    { 0x0000505e, 0x00000004 },
+    { 0x00007565, 0x00000002 },
+    { 0x00007566, 0x00000002 },
+    { 0x00000065, 0x00000004 },
+    { 0x01e655b4, 0x00000002 },
+    { 0x4401b0f0, 0x00000002 },
+    { 0x01c110f0, 0x00000002 },
+    { 0x26667071, 0x00000018 },
+    { 0x040c2565, 0x00000002 },
+    { 0x00000071, 0x00000018 },
+    { 0x04002564, 0x00000002 },
+    { 0x00007566, 0x00000002 },
+    { 0x00000068, 0x00000004 },
+    { 0x00401074, 0x00000008 },
+    { 0x00101000, 0x00000002 },
+    { 0x000d80ff, 0x00000002 },
+    { 0x00800077, 0x00000008 },
+    { 0x000f9000, 0x00000002 },
+    { 0x000e00ff, 0x00000002 },
+    { 0000000000, 0x00000006 },
+    { 0x00000094, 0x00000018 },
+    { 0x00000068, 0x00000004 },
+    { 0x00007576, 0x00000002 },
+    { 0x00065000, 0x00000002 },
+    { 0x00009000, 0x00000002 },
+    { 0x00041000, 0x00000002 },
+    { 0x0c00350e, 0x00000002 },
+    { 0x00049000, 0x00000002 },
+    { 0x00051000, 0x00000002 },
+    { 0x01e785f8, 0x00000002 },
+    { 0x00200000, 0x00000002 },
+    { 0x00600087, 0x0000000c },
+    { 0x00007563, 0x00000002 },
+    { 0x006075f0, 0x00000021 },
+    { 0x2000707c, 0x00000004 },
+    { 0x0000507c, 0x00000004 },
+    { 0x00007576, 0x00000002 },
+    { 0x00007577, 0x00000002 },
+    { 0x0000750e, 0x00000002 },
+    { 0x0000750f, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x0060008a, 0x0000000c },
+    { 0x006075f0, 0x00000021 },
+    { 0x000075f8, 0x00000002 },
+    { 0x0000008a, 0x00000004 },
+    { 0x000a750e, 0x00000002 },
+    { 0x0020750f, 0x00000002 },
+    { 0x0060008d, 0x00000004 },
+    { 0x00007570, 0x00000002 },
+    { 0x00007571, 0x00000002 },
+    { 0x00007572, 0x00000006 },
+    { 0x00005000, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x00007568, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x00000098, 0x0000000c },
+    { 0x00058000, 0x00000002 },
+    { 0x0c607562, 0x00000002 },
+    { 0x0000009a, 0x00000004 },
+    { 0x00600099, 0x00000004 },
+    { 0x400070f1, 0000000000 },
+    { 0x000380f1, 0x00000002 },
+    { 0x000000a7, 0x0000001c },
+    { 0x000650a9, 0x00000018 },
+    { 0x040025bb, 0x00000002 },
+    { 0x000610aa, 0x00000018 },
+    { 0x040075bc, 0000000000 },
+    { 0x000075bb, 0x00000002 },
+    { 0x000075bc, 0000000000 },
+    { 0x00090000, 0x00000006 },
+    { 0x00090000, 0x00000002 },
+    { 0x000d8002, 0x00000006 },
+    { 0x00005000, 0x00000002 },
+    { 0x00007821, 0x00000002 },
+    { 0x00007800, 0000000000 },
+    { 0x00007821, 0x00000002 },
+    { 0x00007800, 0000000000 },
+    { 0x01665000, 0x00000002 },
+    { 0x000a0000, 0x00000002 },
+    { 0x000671cc, 0x00000002 },
+    { 0x0286f1cd, 0x00000002 },
+    { 0x000000b7, 0x00000010 },
+    { 0x21007000, 0000000000 },
+    { 0x000000be, 0x0000001c },
+    { 0x00065000, 0x00000002 },
+    { 0x000a0000, 0x00000002 },
+    { 0x00061000, 0x00000002 },
+    { 0x000b0000, 0x00000002 },
+    { 0x38067000, 0x00000002 },
+    { 0x000a00ba, 0x00000004 },
+    { 0x20007000, 0000000000 },
+    { 0x01200000, 0x00000002 },
+    { 0x20077000, 0x00000002 },
+    { 0x01200000, 0x00000002 },
+    { 0x20007000, 0000000000 },
+    { 0x00061000, 0x00000002 },
+    { 0x0120751b, 0x00000002 },
+    { 0x8040750a, 0x00000002 },
+    { 0x8040750b, 0x00000002 },
+    { 0x00110000, 0x00000002 },
+    { 0x000380f1, 0x00000002 },
+    { 0x000000d1, 0x0000001c },
+    { 0x000610aa, 0x00000018 },
+    { 0x844075bd, 0x00000002 },
+    { 0x000610a9, 0x00000018 },
+    { 0x840075bb, 0x00000002 },
+    { 0x000610aa, 0x00000018 },
+    { 0x844075bc, 0x00000002 },
+    { 0x000000d4, 0x00000004 },
+    { 0x804075bd, 0x00000002 },
+    { 0x800075bb, 0x00000002 },
+    { 0x804075bc, 0x00000002 },
+    { 0x00108000, 0x00000002 },
+    { 0x01400000, 0x00000002 },
+    { 0x006000d8, 0x0000000c },
+    { 0x20c07000, 0x00000020 },
+    { 0x000000da, 0x00000012 },
+    { 0x00800000, 0x00000006 },
+    { 0x0080751d, 0x00000006 },
+    { 0x000025bb, 0x00000002 },
+    { 0x000040d4, 0x00000004 },
+    { 0x0000775c, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x00661000, 0x00000002 },
+    { 0x0460275d, 0x00000020 },
+    { 0x00004000, 0000000000 },
+    { 0x00007999, 0x00000002 },
+    { 0x00a05000, 0x00000002 },
+    { 0x00661000, 0x00000002 },
+    { 0x0460299b, 0x00000020 },
+    { 0x00004000, 0000000000 },
+    { 0x01e00830, 0x00000002 },
+    { 0x21007000, 0000000000 },
+    { 0x00005000, 0x00000002 },
+    { 0x00038056, 0x00000002 },
+    { 0x040025e0, 0x00000002 },
+    { 0x000075e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000380ed, 0x00000002 },
+    { 0x04007394, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x000078c4, 0x00000002 },
+    { 0x000078c5, 0x00000002 },
+    { 0x000078c6, 0x00000002 },
+    { 0x00007924, 0x00000002 },
+    { 0x00007925, 0x00000002 },
+    { 0x00007926, 0x00000002 },
+    { 0x000000f2, 0x00000004 },
+    { 0x00007924, 0x00000002 },
+    { 0x00007925, 0x00000002 },
+    { 0x00007926, 0x00000002 },
+    { 0x000000f9, 0x00000004 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+static const u32 R300_cp_microcode[][2] = {
+    { 0x4200e000, 0000000000 },
+    { 0x4000e000, 0000000000 },
+    { 0x000000ae, 0x00000008 },
+    { 0x000000b2, 0x00000008 },
+    { 0x67554b4a, 0000000000 },
+    { 0x4a4a4475, 0000000000 },
+    { 0x55527d83, 0000000000 },
+    { 0x4a8c8b65, 0000000000 },
+    { 0x4aef4af6, 0000000000 },
+    { 0x4ae14a4a, 0000000000 },
+    { 0xe4979797, 0000000000 },
+    { 0xdb4aebdd, 0000000000 },
+    { 0x9ccc4a4a, 0000000000 },
+    { 0xd1989898, 0000000000 },
+    { 0x4a0f9ad6, 0000000000 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000d0012, 0x00000038 },
+    { 0x0000e8b4, 0x00000004 },
+    { 0x000d0014, 0x00000038 },
+    { 0x0000e8b6, 0x00000004 },
+    { 0x000d0016, 0x00000038 },
+    { 0x0000e854, 0x00000004 },
+    { 0x000d0018, 0x00000038 },
+    { 0x0000e855, 0x00000004 },
+    { 0x000d001a, 0x00000038 },
+    { 0x0000e856, 0x00000004 },
+    { 0x000d001c, 0x00000038 },
+    { 0x0000e857, 0x00000004 },
+    { 0x000d001e, 0x00000038 },
+    { 0x0000e824, 0x00000004 },
+    { 0x000d0020, 0x00000038 },
+    { 0x0000e825, 0x00000004 },
+    { 0x000d0022, 0x00000038 },
+    { 0x0000e830, 0x00000004 },
+    { 0x000d0024, 0x00000038 },
+    { 0x0000f0c0, 0x00000004 },
+    { 0x000d0026, 0x00000038 },
+    { 0x0000f0c1, 0x00000004 },
+    { 0x000d0028, 0x00000038 },
+    { 0x0000f041, 0x00000004 },
+    { 0x000d002a, 0x00000038 },
+    { 0x0000f184, 0x00000004 },
+    { 0x000d002c, 0x00000038 },
+    { 0x0000f185, 0x00000004 },
+    { 0x000d002e, 0x00000038 },
+    { 0x0000f186, 0x00000004 },
+    { 0x000d0030, 0x00000038 },
+    { 0x0000f187, 0x00000004 },
+    { 0x000d0032, 0x00000038 },
+    { 0x0000f180, 0x00000004 },
+    { 0x000d0034, 0x00000038 },
+    { 0x0000f393, 0x00000004 },
+    { 0x000d0036, 0x00000038 },
+    { 0x0000f38a, 0x00000004 },
+    { 0x000d0038, 0x00000038 },
+    { 0x0000f38e, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000043, 0x00000018 },
+    { 0x00cce800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x0000003a, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x2000451d, 0x00000004 },
+    { 0x0000e580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x08004580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x00000047, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x00032000, 0x00000004 },
+    { 0x00022051, 0x00000028 },
+    { 0x00000051, 0x00000024 },
+    { 0x0800450f, 0x00000004 },
+    { 0x0000a04b, 0x00000008 },
+    { 0x0000e565, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000052, 0x00000008 },
+    { 0x03cca5b4, 0x00000004 },
+    { 0x05432000, 0x00000004 },
+    { 0x00022000, 0x00000004 },
+    { 0x4ccce05e, 0x00000030 },
+    { 0x08274565, 0x00000004 },
+    { 0x0000005e, 0x00000030 },
+    { 0x08004564, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000055, 0x00000008 },
+    { 0x00802061, 0x00000010 },
+    { 0x00202000, 0x00000004 },
+    { 0x001b00ff, 0x00000004 },
+    { 0x01000064, 0x00000010 },
+    { 0x001f2000, 0x00000004 },
+    { 0x001c00ff, 0x00000004 },
+    { 0000000000, 0x0000000c },
+    { 0x00000080, 0x00000030 },
+    { 0x00000055, 0x00000008 },
+    { 0x0000e576, 0x00000004 },
+    { 0x000ca000, 0x00000004 },
+    { 0x00012000, 0x00000004 },
+    { 0x00082000, 0x00000004 },
+    { 0x1800650e, 0x00000004 },
+    { 0x00092000, 0x00000004 },
+    { 0x000a2000, 0x00000004 },
+    { 0x000f0000, 0x00000004 },
+    { 0x00400000, 0x00000004 },
+    { 0x00000074, 0x00000018 },
+    { 0x0000e563, 0x00000004 },
+    { 0x00c0e5f9, 0x000000c2 },
+    { 0x00000069, 0x00000008 },
+    { 0x0000a069, 0x00000008 },
+    { 0x0000e576, 0x00000004 },
+    { 0x0000e577, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x0000e50f, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000077, 0x00000018 },
+    { 0x00c0e5f9, 0x000000c2 },
+    { 0x00000077, 0x00000008 },
+    { 0x0014e50e, 0x00000004 },
+    { 0x0040e50f, 0x00000004 },
+    { 0x00c0007a, 0x00000008 },
+    { 0x0000e570, 0x00000004 },
+    { 0x0000e571, 0x00000004 },
+    { 0x0000e572, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x0000e568, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00000084, 0x00000018 },
+    { 0x000b0000, 0x00000004 },
+    { 0x18c0e562, 0x00000004 },
+    { 0x00000086, 0x00000008 },
+    { 0x00c00085, 0x00000008 },
+    { 0x000700e3, 0x00000004 },
+    { 0x00000092, 0x00000038 },
+    { 0x000ca094, 0x00000030 },
+    { 0x080045bb, 0x00000004 },
+    { 0x000c2095, 0x00000030 },
+    { 0x0800e5bc, 0000000000 },
+    { 0x0000e5bb, 0x00000004 },
+    { 0x0000e5bc, 0000000000 },
+    { 0x00120000, 0x0000000c },
+    { 0x00120000, 0x00000004 },
+    { 0x001b0002, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e800, 0000000000 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e82e, 0000000000 },
+    { 0x02cca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000ce1cc, 0x00000004 },
+    { 0x050de1cd, 0x00000004 },
+    { 0x00400000, 0x00000004 },
+    { 0x000000a4, 0x00000018 },
+    { 0x00c0a000, 0x00000004 },
+    { 0x000000a1, 0x00000008 },
+    { 0x000000a6, 0x00000020 },
+    { 0x4200e000, 0000000000 },
+    { 0x000000ad, 0x00000038 },
+    { 0x000ca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00160000, 0x00000004 },
+    { 0x700ce000, 0x00000004 },
+    { 0x001400a9, 0x00000008 },
+    { 0x4000e000, 0000000000 },
+    { 0x02400000, 0x00000004 },
+    { 0x400ee000, 0x00000004 },
+    { 0x02400000, 0x00000004 },
+    { 0x4000e000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0240e51b, 0x00000004 },
+    { 0x0080e50a, 0x00000005 },
+    { 0x0080e50b, 0x00000005 },
+    { 0x00220000, 0x00000004 },
+    { 0x000700e3, 0x00000004 },
+    { 0x000000c0, 0x00000038 },
+    { 0x000c2095, 0x00000030 },
+    { 0x0880e5bd, 0x00000005 },
+    { 0x000c2094, 0x00000030 },
+    { 0x0800e5bb, 0x00000005 },
+    { 0x000c2095, 0x00000030 },
+    { 0x0880e5bc, 0x00000005 },
+    { 0x000000c3, 0x00000008 },
+    { 0x0080e5bd, 0x00000005 },
+    { 0x0000e5bb, 0x00000005 },
+    { 0x0080e5bc, 0x00000005 },
+    { 0x00210000, 0x00000004 },
+    { 0x02800000, 0x00000004 },
+    { 0x00c000c7, 0x00000018 },
+    { 0x4180e000, 0x00000040 },
+    { 0x000000c9, 0x00000024 },
+    { 0x01000000, 0x0000000c },
+    { 0x0100e51d, 0x0000000c },
+    { 0x000045bb, 0x00000004 },
+    { 0x000080c3, 0x00000008 },
+    { 0x0000f3ce, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053cf, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f3d2, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053d3, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f39d, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c0539e, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x03c00830, 0x00000004 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x200045e0, 0x00000004 },
+    { 0x0000e5e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000700e0, 0x00000004 },
+    { 0x0800e394, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x0000e8c4, 0x00000004 },
+    { 0x0000e8c5, 0x00000004 },
+    { 0x0000e8c6, 0x00000004 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000e4, 0x00000008 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000eb, 0x00000008 },
+    { 0x02c02000, 0x00000004 },
+    { 0x00060000, 0x00000004 },
+    { 0x000000f3, 0x00000034 },
+    { 0x000000f0, 0x00000008 },
+    { 0x00008000, 0x00000004 },
+    { 0xc000e000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x001d0018, 0x00000004 },
+    { 0x001a0001, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0x0500a04a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+static const u32 R420_cp_microcode[][2] = {
+    { 0x4200e000, 0000000000 },
+    { 0x4000e000, 0000000000 },
+    { 0x00000099, 0x00000008 },
+    { 0x0000009d, 0x00000008 },
+    { 0x4a554b4a, 0000000000 },
+    { 0x4a4a4467, 0000000000 },
+    { 0x55526f75, 0000000000 },
+    { 0x4a7e7d65, 0000000000 },
+    { 0xd9d3dff6, 0000000000 },
+    { 0x4ac54a4a, 0000000000 },
+    { 0xc8828282, 0000000000 },
+    { 0xbf4acfc1, 0000000000 },
+    { 0x87b04a4a, 0000000000 },
+    { 0xb5838383, 0000000000 },
+    { 0x4a0f85ba, 0000000000 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000d0012, 0x00000038 },
+    { 0x0000e8b4, 0x00000004 },
+    { 0x000d0014, 0x00000038 },
+    { 0x0000e8b6, 0x00000004 },
+    { 0x000d0016, 0x00000038 },
+    { 0x0000e854, 0x00000004 },
+    { 0x000d0018, 0x00000038 },
+    { 0x0000e855, 0x00000004 },
+    { 0x000d001a, 0x00000038 },
+    { 0x0000e856, 0x00000004 },
+    { 0x000d001c, 0x00000038 },
+    { 0x0000e857, 0x00000004 },
+    { 0x000d001e, 0x00000038 },
+    { 0x0000e824, 0x00000004 },
+    { 0x000d0020, 0x00000038 },
+    { 0x0000e825, 0x00000004 },
+    { 0x000d0022, 0x00000038 },
+    { 0x0000e830, 0x00000004 },
+    { 0x000d0024, 0x00000038 },
+    { 0x0000f0c0, 0x00000004 },
+    { 0x000d0026, 0x00000038 },
+    { 0x0000f0c1, 0x00000004 },
+    { 0x000d0028, 0x00000038 },
+    { 0x0000f041, 0x00000004 },
+    { 0x000d002a, 0x00000038 },
+    { 0x0000f184, 0x00000004 },
+    { 0x000d002c, 0x00000038 },
+    { 0x0000f185, 0x00000004 },
+    { 0x000d002e, 0x00000038 },
+    { 0x0000f186, 0x00000004 },
+    { 0x000d0030, 0x00000038 },
+    { 0x0000f187, 0x00000004 },
+    { 0x000d0032, 0x00000038 },
+    { 0x0000f180, 0x00000004 },
+    { 0x000d0034, 0x00000038 },
+    { 0x0000f393, 0x00000004 },
+    { 0x000d0036, 0x00000038 },
+    { 0x0000f38a, 0x00000004 },
+    { 0x000d0038, 0x00000038 },
+    { 0x0000f38e, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000043, 0x00000018 },
+    { 0x00cce800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x0000003a, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x2000451d, 0x00000004 },
+    { 0x0000e580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x08004580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x00000047, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x00032000, 0x00000004 },
+    { 0x00022051, 0x00000028 },
+    { 0x00000051, 0x00000024 },
+    { 0x0800450f, 0x00000004 },
+    { 0x0000a04b, 0x00000008 },
+    { 0x0000e565, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000052, 0x00000008 },
+    { 0x03cca5b4, 0x00000004 },
+    { 0x05432000, 0x00000004 },
+    { 0x00022000, 0x00000004 },
+    { 0x4ccce05e, 0x00000030 },
+    { 0x08274565, 0x00000004 },
+    { 0x0000005e, 0x00000030 },
+    { 0x08004564, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000055, 0x00000008 },
+    { 0x00802061, 0x00000010 },
+    { 0x00202000, 0x00000004 },
+    { 0x001b00ff, 0x00000004 },
+    { 0x01000064, 0x00000010 },
+    { 0x001f2000, 0x00000004 },
+    { 0x001c00ff, 0x00000004 },
+    { 0000000000, 0x0000000c },
+    { 0x00000072, 0x00000030 },
+    { 0x00000055, 0x00000008 },
+    { 0x0000e576, 0x00000004 },
+    { 0x0000e577, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x0000e50f, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000069, 0x00000018 },
+    { 0x00c0e5f9, 0x000000c2 },
+    { 0x00000069, 0x00000008 },
+    { 0x0014e50e, 0x00000004 },
+    { 0x0040e50f, 0x00000004 },
+    { 0x00c0006c, 0x00000008 },
+    { 0x0000e570, 0x00000004 },
+    { 0x0000e571, 0x00000004 },
+    { 0x0000e572, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x0000e568, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00000076, 0x00000018 },
+    { 0x000b0000, 0x00000004 },
+    { 0x18c0e562, 0x00000004 },
+    { 0x00000078, 0x00000008 },
+    { 0x00c00077, 0x00000008 },
+    { 0x000700c7, 0x00000004 },
+    { 0x00000080, 0x00000038 },
+    { 0x0000e5bb, 0x00000004 },
+    { 0x0000e5bc, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e800, 0000000000 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e82e, 0000000000 },
+    { 0x02cca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000ce1cc, 0x00000004 },
+    { 0x050de1cd, 0x00000004 },
+    { 0x00400000, 0x00000004 },
+    { 0x0000008f, 0x00000018 },
+    { 0x00c0a000, 0x00000004 },
+    { 0x0000008c, 0x00000008 },
+    { 0x00000091, 0x00000020 },
+    { 0x4200e000, 0000000000 },
+    { 0x00000098, 0x00000038 },
+    { 0x000ca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00160000, 0x00000004 },
+    { 0x700ce000, 0x00000004 },
+    { 0x00140094, 0x00000008 },
+    { 0x4000e000, 0000000000 },
+    { 0x02400000, 0x00000004 },
+    { 0x400ee000, 0x00000004 },
+    { 0x02400000, 0x00000004 },
+    { 0x4000e000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0240e51b, 0x00000004 },
+    { 0x0080e50a, 0x00000005 },
+    { 0x0080e50b, 0x00000005 },
+    { 0x00220000, 0x00000004 },
+    { 0x000700c7, 0x00000004 },
+    { 0x000000a4, 0x00000038 },
+    { 0x0080e5bd, 0x00000005 },
+    { 0x0000e5bb, 0x00000005 },
+    { 0x0080e5bc, 0x00000005 },
+    { 0x00210000, 0x00000004 },
+    { 0x02800000, 0x00000004 },
+    { 0x00c000ab, 0x00000018 },
+    { 0x4180e000, 0x00000040 },
+    { 0x000000ad, 0x00000024 },
+    { 0x01000000, 0x0000000c },
+    { 0x0100e51d, 0x0000000c },
+    { 0x000045bb, 0x00000004 },
+    { 0x000080a7, 0x00000008 },
+    { 0x0000f3ce, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053cf, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f3d2, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053d3, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f39d, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c0539e, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x03c00830, 0x00000004 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x200045e0, 0x00000004 },
+    { 0x0000e5e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000700c4, 0x00000004 },
+    { 0x0800e394, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x0000e8c4, 0x00000004 },
+    { 0x0000e8c5, 0x00000004 },
+    { 0x0000e8c6, 0x00000004 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000c8, 0x00000008 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000cf, 0x00000008 },
+    { 0x02c02000, 0x00000004 },
+    { 0x00060000, 0x00000004 },
+    { 0x000000d7, 0x00000034 },
+    { 0x000000d4, 0x00000008 },
+    { 0x00008000, 0x00000004 },
+    { 0xc000e000, 0000000000 },
+    { 0x0000e1cc, 0x00000004 },
+    { 0x0500e1cd, 0x00000004 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000000de, 0x00000034 },
+    { 0x000000da, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x0019e1cc, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x0500a000, 0x00000004 },
+    { 0x080041cd, 0x00000004 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x001d0018, 0x00000004 },
+    { 0x001a0001, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0x0500a04a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+static const u32 RS600_cp_microcode[][2] = {
+    { 0x4200e000, 0000000000 },
+    { 0x4000e000, 0000000000 },
+    { 0x000000a0, 0x00000008 },
+    { 0x000000a4, 0x00000008 },
+    { 0x4a554b4a, 0000000000 },
+    { 0x4a4a4467, 0000000000 },
+    { 0x55526f75, 0000000000 },
+    { 0x4a7e7d65, 0000000000 },
+    { 0x4ae74af6, 0000000000 },
+    { 0x4ad34a4a, 0000000000 },
+    { 0xd6898989, 0000000000 },
+    { 0xcd4addcf, 0000000000 },
+    { 0x8ebe4ae2, 0000000000 },
+    { 0xc38a8a8a, 0000000000 },
+    { 0x4a0f8cc8, 0000000000 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000d0012, 0x00000038 },
+    { 0x0000e8b4, 0x00000004 },
+    { 0x000d0014, 0x00000038 },
+    { 0x0000e8b6, 0x00000004 },
+    { 0x000d0016, 0x00000038 },
+    { 0x0000e854, 0x00000004 },
+    { 0x000d0018, 0x00000038 },
+    { 0x0000e855, 0x00000004 },
+    { 0x000d001a, 0x00000038 },
+    { 0x0000e856, 0x00000004 },
+    { 0x000d001c, 0x00000038 },
+    { 0x0000e857, 0x00000004 },
+    { 0x000d001e, 0x00000038 },
+    { 0x0000e824, 0x00000004 },
+    { 0x000d0020, 0x00000038 },
+    { 0x0000e825, 0x00000004 },
+    { 0x000d0022, 0x00000038 },
+    { 0x0000e830, 0x00000004 },
+    { 0x000d0024, 0x00000038 },
+    { 0x0000f0c0, 0x00000004 },
+    { 0x000d0026, 0x00000038 },
+    { 0x0000f0c1, 0x00000004 },
+    { 0x000d0028, 0x00000038 },
+    { 0x0000f041, 0x00000004 },
+    { 0x000d002a, 0x00000038 },
+    { 0x0000f184, 0x00000004 },
+    { 0x000d002c, 0x00000038 },
+    { 0x0000f185, 0x00000004 },
+    { 0x000d002e, 0x00000038 },
+    { 0x0000f186, 0x00000004 },
+    { 0x000d0030, 0x00000038 },
+    { 0x0000f187, 0x00000004 },
+    { 0x000d0032, 0x00000038 },
+    { 0x0000f180, 0x00000004 },
+    { 0x000d0034, 0x00000038 },
+    { 0x0000f393, 0x00000004 },
+    { 0x000d0036, 0x00000038 },
+    { 0x0000f38a, 0x00000004 },
+    { 0x000d0038, 0x00000038 },
+    { 0x0000f38e, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000043, 0x00000018 },
+    { 0x00cce800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x0000003a, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x2000451d, 0x00000004 },
+    { 0x0000e580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x08004580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x00000047, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x00032000, 0x00000004 },
+    { 0x00022051, 0x00000028 },
+    { 0x00000051, 0x00000024 },
+    { 0x0800450f, 0x00000004 },
+    { 0x0000a04b, 0x00000008 },
+    { 0x0000e565, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000052, 0x00000008 },
+    { 0x03cca5b4, 0x00000004 },
+    { 0x05432000, 0x00000004 },
+    { 0x00022000, 0x00000004 },
+    { 0x4ccce05e, 0x00000030 },
+    { 0x08274565, 0x00000004 },
+    { 0x0000005e, 0x00000030 },
+    { 0x08004564, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000055, 0x00000008 },
+    { 0x00802061, 0x00000010 },
+    { 0x00202000, 0x00000004 },
+    { 0x001b00ff, 0x00000004 },
+    { 0x01000064, 0x00000010 },
+    { 0x001f2000, 0x00000004 },
+    { 0x001c00ff, 0x00000004 },
+    { 0000000000, 0x0000000c },
+    { 0x00000072, 0x00000030 },
+    { 0x00000055, 0x00000008 },
+    { 0x0000e576, 0x00000004 },
+    { 0x0000e577, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x0000e50f, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000069, 0x00000018 },
+    { 0x00c0e5f9, 0x000000c2 },
+    { 0x00000069, 0x00000008 },
+    { 0x0014e50e, 0x00000004 },
+    { 0x0040e50f, 0x00000004 },
+    { 0x00c0006c, 0x00000008 },
+    { 0x0000e570, 0x00000004 },
+    { 0x0000e571, 0x00000004 },
+    { 0x0000e572, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x0000e568, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00000076, 0x00000018 },
+    { 0x000b0000, 0x00000004 },
+    { 0x18c0e562, 0x00000004 },
+    { 0x00000078, 0x00000008 },
+    { 0x00c00077, 0x00000008 },
+    { 0x000700d5, 0x00000004 },
+    { 0x00000084, 0x00000038 },
+    { 0x000ca086, 0x00000030 },
+    { 0x080045bb, 0x00000004 },
+    { 0x000c2087, 0x00000030 },
+    { 0x0800e5bc, 0000000000 },
+    { 0x0000e5bb, 0x00000004 },
+    { 0x0000e5bc, 0000000000 },
+    { 0x00120000, 0x0000000c },
+    { 0x00120000, 0x00000004 },
+    { 0x001b0002, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e800, 0000000000 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e82e, 0000000000 },
+    { 0x02cca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000ce1cc, 0x00000004 },
+    { 0x050de1cd, 0x00000004 },
+    { 0x00400000, 0x00000004 },
+    { 0x00000096, 0x00000018 },
+    { 0x00c0a000, 0x00000004 },
+    { 0x00000093, 0x00000008 },
+    { 0x00000098, 0x00000020 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000009f, 0x00000038 },
+    { 0x000ca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00160000, 0x00000004 },
+    { 0x700ce000, 0x00000004 },
+    { 0x0014009b, 0x00000008 },
+    { 0x4000e000, 0000000000 },
+    { 0x02400000, 0x00000004 },
+    { 0x400ee000, 0x00000004 },
+    { 0x02400000, 0x00000004 },
+    { 0x4000e000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0240e51b, 0x00000004 },
+    { 0x0080e50a, 0x00000005 },
+    { 0x0080e50b, 0x00000005 },
+    { 0x00220000, 0x00000004 },
+    { 0x000700d5, 0x00000004 },
+    { 0x000000b2, 0x00000038 },
+    { 0x000c2087, 0x00000030 },
+    { 0x0880e5bd, 0x00000005 },
+    { 0x000c2086, 0x00000030 },
+    { 0x0800e5bb, 0x00000005 },
+    { 0x000c2087, 0x00000030 },
+    { 0x0880e5bc, 0x00000005 },
+    { 0x000000b5, 0x00000008 },
+    { 0x0080e5bd, 0x00000005 },
+    { 0x0000e5bb, 0x00000005 },
+    { 0x0080e5bc, 0x00000005 },
+    { 0x00210000, 0x00000004 },
+    { 0x02800000, 0x00000004 },
+    { 0x00c000b9, 0x00000018 },
+    { 0x4180e000, 0x00000040 },
+    { 0x000000bb, 0x00000024 },
+    { 0x01000000, 0x0000000c },
+    { 0x0100e51d, 0x0000000c },
+    { 0x000045bb, 0x00000004 },
+    { 0x000080b5, 0x00000008 },
+    { 0x0000f3ce, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053cf, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f3d2, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053d3, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f39d, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c0539e, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x03c00830, 0x00000004 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x200045e0, 0x00000004 },
+    { 0x0000e5e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000700d2, 0x00000004 },
+    { 0x0800e394, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x0000e8c4, 0x00000004 },
+    { 0x0000e8c5, 0x00000004 },
+    { 0x0000e8c6, 0x00000004 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000d6, 0x00000008 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000dd, 0x00000008 },
+    { 0x00e00116, 0000000000 },
+    { 0x000700e1, 0x00000004 },
+    { 0x0800401c, 0x00000004 },
+    { 0x200050e7, 0x00000004 },
+    { 0x0000e01d, 0x00000004 },
+    { 0x000000e4, 0x00000008 },
+    { 0x02c02000, 0x00000004 },
+    { 0x00060000, 0x00000004 },
+    { 0x000000eb, 0x00000034 },
+    { 0x000000e8, 0x00000008 },
+    { 0x00008000, 0x00000004 },
+    { 0xc000e000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x001d0018, 0x00000004 },
+    { 0x001a0001, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0x0500a04a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+static const u32 RS690_cp_microcode[][2] = {
+    { 0x000000dd, 0x00000008 },
+    { 0x000000df, 0x00000008 },
+    { 0x000000a0, 0x00000008 },
+    { 0x000000a4, 0x00000008 },
+    { 0x4a554b4a, 0000000000 },
+    { 0x4a4a4467, 0000000000 },
+    { 0x55526f75, 0000000000 },
+    { 0x4a7e7d65, 0000000000 },
+    { 0x4ad74af6, 0000000000 },
+    { 0x4ac94a4a, 0000000000 },
+    { 0xcc898989, 0000000000 },
+    { 0xc34ad3c5, 0000000000 },
+    { 0x8e4a4a4a, 0000000000 },
+    { 0x4a8a8a8a, 0000000000 },
+    { 0x4a0f8c4a, 0000000000 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000d0012, 0x00000038 },
+    { 0x0000e8b4, 0x00000004 },
+    { 0x000d0014, 0x00000038 },
+    { 0x0000e8b6, 0x00000004 },
+    { 0x000d0016, 0x00000038 },
+    { 0x0000e854, 0x00000004 },
+    { 0x000d0018, 0x00000038 },
+    { 0x0000e855, 0x00000004 },
+    { 0x000d001a, 0x00000038 },
+    { 0x0000e856, 0x00000004 },
+    { 0x000d001c, 0x00000038 },
+    { 0x0000e857, 0x00000004 },
+    { 0x000d001e, 0x00000038 },
+    { 0x0000e824, 0x00000004 },
+    { 0x000d0020, 0x00000038 },
+    { 0x0000e825, 0x00000004 },
+    { 0x000d0022, 0x00000038 },
+    { 0x0000e830, 0x00000004 },
+    { 0x000d0024, 0x00000038 },
+    { 0x0000f0c0, 0x00000004 },
+    { 0x000d0026, 0x00000038 },
+    { 0x0000f0c1, 0x00000004 },
+    { 0x000d0028, 0x00000038 },
+    { 0x0000f041, 0x00000004 },
+    { 0x000d002a, 0x00000038 },
+    { 0x0000f184, 0x00000004 },
+    { 0x000d002c, 0x00000038 },
+    { 0x0000f185, 0x00000004 },
+    { 0x000d002e, 0x00000038 },
+    { 0x0000f186, 0x00000004 },
+    { 0x000d0030, 0x00000038 },
+    { 0x0000f187, 0x00000004 },
+    { 0x000d0032, 0x00000038 },
+    { 0x0000f180, 0x00000004 },
+    { 0x000d0034, 0x00000038 },
+    { 0x0000f393, 0x00000004 },
+    { 0x000d0036, 0x00000038 },
+    { 0x0000f38a, 0x00000004 },
+    { 0x000d0038, 0x00000038 },
+    { 0x0000f38e, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000043, 0x00000018 },
+    { 0x00cce800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x0000003a, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x2000451d, 0x00000004 },
+    { 0x0000e580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x08004580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x00000047, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x00032000, 0x00000004 },
+    { 0x00022051, 0x00000028 },
+    { 0x00000051, 0x00000024 },
+    { 0x0800450f, 0x00000004 },
+    { 0x0000a04b, 0x00000008 },
+    { 0x0000e565, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000052, 0x00000008 },
+    { 0x03cca5b4, 0x00000004 },
+    { 0x05432000, 0x00000004 },
+    { 0x00022000, 0x00000004 },
+    { 0x4ccce05e, 0x00000030 },
+    { 0x08274565, 0x00000004 },
+    { 0x0000005e, 0x00000030 },
+    { 0x08004564, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000055, 0x00000008 },
+    { 0x00802061, 0x00000010 },
+    { 0x00202000, 0x00000004 },
+    { 0x001b00ff, 0x00000004 },
+    { 0x01000064, 0x00000010 },
+    { 0x001f2000, 0x00000004 },
+    { 0x001c00ff, 0x00000004 },
+    { 0000000000, 0x0000000c },
+    { 0x00000072, 0x00000030 },
+    { 0x00000055, 0x00000008 },
+    { 0x0000e576, 0x00000004 },
+    { 0x0000e577, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x0000e50f, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000069, 0x00000018 },
+    { 0x00c0e5f9, 0x000000c2 },
+    { 0x00000069, 0x00000008 },
+    { 0x0014e50e, 0x00000004 },
+    { 0x0040e50f, 0x00000004 },
+    { 0x00c0006c, 0x00000008 },
+    { 0x0000e570, 0x00000004 },
+    { 0x0000e571, 0x00000004 },
+    { 0x0000e572, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x0000e568, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00000076, 0x00000018 },
+    { 0x000b0000, 0x00000004 },
+    { 0x18c0e562, 0x00000004 },
+    { 0x00000078, 0x00000008 },
+    { 0x00c00077, 0x00000008 },
+    { 0x000700cb, 0x00000004 },
+    { 0x00000084, 0x00000038 },
+    { 0x000ca086, 0x00000030 },
+    { 0x080045bb, 0x00000004 },
+    { 0x000c2087, 0x00000030 },
+    { 0x0800e5bc, 0000000000 },
+    { 0x0000e5bb, 0x00000004 },
+    { 0x0000e5bc, 0000000000 },
+    { 0x00120000, 0x0000000c },
+    { 0x00120000, 0x00000004 },
+    { 0x001b0002, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e800, 0000000000 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e82e, 0000000000 },
+    { 0x02cca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000ce1cc, 0x00000004 },
+    { 0x050de1cd, 0x00000004 },
+    { 0x00400000, 0x00000004 },
+    { 0x00000096, 0x00000018 },
+    { 0x00c0a000, 0x00000004 },
+    { 0x00000093, 0x00000008 },
+    { 0x00000098, 0x00000020 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000009f, 0x00000038 },
+    { 0x000ca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00160000, 0x00000004 },
+    { 0x700ce000, 0x00000004 },
+    { 0x0014009b, 0x00000008 },
+    { 0x4000e000, 0000000000 },
+    { 0x02400000, 0x00000004 },
+    { 0x400ee000, 0x00000004 },
+    { 0x02400000, 0x00000004 },
+    { 0x4000e000, 0000000000 },
+    { 0x00100000, 0x0000002c },
+    { 0x00004000, 0000000000 },
+    { 0x080045c8, 0x00000004 },
+    { 0x00240005, 0x00000004 },
+    { 0x08004d0b, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0240e51b, 0x00000004 },
+    { 0x0080e50a, 0x00000005 },
+    { 0x0080e50b, 0x00000005 },
+    { 0x00220000, 0x00000004 },
+    { 0x000700cb, 0x00000004 },
+    { 0x000000b7, 0x00000038 },
+    { 0x000c2087, 0x00000030 },
+    { 0x0880e5bd, 0x00000005 },
+    { 0x000c2086, 0x00000030 },
+    { 0x0800e5bb, 0x00000005 },
+    { 0x000c2087, 0x00000030 },
+    { 0x0880e5bc, 0x00000005 },
+    { 0x000000ba, 0x00000008 },
+    { 0x0080e5bd, 0x00000005 },
+    { 0x0000e5bb, 0x00000005 },
+    { 0x0080e5bc, 0x00000005 },
+    { 0x00210000, 0x00000004 },
+    { 0x02800000, 0x00000004 },
+    { 0x00c000be, 0x00000018 },
+    { 0x4180e000, 0x00000040 },
+    { 0x000000c0, 0x00000024 },
+    { 0x01000000, 0x0000000c },
+    { 0x0100e51d, 0x0000000c },
+    { 0x000045bb, 0x00000004 },
+    { 0x000080ba, 0x00000008 },
+    { 0x03c00830, 0x00000004 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x200045e0, 0x00000004 },
+    { 0x0000e5e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000700c8, 0x00000004 },
+    { 0x0800e394, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x0000e8c4, 0x00000004 },
+    { 0x0000e8c5, 0x00000004 },
+    { 0x0000e8c6, 0x00000004 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000cc, 0x00000008 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000d3, 0x00000008 },
+    { 0x02c02000, 0x00000004 },
+    { 0x00060000, 0x00000004 },
+    { 0x000000db, 0x00000034 },
+    { 0x000000d8, 0x00000008 },
+    { 0x00008000, 0x00000004 },
+    { 0xc000e000, 0000000000 },
+    { 0x000000e1, 0x00000030 },
+    { 0x4200e000, 0000000000 },
+    { 0x000000e1, 0x00000030 },
+    { 0x4000e000, 0000000000 },
+    { 0x0025001b, 0x00000004 },
+    { 0x00230000, 0x00000004 },
+    { 0x00250005, 0x00000004 },
+    { 0x000000e6, 0x00000034 },
+    { 0000000000, 0x0000000c },
+    { 0x00244000, 0x00000004 },
+    { 0x080045c8, 0x00000004 },
+    { 0x00240005, 0x00000004 },
+    { 0x08004d0b, 0x0000000c },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x001d0018, 0x00000004 },
+    { 0x001a0001, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0x0500a04a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+static const u32 R520_cp_microcode[][2] = {
+    { 0x4200e000, 0000000000 },
+    { 0x4000e000, 0000000000 },
+    { 0x00000099, 0x00000008 },
+    { 0x0000009d, 0x00000008 },
+    { 0x4a554b4a, 0000000000 },
+    { 0x4a4a4467, 0000000000 },
+    { 0x55526f75, 0000000000 },
+    { 0x4a7e7d65, 0000000000 },
+    { 0xe0dae6f6, 0000000000 },
+    { 0x4ac54a4a, 0000000000 },
+    { 0xc8828282, 0000000000 },
+    { 0xbf4acfc1, 0000000000 },
+    { 0x87b04ad5, 0000000000 },
+    { 0xb5838383, 0000000000 },
+    { 0x4a0f85ba, 0000000000 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000d0012, 0x00000038 },
+    { 0x0000e8b4, 0x00000004 },
+    { 0x000d0014, 0x00000038 },
+    { 0x0000e8b6, 0x00000004 },
+    { 0x000d0016, 0x00000038 },
+    { 0x0000e854, 0x00000004 },
+    { 0x000d0018, 0x00000038 },
+    { 0x0000e855, 0x00000004 },
+    { 0x000d001a, 0x00000038 },
+    { 0x0000e856, 0x00000004 },
+    { 0x000d001c, 0x00000038 },
+    { 0x0000e857, 0x00000004 },
+    { 0x000d001e, 0x00000038 },
+    { 0x0000e824, 0x00000004 },
+    { 0x000d0020, 0x00000038 },
+    { 0x0000e825, 0x00000004 },
+    { 0x000d0022, 0x00000038 },
+    { 0x0000e830, 0x00000004 },
+    { 0x000d0024, 0x00000038 },
+    { 0x0000f0c0, 0x00000004 },
+    { 0x000d0026, 0x00000038 },
+    { 0x0000f0c1, 0x00000004 },
+    { 0x000d0028, 0x00000038 },
+    { 0x0000e000, 0x00000004 },
+    { 0x000d002a, 0x00000038 },
+    { 0x0000e000, 0x00000004 },
+    { 0x000d002c, 0x00000038 },
+    { 0x0000e000, 0x00000004 },
+    { 0x000d002e, 0x00000038 },
+    { 0x0000e000, 0x00000004 },
+    { 0x000d0030, 0x00000038 },
+    { 0x0000e000, 0x00000004 },
+    { 0x000d0032, 0x00000038 },
+    { 0x0000f180, 0x00000004 },
+    { 0x000d0034, 0x00000038 },
+    { 0x0000f393, 0x00000004 },
+    { 0x000d0036, 0x00000038 },
+    { 0x0000f38a, 0x00000004 },
+    { 0x000d0038, 0x00000038 },
+    { 0x0000f38e, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000043, 0x00000018 },
+    { 0x00cce800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x08004800, 0x00000004 },
+    { 0x0000003a, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x2000451d, 0x00000004 },
+    { 0x0000e580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x08004580, 0x00000004 },
+    { 0x000ce581, 0x00000004 },
+    { 0x00000047, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x00032000, 0x00000004 },
+    { 0x00022051, 0x00000028 },
+    { 0x00000051, 0x00000024 },
+    { 0x0800450f, 0x00000004 },
+    { 0x0000a04b, 0x00000008 },
+    { 0x0000e565, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000052, 0x00000008 },
+    { 0x03cca5b4, 0x00000004 },
+    { 0x05432000, 0x00000004 },
+    { 0x00022000, 0x00000004 },
+    { 0x4ccce05e, 0x00000030 },
+    { 0x08274565, 0x00000004 },
+    { 0x0000005e, 0x00000030 },
+    { 0x08004564, 0x00000004 },
+    { 0x0000e566, 0x00000004 },
+    { 0x00000055, 0x00000008 },
+    { 0x00802061, 0x00000010 },
+    { 0x00202000, 0x00000004 },
+    { 0x001b00ff, 0x00000004 },
+    { 0x01000064, 0x00000010 },
+    { 0x001f2000, 0x00000004 },
+    { 0x001c00ff, 0x00000004 },
+    { 0000000000, 0x0000000c },
+    { 0x00000072, 0x00000030 },
+    { 0x00000055, 0x00000008 },
+    { 0x0000e576, 0x00000004 },
+    { 0x0000e577, 0x00000004 },
+    { 0x0000e50e, 0x00000004 },
+    { 0x0000e50f, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00000069, 0x00000018 },
+    { 0x00c0e5f9, 0x000000c2 },
+    { 0x00000069, 0x00000008 },
+    { 0x0014e50e, 0x00000004 },
+    { 0x0040e50f, 0x00000004 },
+    { 0x00c0006c, 0x00000008 },
+    { 0x0000e570, 0x00000004 },
+    { 0x0000e571, 0x00000004 },
+    { 0x0000e572, 0x0000000c },
+    { 0x0000a000, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x0000e568, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00000076, 0x00000018 },
+    { 0x000b0000, 0x00000004 },
+    { 0x18c0e562, 0x00000004 },
+    { 0x00000078, 0x00000008 },
+    { 0x00c00077, 0x00000008 },
+    { 0x000700c7, 0x00000004 },
+    { 0x00000080, 0x00000038 },
+    { 0x0000e5bb, 0x00000004 },
+    { 0x0000e5bc, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e800, 0000000000 },
+    { 0x0000e821, 0x00000004 },
+    { 0x0000e82e, 0000000000 },
+    { 0x02cca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000ce1cc, 0x00000004 },
+    { 0x050de1cd, 0x00000004 },
+    { 0x00400000, 0x00000004 },
+    { 0x0000008f, 0x00000018 },
+    { 0x00c0a000, 0x00000004 },
+    { 0x0000008c, 0x00000008 },
+    { 0x00000091, 0x00000020 },
+    { 0x4200e000, 0000000000 },
+    { 0x00000098, 0x00000038 },
+    { 0x000ca000, 0x00000004 },
+    { 0x00140000, 0x00000004 },
+    { 0x000c2000, 0x00000004 },
+    { 0x00160000, 0x00000004 },
+    { 0x700ce000, 0x00000004 },
+    { 0x00140094, 0x00000008 },
+    { 0x4000e000, 0000000000 },
+    { 0x02400000, 0x00000004 },
+    { 0x400ee000, 0x00000004 },
+    { 0x02400000, 0x00000004 },
+    { 0x4000e000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x0240e51b, 0x00000004 },
+    { 0x0080e50a, 0x00000005 },
+    { 0x0080e50b, 0x00000005 },
+    { 0x00220000, 0x00000004 },
+    { 0x000700c7, 0x00000004 },
+    { 0x000000a4, 0x00000038 },
+    { 0x0080e5bd, 0x00000005 },
+    { 0x0000e5bb, 0x00000005 },
+    { 0x0080e5bc, 0x00000005 },
+    { 0x00210000, 0x00000004 },
+    { 0x02800000, 0x00000004 },
+    { 0x00c000ab, 0x00000018 },
+    { 0x4180e000, 0x00000040 },
+    { 0x000000ad, 0x00000024 },
+    { 0x01000000, 0x0000000c },
+    { 0x0100e51d, 0x0000000c },
+    { 0x000045bb, 0x00000004 },
+    { 0x000080a7, 0x00000008 },
+    { 0x0000f3ce, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053cf, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f3d2, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c053d3, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x0000f39d, 0x00000004 },
+    { 0x0140a000, 0x00000004 },
+    { 0x00cc2000, 0x00000004 },
+    { 0x08c0539e, 0x00000040 },
+    { 0x00008000, 0000000000 },
+    { 0x03c00830, 0x00000004 },
+    { 0x4200e000, 0000000000 },
+    { 0x0000a000, 0x00000004 },
+    { 0x200045e0, 0x00000004 },
+    { 0x0000e5e1, 0000000000 },
+    { 0x00000001, 0000000000 },
+    { 0x000700c4, 0x00000004 },
+    { 0x0800e394, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x0000e8c4, 0x00000004 },
+    { 0x0000e8c5, 0x00000004 },
+    { 0x0000e8c6, 0x00000004 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000c8, 0x00000008 },
+    { 0x0000e928, 0x00000004 },
+    { 0x0000e929, 0x00000004 },
+    { 0x0000e92a, 0x00000004 },
+    { 0x000000cf, 0x00000008 },
+    { 0xdeadbeef, 0000000000 },
+    { 0x00000116, 0000000000 },
+    { 0x000700d3, 0x00000004 },
+    { 0x080050e7, 0x00000004 },
+    { 0x000700d4, 0x00000004 },
+    { 0x0800401c, 0x00000004 },
+    { 0x0000e01d, 0000000000 },
+    { 0x02c02000, 0x00000004 },
+    { 0x00060000, 0x00000004 },
+    { 0x000000de, 0x00000034 },
+    { 0x000000db, 0x00000008 },
+    { 0x00008000, 0x00000004 },
+    { 0xc000e000, 0000000000 },
+    { 0x0000e1cc, 0x00000004 },
+    { 0x0500e1cd, 0x00000004 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000000e5, 0x00000034 },
+    { 0x000000e1, 0x00000008 },
+    { 0x0000a000, 0000000000 },
+    { 0x0019e1cc, 0x00000004 },
+    { 0x001b0001, 0x00000004 },
+    { 0x0500a000, 0x00000004 },
+    { 0x080041cd, 0x00000004 },
+    { 0x000ca000, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0x000c2000, 0x00000004 },
+    { 0x001d0018, 0x00000004 },
+    { 0x001a0001, 0x00000004 },
+    { 0x000000fb, 0x00000034 },
+    { 0x0000004a, 0x00000008 },
+    { 0x0500a04a, 0x00000008 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+    { 0000000000, 0000000000 },
+};
+
+
+#endif
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c
new file mode 100644 (file)
index 0000000..11c146b
--- /dev/null
@@ -0,0 +1,3203 @@
+/* radeon_state.c -- State support for Radeon -*- linux-c -*- */
+/*
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Kevin E. Martin <martin@valinux.com>
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "drm_sarea.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+/* ================================================================
+ * Helper functions for client state checking and fixup
+ */
+
+static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
+                                                   dev_priv,
+                                                   struct drm_file * file_priv,
+                                                   u32 *offset)
+{
+       u64 off = *offset;
+       u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1;
+       struct drm_radeon_driver_file_fields *radeon_priv;
+
+       /* Hrm ... the story of the offset ... So this function converts
+        * the various ideas of what userland clients might have for an
+        * offset in the card address space into an offset into the card
+        * address space :) So with a sane client, it should just keep
+        * the value intact and just do some boundary checking. However,
+        * not all clients are sane. Some older clients pass us 0 based
+        * offsets relative to the start of the framebuffer and some may
+        * assume the AGP aperture it appended to the framebuffer, so we
+        * try to detect those cases and fix them up.
+        *
+        * Note: It might be a good idea here to make sure the offset lands
+        * in some "allowed" area to protect things like the PCIE GART...
+        */
+
+       /* First, the best case, the offset already lands in either the
+        * framebuffer or the GART mapped space
+        */
+       if (radeon_check_offset(dev_priv, off))
+               return 0;
+
+       /* Ok, that didn't happen... now check if we have a zero based
+        * offset that fits in the framebuffer + gart space, apply the
+        * magic offset we get from SETPARAM or calculated from fb_location
+        */
+       if (off < (dev_priv->fb_size + dev_priv->gart_size)) {
+               radeon_priv = file_priv->driver_priv;
+               off += radeon_priv->radeon_fb_delta;
+       }
+
+       /* Finally, assume we aimed at a GART offset if beyond the fb */
+       if (off > fb_end)
+               off = off - fb_end - 1 + dev_priv->gart_vm_start;
+
+       /* Now recheck and fail if out of bounds */
+       if (radeon_check_offset(dev_priv, off)) {
+               DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
+               *offset = off;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
+                                                    dev_priv,
+                                                    struct drm_file *file_priv,
+                                                    int id, u32 *data)
+{
+       switch (id) {
+
+       case RADEON_EMIT_PP_MISC:
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
+                   &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) {
+                       DRM_ERROR("Invalid depth buffer offset\n");
+                       return -EINVAL;
+               }
+               break;
+
+       case RADEON_EMIT_PP_CNTL:
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
+                   &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) {
+                       DRM_ERROR("Invalid colour buffer offset\n");
+                       return -EINVAL;
+               }
+               break;
+
+       case R200_EMIT_PP_TXOFFSET_0:
+       case R200_EMIT_PP_TXOFFSET_1:
+       case R200_EMIT_PP_TXOFFSET_2:
+       case R200_EMIT_PP_TXOFFSET_3:
+       case R200_EMIT_PP_TXOFFSET_4:
+       case R200_EMIT_PP_TXOFFSET_5:
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
+                                                 &data[0])) {
+                       DRM_ERROR("Invalid R200 texture offset\n");
+                       return -EINVAL;
+               }
+               break;
+
+       case RADEON_EMIT_PP_TXFILTER_0:
+       case RADEON_EMIT_PP_TXFILTER_1:
+       case RADEON_EMIT_PP_TXFILTER_2:
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
+                   &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) {
+                       DRM_ERROR("Invalid R100 texture offset\n");
+                       return -EINVAL;
+               }
+               break;
+
+       case R200_EMIT_PP_CUBIC_OFFSETS_0:
+       case R200_EMIT_PP_CUBIC_OFFSETS_1:
+       case R200_EMIT_PP_CUBIC_OFFSETS_2:
+       case R200_EMIT_PP_CUBIC_OFFSETS_3:
+       case R200_EMIT_PP_CUBIC_OFFSETS_4:
+       case R200_EMIT_PP_CUBIC_OFFSETS_5:{
+                       int i;
+                       for (i = 0; i < 5; i++) {
+                               if (radeon_check_and_fixup_offset(dev_priv,
+                                                                 file_priv,
+                                                                 &data[i])) {
+                                       DRM_ERROR
+                                           ("Invalid R200 cubic texture offset\n");
+                                       return -EINVAL;
+                               }
+                       }
+                       break;
+               }
+
+       case RADEON_EMIT_PP_CUBIC_OFFSETS_T0:
+       case RADEON_EMIT_PP_CUBIC_OFFSETS_T1:
+       case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
+                       int i;
+                       for (i = 0; i < 5; i++) {
+                               if (radeon_check_and_fixup_offset(dev_priv,
+                                                                 file_priv,
+                                                                 &data[i])) {
+                                       DRM_ERROR
+                                           ("Invalid R100 cubic texture offset\n");
+                                       return -EINVAL;
+                               }
+                       }
+               }
+               break;
+
+       case R200_EMIT_VAP_CTL:{
+                       RING_LOCALS;
+                       BEGIN_RING(2);
+                       OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+                       ADVANCE_RING();
+               }
+               break;
+
+       case RADEON_EMIT_RB3D_COLORPITCH:
+       case RADEON_EMIT_RE_LINE_PATTERN:
+       case RADEON_EMIT_SE_LINE_WIDTH:
+       case RADEON_EMIT_PP_LUM_MATRIX:
+       case RADEON_EMIT_PP_ROT_MATRIX_0:
+       case RADEON_EMIT_RB3D_STENCILREFMASK:
+       case RADEON_EMIT_SE_VPORT_XSCALE:
+       case RADEON_EMIT_SE_CNTL:
+       case RADEON_EMIT_SE_CNTL_STATUS:
+       case RADEON_EMIT_RE_MISC:
+       case RADEON_EMIT_PP_BORDER_COLOR_0:
+       case RADEON_EMIT_PP_BORDER_COLOR_1:
+       case RADEON_EMIT_PP_BORDER_COLOR_2:
+       case RADEON_EMIT_SE_ZBIAS_FACTOR:
+       case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
+       case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
+       case R200_EMIT_PP_TXCBLEND_0:
+       case R200_EMIT_PP_TXCBLEND_1:
+       case R200_EMIT_PP_TXCBLEND_2:
+       case R200_EMIT_PP_TXCBLEND_3:
+       case R200_EMIT_PP_TXCBLEND_4:
+       case R200_EMIT_PP_TXCBLEND_5:
+       case R200_EMIT_PP_TXCBLEND_6:
+       case R200_EMIT_PP_TXCBLEND_7:
+       case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
+       case R200_EMIT_TFACTOR_0:
+       case R200_EMIT_VTX_FMT_0:
+       case R200_EMIT_MATRIX_SELECT_0:
+       case R200_EMIT_TEX_PROC_CTL_2:
+       case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
+       case R200_EMIT_PP_TXFILTER_0:
+       case R200_EMIT_PP_TXFILTER_1:
+       case R200_EMIT_PP_TXFILTER_2:
+       case R200_EMIT_PP_TXFILTER_3:
+       case R200_EMIT_PP_TXFILTER_4:
+       case R200_EMIT_PP_TXFILTER_5:
+       case R200_EMIT_VTE_CNTL:
+       case R200_EMIT_OUTPUT_VTX_COMP_SEL:
+       case R200_EMIT_PP_TAM_DEBUG3:
+       case R200_EMIT_PP_CNTL_X:
+       case R200_EMIT_RB3D_DEPTHXY_OFFSET:
+       case R200_EMIT_RE_AUX_SCISSOR_CNTL:
+       case R200_EMIT_RE_SCISSOR_TL_0:
+       case R200_EMIT_RE_SCISSOR_TL_1:
+       case R200_EMIT_RE_SCISSOR_TL_2:
+       case R200_EMIT_SE_VAP_CNTL_STATUS:
+       case R200_EMIT_SE_VTX_STATE_CNTL:
+       case R200_EMIT_RE_POINTSIZE:
+       case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0:
+       case R200_EMIT_PP_CUBIC_FACES_0:
+       case R200_EMIT_PP_CUBIC_FACES_1:
+       case R200_EMIT_PP_CUBIC_FACES_2:
+       case R200_EMIT_PP_CUBIC_FACES_3:
+       case R200_EMIT_PP_CUBIC_FACES_4:
+       case R200_EMIT_PP_CUBIC_FACES_5:
+       case RADEON_EMIT_PP_TEX_SIZE_0:
+       case RADEON_EMIT_PP_TEX_SIZE_1:
+       case RADEON_EMIT_PP_TEX_SIZE_2:
+       case R200_EMIT_RB3D_BLENDCOLOR:
+       case R200_EMIT_TCL_POINT_SPRITE_CNTL:
+       case RADEON_EMIT_PP_CUBIC_FACES_0:
+       case RADEON_EMIT_PP_CUBIC_FACES_1:
+       case RADEON_EMIT_PP_CUBIC_FACES_2:
+       case R200_EMIT_PP_TRI_PERF_CNTL:
+       case R200_EMIT_PP_AFS_0:
+       case R200_EMIT_PP_AFS_1:
+       case R200_EMIT_ATF_TFACTOR:
+       case R200_EMIT_PP_TXCTLALL_0:
+       case R200_EMIT_PP_TXCTLALL_1:
+       case R200_EMIT_PP_TXCTLALL_2:
+       case R200_EMIT_PP_TXCTLALL_3:
+       case R200_EMIT_PP_TXCTLALL_4:
+       case R200_EMIT_PP_TXCTLALL_5:
+       case R200_EMIT_VAP_PVS_CNTL:
+               /* These packets don't contain memory offsets */
+               break;
+
+       default:
+               DRM_ERROR("Unknown state packet ID %d\n", id);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
+                                                    dev_priv,
+                                                    struct drm_file *file_priv,
+                                                    drm_radeon_kcmd_buffer_t *
+                                                    cmdbuf,
+                                                    unsigned int *cmdsz)
+{
+       u32 *cmd = (u32 *) cmdbuf->buf;
+       u32 offset, narrays;
+       int count, i, k;
+
+       *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+
+       if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
+               DRM_ERROR("Not a type 3 packet\n");
+               return -EINVAL;
+       }
+
+       if (4 * *cmdsz > cmdbuf->bufsz) {
+               DRM_ERROR("Packet size larger than size of data provided\n");
+               return -EINVAL;
+       }
+
+       switch(cmd[0] & 0xff00) {
+       /* XXX Are there old drivers needing other packets? */
+
+       case RADEON_3D_DRAW_IMMD:
+       case RADEON_3D_DRAW_VBUF:
+       case RADEON_3D_DRAW_INDX:
+       case RADEON_WAIT_FOR_IDLE:
+       case RADEON_CP_NOP:
+       case RADEON_3D_CLEAR_ZMASK:
+/*     case RADEON_CP_NEXT_CHAR:
+       case RADEON_CP_PLY_NEXTSCAN:
+       case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */
+               /* these packets are safe */
+               break;
+
+       case RADEON_CP_3D_DRAW_IMMD_2:
+       case RADEON_CP_3D_DRAW_VBUF_2:
+       case RADEON_CP_3D_DRAW_INDX_2:
+       case RADEON_3D_CLEAR_HIZ:
+               /* safe but r200 only */
+               if (dev_priv->microcode_version != UCODE_R200) {
+                       DRM_ERROR("Invalid 3d packet for r100-class chip\n");
+                       return -EINVAL;
+               }
+               break;
+
+       case RADEON_3D_LOAD_VBPNTR:
+               count = (cmd[0] >> 16) & 0x3fff;
+
+               if (count > 18) { /* 12 arrays max */
+                       DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
+                                 count);
+                       return -EINVAL;
+               }
+
+               /* carefully check packet contents */
+               narrays = cmd[1] & ~0xc000;
+               k = 0;
+               i = 2;
+               while ((k < narrays) && (i < (count + 2))) {
+                       i++;            /* skip attribute field */
+                       if (radeon_check_and_fixup_offset(dev_priv, file_priv,
+                                                         &cmd[i])) {
+                               DRM_ERROR
+                                   ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
+                                    k, i);
+                               return -EINVAL;
+                       }
+                       k++;
+                       i++;
+                       if (k == narrays)
+                               break;
+                       /* have one more to process, they come in pairs */
+                       if (radeon_check_and_fixup_offset(dev_priv,
+                                                         file_priv, &cmd[i]))
+                       {
+                               DRM_ERROR
+                                   ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
+                                    k, i);
+                               return -EINVAL;
+                       }
+                       k++;
+                       i++;
+               }
+               /* do the counts match what we expect ? */
+               if ((k != narrays) || (i != (count + 2))) {
+                       DRM_ERROR
+                           ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
+                             k, i, narrays, count + 1);
+                       return -EINVAL;
+               }
+               break;
+
+       case RADEON_3D_RNDR_GEN_INDX_PRIM:
+               if (dev_priv->microcode_version != UCODE_R100) {
+                       DRM_ERROR("Invalid 3d packet for r200-class chip\n");
+                       return -EINVAL;
+               }
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) {
+                               DRM_ERROR("Invalid rndr_gen_indx offset\n");
+                               return -EINVAL;
+               }
+               break;
+
+       case RADEON_CP_INDX_BUFFER:
+               if (dev_priv->microcode_version != UCODE_R200) {
+                       DRM_ERROR("Invalid 3d packet for r100-class chip\n");
+                       return -EINVAL;
+               }
+               if ((cmd[1] & 0x8000ffff) != 0x80000810) {
+                       DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
+                       return -EINVAL;
+               }
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[2])) {
+                       DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
+                       return -EINVAL;
+               }
+               break;
+
+       case RADEON_CNTL_HOSTDATA_BLT:
+       case RADEON_CNTL_PAINT_MULTI:
+       case RADEON_CNTL_BITBLT_MULTI:
+               /* MSB of opcode: next DWORD GUI_CNTL */
+               if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+                             | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+                       offset = cmd[2] << 10;
+                       if (radeon_check_and_fixup_offset
+                           (dev_priv, file_priv, &offset)) {
+                               DRM_ERROR("Invalid first packet offset\n");
+                               return -EINVAL;
+                       }
+                       cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
+               }
+
+               if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
+                   (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
+                       offset = cmd[3] << 10;
+                       if (radeon_check_and_fixup_offset
+                           (dev_priv, file_priv, &offset)) {
+                               DRM_ERROR("Invalid second packet offset\n");
+                               return -EINVAL;
+                       }
+                       cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
+               }
+               break;
+
+       default:
+               DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* ================================================================
+ * CP hardware state programming functions
+ */
+
+static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
+                                            struct drm_clip_rect * box)
+{
+       RING_LOCALS;
+
+       DRM_DEBUG("   box:  x1=%d y1=%d  x2=%d y2=%d\n",
+                 box->x1, box->y1, box->x2, box->y2);
+
+       BEGIN_RING(4);
+       OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
+       OUT_RING((box->y1 << 16) | box->x1);
+       OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
+       OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1));
+       ADVANCE_RING();
+}
+
+/* Emit 1.1 state
+ */
+static int radeon_emit_state(drm_radeon_private_t * dev_priv,
+                            struct drm_file *file_priv,
+                            drm_radeon_context_regs_t * ctx,
+                            drm_radeon_texture_regs_t * tex,
+                            unsigned int dirty)
+{
+       RING_LOCALS;
+       DRM_DEBUG("dirty=0x%08x\n", dirty);
+
+       if (dirty & RADEON_UPLOAD_CONTEXT) {
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
+                                                 &ctx->rb3d_depthoffset)) {
+                       DRM_ERROR("Invalid depth buffer offset\n");
+                       return -EINVAL;
+               }
+
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
+                                                 &ctx->rb3d_coloroffset)) {
+                       DRM_ERROR("Invalid depth buffer offset\n");
+                       return -EINVAL;
+               }
+
+               BEGIN_RING(14);
+               OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6));
+               OUT_RING(ctx->pp_misc);
+               OUT_RING(ctx->pp_fog_color);
+               OUT_RING(ctx->re_solid_color);
+               OUT_RING(ctx->rb3d_blendcntl);
+               OUT_RING(ctx->rb3d_depthoffset);
+               OUT_RING(ctx->rb3d_depthpitch);
+               OUT_RING(ctx->rb3d_zstencilcntl);
+               OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2));
+               OUT_RING(ctx->pp_cntl);
+               OUT_RING(ctx->rb3d_cntl);
+               OUT_RING(ctx->rb3d_coloroffset);
+               OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
+               OUT_RING(ctx->rb3d_colorpitch);
+               ADVANCE_RING();
+       }
+
+       if (dirty & RADEON_UPLOAD_VERTFMT) {
+               BEGIN_RING(2);
+               OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0));
+               OUT_RING(ctx->se_coord_fmt);
+               ADVANCE_RING();
+       }
+
+       if (dirty & RADEON_UPLOAD_LINE) {
+               BEGIN_RING(5);
+               OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1));
+               OUT_RING(ctx->re_line_pattern);
+               OUT_RING(ctx->re_line_state);
+               OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0));
+               OUT_RING(ctx->se_line_width);
+               ADVANCE_RING();
+       }
+
+       if (dirty & RADEON_UPLOAD_BUMPMAP) {
+               BEGIN_RING(5);
+               OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0));
+               OUT_RING(ctx->pp_lum_matrix);
+               OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1));
+               OUT_RING(ctx->pp_rot_matrix_0);
+               OUT_RING(ctx->pp_rot_matrix_1);
+               ADVANCE_RING();
+       }
+
+       if (dirty & RADEON_UPLOAD_MASKS) {
+               BEGIN_RING(4);
+               OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2));
+               OUT_RING(ctx->rb3d_stencilrefmask);
+               OUT_RING(ctx->rb3d_ropcntl);
+               OUT_RING(ctx->rb3d_planemask);
+               ADVANCE_RING();
+       }
+
+       if (dirty & RADEON_UPLOAD_VIEWPORT) {
+               BEGIN_RING(7);
+               OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5));
+               OUT_RING(ctx->se_vport_xscale);
+               OUT_RING(ctx->se_vport_xoffset);
+               OUT_RING(ctx->se_vport_yscale);
+               OUT_RING(ctx->se_vport_yoffset);
+               OUT_RING(ctx->se_vport_zscale);
+               OUT_RING(ctx->se_vport_zoffset);
+               ADVANCE_RING();
+       }
+
+       if (dirty & RADEON_UPLOAD_SETUP) {
+               BEGIN_RING(4);
+               OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0));
+               OUT_RING(ctx->se_cntl);
+               OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0));
+               OUT_RING(ctx->se_cntl_status);
+               ADVANCE_RING();
+       }
+
+       if (dirty & RADEON_UPLOAD_MISC) {
+               BEGIN_RING(2);
+               OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0));
+               OUT_RING(ctx->re_misc);
+               ADVANCE_RING();
+       }
+
+       if (dirty & RADEON_UPLOAD_TEX0) {
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
+                                                 &tex[0].pp_txoffset)) {
+                       DRM_ERROR("Invalid texture offset for unit 0\n");
+                       return -EINVAL;
+               }
+
+               BEGIN_RING(9);
+               OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5));
+               OUT_RING(tex[0].pp_txfilter);
+               OUT_RING(tex[0].pp_txformat);
+               OUT_RING(tex[0].pp_txoffset);
+               OUT_RING(tex[0].pp_txcblend);
+               OUT_RING(tex[0].pp_txablend);
+               OUT_RING(tex[0].pp_tfactor);
+               OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0));
+               OUT_RING(tex[0].pp_border_color);
+               ADVANCE_RING();
+       }
+
+       if (dirty & RADEON_UPLOAD_TEX1) {
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
+                                                 &tex[1].pp_txoffset)) {
+                       DRM_ERROR("Invalid texture offset for unit 1\n");
+                       return -EINVAL;
+               }
+
+               BEGIN_RING(9);
+               OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5));
+               OUT_RING(tex[1].pp_txfilter);
+               OUT_RING(tex[1].pp_txformat);
+               OUT_RING(tex[1].pp_txoffset);
+               OUT_RING(tex[1].pp_txcblend);
+               OUT_RING(tex[1].pp_txablend);
+               OUT_RING(tex[1].pp_tfactor);
+               OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0));
+               OUT_RING(tex[1].pp_border_color);
+               ADVANCE_RING();
+       }
+
+       if (dirty & RADEON_UPLOAD_TEX2) {
+               if (radeon_check_and_fixup_offset(dev_priv, file_priv,
+                                                 &tex[2].pp_txoffset)) {
+                       DRM_ERROR("Invalid texture offset for unit 2\n");
+                       return -EINVAL;
+               }
+
+               BEGIN_RING(9);
+               OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5));
+               OUT_RING(tex[2].pp_txfilter);
+               OUT_RING(tex[2].pp_txformat);
+               OUT_RING(tex[2].pp_txoffset);
+               OUT_RING(tex[2].pp_txcblend);
+               OUT_RING(tex[2].pp_txablend);
+               OUT_RING(tex[2].pp_tfactor);
+               OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0));
+               OUT_RING(tex[2].pp_border_color);
+               ADVANCE_RING();
+       }
+
+       return 0;
+}
+
+/* Emit 1.2 state
+ */
+static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
+                             struct drm_file *file_priv,
+                             drm_radeon_state_t * state)
+{
+       RING_LOCALS;
+
+       if (state->dirty & RADEON_UPLOAD_ZBIAS) {
+               BEGIN_RING(3);
+               OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1));
+               OUT_RING(state->context2.se_zbias_factor);
+               OUT_RING(state->context2.se_zbias_constant);
+               ADVANCE_RING();
+       }
+
+       return radeon_emit_state(dev_priv, file_priv, &state->context,
+                                state->tex, state->dirty);
+}
+
+/* New (1.3) state mechanism.  3 commands (packet, scalar, vector) in
+ * 1.3 cmdbuffers allow all previous state to be updated as well as
+ * the tcl scalar and vector areas.
+ */
+static struct {
+       int start;
+       int len;
+       const char *name;
+} packet[RADEON_MAX_STATE_PACKETS] = {
+       {RADEON_PP_MISC, 7, "RADEON_PP_MISC"},
+       {RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"},
+       {RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"},
+       {RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"},
+       {RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"},
+       {RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"},
+       {RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"},
+       {RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"},
+       {RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"},
+       {RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"},
+       {RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"},
+       {RADEON_RE_MISC, 1, "RADEON_RE_MISC"},
+       {RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"},
+       {RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"},
+       {RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"},
+       {RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"},
+       {RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"},
+       {RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"},
+       {RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"},
+       {RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"},
+       {RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17,
+                   "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"},
+       {R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"},
+       {R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"},
+       {R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"},
+       {R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"},
+       {R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"},
+       {R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"},
+       {R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"},
+       {R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"},
+       {R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"},
+       {R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"},
+       {R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"},
+       {R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"},
+       {R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"},
+       {R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"},
+       {R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"},
+       {R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"},
+       {R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"},
+       {R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"},
+       {R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"},
+       {R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"},
+       {R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"},
+       {R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"},
+       {R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"},
+       {R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"},
+       {R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"},
+       {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
+       {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
+       {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
+       {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1,
+        "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
+       {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
+       {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
+       {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
+       {R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"},
+       {R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"},
+       {R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"},
+       {R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"},
+       {R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"},
+       {R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"},
+       {R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"},
+       {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
+                   "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
+       {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"},    /* 61 */
+       {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
+       {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
+       {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
+       {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
+       {R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"},
+       {R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"},
+       {R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"},
+       {R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"},
+       {R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"},
+       {R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"},
+       {R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"},
+       {RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"},
+       {RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"},
+       {RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"},
+       {R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"},
+       {R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"},
+       {RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
+       {RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
+       {RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
+       {RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
+       {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
+       {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
+       {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
+       {R200_PP_AFS_0, 32, "R200_PP_AFS_0"},     /* 85 */
+       {R200_PP_AFS_1, 32, "R200_PP_AFS_1"},
+       {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
+       {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
+       {R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"},
+       {R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"},
+       {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
+       {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
+       {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
+       {R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"},
+};
+
+/* ================================================================
+ * Performance monitoring functions
+ */
+
+static void radeon_clear_box(drm_radeon_private_t * dev_priv,
+                            int x, int y, int w, int h, int r, int g, int b)
+{
+       u32 color;
+       RING_LOCALS;
+
+       x += dev_priv->sarea_priv->boxes[0].x1;
+       y += dev_priv->sarea_priv->boxes[0].y1;
+
+       switch (dev_priv->color_fmt) {
+       case RADEON_COLOR_FORMAT_RGB565:
+               color = (((r & 0xf8) << 8) |
+                        ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
+               break;
+       case RADEON_COLOR_FORMAT_ARGB8888:
+       default:
+               color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
+               break;
+       }
+
+       BEGIN_RING(4);
+       RADEON_WAIT_UNTIL_3D_IDLE();
+       OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
+       OUT_RING(0xffffffff);
+       ADVANCE_RING();
+
+       BEGIN_RING(6);
+
+       OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4));
+       OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+                RADEON_GMC_BRUSH_SOLID_COLOR |
+                (dev_priv->color_fmt << 8) |
+                RADEON_GMC_SRC_DATATYPE_COLOR |
+                RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
+
+       if (dev_priv->sarea_priv->pfCurrentPage == 1) {
+               OUT_RING(dev_priv->front_pitch_offset);
+       } else {
+               OUT_RING(dev_priv->back_pitch_offset);
+       }
+
+       OUT_RING(color);
+
+       OUT_RING((x << 16) | y);
+       OUT_RING((w << 16) | h);
+
+       ADVANCE_RING();
+}
+
+static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
+{
+       /* Collapse various things into a wait flag -- trying to
+        * guess if userspase slept -- better just to have them tell us.
+        */
+       if (dev_priv->stats.last_frame_reads > 1 ||
+           dev_priv->stats.last_clear_reads > dev_priv->stats.clears) {
+               dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+       }
+
+       if (dev_priv->stats.freelist_loops) {
+               dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+       }
+
+       /* Purple box for page flipping
+        */
+       if (dev_priv->stats.boxes & RADEON_BOX_FLIP)
+               radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255);
+
+       /* Red box if we have to wait for idle at any point
+        */
+       if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE)
+               radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0);
+
+       /* Blue box: lost context?
+        */
+
+       /* Yellow box for texture swaps
+        */
+       if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD)
+               radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0);
+
+       /* Green box if hardware never idles (as far as we can tell)
+        */
+       if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE))
+               radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
+
+       /* Draw bars indicating number of buffers allocated
+        * (not a great measure, easily confused)
+        */
+       if (dev_priv->stats.requested_bufs) {
+               if (dev_priv->stats.requested_bufs > 100)
+                       dev_priv->stats.requested_bufs = 100;
+
+               radeon_clear_box(dev_priv, 4, 16,
+                                dev_priv->stats.requested_bufs, 4,
+                                196, 128, 128);
+       }
+
+       memset(&dev_priv->stats, 0, sizeof(dev_priv->stats));
+
+}
+
+/* ================================================================
+ * CP command dispatch functions
+ */
+
+static void radeon_cp_dispatch_clear(struct drm_device * dev,
+                                    drm_radeon_clear_t * clear,
+                                    drm_radeon_clear_rect_t * depth_boxes)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
+       int nbox = sarea_priv->nbox;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
+       unsigned int flags = clear->flags;
+       u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0;
+       int i;
+       RING_LOCALS;
+       DRM_DEBUG("flags = 0x%x\n", flags);
+
+       dev_priv->stats.clears++;
+
+       if (dev_priv->sarea_priv->pfCurrentPage == 1) {
+               unsigned int tmp = flags;
+
+               flags &= ~(RADEON_FRONT | RADEON_BACK);
+               if (tmp & RADEON_FRONT)
+                       flags |= RADEON_BACK;
+               if (tmp & RADEON_BACK)
+                       flags |= RADEON_FRONT;
+       }
+
+       if (flags & (RADEON_FRONT | RADEON_BACK)) {
+
+               BEGIN_RING(4);
+
+               /* Ensure the 3D stream is idle before doing a
+                * 2D fill to clear the front or back buffer.
+                */
+               RADEON_WAIT_UNTIL_3D_IDLE();
+
+               OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0));
+               OUT_RING(clear->color_mask);
+
+               ADVANCE_RING();
+
+               /* Make sure we restore the 3D state next time.
+                */
+               dev_priv->sarea_priv->ctx_owner = 0;
+
+               for (i = 0; i < nbox; i++) {
+                       int x = pbox[i].x1;
+                       int y = pbox[i].y1;
+                       int w = pbox[i].x2 - x;
+                       int h = pbox[i].y2 - y;
+
+                       DRM_DEBUG("%d,%d-%d,%d flags 0x%x\n",
+                                 x, y, w, h, flags);
+
+                       if (flags & RADEON_FRONT) {
+                               BEGIN_RING(6);
+
+                               OUT_RING(CP_PACKET3
+                                        (RADEON_CNTL_PAINT_MULTI, 4));
+                               OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+                                        RADEON_GMC_BRUSH_SOLID_COLOR |
+                                        (dev_priv->
+                                         color_fmt << 8) |
+                                        RADEON_GMC_SRC_DATATYPE_COLOR |
+                                        RADEON_ROP3_P |
+                                        RADEON_GMC_CLR_CMP_CNTL_DIS);
+
+                               OUT_RING(dev_priv->front_pitch_offset);
+                               OUT_RING(clear->clear_color);
+
+                               OUT_RING((x << 16) | y);
+                               OUT_RING((w << 16) | h);
+
+                               ADVANCE_RING();
+                       }
+
+                       if (flags & RADEON_BACK) {
+                               BEGIN_RING(6);
+
+                               OUT_RING(CP_PACKET3
+                                        (RADEON_CNTL_PAINT_MULTI, 4));
+                               OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+                                        RADEON_GMC_BRUSH_SOLID_COLOR |
+                                        (dev_priv->
+                                         color_fmt << 8) |
+                                        RADEON_GMC_SRC_DATATYPE_COLOR |
+                                        RADEON_ROP3_P |
+                                        RADEON_GMC_CLR_CMP_CNTL_DIS);
+
+                               OUT_RING(dev_priv->back_pitch_offset);
+                               OUT_RING(clear->clear_color);
+
+                               OUT_RING((x << 16) | y);
+                               OUT_RING((w << 16) | h);
+
+                               ADVANCE_RING();
+                       }
+               }
+       }
+
+       /* hyper z clear */
+       /* no docs available, based on reverse engeneering by Stephane Marchesin */
+       if ((flags & (RADEON_DEPTH | RADEON_STENCIL))
+           && (flags & RADEON_CLEAR_FASTZ)) {
+
+               int i;
+               int depthpixperline =
+                   dev_priv->depth_fmt ==
+                   RADEON_DEPTH_FORMAT_16BIT_INT_Z ? (dev_priv->depth_pitch /
+                                                      2) : (dev_priv->
+                                                            depth_pitch / 4);
+
+               u32 clearmask;
+
+               u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth |
+                   ((clear->depth_mask & 0xff) << 24);
+
+               /* Make sure we restore the 3D state next time.
+                * we haven't touched any "normal" state - still need this?
+                */
+               dev_priv->sarea_priv->ctx_owner = 0;
+
+               if ((dev_priv->flags & RADEON_HAS_HIERZ)
+                   && (flags & RADEON_USE_HIERZ)) {
+                       /* FIXME : reverse engineer that for Rx00 cards */
+                       /* FIXME : the mask supposedly contains low-res z values. So can't set
+                          just to the max (0xff? or actually 0x3fff?), need to take z clear
+                          value into account? */
+                       /* pattern seems to work for r100, though get slight
+                          rendering errors with glxgears. If hierz is not enabled for r100,
+                          only 4 bits which indicate clear (15,16,31,32, all zero) matter, the
+                          other ones are ignored, and the same clear mask can be used. That's
+                          very different behaviour than R200 which needs different clear mask
+                          and different number of tiles to clear if hierz is enabled or not !?!
+                        */
+                       clearmask = (0xff << 22) | (0xff << 6) | 0x003f003f;
+               } else {
+                       /* clear mask : chooses the clearing pattern.
+                          rv250: could be used to clear only parts of macrotiles
+                          (but that would get really complicated...)?
+                          bit 0 and 1 (either or both of them ?!?!) are used to
+                          not clear tile (or maybe one of the bits indicates if the tile is
+                          compressed or not), bit 2 and 3 to not clear tile 1,...,.
+                          Pattern is as follows:
+                          | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29|
+                          bits -------------------------------------------------
+                          | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31|
+                          rv100: clearmask covers 2x8 4x1 tiles, but one clear still
+                          covers 256 pixels ?!?
+                        */
+                       clearmask = 0x0;
+               }
+
+               BEGIN_RING(8);
+               RADEON_WAIT_UNTIL_2D_IDLE();
+               OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE,
+                            tempRB3D_DEPTHCLEARVALUE);
+               /* what offset is this exactly ? */
+               OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0);
+               /* need ctlstat, otherwise get some strange black flickering */
+               OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT,
+                            RADEON_RB3D_ZC_FLUSH_ALL);
+               ADVANCE_RING();
+
+               for (i = 0; i < nbox; i++) {
+                       int tileoffset, nrtilesx, nrtilesy, j;
+                       /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
+                       if ((dev_priv->flags & RADEON_HAS_HIERZ)
+                           && !(dev_priv->microcode_version == UCODE_R200)) {
+                               /* FIXME : figure this out for r200 (when hierz is enabled). Or
+                                  maybe r200 actually doesn't need to put the low-res z value into
+                                  the tile cache like r100, but just needs to clear the hi-level z-buffer?
+                                  Works for R100, both with hierz and without.
+                                  R100 seems to operate on 2x1 8x8 tiles, but...
+                                  odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially
+                                  problematic with resolutions which are not 64 pix aligned? */
+                               tileoffset =
+                                   ((pbox[i].y1 >> 3) * depthpixperline +
+                                    pbox[i].x1) >> 6;
+                               nrtilesx =
+                                   ((pbox[i].x2 & ~63) -
+                                    (pbox[i].x1 & ~63)) >> 4;
+                               nrtilesy =
+                                   (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
+                               for (j = 0; j <= nrtilesy; j++) {
+                                       BEGIN_RING(4);
+                                       OUT_RING(CP_PACKET3
+                                                (RADEON_3D_CLEAR_ZMASK, 2));
+                                       /* first tile */
+                                       OUT_RING(tileoffset * 8);
+                                       /* the number of tiles to clear */
+                                       OUT_RING(nrtilesx + 4);
+                                       /* clear mask : chooses the clearing pattern. */
+                                       OUT_RING(clearmask);
+                                       ADVANCE_RING();
+                                       tileoffset += depthpixperline >> 6;
+                               }
+                       } else if (dev_priv->microcode_version == UCODE_R200) {
+                               /* works for rv250. */
+                               /* find first macro tile (8x2 4x4 z-pixels on rv250) */
+                               tileoffset =
+                                   ((pbox[i].y1 >> 3) * depthpixperline +
+                                    pbox[i].x1) >> 5;
+                               nrtilesx =
+                                   (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);
+                               nrtilesy =
+                                   (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);
+                               for (j = 0; j <= nrtilesy; j++) {
+                                       BEGIN_RING(4);
+                                       OUT_RING(CP_PACKET3
+                                                (RADEON_3D_CLEAR_ZMASK, 2));
+                                       /* first tile */
+                                       /* judging by the first tile offset needed, could possibly
+                                          directly address/clear 4x4 tiles instead of 8x2 * 4x4
+                                          macro tiles, though would still need clear mask for
+                                          right/bottom if truely 4x4 granularity is desired ? */
+                                       OUT_RING(tileoffset * 16);
+                                       /* the number of tiles to clear */
+                                       OUT_RING(nrtilesx + 1);
+                                       /* clear mask : chooses the clearing pattern. */
+                                       OUT_RING(clearmask);
+                                       ADVANCE_RING();
+                                       tileoffset += depthpixperline >> 5;
+                               }
+                       } else {        /* rv 100 */
+                               /* rv100 might not need 64 pix alignment, who knows */
+                               /* offsets are, hmm, weird */
+                               tileoffset =
+                                   ((pbox[i].y1 >> 4) * depthpixperline +
+                                    pbox[i].x1) >> 6;
+                               nrtilesx =
+                                   ((pbox[i].x2 & ~63) -
+                                    (pbox[i].x1 & ~63)) >> 4;
+                               nrtilesy =
+                                   (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);
+                               for (j = 0; j <= nrtilesy; j++) {
+                                       BEGIN_RING(4);
+                                       OUT_RING(CP_PACKET3
+                                                (RADEON_3D_CLEAR_ZMASK, 2));
+                                       OUT_RING(tileoffset * 128);
+                                       /* the number of tiles to clear */
+                                       OUT_RING(nrtilesx + 4);
+                                       /* clear mask : chooses the clearing pattern. */
+                                       OUT_RING(clearmask);
+                                       ADVANCE_RING();
+                                       tileoffset += depthpixperline >> 6;
+                               }
+                       }
+               }
+
+               /* TODO don't always clear all hi-level z tiles */
+               if ((dev_priv->flags & RADEON_HAS_HIERZ)
+                   && (dev_priv->microcode_version == UCODE_R200)
+                   && (flags & RADEON_USE_HIERZ))
+                       /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
+                       /* FIXME : the mask supposedly contains low-res z values. So can't set
+                          just to the max (0xff? or actually 0x3fff?), need to take z clear
+                          value into account? */
+               {
+                       BEGIN_RING(4);
+                       OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2));
+                       OUT_RING(0x0);  /* First tile */
+                       OUT_RING(0x3cc0);
+                       OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f);
+                       ADVANCE_RING();
+               }
+       }
+
+       /* We have to clear the depth and/or stencil buffers by
+        * rendering a quad into just those buffers.  Thus, we have to
+        * make sure the 3D engine is configured correctly.
+        */
+       else if ((dev_priv->microcode_version == UCODE_R200) &&
+               (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
+
+               int tempPP_CNTL;
+               int tempRE_CNTL;
+               int tempRB3D_CNTL;
+               int tempRB3D_ZSTENCILCNTL;
+               int tempRB3D_STENCILREFMASK;
+               int tempRB3D_PLANEMASK;
+               int tempSE_CNTL;
+               int tempSE_VTE_CNTL;
+               int tempSE_VTX_FMT_0;
+               int tempSE_VTX_FMT_1;
+               int tempSE_VAP_CNTL;
+               int tempRE_AUX_SCISSOR_CNTL;
+
+               tempPP_CNTL = 0;
+               tempRE_CNTL = 0;
+
+               tempRB3D_CNTL = depth_clear->rb3d_cntl;
+
+               tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
+               tempRB3D_STENCILREFMASK = 0x0;
+
+               tempSE_CNTL = depth_clear->se_cntl;
+
+               /* Disable TCL */
+
+               tempSE_VAP_CNTL = (     /* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK |  */
+                                         (0x9 <<
+                                          SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));
+
+               tempRB3D_PLANEMASK = 0x0;
+
+               tempRE_AUX_SCISSOR_CNTL = 0x0;
+
+               tempSE_VTE_CNTL =
+                   SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK;
+
+               /* Vertex format (X, Y, Z, W) */
+               tempSE_VTX_FMT_0 =
+                   SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |
+                   SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;
+               tempSE_VTX_FMT_1 = 0x0;
+
+               /*
+                * Depth buffer specific enables
+                */
+               if (flags & RADEON_DEPTH) {
+                       /* Enable depth buffer */
+                       tempRB3D_CNTL |= RADEON_Z_ENABLE;
+               } else {
+                       /* Disable depth buffer */
+                       tempRB3D_CNTL &= ~RADEON_Z_ENABLE;
+               }
+
+               /*
+                * Stencil buffer specific enables
+                */
+               if (flags & RADEON_STENCIL) {
+                       tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;
+                       tempRB3D_STENCILREFMASK = clear->depth_mask;
+               } else {
+                       tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;
+                       tempRB3D_STENCILREFMASK = 0x00000000;
+               }
+
+               if (flags & RADEON_USE_COMP_ZBUF) {
+                       tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
+                           RADEON_Z_DECOMPRESSION_ENABLE;
+               }
+               if (flags & RADEON_USE_HIERZ) {
+                       tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
+               }
+
+               BEGIN_RING(26);
+               RADEON_WAIT_UNTIL_2D_IDLE();
+
+               OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL);
+               OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL);
+               OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL);
+               OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
+               OUT_RING_REG(RADEON_RB3D_STENCILREFMASK,
+                            tempRB3D_STENCILREFMASK);
+               OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK);
+               OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL);
+               OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL);
+               OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0);
+               OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1);
+               OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL);
+               OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL);
+               ADVANCE_RING();
+
+               /* Make sure we restore the 3D state next time.
+                */
+               dev_priv->sarea_priv->ctx_owner = 0;
+
+               for (i = 0; i < nbox; i++) {
+
+                       /* Funny that this should be required --
+                        *  sets top-left?
+                        */
+                       radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+
+                       BEGIN_RING(14);
+                       OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12));
+                       OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
+                                 RADEON_PRIM_WALK_RING |
+                                 (3 << RADEON_NUM_VERTICES_SHIFT)));
+                       OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+                       OUT_RING(0x3f800000);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+                       OUT_RING(0x3f800000);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+                       OUT_RING(0x3f800000);
+                       ADVANCE_RING();
+               }
+       } else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) {
+
+               int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;
+
+               rb3d_cntl = depth_clear->rb3d_cntl;
+
+               if (flags & RADEON_DEPTH) {
+                       rb3d_cntl |= RADEON_Z_ENABLE;
+               } else {
+                       rb3d_cntl &= ~RADEON_Z_ENABLE;
+               }
+
+               if (flags & RADEON_STENCIL) {
+                       rb3d_cntl |= RADEON_STENCIL_ENABLE;
+                       rb3d_stencilrefmask = clear->depth_mask;        /* misnamed field */
+               } else {
+                       rb3d_cntl &= ~RADEON_STENCIL_ENABLE;
+                       rb3d_stencilrefmask = 0x00000000;
+               }
+
+               if (flags & RADEON_USE_COMP_ZBUF) {
+                       tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |
+                           RADEON_Z_DECOMPRESSION_ENABLE;
+               }
+               if (flags & RADEON_USE_HIERZ) {
+                       tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;
+               }
+
+               BEGIN_RING(13);
+               RADEON_WAIT_UNTIL_2D_IDLE();
+
+               OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1));
+               OUT_RING(0x00000000);
+               OUT_RING(rb3d_cntl);
+
+               OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);
+               OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask);
+               OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000);
+               OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl);
+               ADVANCE_RING();
+
+               /* Make sure we restore the 3D state next time.
+                */
+               dev_priv->sarea_priv->ctx_owner = 0;
+
+               for (i = 0; i < nbox; i++) {
+
+                       /* Funny that this should be required --
+                        *  sets top-left?
+                        */
+                       radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+
+                       BEGIN_RING(15);
+
+                       OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13));
+                       OUT_RING(RADEON_VTX_Z_PRESENT |
+                                RADEON_VTX_PKCOLOR_PRESENT);
+                       OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |
+                                 RADEON_PRIM_WALK_RING |
+                                 RADEON_MAOS_ENABLE |
+                                 RADEON_VTX_FMT_RADEON_MODE |
+                                 (3 << RADEON_NUM_VERTICES_SHIFT)));
+
+                       OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+                       OUT_RING(0x0);
+
+                       OUT_RING(depth_boxes[i].ui[CLEAR_X1]);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+                       OUT_RING(0x0);
+
+                       OUT_RING(depth_boxes[i].ui[CLEAR_X2]);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);
+                       OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);
+                       OUT_RING(0x0);
+
+                       ADVANCE_RING();
+               }
+       }
+
+       /* Increment the clear counter.  The client-side 3D driver must
+        * wait on this value before performing the clear ioctl.  We
+        * need this because the card's so damned fast...
+        */
+       dev_priv->sarea_priv->last_clear++;
+
+       BEGIN_RING(4);
+
+       RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear);
+       RADEON_WAIT_UNTIL_IDLE();
+
+       ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_swap(struct drm_device * dev)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int nbox = sarea_priv->nbox;
+       struct drm_clip_rect *pbox = sarea_priv->boxes;
+       int i;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       /* Do some trivial performance monitoring...
+        */
+       if (dev_priv->do_boxes)
+               radeon_cp_performance_boxes(dev_priv);
+
+       /* Wait for the 3D stream to idle before dispatching the bitblt.
+        * This will prevent data corruption between the two streams.
+        */
+       BEGIN_RING(2);
+
+       RADEON_WAIT_UNTIL_3D_IDLE();
+
+       ADVANCE_RING();
+
+       for (i = 0; i < nbox; i++) {
+               int x = pbox[i].x1;
+               int y = pbox[i].y1;
+               int w = pbox[i].x2 - x;
+               int h = pbox[i].y2 - y;
+
+               DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h);
+
+               BEGIN_RING(9);
+
+               OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0));
+               OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+                        RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+                        RADEON_GMC_BRUSH_NONE |
+                        (dev_priv->color_fmt << 8) |
+                        RADEON_GMC_SRC_DATATYPE_COLOR |
+                        RADEON_ROP3_S |
+                        RADEON_DP_SRC_SOURCE_MEMORY |
+                        RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
+
+               /* Make this work even if front & back are flipped:
+                */
+               OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
+               if (dev_priv->sarea_priv->pfCurrentPage == 0) {
+                       OUT_RING(dev_priv->back_pitch_offset);
+                       OUT_RING(dev_priv->front_pitch_offset);
+               } else {
+                       OUT_RING(dev_priv->front_pitch_offset);
+                       OUT_RING(dev_priv->back_pitch_offset);
+               }
+
+               OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2));
+               OUT_RING((x << 16) | y);
+               OUT_RING((x << 16) | y);
+               OUT_RING((w << 16) | h);
+
+               ADVANCE_RING();
+       }
+
+       /* Increment the frame counter.  The client-side 3D driver must
+        * throttle the framerate by waiting for this value before
+        * performing the swapbuffer ioctl.
+        */
+       dev_priv->sarea_priv->last_frame++;
+
+       BEGIN_RING(4);
+
+       RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
+       RADEON_WAIT_UNTIL_2D_IDLE();
+
+       ADVANCE_RING();
+}
+
+static void radeon_cp_dispatch_flip(struct drm_device * dev)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle;
+       int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
+           ? dev_priv->front_offset : dev_priv->back_offset;
+       RING_LOCALS;
+       DRM_DEBUG("pfCurrentPage=%d\n",
+                 dev_priv->sarea_priv->pfCurrentPage);
+
+       /* Do some trivial performance monitoring...
+        */
+       if (dev_priv->do_boxes) {
+               dev_priv->stats.boxes |= RADEON_BOX_FLIP;
+               radeon_cp_performance_boxes(dev_priv);
+       }
+
+       /* Update the frame offsets for both CRTCs
+        */
+       BEGIN_RING(6);
+
+       RADEON_WAIT_UNTIL_3D_IDLE();
+       OUT_RING_REG(RADEON_CRTC_OFFSET,
+                    ((sarea->frame.y * dev_priv->front_pitch +
+                      sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7)
+                    + offset);
+       OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
+                    + offset);
+
+       ADVANCE_RING();
+
+       /* Increment the frame counter.  The client-side 3D driver must
+        * throttle the framerate by waiting for this value before
+        * performing the swapbuffer ioctl.
+        */
+       dev_priv->sarea_priv->last_frame++;
+       dev_priv->sarea_priv->pfCurrentPage =
+               1 - dev_priv->sarea_priv->pfCurrentPage;
+
+       BEGIN_RING(2);
+
+       RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
+
+       ADVANCE_RING();
+}
+
+static int bad_prim_vertex_nr(int primitive, int nr)
+{
+       switch (primitive & RADEON_PRIM_TYPE_MASK) {
+       case RADEON_PRIM_TYPE_NONE:
+       case RADEON_PRIM_TYPE_POINT:
+               return nr < 1;
+       case RADEON_PRIM_TYPE_LINE:
+               return (nr & 1) || nr == 0;
+       case RADEON_PRIM_TYPE_LINE_STRIP:
+               return nr < 2;
+       case RADEON_PRIM_TYPE_TRI_LIST:
+       case RADEON_PRIM_TYPE_3VRT_POINT_LIST:
+       case RADEON_PRIM_TYPE_3VRT_LINE_LIST:
+       case RADEON_PRIM_TYPE_RECT_LIST:
+               return nr % 3 || nr == 0;
+       case RADEON_PRIM_TYPE_TRI_FAN:
+       case RADEON_PRIM_TYPE_TRI_STRIP:
+               return nr < 3;
+       default:
+               return 1;
+       }
+}
+
+typedef struct {
+       unsigned int start;
+       unsigned int finish;
+       unsigned int prim;
+       unsigned int numverts;
+       unsigned int offset;
+       unsigned int vc_format;
+} drm_radeon_tcl_prim_t;
+
+static void radeon_cp_dispatch_vertex(struct drm_device * dev,
+                                     struct drm_buf * buf,
+                                     drm_radeon_tcl_prim_t * prim)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
+       int numverts = (int)prim->numverts;
+       int nbox = sarea_priv->nbox;
+       int i = 0;
+       RING_LOCALS;
+
+       DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",
+                 prim->prim,
+                 prim->vc_format, prim->start, prim->finish, prim->numverts);
+
+       if (bad_prim_vertex_nr(prim->prim, prim->numverts)) {
+               DRM_ERROR("bad prim %x numverts %d\n",
+                         prim->prim, prim->numverts);
+               return;
+       }
+
+       do {
+               /* Emit the next cliprect */
+               if (i < nbox) {
+                       radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+               }
+
+               /* Emit the vertex buffer rendering commands */
+               BEGIN_RING(5);
+
+               OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3));
+               OUT_RING(offset);
+               OUT_RING(numverts);
+               OUT_RING(prim->vc_format);
+               OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST |
+                        RADEON_COLOR_ORDER_RGBA |
+                        RADEON_VTX_FMT_RADEON_MODE |
+                        (numverts << RADEON_NUM_VERTICES_SHIFT));
+
+               ADVANCE_RING();
+
+               i++;
+       } while (i < nbox);
+}
+
+static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
+       RING_LOCALS;
+
+       buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
+
+       /* Emit the vertex buffer age */
+       BEGIN_RING(2);
+       RADEON_DISPATCH_AGE(buf_priv->age);
+       ADVANCE_RING();
+
+       buf->pending = 1;
+       buf->used = 0;
+}
+
+static void radeon_cp_dispatch_indirect(struct drm_device * dev,
+                                       struct drm_buf * buf, int start, int end)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+       DRM_DEBUG("buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
+
+       if (start != end) {
+               int offset = (dev_priv->gart_buffers_offset
+                             + buf->offset + start);
+               int dwords = (end - start + 3) / sizeof(u32);
+
+               /* Indirect buffer data must be an even number of
+                * dwords, so if we've been given an odd number we must
+                * pad the data with a Type-2 CP packet.
+                */
+               if (dwords & 1) {
+                       u32 *data = (u32 *)
+                           ((char *)dev->agp_buffer_map->handle
+                            + buf->offset + start);
+                       data[dwords++] = RADEON_CP_PACKET2;
+               }
+
+               /* Fire off the indirect buffer */
+               BEGIN_RING(3);
+
+               OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
+               OUT_RING(offset);
+               OUT_RING(dwords);
+
+               ADVANCE_RING();
+       }
+}
+
+static void radeon_cp_dispatch_indices(struct drm_device * dev,
+                                      struct drm_buf * elt_buf,
+                                      drm_radeon_tcl_prim_t * prim)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       int offset = dev_priv->gart_buffers_offset + prim->offset;
+       u32 *data;
+       int dwords;
+       int i = 0;
+       int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
+       int count = (prim->finish - start) / sizeof(u16);
+       int nbox = sarea_priv->nbox;
+
+       DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
+                 prim->prim,
+                 prim->vc_format,
+                 prim->start, prim->finish, prim->offset, prim->numverts);
+
+       if (bad_prim_vertex_nr(prim->prim, count)) {
+               DRM_ERROR("bad prim %x count %d\n", prim->prim, count);
+               return;
+       }
+
+       if (start >= prim->finish || (prim->start & 0x7)) {
+               DRM_ERROR("buffer prim %d\n", prim->prim);
+               return;
+       }
+
+       dwords = (prim->finish - prim->start + 3) / sizeof(u32);
+
+       data = (u32 *) ((char *)dev->agp_buffer_map->handle +
+                       elt_buf->offset + prim->start);
+
+       data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2);
+       data[1] = offset;
+       data[2] = prim->numverts;
+       data[3] = prim->vc_format;
+       data[4] = (prim->prim |
+                  RADEON_PRIM_WALK_IND |
+                  RADEON_COLOR_ORDER_RGBA |
+                  RADEON_VTX_FMT_RADEON_MODE |
+                  (count << RADEON_NUM_VERTICES_SHIFT));
+
+       do {
+               if (i < nbox)
+                       radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);
+
+               radeon_cp_dispatch_indirect(dev, elt_buf,
+                                           prim->start, prim->finish);
+
+               i++;
+       } while (i < nbox);
+
+}
+
+#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE
+
+static int radeon_cp_dispatch_texture(struct drm_device * dev,
+                                     struct drm_file *file_priv,
+                                     drm_radeon_texture_t * tex,
+                                     drm_radeon_tex_image_t * image)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       struct drm_buf *buf;
+       u32 format;
+       u32 *buffer;
+       const u8 __user *data;
+       int size, dwords, tex_width, blit_width, spitch;
+       u32 height;
+       int i;
+       u32 texpitch, microtile;
+       u32 offset, byte_offset;
+       RING_LOCALS;
+
+       if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) {
+               DRM_ERROR("Invalid destination offset\n");
+               return -EINVAL;
+       }
+
+       dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;
+
+       /* Flush the pixel cache.  This ensures no pixel data gets mixed
+        * up with the texture data from the host data blit, otherwise
+        * part of the texture image may be corrupted.
+        */
+       BEGIN_RING(4);
+       RADEON_FLUSH_CACHE();
+       RADEON_WAIT_UNTIL_IDLE();
+       ADVANCE_RING();
+
+       /* The compiler won't optimize away a division by a variable,
+        * even if the only legal values are powers of two.  Thus, we'll
+        * use a shift instead.
+        */
+       switch (tex->format) {
+       case RADEON_TXFORMAT_ARGB8888:
+       case RADEON_TXFORMAT_RGBA8888:
+               format = RADEON_COLOR_FORMAT_ARGB8888;
+               tex_width = tex->width * 4;
+               blit_width = image->width * 4;
+               break;
+       case RADEON_TXFORMAT_AI88:
+       case RADEON_TXFORMAT_ARGB1555:
+       case RADEON_TXFORMAT_RGB565:
+       case RADEON_TXFORMAT_ARGB4444:
+       case RADEON_TXFORMAT_VYUY422:
+       case RADEON_TXFORMAT_YVYU422:
+               format = RADEON_COLOR_FORMAT_RGB565;
+               tex_width = tex->width * 2;
+               blit_width = image->width * 2;
+               break;
+       case RADEON_TXFORMAT_I8:
+       case RADEON_TXFORMAT_RGB332:
+               format = RADEON_COLOR_FORMAT_CI8;
+               tex_width = tex->width * 1;
+               blit_width = image->width * 1;
+               break;
+       default:
+               DRM_ERROR("invalid texture format %d\n", tex->format);
+               return -EINVAL;
+       }
+       spitch = blit_width >> 6;
+       if (spitch == 0 && image->height > 1)
+               return -EINVAL;
+
+       texpitch = tex->pitch;
+       if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
+               microtile = 1;
+               if (tex_width < 64) {
+                       texpitch &= ~(RADEON_DST_TILE_MICRO >> 22);
+                       /* we got tiled coordinates, untile them */
+                       image->x *= 2;
+               }
+       } else
+               microtile = 0;
+
+       /* this might fail for zero-sized uploads - are those illegal? */
+       if (!radeon_check_offset(dev_priv, tex->offset + image->height *
+                               blit_width - 1)) {
+               DRM_ERROR("Invalid final destination offset\n");
+               return -EINVAL;
+       }
+
+       DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width);
+
+       do {
+               DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",
+                         tex->offset >> 10, tex->pitch, tex->format,
+                         image->x, image->y, image->width, image->height);
+
+               /* Make a copy of some parameters in case we have to
+                * update them for a multi-pass texture blit.
+                */
+               height = image->height;
+               data = (const u8 __user *)image->data;
+
+               size = height * blit_width;
+
+               if (size > RADEON_MAX_TEXTURE_SIZE) {
+                       height = RADEON_MAX_TEXTURE_SIZE / blit_width;
+                       size = height * blit_width;
+               } else if (size < 4 && size > 0) {
+                       size = 4;
+               } else if (size == 0) {
+                       return 0;
+               }
+
+               buf = radeon_freelist_get(dev);
+               if (0 && !buf) {
+                       radeon_do_cp_idle(dev_priv);
+                       buf = radeon_freelist_get(dev);
+               }
+               if (!buf) {
+                       DRM_DEBUG("EAGAIN\n");
+                       if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
+                               return -EFAULT;
+                       return -EAGAIN;
+               }
+
+               /* Dispatch the indirect buffer.
+                */
+               buffer =
+                   (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
+               dwords = size / 4;
+
+#define RADEON_COPY_MT(_buf, _data, _width) \
+       do { \
+               if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\
+                       DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \
+                       return -EFAULT; \
+               } \
+       } while(0)
+
+               if (microtile) {
+                       /* texture micro tiling in use, minimum texture width is thus 16 bytes.
+                          however, we cannot use blitter directly for texture width < 64 bytes,
+                          since minimum tex pitch is 64 bytes and we need this to match
+                          the texture width, otherwise the blitter will tile it wrong.
+                          Thus, tiling manually in this case. Additionally, need to special
+                          case tex height = 1, since our actual image will have height 2
+                          and we need to ensure we don't read beyond the texture size
+                          from user space. */
+                       if (tex->height == 1) {
+                               if (tex_width >= 64 || tex_width <= 16) {
+                                       RADEON_COPY_MT(buffer, data,
+                                               (int)(tex_width * sizeof(u32)));
+                               } else if (tex_width == 32) {
+                                       RADEON_COPY_MT(buffer, data, 16);
+                                       RADEON_COPY_MT(buffer + 8,
+                                                      data + 16, 16);
+                               }
+                       } else if (tex_width >= 64 || tex_width == 16) {
+                               RADEON_COPY_MT(buffer, data,
+                                              (int)(dwords * sizeof(u32)));
+                       } else if (tex_width < 16) {
+                               for (i = 0; i < tex->height; i++) {
+                                       RADEON_COPY_MT(buffer, data, tex_width);
+                                       buffer += 4;
+                                       data += tex_width;
+                               }
+                       } else if (tex_width == 32) {
+                               /* TODO: make sure this works when not fitting in one buffer
+                                  (i.e. 32bytes x 2048...) */
+                               for (i = 0; i < tex->height; i += 2) {
+                                       RADEON_COPY_MT(buffer, data, 16);
+                                       data += 16;
+                                       RADEON_COPY_MT(buffer + 8, data, 16);
+                                       data += 16;
+                                       RADEON_COPY_MT(buffer + 4, data, 16);
+                                       data += 16;
+                                       RADEON_COPY_MT(buffer + 12, data, 16);
+                                       data += 16;
+                                       buffer += 16;
+                               }
+                       }
+               } else {
+                       if (tex_width >= 32) {
+                               /* Texture image width is larger than the minimum, so we
+                                * can upload it directly.
+                                */
+                               RADEON_COPY_MT(buffer, data,
+                                              (int)(dwords * sizeof(u32)));
+                       } else {
+                               /* Texture image width is less than the minimum, so we
+                                * need to pad out each image scanline to the minimum
+                                * width.
+                                */
+                               for (i = 0; i < tex->height; i++) {
+                                       RADEON_COPY_MT(buffer, data, tex_width);
+                                       buffer += 8;
+                                       data += tex_width;
+                               }
+                       }
+               }
+
+#undef RADEON_COPY_MT
+               byte_offset = (image->y & ~2047) * blit_width;
+               buf->file_priv = file_priv;
+               buf->used = size;
+               offset = dev_priv->gart_buffers_offset + buf->offset;
+               BEGIN_RING(9);
+               OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
+               OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+                        RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+                        RADEON_GMC_BRUSH_NONE |
+                        (format << 8) |
+                        RADEON_GMC_SRC_DATATYPE_COLOR |
+                        RADEON_ROP3_S |
+                        RADEON_DP_SRC_SOURCE_MEMORY |
+                        RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
+               OUT_RING((spitch << 22) | (offset >> 10));
+               OUT_RING((texpitch << 22) | ((tex->offset >> 10) + (byte_offset >> 10)));
+               OUT_RING(0);
+               OUT_RING((image->x << 16) | (image->y % 2048));
+               OUT_RING((image->width << 16) | height);
+               RADEON_WAIT_UNTIL_2D_IDLE();
+               ADVANCE_RING();
+               COMMIT_RING();
+
+               radeon_cp_discard_buffer(dev, buf);
+
+               /* Update the input parameters for next time */
+               image->y += height;
+               image->height -= height;
+               image->data = (const u8 __user *)image->data + size;
+       } while (image->height > 0);
+
+       /* Flush the pixel cache after the blit completes.  This ensures
+        * the texture data is written out to memory before rendering
+        * continues.
+        */
+       BEGIN_RING(4);
+       RADEON_FLUSH_CACHE();
+       RADEON_WAIT_UNTIL_2D_IDLE();
+       ADVANCE_RING();
+       COMMIT_RING();
+
+       return 0;
+}
+
+static void radeon_cp_dispatch_stipple(struct drm_device * dev, u32 * stipple)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       int i;
+       RING_LOCALS;
+       DRM_DEBUG("\n");
+
+       BEGIN_RING(35);
+
+       OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0));
+       OUT_RING(0x00000000);
+
+       OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31));
+       for (i = 0; i < 32; i++) {
+               OUT_RING(stipple[i]);
+       }
+
+       ADVANCE_RING();
+}
+
+static void radeon_apply_surface_regs(int surf_index,
+                                     drm_radeon_private_t *dev_priv)
+{
+       if (!dev_priv->mmio)
+               return;
+
+       radeon_do_cp_idle(dev_priv);
+
+       RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * surf_index,
+                    dev_priv->surfaces[surf_index].flags);
+       RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * surf_index,
+                    dev_priv->surfaces[surf_index].lower);
+       RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * surf_index,
+                    dev_priv->surfaces[surf_index].upper);
+}
+
+/* Allocates a virtual surface
+ * doesn't always allocate a real surface, will stretch an existing
+ * surface when possible.
+ *
+ * Note that refcount can be at most 2, since during a free refcount=3
+ * might mean we have to allocate a new surface which might not always
+ * be available.
+ * For example : we allocate three contigous surfaces ABC. If B is
+ * freed, we suddenly need two surfaces to store A and C, which might
+ * not always be available.
+ */
+static int alloc_surface(drm_radeon_surface_alloc_t *new,
+                        drm_radeon_private_t *dev_priv,
+                        struct drm_file *file_priv)
+{
+       struct radeon_virt_surface *s;
+       int i;
+       int virt_surface_index;
+       uint32_t new_upper, new_lower;
+
+       new_lower = new->address;
+       new_upper = new_lower + new->size - 1;
+
+       /* sanity check */
+       if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) ||
+           ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) !=
+            RADEON_SURF_ADDRESS_FIXED_MASK)
+           || ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0))
+               return -1;
+
+       /* make sure there is no overlap with existing surfaces */
+       for (i = 0; i < RADEON_MAX_SURFACES; i++) {
+               if ((dev_priv->surfaces[i].refcount != 0) &&
+                   (((new_lower >= dev_priv->surfaces[i].lower) &&
+                     (new_lower < dev_priv->surfaces[i].upper)) ||
+                    ((new_lower < dev_priv->surfaces[i].lower) &&
+                     (new_upper > dev_priv->surfaces[i].lower)))) {
+                       return -1;
+               }
+       }
+
+       /* find a virtual surface */
+       for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++)
+               if (dev_priv->virt_surfaces[i].file_priv == 0)
+                       break;
+       if (i == 2 * RADEON_MAX_SURFACES) {
+               return -1;
+       }
+       virt_surface_index = i;
+
+       /* try to reuse an existing surface */
+       for (i = 0; i < RADEON_MAX_SURFACES; i++) {
+               /* extend before */
+               if ((dev_priv->surfaces[i].refcount == 1) &&
+                   (new->flags == dev_priv->surfaces[i].flags) &&
+                   (new_upper + 1 == dev_priv->surfaces[i].lower)) {
+                       s = &(dev_priv->virt_surfaces[virt_surface_index]);
+                       s->surface_index = i;
+                       s->lower = new_lower;
+                       s->upper = new_upper;
+                       s->flags = new->flags;
+                       s->file_priv = file_priv;
+                       dev_priv->surfaces[i].refcount++;
+                       dev_priv->surfaces[i].lower = s->lower;
+                       radeon_apply_surface_regs(s->surface_index, dev_priv);
+                       return virt_surface_index;
+               }
+
+               /* extend after */
+               if ((dev_priv->surfaces[i].refcount == 1) &&
+                   (new->flags == dev_priv->surfaces[i].flags) &&
+                   (new_lower == dev_priv->surfaces[i].upper + 1)) {
+                       s = &(dev_priv->virt_surfaces[virt_surface_index]);
+                       s->surface_index = i;
+                       s->lower = new_lower;
+                       s->upper = new_upper;
+                       s->flags = new->flags;
+                       s->file_priv = file_priv;
+                       dev_priv->surfaces[i].refcount++;
+                       dev_priv->surfaces[i].upper = s->upper;
+                       radeon_apply_surface_regs(s->surface_index, dev_priv);
+                       return virt_surface_index;
+               }
+       }
+
+       /* okay, we need a new one */
+       for (i = 0; i < RADEON_MAX_SURFACES; i++) {
+               if (dev_priv->surfaces[i].refcount == 0) {
+                       s = &(dev_priv->virt_surfaces[virt_surface_index]);
+                       s->surface_index = i;
+                       s->lower = new_lower;
+                       s->upper = new_upper;
+                       s->flags = new->flags;
+                       s->file_priv = file_priv;
+                       dev_priv->surfaces[i].refcount = 1;
+                       dev_priv->surfaces[i].lower = s->lower;
+                       dev_priv->surfaces[i].upper = s->upper;
+                       dev_priv->surfaces[i].flags = s->flags;
+                       radeon_apply_surface_regs(s->surface_index, dev_priv);
+                       return virt_surface_index;
+               }
+       }
+
+       /* we didn't find anything */
+       return -1;
+}
+
+static int free_surface(struct drm_file *file_priv,
+                       drm_radeon_private_t * dev_priv,
+                       int lower)
+{
+       struct radeon_virt_surface *s;
+       int i;
+       /* find the virtual surface */
+       for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
+               s = &(dev_priv->virt_surfaces[i]);
+               if (s->file_priv) {
+                       if ((lower == s->lower) && (file_priv == s->file_priv))
+                       {
+                               if (dev_priv->surfaces[s->surface_index].
+                                   lower == s->lower)
+                                       dev_priv->surfaces[s->surface_index].
+                                           lower = s->upper;
+
+                               if (dev_priv->surfaces[s->surface_index].
+                                   upper == s->upper)
+                                       dev_priv->surfaces[s->surface_index].
+                                           upper = s->lower;
+
+                               dev_priv->surfaces[s->surface_index].refcount--;
+                               if (dev_priv->surfaces[s->surface_index].
+                                   refcount == 0)
+                                       dev_priv->surfaces[s->surface_index].
+                                           flags = 0;
+                               s->file_priv = NULL;
+                               radeon_apply_surface_regs(s->surface_index,
+                                                         dev_priv);
+                               return 0;
+                       }
+               }
+       }
+       return 1;
+}
+
+static void radeon_surfaces_release(struct drm_file *file_priv,
+                                   drm_radeon_private_t * dev_priv)
+{
+       int i;
+       for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) {
+               if (dev_priv->virt_surfaces[i].file_priv == file_priv)
+                       free_surface(file_priv, dev_priv,
+                                    dev_priv->virt_surfaces[i].lower);
+       }
+}
+
+/* ================================================================
+ * IOCTL functions
+ */
+static int radeon_surface_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_surface_alloc_t *alloc = data;
+
+       if (alloc_surface(alloc, dev_priv, file_priv) == -1)
+               return -EINVAL;
+       else
+               return 0;
+}
+
+static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_surface_free_t *memfree = data;
+
+       if (free_surface(file_priv, dev_priv, memfree->address))
+               return -EINVAL;
+       else
+               return 0;
+}
+
+static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       drm_radeon_clear_t *clear = data;
+       drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+       if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
+               sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+       if (DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes,
+                              sarea_priv->nbox * sizeof(depth_boxes[0])))
+               return -EFAULT;
+
+       radeon_cp_dispatch_clear(dev, clear, depth_boxes);
+
+       COMMIT_RING();
+       return 0;
+}
+
+/* Not sure why this isn't set all the time:
+ */
+static int radeon_do_init_pageflip(struct drm_device * dev)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       DRM_DEBUG("\n");
+
+       BEGIN_RING(6);
+       RADEON_WAIT_UNTIL_3D_IDLE();
+       OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0));
+       OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) |
+                RADEON_CRTC_OFFSET_FLIP_CNTL);
+       OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0));
+       OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) |
+                RADEON_CRTC_OFFSET_FLIP_CNTL);
+       ADVANCE_RING();
+
+       dev_priv->page_flipping = 1;
+
+       if (dev_priv->sarea_priv->pfCurrentPage != 1)
+               dev_priv->sarea_priv->pfCurrentPage = 0;
+
+       return 0;
+}
+
+/* Swapping and flipping are different operations, need different ioctls.
+ * They can & should be intermixed to support multiple 3d windows.
+ */
+static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+       if (!dev_priv->page_flipping)
+               radeon_do_init_pageflip(dev);
+
+       radeon_cp_dispatch_flip(dev);
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+       if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
+               sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
+
+       radeon_cp_dispatch_swap(dev);
+       dev_priv->sarea_priv->ctx_owner = 0;
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_radeon_vertex_t *vertex = data;
+       drm_radeon_tcl_prim_t prim;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
+                 DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
+
+       if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
+               DRM_ERROR("buffer index %d (of %d max)\n",
+                         vertex->idx, dma->buf_count - 1);
+               return -EINVAL;
+       }
+       if (vertex->prim < 0 || vertex->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
+               DRM_ERROR("buffer prim %d\n", vertex->prim);
+               return -EINVAL;
+       }
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+       VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+       buf = dma->buflist[vertex->idx];
+
+       if (buf->file_priv != file_priv) {
+               DRM_ERROR("process %d using buffer owned by %p\n",
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
+       }
+       if (buf->pending) {
+               DRM_ERROR("sending pending buffer %d\n", vertex->idx);
+               return -EINVAL;
+       }
+
+       /* Build up a prim_t record:
+        */
+       if (vertex->count) {
+               buf->used = vertex->count;      /* not used? */
+
+               if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
+                       if (radeon_emit_state(dev_priv, file_priv,
+                                             &sarea_priv->context_state,
+                                             sarea_priv->tex_state,
+                                             sarea_priv->dirty)) {
+                               DRM_ERROR("radeon_emit_state failed\n");
+                               return -EINVAL;
+                       }
+
+                       sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+                                              RADEON_UPLOAD_TEX1IMAGES |
+                                              RADEON_UPLOAD_TEX2IMAGES |
+                                              RADEON_REQUIRE_QUIESCENCE);
+               }
+
+               prim.start = 0;
+               prim.finish = vertex->count;    /* unused */
+               prim.prim = vertex->prim;
+               prim.numverts = vertex->count;
+               prim.vc_format = dev_priv->sarea_priv->vc_format;
+
+               radeon_cp_dispatch_vertex(dev, buf, &prim);
+       }
+
+       if (vertex->discard) {
+               radeon_cp_discard_buffer(dev, buf);
+       }
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_radeon_indices_t *elts = data;
+       drm_radeon_tcl_prim_t prim;
+       int count;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
+                 DRM_CURRENTPID, elts->idx, elts->start, elts->end,
+                 elts->discard);
+
+       if (elts->idx < 0 || elts->idx >= dma->buf_count) {
+               DRM_ERROR("buffer index %d (of %d max)\n",
+                         elts->idx, dma->buf_count - 1);
+               return -EINVAL;
+       }
+       if (elts->prim < 0 || elts->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) {
+               DRM_ERROR("buffer prim %d\n", elts->prim);
+               return -EINVAL;
+       }
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+       VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+       buf = dma->buflist[elts->idx];
+
+       if (buf->file_priv != file_priv) {
+               DRM_ERROR("process %d using buffer owned by %p\n",
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
+       }
+       if (buf->pending) {
+               DRM_ERROR("sending pending buffer %d\n", elts->idx);
+               return -EINVAL;
+       }
+
+       count = (elts->end - elts->start) / sizeof(u16);
+       elts->start -= RADEON_INDEX_PRIM_OFFSET;
+
+       if (elts->start & 0x7) {
+               DRM_ERROR("misaligned buffer 0x%x\n", elts->start);
+               return -EINVAL;
+       }
+       if (elts->start < buf->used) {
+               DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);
+               return -EINVAL;
+       }
+
+       buf->used = elts->end;
+
+       if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) {
+               if (radeon_emit_state(dev_priv, file_priv,
+                                     &sarea_priv->context_state,
+                                     sarea_priv->tex_state,
+                                     sarea_priv->dirty)) {
+                       DRM_ERROR("radeon_emit_state failed\n");
+                       return -EINVAL;
+               }
+
+               sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
+                                      RADEON_UPLOAD_TEX1IMAGES |
+                                      RADEON_UPLOAD_TEX2IMAGES |
+                                      RADEON_REQUIRE_QUIESCENCE);
+       }
+
+       /* Build up a prim_t record:
+        */
+       prim.start = elts->start;
+       prim.finish = elts->end;
+       prim.prim = elts->prim;
+       prim.offset = 0;        /* offset from start of dma buffers */
+       prim.numverts = RADEON_MAX_VB_VERTS;    /* duh */
+       prim.vc_format = dev_priv->sarea_priv->vc_format;
+
+       radeon_cp_dispatch_indices(dev, buf, &prim);
+       if (elts->discard) {
+               radeon_cp_discard_buffer(dev, buf);
+       }
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_texture_t *tex = data;
+       drm_radeon_tex_image_t image;
+       int ret;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (tex->image == NULL) {
+               DRM_ERROR("null texture image!\n");
+               return -EINVAL;
+       }
+
+       if (DRM_COPY_FROM_USER(&image,
+                              (drm_radeon_tex_image_t __user *) tex->image,
+                              sizeof(image)))
+               return -EFAULT;
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+       VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+       ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image);
+
+       return ret;
+}
+
+static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_stipple_t *stipple = data;
+       u32 mask[32];
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
+               return -EFAULT;
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+
+       radeon_cp_dispatch_stipple(dev, mask);
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_radeon_indirect_t *indirect = data;
+       RING_LOCALS;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
+                 indirect->idx, indirect->start, indirect->end,
+                 indirect->discard);
+
+       if (indirect->idx < 0 || indirect->idx >= dma->buf_count) {
+               DRM_ERROR("buffer index %d (of %d max)\n",
+                         indirect->idx, dma->buf_count - 1);
+               return -EINVAL;
+       }
+
+       buf = dma->buflist[indirect->idx];
+
+       if (buf->file_priv != file_priv) {
+               DRM_ERROR("process %d using buffer owned by %p\n",
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
+       }
+       if (buf->pending) {
+               DRM_ERROR("sending pending buffer %d\n", indirect->idx);
+               return -EINVAL;
+       }
+
+       if (indirect->start < buf->used) {
+               DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
+                         indirect->start, buf->used);
+               return -EINVAL;
+       }
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+       VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+       buf->used = indirect->end;
+
+       /* Wait for the 3D stream to idle before the indirect buffer
+        * containing 2D acceleration commands is processed.
+        */
+       BEGIN_RING(2);
+
+       RADEON_WAIT_UNTIL_3D_IDLE();
+
+       ADVANCE_RING();
+
+       /* Dispatch the indirect buffer full of commands from the
+        * X server.  This is insecure and is thus only available to
+        * privileged clients.
+        */
+       radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);
+       if (indirect->discard) {
+               radeon_cp_discard_buffer(dev, buf);
+       }
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_radeon_vertex2_t *vertex = data;
+       int i;
+       unsigned char laststate;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       DRM_DEBUG("pid=%d index=%d discard=%d\n",
+                 DRM_CURRENTPID, vertex->idx, vertex->discard);
+
+       if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
+               DRM_ERROR("buffer index %d (of %d max)\n",
+                         vertex->idx, dma->buf_count - 1);
+               return -EINVAL;
+       }
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+       VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+       buf = dma->buflist[vertex->idx];
+
+       if (buf->file_priv != file_priv) {
+               DRM_ERROR("process %d using buffer owned by %p\n",
+                         DRM_CURRENTPID, buf->file_priv);
+               return -EINVAL;
+       }
+
+       if (buf->pending) {
+               DRM_ERROR("sending pending buffer %d\n", vertex->idx);
+               return -EINVAL;
+       }
+
+       if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
+               return -EINVAL;
+
+       for (laststate = 0xff, i = 0; i < vertex->nr_prims; i++) {
+               drm_radeon_prim_t prim;
+               drm_radeon_tcl_prim_t tclprim;
+
+               if (DRM_COPY_FROM_USER(&prim, &vertex->prim[i], sizeof(prim)))
+                       return -EFAULT;
+
+               if (prim.stateidx != laststate) {
+                       drm_radeon_state_t state;
+
+                       if (DRM_COPY_FROM_USER(&state,
+                                              &vertex->state[prim.stateidx],
+                                              sizeof(state)))
+                               return -EFAULT;
+
+                       if (radeon_emit_state2(dev_priv, file_priv, &state)) {
+                               DRM_ERROR("radeon_emit_state2 failed\n");
+                               return -EINVAL;
+                       }
+
+                       laststate = prim.stateidx;
+               }
+
+               tclprim.start = prim.start;
+               tclprim.finish = prim.finish;
+               tclprim.prim = prim.prim;
+               tclprim.vc_format = prim.vc_format;
+
+               if (prim.prim & RADEON_PRIM_WALK_IND) {
+                       tclprim.offset = prim.numverts * 64;
+                       tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
+
+                       radeon_cp_dispatch_indices(dev, buf, &tclprim);
+               } else {
+                       tclprim.numverts = prim.numverts;
+                       tclprim.offset = 0;     /* not used */
+
+                       radeon_cp_dispatch_vertex(dev, buf, &tclprim);
+               }
+
+               if (sarea_priv->nbox == 1)
+                       sarea_priv->nbox = 0;
+       }
+
+       if (vertex->discard) {
+               radeon_cp_discard_buffer(dev, buf);
+       }
+
+       COMMIT_RING();
+       return 0;
+}
+
+static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
+                              struct drm_file *file_priv,
+                              drm_radeon_cmd_header_t header,
+                              drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       int id = (int)header.packet.packet_id;
+       int sz, reg;
+       int *data = (int *)cmdbuf->buf;
+       RING_LOCALS;
+
+       if (id >= RADEON_MAX_STATE_PACKETS)
+               return -EINVAL;
+
+       sz = packet[id].len;
+       reg = packet[id].start;
+
+       if (sz * sizeof(int) > cmdbuf->bufsz) {
+               DRM_ERROR("Packet size provided larger than data provided\n");
+               return -EINVAL;
+       }
+
+       if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, data)) {
+               DRM_ERROR("Packet verification failed\n");
+               return -EINVAL;
+       }
+
+       BEGIN_RING(sz + 1);
+       OUT_RING(CP_PACKET0(reg, (sz - 1)));
+       OUT_RING_TABLE(data, sz);
+       ADVANCE_RING();
+
+       cmdbuf->buf += sz * sizeof(int);
+       cmdbuf->bufsz -= sz * sizeof(int);
+       return 0;
+}
+
+static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv,
+                                         drm_radeon_cmd_header_t header,
+                                         drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       int sz = header.scalars.count;
+       int start = header.scalars.offset;
+       int stride = header.scalars.stride;
+       RING_LOCALS;
+
+       BEGIN_RING(3 + sz);
+       OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
+       OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
+       OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
+       OUT_RING_TABLE(cmdbuf->buf, sz);
+       ADVANCE_RING();
+       cmdbuf->buf += sz * sizeof(int);
+       cmdbuf->bufsz -= sz * sizeof(int);
+       return 0;
+}
+
+/* God this is ugly
+ */
+static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv,
+                                          drm_radeon_cmd_header_t header,
+                                          drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       int sz = header.scalars.count;
+       int start = ((unsigned int)header.scalars.offset) + 0x100;
+       int stride = header.scalars.stride;
+       RING_LOCALS;
+
+       BEGIN_RING(3 + sz);
+       OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0));
+       OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
+       OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1));
+       OUT_RING_TABLE(cmdbuf->buf, sz);
+       ADVANCE_RING();
+       cmdbuf->buf += sz * sizeof(int);
+       cmdbuf->bufsz -= sz * sizeof(int);
+       return 0;
+}
+
+static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
+                                         drm_radeon_cmd_header_t header,
+                                         drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       int sz = header.vectors.count;
+       int start = header.vectors.offset;
+       int stride = header.vectors.stride;
+       RING_LOCALS;
+
+       BEGIN_RING(5 + sz);
+       OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+       OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
+       OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+       OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
+       OUT_RING_TABLE(cmdbuf->buf, sz);
+       ADVANCE_RING();
+
+       cmdbuf->buf += sz * sizeof(int);
+       cmdbuf->bufsz -= sz * sizeof(int);
+       return 0;
+}
+
+static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
+                                         drm_radeon_cmd_header_t header,
+                                         drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       int sz = header.veclinear.count * 4;
+       int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8);
+       RING_LOCALS;
+
+        if (!sz)
+                return 0;
+        if (sz * 4 > cmdbuf->bufsz)
+                return -EINVAL;
+
+       BEGIN_RING(5 + sz);
+       OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+       OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
+       OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+       OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
+       OUT_RING_TABLE(cmdbuf->buf, sz);
+       ADVANCE_RING();
+
+       cmdbuf->buf += sz * sizeof(int);
+       cmdbuf->bufsz -= sz * sizeof(int);
+       return 0;
+}
+
+static int radeon_emit_packet3(struct drm_device * dev,
+                              struct drm_file *file_priv,
+                              drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       unsigned int cmdsz;
+       int ret;
+       RING_LOCALS;
+
+       DRM_DEBUG("\n");
+
+       if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv,
+                                                 cmdbuf, &cmdsz))) {
+               DRM_ERROR("Packet verification failed\n");
+               return ret;
+       }
+
+       BEGIN_RING(cmdsz);
+       OUT_RING_TABLE(cmdbuf->buf, cmdsz);
+       ADVANCE_RING();
+
+       cmdbuf->buf += cmdsz * 4;
+       cmdbuf->bufsz -= cmdsz * 4;
+       return 0;
+}
+
+static int radeon_emit_packet3_cliprect(struct drm_device *dev,
+                                       struct drm_file *file_priv,
+                                       drm_radeon_kcmd_buffer_t *cmdbuf,
+                                       int orig_nbox)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       struct drm_clip_rect box;
+       unsigned int cmdsz;
+       int ret;
+       struct drm_clip_rect __user *boxes = cmdbuf->boxes;
+       int i = 0;
+       RING_LOCALS;
+
+       DRM_DEBUG("\n");
+
+       if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv,
+                                                 cmdbuf, &cmdsz))) {
+               DRM_ERROR("Packet verification failed\n");
+               return ret;
+       }
+
+       if (!orig_nbox)
+               goto out;
+
+       do {
+               if (i < cmdbuf->nbox) {
+                       if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box)))
+                               return -EFAULT;
+                       /* FIXME The second and subsequent times round
+                        * this loop, send a WAIT_UNTIL_3D_IDLE before
+                        * calling emit_clip_rect(). This fixes a
+                        * lockup on fast machines when sending
+                        * several cliprects with a cmdbuf, as when
+                        * waving a 2D window over a 3D
+                        * window. Something in the commands from user
+                        * space seems to hang the card when they're
+                        * sent several times in a row. That would be
+                        * the correct place to fix it but this works
+                        * around it until I can figure that out - Tim
+                        * Smith */
+                       if (i) {
+                               BEGIN_RING(2);
+                               RADEON_WAIT_UNTIL_3D_IDLE();
+                               ADVANCE_RING();
+                       }
+                       radeon_emit_clip_rect(dev_priv, &box);
+               }
+
+               BEGIN_RING(cmdsz);
+               OUT_RING_TABLE(cmdbuf->buf, cmdsz);
+               ADVANCE_RING();
+
+       } while (++i < cmdbuf->nbox);
+       if (cmdbuf->nbox == 1)
+               cmdbuf->nbox = 0;
+
+      out:
+       cmdbuf->buf += cmdsz * 4;
+       cmdbuf->bufsz -= cmdsz * 4;
+       return 0;
+}
+
+static int radeon_emit_wait(struct drm_device * dev, int flags)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       RING_LOCALS;
+
+       DRM_DEBUG("%x\n", flags);
+       switch (flags) {
+       case RADEON_WAIT_2D:
+               BEGIN_RING(2);
+               RADEON_WAIT_UNTIL_2D_IDLE();
+               ADVANCE_RING();
+               break;
+       case RADEON_WAIT_3D:
+               BEGIN_RING(2);
+               RADEON_WAIT_UNTIL_3D_IDLE();
+               ADVANCE_RING();
+               break;
+       case RADEON_WAIT_2D | RADEON_WAIT_3D:
+               BEGIN_RING(2);
+               RADEON_WAIT_UNTIL_IDLE();
+               ADVANCE_RING();
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf = NULL;
+       int idx;
+       drm_radeon_kcmd_buffer_t *cmdbuf = data;
+       drm_radeon_cmd_header_t header;
+       int orig_nbox, orig_bufsz;
+       char *kbuf = NULL;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       RING_SPACE_TEST_WITH_RETURN(dev_priv);
+       VB_AGE_TEST_WITH_RETURN(dev_priv);
+
+       if (cmdbuf->bufsz > 64 * 1024 || cmdbuf->bufsz < 0) {
+               return -EINVAL;
+       }
+
+       /* Allocate an in-kernel area and copy in the cmdbuf.  Do this to avoid
+        * races between checking values and using those values in other code,
+        * and simply to avoid a lot of function calls to copy in data.
+        */
+       orig_bufsz = cmdbuf->bufsz;
+       if (orig_bufsz != 0) {
+               kbuf = drm_alloc(cmdbuf->bufsz, DRM_MEM_DRIVER);
+               if (kbuf == NULL)
+                       return -ENOMEM;
+               if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf,
+                                      cmdbuf->bufsz)) {
+                       drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+                       return -EFAULT;
+               }
+               cmdbuf->buf = kbuf;
+       }
+
+       orig_nbox = cmdbuf->nbox;
+
+       if (dev_priv->microcode_version == UCODE_R300) {
+               int temp;
+               temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
+
+               if (orig_bufsz != 0)
+                       drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+
+               return temp;
+       }
+
+       /* microcode_version != r300 */
+       while (cmdbuf->bufsz >= sizeof(header)) {
+
+               header.i = *(int *)cmdbuf->buf;
+               cmdbuf->buf += sizeof(header);
+               cmdbuf->bufsz -= sizeof(header);
+
+               switch (header.header.cmd_type) {
+               case RADEON_CMD_PACKET:
+                       DRM_DEBUG("RADEON_CMD_PACKET\n");
+                       if (radeon_emit_packets
+                           (dev_priv, file_priv, header, cmdbuf)) {
+                               DRM_ERROR("radeon_emit_packets failed\n");
+                               goto err;
+                       }
+                       break;
+
+               case RADEON_CMD_SCALARS:
+                       DRM_DEBUG("RADEON_CMD_SCALARS\n");
+                       if (radeon_emit_scalars(dev_priv, header, cmdbuf)) {
+                               DRM_ERROR("radeon_emit_scalars failed\n");
+                               goto err;
+                       }
+                       break;
+
+               case RADEON_CMD_VECTORS:
+                       DRM_DEBUG("RADEON_CMD_VECTORS\n");
+                       if (radeon_emit_vectors(dev_priv, header, cmdbuf)) {
+                               DRM_ERROR("radeon_emit_vectors failed\n");
+                               goto err;
+                       }
+                       break;
+
+               case RADEON_CMD_DMA_DISCARD:
+                       DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n");
+                       idx = header.dma.buf_idx;
+                       if (idx < 0 || idx >= dma->buf_count) {
+                               DRM_ERROR("buffer index %d (of %d max)\n",
+                                         idx, dma->buf_count - 1);
+                               goto err;
+                       }
+
+                       buf = dma->buflist[idx];
+                       if (buf->file_priv != file_priv || buf->pending) {
+                               DRM_ERROR("bad buffer %p %p %d\n",
+                                         buf->file_priv, file_priv,
+                                         buf->pending);
+                               goto err;
+                       }
+
+                       radeon_cp_discard_buffer(dev, buf);
+                       break;
+
+               case RADEON_CMD_PACKET3:
+                       DRM_DEBUG("RADEON_CMD_PACKET3\n");
+                       if (radeon_emit_packet3(dev, file_priv, cmdbuf)) {
+                               DRM_ERROR("radeon_emit_packet3 failed\n");
+                               goto err;
+                       }
+                       break;
+
+               case RADEON_CMD_PACKET3_CLIP:
+                       DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
+                       if (radeon_emit_packet3_cliprect
+                           (dev, file_priv, cmdbuf, orig_nbox)) {
+                               DRM_ERROR("radeon_emit_packet3_clip failed\n");
+                               goto err;
+                       }
+                       break;
+
+               case RADEON_CMD_SCALARS2:
+                       DRM_DEBUG("RADEON_CMD_SCALARS2\n");
+                       if (radeon_emit_scalars2(dev_priv, header, cmdbuf)) {
+                               DRM_ERROR("radeon_emit_scalars2 failed\n");
+                               goto err;
+                       }
+                       break;
+
+               case RADEON_CMD_WAIT:
+                       DRM_DEBUG("RADEON_CMD_WAIT\n");
+                       if (radeon_emit_wait(dev, header.wait.flags)) {
+                               DRM_ERROR("radeon_emit_wait failed\n");
+                               goto err;
+                       }
+                       break;
+               case RADEON_CMD_VECLINEAR:
+                       DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
+                       if (radeon_emit_veclinear(dev_priv, header, cmdbuf)) {
+                               DRM_ERROR("radeon_emit_veclinear failed\n");
+                               goto err;
+                       }
+                       break;
+
+               default:
+                       DRM_ERROR("bad cmd_type %d at %p\n",
+                                 header.header.cmd_type,
+                                 cmdbuf->buf - sizeof(header));
+                       goto err;
+               }
+       }
+
+       if (orig_bufsz != 0)
+               drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+
+       DRM_DEBUG("DONE\n");
+       COMMIT_RING();
+       return 0;
+
+      err:
+       if (orig_bufsz != 0)
+               drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+       return -EINVAL;
+}
+
+static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_getparam_t *param = data;
+       int value;
+
+       DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
+
+       switch (param->param) {
+       case RADEON_PARAM_GART_BUFFER_OFFSET:
+               value = dev_priv->gart_buffers_offset;
+               break;
+       case RADEON_PARAM_LAST_FRAME:
+               dev_priv->stats.last_frame_reads++;
+               value = GET_SCRATCH(0);
+               break;
+       case RADEON_PARAM_LAST_DISPATCH:
+               value = GET_SCRATCH(1);
+               break;
+       case RADEON_PARAM_LAST_CLEAR:
+               dev_priv->stats.last_clear_reads++;
+               value = GET_SCRATCH(2);
+               break;
+       case RADEON_PARAM_IRQ_NR:
+               value = dev->irq;
+               break;
+       case RADEON_PARAM_GART_BASE:
+               value = dev_priv->gart_vm_start;
+               break;
+       case RADEON_PARAM_REGISTER_HANDLE:
+               value = dev_priv->mmio->offset;
+               break;
+       case RADEON_PARAM_STATUS_HANDLE:
+               value = dev_priv->ring_rptr_offset;
+               break;
+#if BITS_PER_LONG == 32
+               /*
+                * This ioctl() doesn't work on 64-bit platforms because hw_lock is a
+                * pointer which can't fit into an int-sized variable.  According to
+                * Michel Dänzer, the ioctl() is only used on embedded platforms, so
+                * not supporting it shouldn't be a problem.  If the same functionality
+                * is needed on 64-bit platforms, a new ioctl() would have to be added,
+                * so backwards-compatibility for the embedded platforms can be
+                * maintained.  --davidm 4-Feb-2004.
+                */
+       case RADEON_PARAM_SAREA_HANDLE:
+               /* The lock is the first dword in the sarea. */
+               value = (long)dev->lock.hw_lock;
+               break;
+#endif
+       case RADEON_PARAM_GART_TEX_HANDLE:
+               value = dev_priv->gart_textures_offset;
+               break;
+       case RADEON_PARAM_SCRATCH_OFFSET:
+               if (!dev_priv->writeback_works)
+                       return -EINVAL;
+               value = RADEON_SCRATCH_REG_OFFSET;
+               break;
+       case RADEON_PARAM_CARD_TYPE:
+               if (dev_priv->flags & RADEON_IS_PCIE)
+                       value = RADEON_CARD_PCIE;
+               else if (dev_priv->flags & RADEON_IS_AGP)
+                       value = RADEON_CARD_AGP;
+               else
+                       value = RADEON_CARD_PCI;
+               break;
+       case RADEON_PARAM_VBLANK_CRTC:
+               value = radeon_vblank_crtc_get(dev);
+               break;
+       case RADEON_PARAM_FB_LOCATION:
+               value = radeon_read_fb_location(dev_priv);
+               break;
+       case RADEON_PARAM_NUM_GB_PIPES:
+               value = dev_priv->num_gb_pipes;
+               break;
+       default:
+               DRM_DEBUG("Invalid parameter %d\n", param->param);
+               return -EINVAL;
+       }
+
+       if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
+               DRM_ERROR("copy_to_user\n");
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       drm_radeon_setparam_t *sp = data;
+       struct drm_radeon_driver_file_fields *radeon_priv;
+
+       switch (sp->param) {
+       case RADEON_SETPARAM_FB_LOCATION:
+               radeon_priv = file_priv->driver_priv;
+               radeon_priv->radeon_fb_delta = dev_priv->fb_location -
+                   sp->value;
+               break;
+       case RADEON_SETPARAM_SWITCH_TILING:
+               if (sp->value == 0) {
+                       DRM_DEBUG("color tiling disabled\n");
+                       dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
+                       dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
+                       dev_priv->sarea_priv->tiling_enabled = 0;
+               } else if (sp->value == 1) {
+                       DRM_DEBUG("color tiling enabled\n");
+                       dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
+                       dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
+                       dev_priv->sarea_priv->tiling_enabled = 1;
+               }
+               break;
+       case RADEON_SETPARAM_PCIGART_LOCATION:
+               dev_priv->pcigart_offset = sp->value;
+               dev_priv->pcigart_offset_set = 1;
+               break;
+       case RADEON_SETPARAM_NEW_MEMMAP:
+               dev_priv->new_memmap = sp->value;
+               break;
+       case RADEON_SETPARAM_PCIGART_TABLE_SIZE:
+               dev_priv->gart_info.table_size = sp->value;
+               if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE)
+                       dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
+               break;
+       case RADEON_SETPARAM_VBLANK_CRTC:
+               return radeon_vblank_crtc_set(dev, sp->value);
+               break;
+       default:
+               DRM_DEBUG("Invalid parameter %d\n", sp->param);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* When a client dies:
+ *    - Check for and clean up flipped page state
+ *    - Free any alloced GART memory.
+ *    - Free any alloced radeon surfaces.
+ *
+ * DRM infrastructure takes care of reclaiming dma buffers.
+ */
+void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
+{
+       if (dev->dev_private) {
+               drm_radeon_private_t *dev_priv = dev->dev_private;
+               dev_priv->page_flipping = 0;
+               radeon_mem_release(file_priv, dev_priv->gart_heap);
+               radeon_mem_release(file_priv, dev_priv->fb_heap);
+               radeon_surfaces_release(file_priv, dev_priv);
+       }
+}
+
+void radeon_driver_lastclose(struct drm_device *dev)
+{
+       if (dev->dev_private) {
+               drm_radeon_private_t *dev_priv = dev->dev_private;
+
+               if (dev_priv->sarea_priv &&
+                   dev_priv->sarea_priv->pfCurrentPage != 0)
+                       radeon_cp_dispatch_flip(dev);
+       }
+
+       radeon_do_release(dev);
+}
+
+int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       struct drm_radeon_driver_file_fields *radeon_priv;
+
+       DRM_DEBUG("\n");
+       radeon_priv =
+           (struct drm_radeon_driver_file_fields *)
+           drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
+
+       if (!radeon_priv)
+               return -ENOMEM;
+
+       file_priv->driver_priv = radeon_priv;
+
+       if (dev_priv)
+               radeon_priv->radeon_fb_delta = dev_priv->fb_location;
+       else
+               radeon_priv->radeon_fb_delta = 0;
+       return 0;
+}
+
+void radeon_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
+{
+       struct drm_radeon_driver_file_fields *radeon_priv =
+           file_priv->driver_priv;
+
+       drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
+}
+
+struct drm_ioctl_desc radeon_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH)
+};
+
+int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
diff --git a/drivers/gpu/drm/savage/Makefile b/drivers/gpu/drm/savage/Makefile
new file mode 100644 (file)
index 0000000..d8f84ac
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y = -Iinclude/drm
+savage-y := savage_drv.o savage_bci.o savage_state.o
+
+obj-$(CONFIG_DRM_SAVAGE)+= savage.o
+
diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c
new file mode 100644 (file)
index 0000000..d465b2f
--- /dev/null
@@ -0,0 +1,1095 @@
+/* savage_bci.c -- BCI support for Savage
+ *
+ * Copyright 2004  Felix Kuehling
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "drmP.h"
+#include "savage_drm.h"
+#include "savage_drv.h"
+
+/* Need a long timeout for shadow status updates can take a while
+ * and so can waiting for events when the queue is full. */
+#define SAVAGE_DEFAULT_USEC_TIMEOUT    1000000 /* 1s */
+#define SAVAGE_EVENT_USEC_TIMEOUT      5000000 /* 5s */
+#define SAVAGE_FREELIST_DEBUG          0
+
+static int savage_do_cleanup_bci(struct drm_device *dev);
+
+static int
+savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n)
+{
+       uint32_t mask = dev_priv->status_used_mask;
+       uint32_t threshold = dev_priv->bci_threshold_hi;
+       uint32_t status;
+       int i;
+
+#if SAVAGE_BCI_DEBUG
+       if (n > dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - threshold)
+               DRM_ERROR("Trying to emit %d words "
+                         "(more than guaranteed space in COB)\n", n);
+#endif
+
+       for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
+               DRM_MEMORYBARRIER();
+               status = dev_priv->status_ptr[0];
+               if ((status & mask) < threshold)
+                       return 0;
+               DRM_UDELAY(1);
+       }
+
+#if SAVAGE_BCI_DEBUG
+       DRM_ERROR("failed!\n");
+       DRM_INFO("   status=0x%08x, threshold=0x%08x\n", status, threshold);
+#endif
+       return -EBUSY;
+}
+
+static int
+savage_bci_wait_fifo_s3d(drm_savage_private_t * dev_priv, unsigned int n)
+{
+       uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n;
+       uint32_t status;
+       int i;
+
+       for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
+               status = SAVAGE_READ(SAVAGE_STATUS_WORD0);
+               if ((status & SAVAGE_FIFO_USED_MASK_S3D) <= maxUsed)
+                       return 0;
+               DRM_UDELAY(1);
+       }
+
+#if SAVAGE_BCI_DEBUG
+       DRM_ERROR("failed!\n");
+       DRM_INFO("   status=0x%08x\n", status);
+#endif
+       return -EBUSY;
+}
+
+static int
+savage_bci_wait_fifo_s4(drm_savage_private_t * dev_priv, unsigned int n)
+{
+       uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n;
+       uint32_t status;
+       int i;
+
+       for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) {
+               status = SAVAGE_READ(SAVAGE_ALT_STATUS_WORD0);
+               if ((status & SAVAGE_FIFO_USED_MASK_S4) <= maxUsed)
+                       return 0;
+               DRM_UDELAY(1);
+       }
+
+#if SAVAGE_BCI_DEBUG
+       DRM_ERROR("failed!\n");
+       DRM_INFO("   status=0x%08x\n", status);
+#endif
+       return -EBUSY;
+}
+
+/*
+ * Waiting for events.
+ *
+ * The BIOSresets the event tag to 0 on mode changes. Therefore we
+ * never emit 0 to the event tag. If we find a 0 event tag we know the
+ * BIOS stomped on it and return success assuming that the BIOS waited
+ * for engine idle.
+ *
+ * Note: if the Xserver uses the event tag it has to follow the same
+ * rule. Otherwise there may be glitches every 2^16 events.
+ */
+static int
+savage_bci_wait_event_shadow(drm_savage_private_t * dev_priv, uint16_t e)
+{
+       uint32_t status;
+       int i;
+
+       for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) {
+               DRM_MEMORYBARRIER();
+               status = dev_priv->status_ptr[1];
+               if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff ||
+                   (status & 0xffff) == 0)
+                       return 0;
+               DRM_UDELAY(1);
+       }
+
+#if SAVAGE_BCI_DEBUG
+       DRM_ERROR("failed!\n");
+       DRM_INFO("   status=0x%08x, e=0x%04x\n", status, e);
+#endif
+
+       return -EBUSY;
+}
+
+static int
+savage_bci_wait_event_reg(drm_savage_private_t * dev_priv, uint16_t e)
+{
+       uint32_t status;
+       int i;
+
+       for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) {
+               status = SAVAGE_READ(SAVAGE_STATUS_WORD1);
+               if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff ||
+                   (status & 0xffff) == 0)
+                       return 0;
+               DRM_UDELAY(1);
+       }
+
+#if SAVAGE_BCI_DEBUG
+       DRM_ERROR("failed!\n");
+       DRM_INFO("   status=0x%08x, e=0x%04x\n", status, e);
+#endif
+
+       return -EBUSY;
+}
+
+uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv,
+                              unsigned int flags)
+{
+       uint16_t count;
+       BCI_LOCALS;
+
+       if (dev_priv->status_ptr) {
+               /* coordinate with Xserver */
+               count = dev_priv->status_ptr[1023];
+               if (count < dev_priv->event_counter)
+                       dev_priv->event_wrap++;
+       } else {
+               count = dev_priv->event_counter;
+       }
+       count = (count + 1) & 0xffff;
+       if (count == 0) {
+               count++;        /* See the comment above savage_wait_event_*. */
+               dev_priv->event_wrap++;
+       }
+       dev_priv->event_counter = count;
+       if (dev_priv->status_ptr)
+               dev_priv->status_ptr[1023] = (uint32_t) count;
+
+       if ((flags & (SAVAGE_WAIT_2D | SAVAGE_WAIT_3D))) {
+               unsigned int wait_cmd = BCI_CMD_WAIT;
+               if ((flags & SAVAGE_WAIT_2D))
+                       wait_cmd |= BCI_CMD_WAIT_2D;
+               if ((flags & SAVAGE_WAIT_3D))
+                       wait_cmd |= BCI_CMD_WAIT_3D;
+               BEGIN_BCI(2);
+               BCI_WRITE(wait_cmd);
+       } else {
+               BEGIN_BCI(1);
+       }
+       BCI_WRITE(BCI_CMD_UPDATE_EVENT_TAG | (uint32_t) count);
+
+       return count;
+}
+
+/*
+ * Freelist management
+ */
+static int savage_freelist_init(struct drm_device * dev)
+{
+       drm_savage_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *buf;
+       drm_savage_buf_priv_t *entry;
+       int i;
+       DRM_DEBUG("count=%d\n", dma->buf_count);
+
+       dev_priv->head.next = &dev_priv->tail;
+       dev_priv->head.prev = NULL;
+       dev_priv->head.buf = NULL;
+
+       dev_priv->tail.next = NULL;
+       dev_priv->tail.prev = &dev_priv->head;
+       dev_priv->tail.buf = NULL;
+
+       for (i = 0; i < dma->buf_count; i++) {
+               buf = dma->buflist[i];
+               entry = buf->dev_private;
+
+               SET_AGE(&entry->age, 0, 0);
+               entry->buf = buf;
+
+               entry->next = dev_priv->head.next;
+               entry->prev = &dev_priv->head;
+               dev_priv->head.next->prev = entry;
+               dev_priv->head.next = entry;
+       }
+
+       return 0;
+}
+
+static struct drm_buf *savage_freelist_get(struct drm_device * dev)
+{
+       drm_savage_private_t *dev_priv = dev->dev_private;
+       drm_savage_buf_priv_t *tail = dev_priv->tail.prev;
+       uint16_t event;
+       unsigned int wrap;
+       DRM_DEBUG("\n");
+
+       UPDATE_EVENT_COUNTER();
+       if (dev_priv->status_ptr)
+               event = dev_priv->status_ptr[1] & 0xffff;
+       else
+               event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+       wrap = dev_priv->event_wrap;
+       if (event > dev_priv->event_counter)
+               wrap--;         /* hardware hasn't passed the last wrap yet */
+
+       DRM_DEBUG("   tail=0x%04x %d\n", tail->age.event, tail->age.wrap);
+       DRM_DEBUG("   head=0x%04x %d\n", event, wrap);
+
+       if (tail->buf && (TEST_AGE(&tail->age, event, wrap) || event == 0)) {
+               drm_savage_buf_priv_t *next = tail->next;
+               drm_savage_buf_priv_t *prev = tail->prev;
+               prev->next = next;
+               next->prev = prev;
+               tail->next = tail->prev = NULL;
+               return tail->buf;
+       }
+
+       DRM_DEBUG("returning NULL, tail->buf=%p!\n", tail->buf);
+       return NULL;
+}
+
+void savage_freelist_put(struct drm_device * dev, struct drm_buf * buf)
+{
+       drm_savage_private_t *dev_priv = dev->dev_private;
+       drm_savage_buf_priv_t *entry = buf->dev_private, *prev, *next;
+
+       DRM_DEBUG("age=0x%04x wrap=%d\n", entry->age.event, entry->age.wrap);
+
+       if (entry->next != NULL || entry->prev != NULL) {
+               DRM_ERROR("entry already on freelist.\n");
+               return;
+       }
+
+       prev = &dev_priv->head;
+       next = prev->next;
+       prev->next = entry;
+       next->prev = entry;
+       entry->prev = prev;
+       entry->next = next;
+}
+
+/*
+ * Command DMA
+ */
+static int savage_dma_init(drm_savage_private_t * dev_priv)
+{
+       unsigned int i;
+
+       dev_priv->nr_dma_pages = dev_priv->cmd_dma->size /
+           (SAVAGE_DMA_PAGE_SIZE * 4);
+       dev_priv->dma_pages = drm_alloc(sizeof(drm_savage_dma_page_t) *
+                                       dev_priv->nr_dma_pages, DRM_MEM_DRIVER);
+       if (dev_priv->dma_pages == NULL)
+               return -ENOMEM;
+
+       for (i = 0; i < dev_priv->nr_dma_pages; ++i) {
+               SET_AGE(&dev_priv->dma_pages[i].age, 0, 0);
+               dev_priv->dma_pages[i].used = 0;
+               dev_priv->dma_pages[i].flushed = 0;
+       }
+       SET_AGE(&dev_priv->last_dma_age, 0, 0);
+
+       dev_priv->first_dma_page = 0;
+       dev_priv->current_dma_page = 0;
+
+       return 0;
+}
+
+void savage_dma_reset(drm_savage_private_t * dev_priv)
+{
+       uint16_t event;
+       unsigned int wrap, i;
+       event = savage_bci_emit_event(dev_priv, 0);
+       wrap = dev_priv->event_wrap;
+       for (i = 0; i < dev_priv->nr_dma_pages; ++i) {
+               SET_AGE(&dev_priv->dma_pages[i].age, event, wrap);
+               dev_priv->dma_pages[i].used = 0;
+               dev_priv->dma_pages[i].flushed = 0;
+       }
+       SET_AGE(&dev_priv->last_dma_age, event, wrap);
+       dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
+}
+
+void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page)
+{
+       uint16_t event;
+       unsigned int wrap;
+
+       /* Faked DMA buffer pages don't age. */
+       if (dev_priv->cmd_dma == &dev_priv->fake_dma)
+               return;
+
+       UPDATE_EVENT_COUNTER();
+       if (dev_priv->status_ptr)
+               event = dev_priv->status_ptr[1] & 0xffff;
+       else
+               event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+       wrap = dev_priv->event_wrap;
+       if (event > dev_priv->event_counter)
+               wrap--;         /* hardware hasn't passed the last wrap yet */
+
+       if (dev_priv->dma_pages[page].age.wrap > wrap ||
+           (dev_priv->dma_pages[page].age.wrap == wrap &&
+            dev_priv->dma_pages[page].age.event > event)) {
+               if (dev_priv->wait_evnt(dev_priv,
+                                       dev_priv->dma_pages[page].age.event)
+                   < 0)
+                       DRM_ERROR("wait_evnt failed!\n");
+       }
+}
+
+uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv, unsigned int n)
+{
+       unsigned int cur = dev_priv->current_dma_page;
+       unsigned int rest = SAVAGE_DMA_PAGE_SIZE -
+           dev_priv->dma_pages[cur].used;
+       unsigned int nr_pages = (n - rest + SAVAGE_DMA_PAGE_SIZE - 1) /
+           SAVAGE_DMA_PAGE_SIZE;
+       uint32_t *dma_ptr;
+       unsigned int i;
+
+       DRM_DEBUG("cur=%u, cur->used=%u, n=%u, rest=%u, nr_pages=%u\n",
+                 cur, dev_priv->dma_pages[cur].used, n, rest, nr_pages);
+
+       if (cur + nr_pages < dev_priv->nr_dma_pages) {
+               dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle +
+                   cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used;
+               if (n < rest)
+                       rest = n;
+               dev_priv->dma_pages[cur].used += rest;
+               n -= rest;
+               cur++;
+       } else {
+               dev_priv->dma_flush(dev_priv);
+               nr_pages =
+                   (n + SAVAGE_DMA_PAGE_SIZE - 1) / SAVAGE_DMA_PAGE_SIZE;
+               for (i = cur; i < dev_priv->nr_dma_pages; ++i) {
+                       dev_priv->dma_pages[i].age = dev_priv->last_dma_age;
+                       dev_priv->dma_pages[i].used = 0;
+                       dev_priv->dma_pages[i].flushed = 0;
+               }
+               dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle;
+               dev_priv->first_dma_page = cur = 0;
+       }
+       for (i = cur; nr_pages > 0; ++i, --nr_pages) {
+#if SAVAGE_DMA_DEBUG
+               if (dev_priv->dma_pages[i].used) {
+                       DRM_ERROR("unflushed page %u: used=%u\n",
+                                 i, dev_priv->dma_pages[i].used);
+               }
+#endif
+               if (n > SAVAGE_DMA_PAGE_SIZE)
+                       dev_priv->dma_pages[i].used = SAVAGE_DMA_PAGE_SIZE;
+               else
+                       dev_priv->dma_pages[i].used = n;
+               n -= SAVAGE_DMA_PAGE_SIZE;
+       }
+       dev_priv->current_dma_page = --i;
+
+       DRM_DEBUG("cur=%u, cur->used=%u, n=%u\n",
+                 i, dev_priv->dma_pages[i].used, n);
+
+       savage_dma_wait(dev_priv, dev_priv->current_dma_page);
+
+       return dma_ptr;
+}
+
+static void savage_dma_flush(drm_savage_private_t * dev_priv)
+{
+       unsigned int first = dev_priv->first_dma_page;
+       unsigned int cur = dev_priv->current_dma_page;
+       uint16_t event;
+       unsigned int wrap, pad, align, len, i;
+       unsigned long phys_addr;
+       BCI_LOCALS;
+
+       if (first == cur &&
+           dev_priv->dma_pages[cur].used == dev_priv->dma_pages[cur].flushed)
+               return;
+
+       /* pad length to multiples of 2 entries
+        * align start of next DMA block to multiles of 8 entries */
+       pad = -dev_priv->dma_pages[cur].used & 1;
+       align = -(dev_priv->dma_pages[cur].used + pad) & 7;
+
+       DRM_DEBUG("first=%u, cur=%u, first->flushed=%u, cur->used=%u, "
+                 "pad=%u, align=%u\n",
+                 first, cur, dev_priv->dma_pages[first].flushed,
+                 dev_priv->dma_pages[cur].used, pad, align);
+
+       /* pad with noops */
+       if (pad) {
+               uint32_t *dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle +
+                   cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used;
+               dev_priv->dma_pages[cur].used += pad;
+               while (pad != 0) {
+                       *dma_ptr++ = BCI_CMD_WAIT;
+                       pad--;
+               }
+       }
+
+       DRM_MEMORYBARRIER();
+
+       /* do flush ... */
+       phys_addr = dev_priv->cmd_dma->offset +
+           (first * SAVAGE_DMA_PAGE_SIZE +
+            dev_priv->dma_pages[first].flushed) * 4;
+       len = (cur - first) * SAVAGE_DMA_PAGE_SIZE +
+           dev_priv->dma_pages[cur].used - dev_priv->dma_pages[first].flushed;
+
+       DRM_DEBUG("phys_addr=%lx, len=%u\n",
+                 phys_addr | dev_priv->dma_type, len);
+
+       BEGIN_BCI(3);
+       BCI_SET_REGISTERS(SAVAGE_DMABUFADDR, 1);
+       BCI_WRITE(phys_addr | dev_priv->dma_type);
+       BCI_DMA(len);
+
+       /* fix alignment of the start of the next block */
+       dev_priv->dma_pages[cur].used += align;
+
+       /* age DMA pages */
+       event = savage_bci_emit_event(dev_priv, 0);
+       wrap = dev_priv->event_wrap;
+       for (i = first; i < cur; ++i) {
+               SET_AGE(&dev_priv->dma_pages[i].age, event, wrap);
+               dev_priv->dma_pages[i].used = 0;
+               dev_priv->dma_pages[i].flushed = 0;
+       }
+       /* age the current page only when it's full */
+       if (dev_priv->dma_pages[cur].used == SAVAGE_DMA_PAGE_SIZE) {
+               SET_AGE(&dev_priv->dma_pages[cur].age, event, wrap);
+               dev_priv->dma_pages[cur].used = 0;
+               dev_priv->dma_pages[cur].flushed = 0;
+               /* advance to next page */
+               cur++;
+               if (cur == dev_priv->nr_dma_pages)
+                       cur = 0;
+               dev_priv->first_dma_page = dev_priv->current_dma_page = cur;
+       } else {
+               dev_priv->first_dma_page = cur;
+               dev_priv->dma_pages[cur].flushed = dev_priv->dma_pages[i].used;
+       }
+       SET_AGE(&dev_priv->last_dma_age, event, wrap);
+
+       DRM_DEBUG("first=cur=%u, cur->used=%u, cur->flushed=%u\n", cur,
+                 dev_priv->dma_pages[cur].used,
+                 dev_priv->dma_pages[cur].flushed);
+}
+
+static void savage_fake_dma_flush(drm_savage_private_t * dev_priv)
+{
+       unsigned int i, j;
+       BCI_LOCALS;
+
+       if (dev_priv->first_dma_page == dev_priv->current_dma_page &&
+           dev_priv->dma_pages[dev_priv->current_dma_page].used == 0)
+               return;
+
+       DRM_DEBUG("first=%u, cur=%u, cur->used=%u\n",
+                 dev_priv->first_dma_page, dev_priv->current_dma_page,
+                 dev_priv->dma_pages[dev_priv->current_dma_page].used);
+
+       for (i = dev_priv->first_dma_page;
+            i <= dev_priv->current_dma_page && dev_priv->dma_pages[i].used;
+            ++i) {
+               uint32_t *dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle +
+                   i * SAVAGE_DMA_PAGE_SIZE;
+#if SAVAGE_DMA_DEBUG
+               /* Sanity check: all pages except the last one must be full. */
+               if (i < dev_priv->current_dma_page &&
+                   dev_priv->dma_pages[i].used != SAVAGE_DMA_PAGE_SIZE) {
+                       DRM_ERROR("partial DMA page %u: used=%u",
+                                 i, dev_priv->dma_pages[i].used);
+               }
+#endif
+               BEGIN_BCI(dev_priv->dma_pages[i].used);
+               for (j = 0; j < dev_priv->dma_pages[i].used; ++j) {
+                       BCI_WRITE(dma_ptr[j]);
+               }
+               dev_priv->dma_pages[i].used = 0;
+       }
+
+       /* reset to first page */
+       dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
+}
+
+int savage_driver_load(struct drm_device *dev, unsigned long chipset)
+{
+       drm_savage_private_t *dev_priv;
+
+       dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       memset(dev_priv, 0, sizeof(drm_savage_private_t));
+       dev->dev_private = (void *)dev_priv;
+
+       dev_priv->chipset = (enum savage_family)chipset;
+
+       return 0;
+}
+
+
+/*
+ * Initalize mappings. On Savage4 and SavageIX the alignment
+ * and size of the aperture is not suitable for automatic MTRR setup
+ * in drm_addmap. Therefore we add them manually before the maps are
+ * initialized, and tear them down on last close.
+ */
+int savage_driver_firstopen(struct drm_device *dev)
+{
+       drm_savage_private_t *dev_priv = dev->dev_private;
+       unsigned long mmio_base, fb_base, fb_size, aperture_base;
+       /* fb_rsrc and aper_rsrc aren't really used currently, but still exist
+        * in case we decide we need information on the BAR for BSD in the
+        * future.
+        */
+       unsigned int fb_rsrc, aper_rsrc;
+       int ret = 0;
+
+       dev_priv->mtrr[0].handle = -1;
+       dev_priv->mtrr[1].handle = -1;
+       dev_priv->mtrr[2].handle = -1;
+       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+               fb_rsrc = 0;
+               fb_base = drm_get_resource_start(dev, 0);
+               fb_size = SAVAGE_FB_SIZE_S3;
+               mmio_base = fb_base + SAVAGE_FB_SIZE_S3;
+               aper_rsrc = 0;
+               aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
+               /* this should always be true */
+               if (drm_get_resource_len(dev, 0) == 0x08000000) {
+                       /* Don't make MMIO write-cobining! We need 3
+                        * MTRRs. */
+                       dev_priv->mtrr[0].base = fb_base;
+                       dev_priv->mtrr[0].size = 0x01000000;
+                       dev_priv->mtrr[0].handle =
+                           drm_mtrr_add(dev_priv->mtrr[0].base,
+                                        dev_priv->mtrr[0].size, DRM_MTRR_WC);
+                       dev_priv->mtrr[1].base = fb_base + 0x02000000;
+                       dev_priv->mtrr[1].size = 0x02000000;
+                       dev_priv->mtrr[1].handle =
+                           drm_mtrr_add(dev_priv->mtrr[1].base,
+                                        dev_priv->mtrr[1].size, DRM_MTRR_WC);
+                       dev_priv->mtrr[2].base = fb_base + 0x04000000;
+                       dev_priv->mtrr[2].size = 0x04000000;
+                       dev_priv->mtrr[2].handle =
+                           drm_mtrr_add(dev_priv->mtrr[2].base,
+                                        dev_priv->mtrr[2].size, DRM_MTRR_WC);
+               } else {
+                       DRM_ERROR("strange pci_resource_len %08lx\n",
+                                 drm_get_resource_len(dev, 0));
+               }
+       } else if (dev_priv->chipset != S3_SUPERSAVAGE &&
+                  dev_priv->chipset != S3_SAVAGE2000) {
+               mmio_base = drm_get_resource_start(dev, 0);
+               fb_rsrc = 1;
+               fb_base = drm_get_resource_start(dev, 1);
+               fb_size = SAVAGE_FB_SIZE_S4;
+               aper_rsrc = 1;
+               aperture_base = fb_base + SAVAGE_APERTURE_OFFSET;
+               /* this should always be true */
+               if (drm_get_resource_len(dev, 1) == 0x08000000) {
+                       /* Can use one MTRR to cover both fb and
+                        * aperture. */
+                       dev_priv->mtrr[0].base = fb_base;
+                       dev_priv->mtrr[0].size = 0x08000000;
+                       dev_priv->mtrr[0].handle =
+                           drm_mtrr_add(dev_priv->mtrr[0].base,
+                                        dev_priv->mtrr[0].size, DRM_MTRR_WC);
+               } else {
+                       DRM_ERROR("strange pci_resource_len %08lx\n",
+                                 drm_get_resource_len(dev, 1));
+               }
+       } else {
+               mmio_base = drm_get_resource_start(dev, 0);
+               fb_rsrc = 1;
+               fb_base = drm_get_resource_start(dev, 1);
+               fb_size = drm_get_resource_len(dev, 1);
+               aper_rsrc = 2;
+               aperture_base = drm_get_resource_start(dev, 2);
+               /* Automatic MTRR setup will do the right thing. */
+       }
+
+       ret = drm_addmap(dev, mmio_base, SAVAGE_MMIO_SIZE, _DRM_REGISTERS,
+                        _DRM_READ_ONLY, &dev_priv->mmio);
+       if (ret)
+               return ret;
+
+       ret = drm_addmap(dev, fb_base, fb_size, _DRM_FRAME_BUFFER,
+                        _DRM_WRITE_COMBINING, &dev_priv->fb);
+       if (ret)
+               return ret;
+
+       ret = drm_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE,
+                        _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING,
+                        &dev_priv->aperture);
+       if (ret)
+               return ret;
+
+       return ret;
+}
+
+/*
+ * Delete MTRRs and free device-private data.
+ */
+void savage_driver_lastclose(struct drm_device *dev)
+{
+       drm_savage_private_t *dev_priv = dev->dev_private;
+       int i;
+
+       for (i = 0; i < 3; ++i)
+               if (dev_priv->mtrr[i].handle >= 0)
+                       drm_mtrr_del(dev_priv->mtrr[i].handle,
+                                dev_priv->mtrr[i].base,
+                                dev_priv->mtrr[i].size, DRM_MTRR_WC);
+}
+
+int savage_driver_unload(struct drm_device *dev)
+{
+       drm_savage_private_t *dev_priv = dev->dev_private;
+
+       drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
+
+       return 0;
+}
+
+static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init)
+{
+       drm_savage_private_t *dev_priv = dev->dev_private;
+
+       if (init->fb_bpp != 16 && init->fb_bpp != 32) {
+               DRM_ERROR("invalid frame buffer bpp %d!\n", init->fb_bpp);
+               return -EINVAL;
+       }
+       if (init->depth_bpp != 16 && init->depth_bpp != 32) {
+               DRM_ERROR("invalid depth buffer bpp %d!\n", init->fb_bpp);
+               return -EINVAL;
+       }
+       if (init->dma_type != SAVAGE_DMA_AGP &&
+           init->dma_type != SAVAGE_DMA_PCI) {
+               DRM_ERROR("invalid dma memory type %d!\n", init->dma_type);
+               return -EINVAL;
+       }
+
+       dev_priv->cob_size = init->cob_size;
+       dev_priv->bci_threshold_lo = init->bci_threshold_lo;
+       dev_priv->bci_threshold_hi = init->bci_threshold_hi;
+       dev_priv->dma_type = init->dma_type;
+
+       dev_priv->fb_bpp = init->fb_bpp;
+       dev_priv->front_offset = init->front_offset;
+       dev_priv->front_pitch = init->front_pitch;
+       dev_priv->back_offset = init->back_offset;
+       dev_priv->back_pitch = init->back_pitch;
+       dev_priv->depth_bpp = init->depth_bpp;
+       dev_priv->depth_offset = init->depth_offset;
+       dev_priv->depth_pitch = init->depth_pitch;
+
+       dev_priv->texture_offset = init->texture_offset;
+       dev_priv->texture_size = init->texture_size;
+
+       dev_priv->sarea = drm_getsarea(dev);
+       if (!dev_priv->sarea) {
+               DRM_ERROR("could not find sarea!\n");
+               savage_do_cleanup_bci(dev);
+               return -EINVAL;
+       }
+       if (init->status_offset != 0) {
+               dev_priv->status = drm_core_findmap(dev, init->status_offset);
+               if (!dev_priv->status) {
+                       DRM_ERROR("could not find shadow status region!\n");
+                       savage_do_cleanup_bci(dev);
+                       return -EINVAL;
+               }
+       } else {
+               dev_priv->status = NULL;
+       }
+       if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) {
+               dev->agp_buffer_token = init->buffers_offset;
+               dev->agp_buffer_map = drm_core_findmap(dev,
+                                                      init->buffers_offset);
+               if (!dev->agp_buffer_map) {
+                       DRM_ERROR("could not find DMA buffer region!\n");
+                       savage_do_cleanup_bci(dev);
+                       return -EINVAL;
+               }
+               drm_core_ioremap(dev->agp_buffer_map, dev);
+               if (!dev->agp_buffer_map) {
+                       DRM_ERROR("failed to ioremap DMA buffer region!\n");
+                       savage_do_cleanup_bci(dev);
+                       return -ENOMEM;
+               }
+       }
+       if (init->agp_textures_offset) {
+               dev_priv->agp_textures =
+                   drm_core_findmap(dev, init->agp_textures_offset);
+               if (!dev_priv->agp_textures) {
+                       DRM_ERROR("could not find agp texture region!\n");
+                       savage_do_cleanup_bci(dev);
+                       return -EINVAL;
+               }
+       } else {
+               dev_priv->agp_textures = NULL;
+       }
+
+       if (init->cmd_dma_offset) {
+               if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+                       DRM_ERROR("command DMA not supported on "
+                                 "Savage3D/MX/IX.\n");
+                       savage_do_cleanup_bci(dev);
+                       return -EINVAL;
+               }
+               if (dev->dma && dev->dma->buflist) {
+                       DRM_ERROR("command and vertex DMA not supported "
+                                 "at the same time.\n");
+                       savage_do_cleanup_bci(dev);
+                       return -EINVAL;
+               }
+               dev_priv->cmd_dma = drm_core_findmap(dev, init->cmd_dma_offset);
+               if (!dev_priv->cmd_dma) {
+                       DRM_ERROR("could not find command DMA region!\n");
+                       savage_do_cleanup_bci(dev);
+                       return -EINVAL;
+               }
+               if (dev_priv->dma_type == SAVAGE_DMA_AGP) {
+                       if (dev_priv->cmd_dma->type != _DRM_AGP) {
+                               DRM_ERROR("AGP command DMA region is not a "
+                                         "_DRM_AGP map!\n");
+                               savage_do_cleanup_bci(dev);
+                               return -EINVAL;
+                       }
+                       drm_core_ioremap(dev_priv->cmd_dma, dev);
+                       if (!dev_priv->cmd_dma->handle) {
+                               DRM_ERROR("failed to ioremap command "
+                                         "DMA region!\n");
+                               savage_do_cleanup_bci(dev);
+                               return -ENOMEM;
+                       }
+               } else if (dev_priv->cmd_dma->type != _DRM_CONSISTENT) {
+                       DRM_ERROR("PCI command DMA region is not a "
+                                 "_DRM_CONSISTENT map!\n");
+                       savage_do_cleanup_bci(dev);
+                       return -EINVAL;
+               }
+       } else {
+               dev_priv->cmd_dma = NULL;
+       }
+
+       dev_priv->dma_flush = savage_dma_flush;
+       if (!dev_priv->cmd_dma) {
+               DRM_DEBUG("falling back to faked command DMA.\n");
+               dev_priv->fake_dma.offset = 0;
+               dev_priv->fake_dma.size = SAVAGE_FAKE_DMA_SIZE;
+               dev_priv->fake_dma.type = _DRM_SHM;
+               dev_priv->fake_dma.handle = drm_alloc(SAVAGE_FAKE_DMA_SIZE,
+                                                     DRM_MEM_DRIVER);
+               if (!dev_priv->fake_dma.handle) {
+                       DRM_ERROR("could not allocate faked DMA buffer!\n");
+                       savage_do_cleanup_bci(dev);
+                       return -ENOMEM;
+               }
+               dev_priv->cmd_dma = &dev_priv->fake_dma;
+               dev_priv->dma_flush = savage_fake_dma_flush;
+       }
+
+       dev_priv->sarea_priv =
+           (drm_savage_sarea_t *) ((uint8_t *) dev_priv->sarea->handle +
+                                   init->sarea_priv_offset);
+
+       /* setup bitmap descriptors */
+       {
+               unsigned int color_tile_format;
+               unsigned int depth_tile_format;
+               unsigned int front_stride, back_stride, depth_stride;
+               if (dev_priv->chipset <= S3_SAVAGE4) {
+                       color_tile_format = dev_priv->fb_bpp == 16 ?
+                           SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
+                       depth_tile_format = dev_priv->depth_bpp == 16 ?
+                           SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP;
+               } else {
+                       color_tile_format = SAVAGE_BD_TILE_DEST;
+                       depth_tile_format = SAVAGE_BD_TILE_DEST;
+               }
+               front_stride = dev_priv->front_pitch / (dev_priv->fb_bpp / 8);
+               back_stride = dev_priv->back_pitch / (dev_priv->fb_bpp / 8);
+               depth_stride =
+                   dev_priv->depth_pitch / (dev_priv->depth_bpp / 8);
+
+               dev_priv->front_bd = front_stride | SAVAGE_BD_BW_DISABLE |
+                   (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
+                   (color_tile_format << SAVAGE_BD_TILE_SHIFT);
+
+               dev_priv->back_bd = back_stride | SAVAGE_BD_BW_DISABLE |
+                   (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) |
+                   (color_tile_format << SAVAGE_BD_TILE_SHIFT);
+
+               dev_priv->depth_bd = depth_stride | SAVAGE_BD_BW_DISABLE |
+                   (dev_priv->depth_bpp << SAVAGE_BD_BPP_SHIFT) |
+                   (depth_tile_format << SAVAGE_BD_TILE_SHIFT);
+       }
+
+       /* setup status and bci ptr */
+       dev_priv->event_counter = 0;
+       dev_priv->event_wrap = 0;
+       dev_priv->bci_ptr = (volatile uint32_t *)
+           ((uint8_t *) dev_priv->mmio->handle + SAVAGE_BCI_OFFSET);
+       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+               dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S3D;
+       } else {
+               dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S4;
+       }
+       if (dev_priv->status != NULL) {
+               dev_priv->status_ptr =
+                   (volatile uint32_t *)dev_priv->status->handle;
+               dev_priv->wait_fifo = savage_bci_wait_fifo_shadow;
+               dev_priv->wait_evnt = savage_bci_wait_event_shadow;
+               dev_priv->status_ptr[1023] = dev_priv->event_counter;
+       } else {
+               dev_priv->status_ptr = NULL;
+               if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+                       dev_priv->wait_fifo = savage_bci_wait_fifo_s3d;
+               } else {
+                       dev_priv->wait_fifo = savage_bci_wait_fifo_s4;
+               }
+               dev_priv->wait_evnt = savage_bci_wait_event_reg;
+       }
+
+       /* cliprect functions */
+       if (S3_SAVAGE3D_SERIES(dev_priv->chipset))
+               dev_priv->emit_clip_rect = savage_emit_clip_rect_s3d;
+       else
+               dev_priv->emit_clip_rect = savage_emit_clip_rect_s4;
+
+       if (savage_freelist_init(dev) < 0) {
+               DRM_ERROR("could not initialize freelist\n");
+               savage_do_cleanup_bci(dev);
+               return -ENOMEM;
+       }
+
+       if (savage_dma_init(dev_priv) < 0) {
+               DRM_ERROR("could not initialize command DMA\n");
+               savage_do_cleanup_bci(dev);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int savage_do_cleanup_bci(struct drm_device * dev)
+{
+       drm_savage_private_t *dev_priv = dev->dev_private;
+
+       if (dev_priv->cmd_dma == &dev_priv->fake_dma) {
+               if (dev_priv->fake_dma.handle)
+                       drm_free(dev_priv->fake_dma.handle,
+                                SAVAGE_FAKE_DMA_SIZE, DRM_MEM_DRIVER);
+       } else if (dev_priv->cmd_dma && dev_priv->cmd_dma->handle &&
+                  dev_priv->cmd_dma->type == _DRM_AGP &&
+                  dev_priv->dma_type == SAVAGE_DMA_AGP)
+               drm_core_ioremapfree(dev_priv->cmd_dma, dev);
+
+       if (dev_priv->dma_type == SAVAGE_DMA_AGP &&
+           dev->agp_buffer_map && dev->agp_buffer_map->handle) {
+               drm_core_ioremapfree(dev->agp_buffer_map, dev);
+               /* make sure the next instance (which may be running
+                * in PCI mode) doesn't try to use an old
+                * agp_buffer_map. */
+               dev->agp_buffer_map = NULL;
+       }
+
+       if (dev_priv->dma_pages)
+               drm_free(dev_priv->dma_pages,
+                        sizeof(drm_savage_dma_page_t) * dev_priv->nr_dma_pages,
+                        DRM_MEM_DRIVER);
+
+       return 0;
+}
+
+static int savage_bci_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_savage_init_t *init = data;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       switch (init->func) {
+       case SAVAGE_INIT_BCI:
+               return savage_do_init_bci(dev, init);
+       case SAVAGE_CLEANUP_BCI:
+               return savage_do_cleanup_bci(dev);
+       }
+
+       return -EINVAL;
+}
+
+static int savage_bci_event_emit(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_savage_private_t *dev_priv = dev->dev_private;
+       drm_savage_event_emit_t *event = data;
+
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       event->count = savage_bci_emit_event(dev_priv, event->flags);
+       event->count |= dev_priv->event_wrap << 16;
+
+       return 0;
+}
+
+static int savage_bci_event_wait(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_savage_private_t *dev_priv = dev->dev_private;
+       drm_savage_event_wait_t *event = data;
+       unsigned int event_e, hw_e;
+       unsigned int event_w, hw_w;
+
+       DRM_DEBUG("\n");
+
+       UPDATE_EVENT_COUNTER();
+       if (dev_priv->status_ptr)
+               hw_e = dev_priv->status_ptr[1] & 0xffff;
+       else
+               hw_e = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff;
+       hw_w = dev_priv->event_wrap;
+       if (hw_e > dev_priv->event_counter)
+               hw_w--;         /* hardware hasn't passed the last wrap yet */
+
+       event_e = event->count & 0xffff;
+       event_w = event->count >> 16;
+
+       /* Don't need to wait if
+        * - event counter wrapped since the event was emitted or
+        * - the hardware has advanced up to or over the event to wait for.
+        */
+       if (event_w < hw_w || (event_w == hw_w && event_e <= hw_e))
+               return 0;
+       else
+               return dev_priv->wait_evnt(dev_priv, event_e);
+}
+
+/*
+ * DMA buffer management
+ */
+
+static int savage_bci_get_buffers(struct drm_device *dev,
+                                 struct drm_file *file_priv,
+                                 struct drm_dma *d)
+{
+       struct drm_buf *buf;
+       int i;
+
+       for (i = d->granted_count; i < d->request_count; i++) {
+               buf = savage_freelist_get(dev);
+               if (!buf)
+                       return -EAGAIN;
+
+               buf->file_priv = file_priv;
+
+               if (DRM_COPY_TO_USER(&d->request_indices[i],
+                                    &buf->idx, sizeof(buf->idx)))
+                       return -EFAULT;
+               if (DRM_COPY_TO_USER(&d->request_sizes[i],
+                                    &buf->total, sizeof(buf->total)))
+                       return -EFAULT;
+
+               d->granted_count++;
+       }
+       return 0;
+}
+
+int savage_bci_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_dma *d = data;
+       int ret = 0;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       /* Please don't send us buffers.
+        */
+       if (d->send_count != 0) {
+               DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
+                         DRM_CURRENTPID, d->send_count);
+               return -EINVAL;
+       }
+
+       /* We'll send you buffers.
+        */
+       if (d->request_count < 0 || d->request_count > dma->buf_count) {
+               DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
+                         DRM_CURRENTPID, d->request_count, dma->buf_count);
+               return -EINVAL;
+       }
+
+       d->granted_count = 0;
+
+       if (d->request_count) {
+               ret = savage_bci_get_buffers(dev, file_priv, d);
+       }
+
+       return ret;
+}
+
+void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
+{
+       struct drm_device_dma *dma = dev->dma;
+       drm_savage_private_t *dev_priv = dev->dev_private;
+       int i;
+
+       if (!dma)
+               return;
+       if (!dev_priv)
+               return;
+       if (!dma->buflist)
+               return;
+
+       /*i830_flush_queue(dev); */
+
+       for (i = 0; i < dma->buf_count; i++) {
+               struct drm_buf *buf = dma->buflist[i];
+               drm_savage_buf_priv_t *buf_priv = buf->dev_private;
+
+               if (buf->file_priv == file_priv && buf_priv &&
+                   buf_priv->next == NULL && buf_priv->prev == NULL) {
+                       uint16_t event;
+                       DRM_DEBUG("reclaimed from client\n");
+                       event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D);
+                       SET_AGE(&buf_priv->age, event, dev_priv->event_wrap);
+                       savage_freelist_put(dev, buf);
+               }
+       }
+
+       drm_core_reclaim_buffers(dev, file_priv);
+}
+
+struct drm_ioctl_desc savage_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_INIT, savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_CMDBUF, savage_bci_cmdbuf, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_EVENT_EMIT, savage_bci_event_emit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SAVAGE_BCI_EVENT_WAIT, savage_bci_event_wait, DRM_AUTH),
+};
+
+int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls);
diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c
new file mode 100644 (file)
index 0000000..eee52aa
--- /dev/null
@@ -0,0 +1,88 @@
+/* savage_drv.c -- Savage driver for Linux
+ *
+ * Copyright 2004  Felix Kuehling
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "savage_drm.h"
+#include "savage_drv.h"
+
+#include "drm_pciids.h"
+
+static struct pci_device_id pciidlist[] = {
+       savage_PCI_IDS
+};
+
+static struct drm_driver driver = {
+       .driver_features =
+           DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_PCI_DMA,
+       .dev_priv_size = sizeof(drm_savage_buf_priv_t),
+       .load = savage_driver_load,
+       .firstopen = savage_driver_firstopen,
+       .lastclose = savage_driver_lastclose,
+       .unload = savage_driver_unload,
+       .reclaim_buffers = savage_reclaim_buffers,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .ioctls = savage_ioctls,
+       .dma_ioctl = savage_bci_buffers,
+       .fops = {
+                .owner = THIS_MODULE,
+                .open = drm_open,
+                .release = drm_release,
+                .ioctl = drm_ioctl,
+                .mmap = drm_mmap,
+                .poll = drm_poll,
+                .fasync = drm_fasync,
+       },
+
+       .pci_driver = {
+                .name = DRIVER_NAME,
+                .id_table = pciidlist,
+       },
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int __init savage_init(void)
+{
+       driver.num_ioctls = savage_max_ioctl;
+       return drm_init(&driver);
+}
+
+static void __exit savage_exit(void)
+{
+       drm_exit(&driver);
+}
+
+module_init(savage_init);
+module_exit(savage_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/savage/savage_drv.h b/drivers/gpu/drm/savage/savage_drv.h
new file mode 100644 (file)
index 0000000..df2aac6
--- /dev/null
@@ -0,0 +1,575 @@
+/* savage_drv.h -- Private header for the savage driver */
+/*
+ * Copyright 2004  Felix Kuehling
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __SAVAGE_DRV_H__
+#define __SAVAGE_DRV_H__
+
+#define DRIVER_AUTHOR  "Felix Kuehling"
+
+#define DRIVER_NAME    "savage"
+#define DRIVER_DESC    "Savage3D/MX/IX, Savage4, SuperSavage, Twister, ProSavage[DDR]"
+#define DRIVER_DATE    "20050313"
+
+#define DRIVER_MAJOR           2
+#define DRIVER_MINOR           4
+#define DRIVER_PATCHLEVEL      1
+/* Interface history:
+ *
+ * 1.x   The DRM driver from the VIA/S3 code drop, basically a dummy
+ * 2.0   The first real DRM
+ * 2.1   Scissors registers managed by the DRM, 3D operations clipped by
+ *       cliprects of the cmdbuf ioctl
+ * 2.2   Implemented SAVAGE_CMD_DMA_IDX and SAVAGE_CMD_VB_IDX
+ * 2.3   Event counters used by BCI_EVENT_EMIT/WAIT ioctls are now 32 bits
+ *       wide and thus very long lived (unlikely to ever wrap). The size
+ *       in the struct was 32 bits before, but only 16 bits were used
+ * 2.4   Implemented command DMA. Now drm_savage_init_t.cmd_dma_offset is
+ *       actually used
+ */
+
+typedef struct drm_savage_age {
+       uint16_t event;
+       unsigned int wrap;
+} drm_savage_age_t;
+
+typedef struct drm_savage_buf_priv {
+       struct drm_savage_buf_priv *next;
+       struct drm_savage_buf_priv *prev;
+       drm_savage_age_t age;
+       struct drm_buf *buf;
+} drm_savage_buf_priv_t;
+
+typedef struct drm_savage_dma_page {
+       drm_savage_age_t age;
+       unsigned int used, flushed;
+} drm_savage_dma_page_t;
+#define SAVAGE_DMA_PAGE_SIZE 1024      /* in dwords */
+/* Fake DMA buffer size in bytes. 4 pages. Allows a maximum command
+ * size of 16kbytes or 4k entries. Minimum requirement would be
+ * 10kbytes for 255 40-byte vertices in one drawing command. */
+#define SAVAGE_FAKE_DMA_SIZE (SAVAGE_DMA_PAGE_SIZE*4*4)
+
+/* interesting bits of hardware state that are saved in dev_priv */
+typedef union {
+       struct drm_savage_common_state {
+               uint32_t vbaddr;
+       } common;
+       struct {
+               unsigned char pad[sizeof(struct drm_savage_common_state)];
+               uint32_t texctrl, texaddr;
+               uint32_t scstart, new_scstart;
+               uint32_t scend, new_scend;
+       } s3d;
+       struct {
+               unsigned char pad[sizeof(struct drm_savage_common_state)];
+               uint32_t texdescr, texaddr0, texaddr1;
+               uint32_t drawctrl0, new_drawctrl0;
+               uint32_t drawctrl1, new_drawctrl1;
+       } s4;
+} drm_savage_state_t;
+
+/* these chip tags should match the ones in the 2D driver in savage_regs.h. */
+enum savage_family {
+       S3_UNKNOWN = 0,
+       S3_SAVAGE3D,
+       S3_SAVAGE_MX,
+       S3_SAVAGE4,
+       S3_PROSAVAGE,
+       S3_TWISTER,
+       S3_PROSAVAGEDDR,
+       S3_SUPERSAVAGE,
+       S3_SAVAGE2000,
+       S3_LAST
+};
+
+extern struct drm_ioctl_desc savage_ioctls[];
+extern int savage_max_ioctl;
+
+#define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
+
+#define S3_SAVAGE4_SERIES(chip)  ((chip==S3_SAVAGE4)            \
+                                  || (chip==S3_PROSAVAGE)       \
+                                  || (chip==S3_TWISTER)         \
+                                  || (chip==S3_PROSAVAGEDDR))
+
+#define        S3_SAVAGE_MOBILE_SERIES(chip)   ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
+
+#define S3_SAVAGE_SERIES(chip)    ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
+
+#define S3_MOBILE_TWISTER_SERIES(chip)   ((chip==S3_TWISTER)    \
+                                          ||(chip==S3_PROSAVAGEDDR))
+
+/* flags */
+#define SAVAGE_IS_AGP 1
+
+typedef struct drm_savage_private {
+       drm_savage_sarea_t *sarea_priv;
+
+       drm_savage_buf_priv_t head, tail;
+
+       /* who am I? */
+       enum savage_family chipset;
+
+       unsigned int cob_size;
+       unsigned int bci_threshold_lo, bci_threshold_hi;
+       unsigned int dma_type;
+
+       /* frame buffer layout */
+       unsigned int fb_bpp;
+       unsigned int front_offset, front_pitch;
+       unsigned int back_offset, back_pitch;
+       unsigned int depth_bpp;
+       unsigned int depth_offset, depth_pitch;
+
+       /* bitmap descriptors for swap and clear */
+       unsigned int front_bd, back_bd, depth_bd;
+
+       /* local textures */
+       unsigned int texture_offset;
+       unsigned int texture_size;
+
+       /* memory regions in physical memory */
+       drm_local_map_t *sarea;
+       drm_local_map_t *mmio;
+       drm_local_map_t *fb;
+       drm_local_map_t *aperture;
+       drm_local_map_t *status;
+       drm_local_map_t *agp_textures;
+       drm_local_map_t *cmd_dma;
+       drm_local_map_t fake_dma;
+
+       struct {
+               int handle;
+               unsigned long base, size;
+       } mtrr[3];
+
+       /* BCI and status-related stuff */
+       volatile uint32_t *status_ptr, *bci_ptr;
+       uint32_t status_used_mask;
+       uint16_t event_counter;
+       unsigned int event_wrap;
+
+       /* Savage4 command DMA */
+       drm_savage_dma_page_t *dma_pages;
+       unsigned int nr_dma_pages, first_dma_page, current_dma_page;
+       drm_savage_age_t last_dma_age;
+
+       /* saved hw state for global/local check on S3D */
+       uint32_t hw_draw_ctrl, hw_zbuf_ctrl;
+       /* and for scissors (global, so don't emit if not changed) */
+       uint32_t hw_scissors_start, hw_scissors_end;
+
+       drm_savage_state_t state;
+
+       /* after emitting a wait cmd Savage3D needs 63 nops before next DMA */
+       unsigned int waiting;
+
+       /* config/hardware-dependent function pointers */
+       int (*wait_fifo) (struct drm_savage_private * dev_priv, unsigned int n);
+       int (*wait_evnt) (struct drm_savage_private * dev_priv, uint16_t e);
+       /* Err, there is a macro wait_event in include/linux/wait.h.
+        * Avoid unwanted macro expansion. */
+       void (*emit_clip_rect) (struct drm_savage_private * dev_priv,
+                               const struct drm_clip_rect * pbox);
+       void (*dma_flush) (struct drm_savage_private * dev_priv);
+} drm_savage_private_t;
+
+/* ioctls */
+extern int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int savage_bci_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv);
+
+/* BCI functions */
+extern uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv,
+                                     unsigned int flags);
+extern void savage_freelist_put(struct drm_device * dev, struct drm_buf * buf);
+extern void savage_dma_reset(drm_savage_private_t * dev_priv);
+extern void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page);
+extern uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv,
+                                 unsigned int n);
+extern int savage_driver_load(struct drm_device *dev, unsigned long chipset);
+extern int savage_driver_firstopen(struct drm_device *dev);
+extern void savage_driver_lastclose(struct drm_device *dev);
+extern int savage_driver_unload(struct drm_device *dev);
+extern void savage_reclaim_buffers(struct drm_device *dev,
+                                  struct drm_file *file_priv);
+
+/* state functions */
+extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
+                                     const struct drm_clip_rect * pbox);
+extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
+                                    const struct drm_clip_rect * pbox);
+
+#define SAVAGE_FB_SIZE_S3      0x01000000      /*  16MB */
+#define SAVAGE_FB_SIZE_S4      0x02000000      /*  32MB */
+#define SAVAGE_MMIO_SIZE        0x00080000     /* 512kB */
+#define SAVAGE_APERTURE_OFFSET  0x02000000     /*  32MB */
+#define SAVAGE_APERTURE_SIZE    0x05000000     /* 5 tiled surfaces, 16MB each */
+
+#define SAVAGE_BCI_OFFSET       0x00010000     /* offset of the BCI region
+                                                * inside the MMIO region */
+#define SAVAGE_BCI_FIFO_SIZE   32      /* number of entries in on-chip
+                                        * BCI FIFO */
+
+/*
+ * MMIO registers
+ */
+#define SAVAGE_STATUS_WORD0            0x48C00
+#define SAVAGE_STATUS_WORD1            0x48C04
+#define SAVAGE_ALT_STATUS_WORD0        0x48C60
+
+#define SAVAGE_FIFO_USED_MASK_S3D      0x0001ffff
+#define SAVAGE_FIFO_USED_MASK_S4       0x001fffff
+
+/* Copied from savage_bci.h in the 2D driver with some renaming. */
+
+/* Bitmap descriptors */
+#define SAVAGE_BD_STRIDE_SHIFT 0
+#define SAVAGE_BD_BPP_SHIFT   16
+#define SAVAGE_BD_TILE_SHIFT  24
+#define SAVAGE_BD_BW_DISABLE  (1<<28)
+/* common: */
+#define        SAVAGE_BD_TILE_LINEAR           0
+/* savage4, MX, IX, 3D */
+#define        SAVAGE_BD_TILE_16BPP            2
+#define        SAVAGE_BD_TILE_32BPP            3
+/* twister, prosavage, DDR, supersavage, 2000 */
+#define        SAVAGE_BD_TILE_DEST             1
+#define        SAVAGE_BD_TILE_TEXTURE          2
+/* GBD - BCI enable */
+/* savage4, MX, IX, 3D */
+#define SAVAGE_GBD_BCI_ENABLE                    8
+/* twister, prosavage, DDR, supersavage, 2000 */
+#define SAVAGE_GBD_BCI_ENABLE_TWISTER            0
+
+#define SAVAGE_GBD_BIG_ENDIAN                    4
+#define SAVAGE_GBD_LITTLE_ENDIAN                 0
+#define SAVAGE_GBD_64                            1
+
+/*  Global Bitmap Descriptor */
+#define SAVAGE_BCI_GLB_BD_LOW             0x8168
+#define SAVAGE_BCI_GLB_BD_HIGH            0x816C
+
+/*
+ * BCI registers
+ */
+/* Savage4/Twister/ProSavage 3D registers */
+#define SAVAGE_DRAWLOCALCTRL_S4                0x1e
+#define SAVAGE_TEXPALADDR_S4           0x1f
+#define SAVAGE_TEXCTRL0_S4             0x20
+#define SAVAGE_TEXCTRL1_S4             0x21
+#define SAVAGE_TEXADDR0_S4             0x22
+#define SAVAGE_TEXADDR1_S4             0x23
+#define SAVAGE_TEXBLEND0_S4            0x24
+#define SAVAGE_TEXBLEND1_S4            0x25
+#define SAVAGE_TEXXPRCLR_S4            0x26    /* never used */
+#define SAVAGE_TEXDESCR_S4             0x27
+#define SAVAGE_FOGTABLE_S4             0x28
+#define SAVAGE_FOGCTRL_S4              0x30
+#define SAVAGE_STENCILCTRL_S4          0x31
+#define SAVAGE_ZBUFCTRL_S4             0x32
+#define SAVAGE_ZBUFOFF_S4              0x33
+#define SAVAGE_DESTCTRL_S4             0x34
+#define SAVAGE_DRAWCTRL0_S4            0x35
+#define SAVAGE_DRAWCTRL1_S4            0x36
+#define SAVAGE_ZWATERMARK_S4           0x37
+#define SAVAGE_DESTTEXRWWATERMARK_S4   0x38
+#define SAVAGE_TEXBLENDCOLOR_S4                0x39
+/* Savage3D/MX/IX 3D registers */
+#define SAVAGE_TEXPALADDR_S3D          0x18
+#define SAVAGE_TEXXPRCLR_S3D           0x19    /* never used */
+#define SAVAGE_TEXADDR_S3D             0x1A
+#define SAVAGE_TEXDESCR_S3D            0x1B
+#define SAVAGE_TEXCTRL_S3D             0x1C
+#define SAVAGE_FOGTABLE_S3D            0x20
+#define SAVAGE_FOGCTRL_S3D             0x30
+#define SAVAGE_DRAWCTRL_S3D            0x31
+#define SAVAGE_ZBUFCTRL_S3D            0x32
+#define SAVAGE_ZBUFOFF_S3D             0x33
+#define SAVAGE_DESTCTRL_S3D            0x34
+#define SAVAGE_SCSTART_S3D             0x35
+#define SAVAGE_SCEND_S3D               0x36
+#define SAVAGE_ZWATERMARK_S3D          0x37
+#define SAVAGE_DESTTEXRWWATERMARK_S3D  0x38
+/* common stuff */
+#define SAVAGE_VERTBUFADDR             0x3e
+#define SAVAGE_BITPLANEWTMASK          0xd7
+#define SAVAGE_DMABUFADDR              0x51
+
+/* texture enable bits (needed for tex addr checking) */
+#define SAVAGE_TEXCTRL_TEXEN_MASK      0x00010000      /* S3D */
+#define SAVAGE_TEXDESCR_TEX0EN_MASK    0x02000000      /* S4 */
+#define SAVAGE_TEXDESCR_TEX1EN_MASK    0x04000000      /* S4 */
+
+/* Global fields in Savage4/Twister/ProSavage 3D registers:
+ *
+ * All texture registers and DrawLocalCtrl are local. All other
+ * registers are global. */
+
+/* Global fields in Savage3D/MX/IX 3D registers:
+ *
+ * All texture registers are local. DrawCtrl and ZBufCtrl are
+ * partially local. All other registers are global.
+ *
+ * DrawCtrl global fields: cullMode, alphaTestCmpFunc, alphaTestEn, alphaRefVal
+ * ZBufCtrl global fields: zCmpFunc, zBufEn
+ */
+#define SAVAGE_DRAWCTRL_S3D_GLOBAL     0x03f3c00c
+#define SAVAGE_ZBUFCTRL_S3D_GLOBAL     0x00000027
+
+/* Masks for scissor bits (drawCtrl[01] on s4, scissorStart/End on s3d)
+ */
+#define SAVAGE_SCISSOR_MASK_S4         0x00fff7ff
+#define SAVAGE_SCISSOR_MASK_S3D                0x07ff07ff
+
+/*
+ * BCI commands
+ */
+#define BCI_CMD_NOP                  0x40000000
+#define BCI_CMD_RECT                 0x48000000
+#define BCI_CMD_RECT_XP              0x01000000
+#define BCI_CMD_RECT_YP              0x02000000
+#define BCI_CMD_SCANLINE             0x50000000
+#define BCI_CMD_LINE                 0x5C000000
+#define BCI_CMD_LINE_LAST_PIXEL      0x58000000
+#define BCI_CMD_BYTE_TEXT            0x63000000
+#define BCI_CMD_NT_BYTE_TEXT         0x67000000
+#define BCI_CMD_BIT_TEXT             0x6C000000
+#define BCI_CMD_GET_ROP(cmd)         (((cmd) >> 16) & 0xFF)
+#define BCI_CMD_SET_ROP(cmd, rop)    ((cmd) |= ((rop & 0xFF) << 16))
+#define BCI_CMD_SEND_COLOR           0x00008000
+
+#define BCI_CMD_CLIP_NONE            0x00000000
+#define BCI_CMD_CLIP_CURRENT         0x00002000
+#define BCI_CMD_CLIP_LR              0x00004000
+#define BCI_CMD_CLIP_NEW             0x00006000
+
+#define BCI_CMD_DEST_GBD             0x00000000
+#define BCI_CMD_DEST_PBD             0x00000800
+#define BCI_CMD_DEST_PBD_NEW         0x00000C00
+#define BCI_CMD_DEST_SBD             0x00001000
+#define BCI_CMD_DEST_SBD_NEW         0x00001400
+
+#define BCI_CMD_SRC_TRANSPARENT      0x00000200
+#define BCI_CMD_SRC_SOLID            0x00000000
+#define BCI_CMD_SRC_GBD              0x00000020
+#define BCI_CMD_SRC_COLOR            0x00000040
+#define BCI_CMD_SRC_MONO             0x00000060
+#define BCI_CMD_SRC_PBD_COLOR        0x00000080
+#define BCI_CMD_SRC_PBD_MONO         0x000000A0
+#define BCI_CMD_SRC_PBD_COLOR_NEW    0x000000C0
+#define BCI_CMD_SRC_PBD_MONO_NEW     0x000000E0
+#define BCI_CMD_SRC_SBD_COLOR        0x00000100
+#define BCI_CMD_SRC_SBD_MONO         0x00000120
+#define BCI_CMD_SRC_SBD_COLOR_NEW    0x00000140
+#define BCI_CMD_SRC_SBD_MONO_NEW     0x00000160
+
+#define BCI_CMD_PAT_TRANSPARENT      0x00000010
+#define BCI_CMD_PAT_NONE             0x00000000
+#define BCI_CMD_PAT_COLOR            0x00000002
+#define BCI_CMD_PAT_MONO             0x00000003
+#define BCI_CMD_PAT_PBD_COLOR        0x00000004
+#define BCI_CMD_PAT_PBD_MONO         0x00000005
+#define BCI_CMD_PAT_PBD_COLOR_NEW    0x00000006
+#define BCI_CMD_PAT_PBD_MONO_NEW     0x00000007
+#define BCI_CMD_PAT_SBD_COLOR        0x00000008
+#define BCI_CMD_PAT_SBD_MONO         0x00000009
+#define BCI_CMD_PAT_SBD_COLOR_NEW    0x0000000A
+#define BCI_CMD_PAT_SBD_MONO_NEW     0x0000000B
+
+#define BCI_BD_BW_DISABLE            0x10000000
+#define BCI_BD_TILE_MASK             0x03000000
+#define BCI_BD_TILE_NONE             0x00000000
+#define BCI_BD_TILE_16               0x02000000
+#define BCI_BD_TILE_32               0x03000000
+#define BCI_BD_GET_BPP(bd)           (((bd) >> 16) & 0xFF)
+#define BCI_BD_SET_BPP(bd, bpp)      ((bd) |= (((bpp) & 0xFF) << 16))
+#define BCI_BD_GET_STRIDE(bd)        ((bd) & 0xFFFF)
+#define BCI_BD_SET_STRIDE(bd, st)    ((bd) |= ((st) & 0xFFFF))
+
+#define BCI_CMD_SET_REGISTER            0x96000000
+
+#define BCI_CMD_WAIT                    0xC0000000
+#define BCI_CMD_WAIT_3D                 0x00010000
+#define BCI_CMD_WAIT_2D                 0x00020000
+
+#define BCI_CMD_UPDATE_EVENT_TAG        0x98000000
+
+#define BCI_CMD_DRAW_PRIM               0x80000000
+#define BCI_CMD_DRAW_INDEXED_PRIM       0x88000000
+#define BCI_CMD_DRAW_CONT               0x01000000
+#define BCI_CMD_DRAW_TRILIST            0x00000000
+#define BCI_CMD_DRAW_TRISTRIP           0x02000000
+#define BCI_CMD_DRAW_TRIFAN             0x04000000
+#define BCI_CMD_DRAW_SKIPFLAGS          0x000000ff
+#define BCI_CMD_DRAW_NO_Z              0x00000001
+#define BCI_CMD_DRAW_NO_W              0x00000002
+#define BCI_CMD_DRAW_NO_CD             0x00000004
+#define BCI_CMD_DRAW_NO_CS             0x00000008
+#define BCI_CMD_DRAW_NO_U0             0x00000010
+#define BCI_CMD_DRAW_NO_V0             0x00000020
+#define BCI_CMD_DRAW_NO_UV0            0x00000030
+#define BCI_CMD_DRAW_NO_U1             0x00000040
+#define BCI_CMD_DRAW_NO_V1             0x00000080
+#define BCI_CMD_DRAW_NO_UV1            0x000000c0
+
+#define BCI_CMD_DMA                    0xa8000000
+
+#define BCI_W_H(w, h)                ((((h) << 16) | (w)) & 0x0FFF0FFF)
+#define BCI_X_Y(x, y)                ((((y) << 16) | (x)) & 0x0FFF0FFF)
+#define BCI_X_W(x, y)                ((((w) << 16) | (x)) & 0x0FFF0FFF)
+#define BCI_CLIP_LR(l, r)            ((((r) << 16) | (l)) & 0x0FFF0FFF)
+#define BCI_CLIP_TL(t, l)            ((((t) << 16) | (l)) & 0x0FFF0FFF)
+#define BCI_CLIP_BR(b, r)            ((((b) << 16) | (r)) & 0x0FFF0FFF)
+
+#define BCI_LINE_X_Y(x, y)           (((y) << 16) | ((x) & 0xFFFF))
+#define BCI_LINE_STEPS(diag, axi)    (((axi) << 16) | ((diag) & 0xFFFF))
+#define BCI_LINE_MISC(maj, ym, xp, yp, err) \
+       (((maj) & 0x1FFF) | \
+       ((ym) ? 1<<13 : 0) | \
+       ((xp) ? 1<<14 : 0) | \
+       ((yp) ? 1<<15 : 0) | \
+       ((err) << 16))
+
+/*
+ * common commands
+ */
+#define BCI_SET_REGISTERS( first, n )                  \
+       BCI_WRITE(BCI_CMD_SET_REGISTER |                \
+                 ((uint32_t)(n) & 0xff) << 16 |        \
+                 ((uint32_t)(first) & 0xffff))
+#define DMA_SET_REGISTERS( first, n )                  \
+       DMA_WRITE(BCI_CMD_SET_REGISTER |                \
+                 ((uint32_t)(n) & 0xff) << 16 |        \
+                 ((uint32_t)(first) & 0xffff))
+
+#define BCI_DRAW_PRIMITIVE(n, type, skip)         \
+        BCI_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \
+                 ((n) << 16))
+#define DMA_DRAW_PRIMITIVE(n, type, skip)         \
+        DMA_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \
+                 ((n) << 16))
+
+#define BCI_DRAW_INDICES_S3D(n, type, i0)         \
+        BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) |  \
+                 ((n) << 16) | (i0))
+
+#define BCI_DRAW_INDICES_S4(n, type, skip)        \
+        BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) |  \
+                  (skip) | ((n) << 16))
+
+#define BCI_DMA(n)     \
+       BCI_WRITE(BCI_CMD_DMA | (((n) >> 1) - 1))
+
+/*
+ * access to MMIO
+ */
+#define SAVAGE_READ(reg)       DRM_READ32(  dev_priv->mmio, (reg) )
+#define SAVAGE_WRITE(reg)      DRM_WRITE32( dev_priv->mmio, (reg) )
+
+/*
+ * access to the burst command interface (BCI)
+ */
+#define SAVAGE_BCI_DEBUG 1
+
+#define BCI_LOCALS    volatile uint32_t *bci_ptr;
+
+#define BEGIN_BCI( n ) do {                    \
+       dev_priv->wait_fifo(dev_priv, (n));     \
+       bci_ptr = dev_priv->bci_ptr;            \
+} while(0)
+
+#define BCI_WRITE( val ) *bci_ptr++ = (uint32_t)(val)
+
+/*
+ * command DMA support
+ */
+#define SAVAGE_DMA_DEBUG 1
+
+#define DMA_LOCALS   uint32_t *dma_ptr;
+
+#define BEGIN_DMA( n ) do {                                            \
+       unsigned int cur = dev_priv->current_dma_page;                  \
+       unsigned int rest = SAVAGE_DMA_PAGE_SIZE -                      \
+               dev_priv->dma_pages[cur].used;                          \
+       if ((n) > rest) {                                               \
+               dma_ptr = savage_dma_alloc(dev_priv, (n));              \
+       } else { /* fast path for small allocations */                  \
+               dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle +       \
+                       cur * SAVAGE_DMA_PAGE_SIZE +                    \
+                       dev_priv->dma_pages[cur].used;                  \
+               if (dev_priv->dma_pages[cur].used == 0)                 \
+                       savage_dma_wait(dev_priv, cur);                 \
+               dev_priv->dma_pages[cur].used += (n);                   \
+       }                                                               \
+} while(0)
+
+#define DMA_WRITE( val ) *dma_ptr++ = (uint32_t)(val)
+
+#define DMA_COPY(src, n) do {                                  \
+       memcpy(dma_ptr, (src), (n)*4);                          \
+       dma_ptr += n;                                           \
+} while(0)
+
+#if SAVAGE_DMA_DEBUG
+#define DMA_COMMIT() do {                                              \
+       unsigned int cur = dev_priv->current_dma_page;                  \
+       uint32_t *expected = (uint32_t *)dev_priv->cmd_dma->handle +    \
+                       cur * SAVAGE_DMA_PAGE_SIZE +                    \
+                       dev_priv->dma_pages[cur].used;                  \
+       if (dma_ptr != expected) {                                      \
+               DRM_ERROR("DMA allocation and use don't match: "        \
+                         "%p != %p\n", expected, dma_ptr);             \
+               savage_dma_reset(dev_priv);                             \
+       }                                                               \
+} while(0)
+#else
+#define DMA_COMMIT() do {/* nothing */} while(0)
+#endif
+
+#define DMA_FLUSH() dev_priv->dma_flush(dev_priv)
+
+/* Buffer aging via event tag
+ */
+
+#define UPDATE_EVENT_COUNTER( ) do {                   \
+       if (dev_priv->status_ptr) {                     \
+               uint16_t count;                         \
+               /* coordinate with Xserver */           \
+               count = dev_priv->status_ptr[1023];     \
+               if (count < dev_priv->event_counter)    \
+                       dev_priv->event_wrap++;         \
+               dev_priv->event_counter = count;        \
+       }                                               \
+} while(0)
+
+#define SET_AGE( age, e, w ) do {      \
+       (age)->event = e;               \
+       (age)->wrap = w;                \
+} while(0)
+
+#define TEST_AGE( age, e, w )                          \
+       ( (age)->wrap < (w) || ( (age)->wrap == (w) && (age)->event <= (e) ) )
+
+#endif                         /* __SAVAGE_DRV_H__ */
diff --git a/drivers/gpu/drm/savage/savage_state.c b/drivers/gpu/drm/savage/savage_state.c
new file mode 100644 (file)
index 0000000..5f6238f
--- /dev/null
@@ -0,0 +1,1163 @@
+/* savage_state.c -- State and drawing support for Savage
+ *
+ * Copyright 2004  Felix Kuehling
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "drmP.h"
+#include "savage_drm.h"
+#include "savage_drv.h"
+
+void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
+                              const struct drm_clip_rect * pbox)
+{
+       uint32_t scstart = dev_priv->state.s3d.new_scstart;
+       uint32_t scend = dev_priv->state.s3d.new_scend;
+       scstart = (scstart & ~SAVAGE_SCISSOR_MASK_S3D) |
+           ((uint32_t) pbox->x1 & 0x000007ff) |
+           (((uint32_t) pbox->y1 << 16) & 0x07ff0000);
+       scend = (scend & ~SAVAGE_SCISSOR_MASK_S3D) |
+           (((uint32_t) pbox->x2 - 1) & 0x000007ff) |
+           ((((uint32_t) pbox->y2 - 1) << 16) & 0x07ff0000);
+       if (scstart != dev_priv->state.s3d.scstart ||
+           scend != dev_priv->state.s3d.scend) {
+               DMA_LOCALS;
+               BEGIN_DMA(4);
+               DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
+               DMA_SET_REGISTERS(SAVAGE_SCSTART_S3D, 2);
+               DMA_WRITE(scstart);
+               DMA_WRITE(scend);
+               dev_priv->state.s3d.scstart = scstart;
+               dev_priv->state.s3d.scend = scend;
+               dev_priv->waiting = 1;
+               DMA_COMMIT();
+       }
+}
+
+void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
+                             const struct drm_clip_rect * pbox)
+{
+       uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;
+       uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;
+       drawctrl0 = (drawctrl0 & ~SAVAGE_SCISSOR_MASK_S4) |
+           ((uint32_t) pbox->x1 & 0x000007ff) |
+           (((uint32_t) pbox->y1 << 12) & 0x00fff000);
+       drawctrl1 = (drawctrl1 & ~SAVAGE_SCISSOR_MASK_S4) |
+           (((uint32_t) pbox->x2 - 1) & 0x000007ff) |
+           ((((uint32_t) pbox->y2 - 1) << 12) & 0x00fff000);
+       if (drawctrl0 != dev_priv->state.s4.drawctrl0 ||
+           drawctrl1 != dev_priv->state.s4.drawctrl1) {
+               DMA_LOCALS;
+               BEGIN_DMA(4);
+               DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
+               DMA_SET_REGISTERS(SAVAGE_DRAWCTRL0_S4, 2);
+               DMA_WRITE(drawctrl0);
+               DMA_WRITE(drawctrl1);
+               dev_priv->state.s4.drawctrl0 = drawctrl0;
+               dev_priv->state.s4.drawctrl1 = drawctrl1;
+               dev_priv->waiting = 1;
+               DMA_COMMIT();
+       }
+}
+
+static int savage_verify_texaddr(drm_savage_private_t * dev_priv, int unit,
+                                uint32_t addr)
+{
+       if ((addr & 6) != 2) {  /* reserved bits */
+               DRM_ERROR("bad texAddr%d %08x (reserved bits)\n", unit, addr);
+               return -EINVAL;
+       }
+       if (!(addr & 1)) {      /* local */
+               addr &= ~7;
+               if (addr < dev_priv->texture_offset ||
+                   addr >= dev_priv->texture_offset + dev_priv->texture_size) {
+                       DRM_ERROR
+                           ("bad texAddr%d %08x (local addr out of range)\n",
+                            unit, addr);
+                       return -EINVAL;
+               }
+       } else {                /* AGP */
+               if (!dev_priv->agp_textures) {
+                       DRM_ERROR("bad texAddr%d %08x (AGP not available)\n",
+                                 unit, addr);
+                       return -EINVAL;
+               }
+               addr &= ~7;
+               if (addr < dev_priv->agp_textures->offset ||
+                   addr >= (dev_priv->agp_textures->offset +
+                            dev_priv->agp_textures->size)) {
+                       DRM_ERROR
+                           ("bad texAddr%d %08x (AGP addr out of range)\n",
+                            unit, addr);
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
+#define SAVE_STATE(reg,where)                  \
+       if(start <= reg && start+count > reg)   \
+               dev_priv->state.where = regs[reg - start]
+#define SAVE_STATE_MASK(reg,where,mask) do {                   \
+       if(start <= reg && start+count > reg) {                 \
+               uint32_t tmp;                                   \
+               tmp = regs[reg - start];                        \
+               dev_priv->state.where = (tmp & (mask)) |        \
+                       (dev_priv->state.where & ~(mask));      \
+       }                                                       \
+} while (0)
+
+static int savage_verify_state_s3d(drm_savage_private_t * dev_priv,
+                                  unsigned int start, unsigned int count,
+                                  const uint32_t *regs)
+{
+       if (start < SAVAGE_TEXPALADDR_S3D ||
+           start + count - 1 > SAVAGE_DESTTEXRWWATERMARK_S3D) {
+               DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
+                         start, start + count - 1);
+               return -EINVAL;
+       }
+
+       SAVE_STATE_MASK(SAVAGE_SCSTART_S3D, s3d.new_scstart,
+                       ~SAVAGE_SCISSOR_MASK_S3D);
+       SAVE_STATE_MASK(SAVAGE_SCEND_S3D, s3d.new_scend,
+                       ~SAVAGE_SCISSOR_MASK_S3D);
+
+       /* if any texture regs were changed ... */
+       if (start <= SAVAGE_TEXCTRL_S3D &&
+           start + count > SAVAGE_TEXPALADDR_S3D) {
+               /* ... check texture state */
+               SAVE_STATE(SAVAGE_TEXCTRL_S3D, s3d.texctrl);
+               SAVE_STATE(SAVAGE_TEXADDR_S3D, s3d.texaddr);
+               if (dev_priv->state.s3d.texctrl & SAVAGE_TEXCTRL_TEXEN_MASK)
+                       return savage_verify_texaddr(dev_priv, 0,
+                                               dev_priv->state.s3d.texaddr);
+       }
+
+       return 0;
+}
+
+static int savage_verify_state_s4(drm_savage_private_t * dev_priv,
+                                 unsigned int start, unsigned int count,
+                                 const uint32_t *regs)
+{
+       int ret = 0;
+
+       if (start < SAVAGE_DRAWLOCALCTRL_S4 ||
+           start + count - 1 > SAVAGE_TEXBLENDCOLOR_S4) {
+               DRM_ERROR("invalid register range (0x%04x-0x%04x)\n",
+                         start, start + count - 1);
+               return -EINVAL;
+       }
+
+       SAVE_STATE_MASK(SAVAGE_DRAWCTRL0_S4, s4.new_drawctrl0,
+                       ~SAVAGE_SCISSOR_MASK_S4);
+       SAVE_STATE_MASK(SAVAGE_DRAWCTRL1_S4, s4.new_drawctrl1,
+                       ~SAVAGE_SCISSOR_MASK_S4);
+
+       /* if any texture regs were changed ... */
+       if (start <= SAVAGE_TEXDESCR_S4 &&
+           start + count > SAVAGE_TEXPALADDR_S4) {
+               /* ... check texture state */
+               SAVE_STATE(SAVAGE_TEXDESCR_S4, s4.texdescr);
+               SAVE_STATE(SAVAGE_TEXADDR0_S4, s4.texaddr0);
+               SAVE_STATE(SAVAGE_TEXADDR1_S4, s4.texaddr1);
+               if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX0EN_MASK)
+                       ret |= savage_verify_texaddr(dev_priv, 0,
+                                               dev_priv->state.s4.texaddr0);
+               if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX1EN_MASK)
+                       ret |= savage_verify_texaddr(dev_priv, 1,
+                                               dev_priv->state.s4.texaddr1);
+       }
+
+       return ret;
+}
+
+#undef SAVE_STATE
+#undef SAVE_STATE_MASK
+
+static int savage_dispatch_state(drm_savage_private_t * dev_priv,
+                                const drm_savage_cmd_header_t * cmd_header,
+                                const uint32_t *regs)
+{
+       unsigned int count = cmd_header->state.count;
+       unsigned int start = cmd_header->state.start;
+       unsigned int count2 = 0;
+       unsigned int bci_size;
+       int ret;
+       DMA_LOCALS;
+
+       if (!count)
+               return 0;
+
+       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+               ret = savage_verify_state_s3d(dev_priv, start, count, regs);
+               if (ret != 0)
+                       return ret;
+               /* scissor regs are emitted in savage_dispatch_draw */
+               if (start < SAVAGE_SCSTART_S3D) {
+                       if (start + count > SAVAGE_SCEND_S3D + 1)
+                               count2 = count - (SAVAGE_SCEND_S3D + 1 - start);
+                       if (start + count > SAVAGE_SCSTART_S3D)
+                               count = SAVAGE_SCSTART_S3D - start;
+               } else if (start <= SAVAGE_SCEND_S3D) {
+                       if (start + count > SAVAGE_SCEND_S3D + 1) {
+                               count -= SAVAGE_SCEND_S3D + 1 - start;
+                               start = SAVAGE_SCEND_S3D + 1;
+                       } else
+                               return 0;
+               }
+       } else {
+               ret = savage_verify_state_s4(dev_priv, start, count, regs);
+               if (ret != 0)
+                       return ret;
+               /* scissor regs are emitted in savage_dispatch_draw */
+               if (start < SAVAGE_DRAWCTRL0_S4) {
+                       if (start + count > SAVAGE_DRAWCTRL1_S4 + 1)
+                               count2 = count -
+                                        (SAVAGE_DRAWCTRL1_S4 + 1 - start);
+                       if (start + count > SAVAGE_DRAWCTRL0_S4)
+                               count = SAVAGE_DRAWCTRL0_S4 - start;
+               } else if (start <= SAVAGE_DRAWCTRL1_S4) {
+                       if (start + count > SAVAGE_DRAWCTRL1_S4 + 1) {
+                               count -= SAVAGE_DRAWCTRL1_S4 + 1 - start;
+                               start = SAVAGE_DRAWCTRL1_S4 + 1;
+                       } else
+                               return 0;
+               }
+       }
+
+       bci_size = count + (count + 254) / 255 + count2 + (count2 + 254) / 255;
+
+       if (cmd_header->state.global) {
+               BEGIN_DMA(bci_size + 1);
+               DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D);
+               dev_priv->waiting = 1;
+       } else {
+               BEGIN_DMA(bci_size);
+       }
+
+       do {
+               while (count > 0) {
+                       unsigned int n = count < 255 ? count : 255;
+                       DMA_SET_REGISTERS(start, n);
+                       DMA_COPY(regs, n);
+                       count -= n;
+                       start += n;
+                       regs += n;
+               }
+               start += 2;
+               regs += 2;
+               count = count2;
+               count2 = 0;
+       } while (count);
+
+       DMA_COMMIT();
+
+       return 0;
+}
+
+static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv,
+                                   const drm_savage_cmd_header_t * cmd_header,
+                                   const struct drm_buf * dmabuf)
+{
+       unsigned char reorder = 0;
+       unsigned int prim = cmd_header->prim.prim;
+       unsigned int skip = cmd_header->prim.skip;
+       unsigned int n = cmd_header->prim.count;
+       unsigned int start = cmd_header->prim.start;
+       unsigned int i;
+       BCI_LOCALS;
+
+       if (!dmabuf) {
+               DRM_ERROR("called without dma buffers!\n");
+               return -EINVAL;
+       }
+
+       if (!n)
+               return 0;
+
+       switch (prim) {
+       case SAVAGE_PRIM_TRILIST_201:
+               reorder = 1;
+               prim = SAVAGE_PRIM_TRILIST;
+       case SAVAGE_PRIM_TRILIST:
+               if (n % 3 != 0) {
+                       DRM_ERROR("wrong number of vertices %u in TRILIST\n",
+                                 n);
+                       return -EINVAL;
+               }
+               break;
+       case SAVAGE_PRIM_TRISTRIP:
+       case SAVAGE_PRIM_TRIFAN:
+               if (n < 3) {
+                       DRM_ERROR
+                           ("wrong number of vertices %u in TRIFAN/STRIP\n",
+                            n);
+                       return -EINVAL;
+               }
+               break;
+       default:
+               DRM_ERROR("invalid primitive type %u\n", prim);
+               return -EINVAL;
+       }
+
+       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+               if (skip != 0) {
+                       DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+                       return -EINVAL;
+               }
+       } else {
+               unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
+                   (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
+                   (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
+               if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
+                       DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+                       return -EINVAL;
+               }
+               if (reorder) {
+                       DRM_ERROR("TRILIST_201 used on Savage4 hardware\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (start + n > dmabuf->total / 32) {
+               DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
+                         start, start + n - 1, dmabuf->total / 32);
+               return -EINVAL;
+       }
+
+       /* Vertex DMA doesn't work with command DMA at the same time,
+        * so we use BCI_... to submit commands here. Flush buffered
+        * faked DMA first. */
+       DMA_FLUSH();
+
+       if (dmabuf->bus_address != dev_priv->state.common.vbaddr) {
+               BEGIN_BCI(2);
+               BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1);
+               BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type);
+               dev_priv->state.common.vbaddr = dmabuf->bus_address;
+       }
+       if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) {
+               /* Workaround for what looks like a hardware bug. If a
+                * WAIT_3D_IDLE was emitted some time before the
+                * indexed drawing command then the engine will lock
+                * up. There are two known workarounds:
+                * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */
+               BEGIN_BCI(63);
+               for (i = 0; i < 63; ++i)
+                       BCI_WRITE(BCI_CMD_WAIT);
+               dev_priv->waiting = 0;
+       }
+
+       prim <<= 25;
+       while (n != 0) {
+               /* Can emit up to 255 indices (85 triangles) at once. */
+               unsigned int count = n > 255 ? 255 : n;
+               if (reorder) {
+                       /* Need to reorder indices for correct flat
+                        * shading while preserving the clock sense
+                        * for correct culling. Only on Savage3D. */
+                       int reorder[3] = { -1, -1, -1 };
+                       reorder[start % 3] = 2;
+
+                       BEGIN_BCI((count + 1 + 1) / 2);
+                       BCI_DRAW_INDICES_S3D(count, prim, start + 2);
+
+                       for (i = start + 1; i + 1 < start + count; i += 2)
+                               BCI_WRITE((i + reorder[i % 3]) |
+                                         ((i + 1 +
+                                           reorder[(i + 1) % 3]) << 16));
+                       if (i < start + count)
+                               BCI_WRITE(i + reorder[i % 3]);
+               } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+                       BEGIN_BCI((count + 1 + 1) / 2);
+                       BCI_DRAW_INDICES_S3D(count, prim, start);
+
+                       for (i = start + 1; i + 1 < start + count; i += 2)
+                               BCI_WRITE(i | ((i + 1) << 16));
+                       if (i < start + count)
+                               BCI_WRITE(i);
+               } else {
+                       BEGIN_BCI((count + 2 + 1) / 2);
+                       BCI_DRAW_INDICES_S4(count, prim, skip);
+
+                       for (i = start; i + 1 < start + count; i += 2)
+                               BCI_WRITE(i | ((i + 1) << 16));
+                       if (i < start + count)
+                               BCI_WRITE(i);
+               }
+
+               start += count;
+               n -= count;
+
+               prim |= BCI_CMD_DRAW_CONT;
+       }
+
+       return 0;
+}
+
+static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv,
+                                  const drm_savage_cmd_header_t * cmd_header,
+                                  const uint32_t *vtxbuf, unsigned int vb_size,
+                                  unsigned int vb_stride)
+{
+       unsigned char reorder = 0;
+       unsigned int prim = cmd_header->prim.prim;
+       unsigned int skip = cmd_header->prim.skip;
+       unsigned int n = cmd_header->prim.count;
+       unsigned int start = cmd_header->prim.start;
+       unsigned int vtx_size;
+       unsigned int i;
+       DMA_LOCALS;
+
+       if (!n)
+               return 0;
+
+       switch (prim) {
+       case SAVAGE_PRIM_TRILIST_201:
+               reorder = 1;
+               prim = SAVAGE_PRIM_TRILIST;
+       case SAVAGE_PRIM_TRILIST:
+               if (n % 3 != 0) {
+                       DRM_ERROR("wrong number of vertices %u in TRILIST\n",
+                                 n);
+                       return -EINVAL;
+               }
+               break;
+       case SAVAGE_PRIM_TRISTRIP:
+       case SAVAGE_PRIM_TRIFAN:
+               if (n < 3) {
+                       DRM_ERROR
+                           ("wrong number of vertices %u in TRIFAN/STRIP\n",
+                            n);
+                       return -EINVAL;
+               }
+               break;
+       default:
+               DRM_ERROR("invalid primitive type %u\n", prim);
+               return -EINVAL;
+       }
+
+       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+               if (skip > SAVAGE_SKIP_ALL_S3D) {
+                       DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+                       return -EINVAL;
+               }
+               vtx_size = 8;   /* full vertex */
+       } else {
+               if (skip > SAVAGE_SKIP_ALL_S4) {
+                       DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+                       return -EINVAL;
+               }
+               vtx_size = 10;  /* full vertex */
+       }
+
+       vtx_size -= (skip & 1) + (skip >> 1 & 1) +
+           (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
+           (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
+
+       if (vtx_size > vb_stride) {
+               DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
+                         vtx_size, vb_stride);
+               return -EINVAL;
+       }
+
+       if (start + n > vb_size / (vb_stride * 4)) {
+               DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n",
+                         start, start + n - 1, vb_size / (vb_stride * 4));
+               return -EINVAL;
+       }
+
+       prim <<= 25;
+       while (n != 0) {
+               /* Can emit up to 255 vertices (85 triangles) at once. */
+               unsigned int count = n > 255 ? 255 : n;
+               if (reorder) {
+                       /* Need to reorder vertices for correct flat
+                        * shading while preserving the clock sense
+                        * for correct culling. Only on Savage3D. */
+                       int reorder[3] = { -1, -1, -1 };
+                       reorder[start % 3] = 2;
+
+                       BEGIN_DMA(count * vtx_size + 1);
+                       DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+                       for (i = start; i < start + count; ++i) {
+                               unsigned int j = i + reorder[i % 3];
+                               DMA_COPY(&vtxbuf[vb_stride * j], vtx_size);
+                       }
+
+                       DMA_COMMIT();
+               } else {
+                       BEGIN_DMA(count * vtx_size + 1);
+                       DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+                       if (vb_stride == vtx_size) {
+                               DMA_COPY(&vtxbuf[vb_stride * start],
+                                        vtx_size * count);
+                       } else {
+                               for (i = start; i < start + count; ++i) {
+                                       DMA_COPY(&vtxbuf [vb_stride * i],
+                                                vtx_size);
+                               }
+                       }
+
+                       DMA_COMMIT();
+               }
+
+               start += count;
+               n -= count;
+
+               prim |= BCI_CMD_DRAW_CONT;
+       }
+
+       return 0;
+}
+
+static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
+                                  const drm_savage_cmd_header_t * cmd_header,
+                                  const uint16_t *idx,
+                                  const struct drm_buf * dmabuf)
+{
+       unsigned char reorder = 0;
+       unsigned int prim = cmd_header->idx.prim;
+       unsigned int skip = cmd_header->idx.skip;
+       unsigned int n = cmd_header->idx.count;
+       unsigned int i;
+       BCI_LOCALS;
+
+       if (!dmabuf) {
+               DRM_ERROR("called without dma buffers!\n");
+               return -EINVAL;
+       }
+
+       if (!n)
+               return 0;
+
+       switch (prim) {
+       case SAVAGE_PRIM_TRILIST_201:
+               reorder = 1;
+               prim = SAVAGE_PRIM_TRILIST;
+       case SAVAGE_PRIM_TRILIST:
+               if (n % 3 != 0) {
+                       DRM_ERROR("wrong number of indices %u in TRILIST\n", n);
+                       return -EINVAL;
+               }
+               break;
+       case SAVAGE_PRIM_TRISTRIP:
+       case SAVAGE_PRIM_TRIFAN:
+               if (n < 3) {
+                       DRM_ERROR
+                           ("wrong number of indices %u in TRIFAN/STRIP\n", n);
+                       return -EINVAL;
+               }
+               break;
+       default:
+               DRM_ERROR("invalid primitive type %u\n", prim);
+               return -EINVAL;
+       }
+
+       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+               if (skip != 0) {
+                       DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+                       return -EINVAL;
+               }
+       } else {
+               unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) -
+                   (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
+                   (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
+               if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) {
+                       DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip);
+                       return -EINVAL;
+               }
+               if (reorder) {
+                       DRM_ERROR("TRILIST_201 used on Savage4 hardware\n");
+                       return -EINVAL;
+               }
+       }
+
+       /* Vertex DMA doesn't work with command DMA at the same time,
+        * so we use BCI_... to submit commands here. Flush buffered
+        * faked DMA first. */
+       DMA_FLUSH();
+
+       if (dmabuf->bus_address != dev_priv->state.common.vbaddr) {
+               BEGIN_BCI(2);
+               BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1);
+               BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type);
+               dev_priv->state.common.vbaddr = dmabuf->bus_address;
+       }
+       if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) {
+               /* Workaround for what looks like a hardware bug. If a
+                * WAIT_3D_IDLE was emitted some time before the
+                * indexed drawing command then the engine will lock
+                * up. There are two known workarounds:
+                * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */
+               BEGIN_BCI(63);
+               for (i = 0; i < 63; ++i)
+                       BCI_WRITE(BCI_CMD_WAIT);
+               dev_priv->waiting = 0;
+       }
+
+       prim <<= 25;
+       while (n != 0) {
+               /* Can emit up to 255 indices (85 triangles) at once. */
+               unsigned int count = n > 255 ? 255 : n;
+
+               /* check indices */
+               for (i = 0; i < count; ++i) {
+                       if (idx[i] > dmabuf->total / 32) {
+                               DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
+                                         i, idx[i], dmabuf->total / 32);
+                               return -EINVAL;
+                       }
+               }
+
+               if (reorder) {
+                       /* Need to reorder indices for correct flat
+                        * shading while preserving the clock sense
+                        * for correct culling. Only on Savage3D. */
+                       int reorder[3] = { 2, -1, -1 };
+
+                       BEGIN_BCI((count + 1 + 1) / 2);
+                       BCI_DRAW_INDICES_S3D(count, prim, idx[2]);
+
+                       for (i = 1; i + 1 < count; i += 2)
+                               BCI_WRITE(idx[i + reorder[i % 3]] |
+                                         (idx[i + 1 +
+                                          reorder[(i + 1) % 3]] << 16));
+                       if (i < count)
+                               BCI_WRITE(idx[i + reorder[i % 3]]);
+               } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+                       BEGIN_BCI((count + 1 + 1) / 2);
+                       BCI_DRAW_INDICES_S3D(count, prim, idx[0]);
+
+                       for (i = 1; i + 1 < count; i += 2)
+                               BCI_WRITE(idx[i] | (idx[i + 1] << 16));
+                       if (i < count)
+                               BCI_WRITE(idx[i]);
+               } else {
+                       BEGIN_BCI((count + 2 + 1) / 2);
+                       BCI_DRAW_INDICES_S4(count, prim, skip);
+
+                       for (i = 0; i + 1 < count; i += 2)
+                               BCI_WRITE(idx[i] | (idx[i + 1] << 16));
+                       if (i < count)
+                               BCI_WRITE(idx[i]);
+               }
+
+               idx += count;
+               n -= count;
+
+               prim |= BCI_CMD_DRAW_CONT;
+       }
+
+       return 0;
+}
+
+static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,
+                                 const drm_savage_cmd_header_t * cmd_header,
+                                 const uint16_t *idx,
+                                 const uint32_t *vtxbuf,
+                                 unsigned int vb_size, unsigned int vb_stride)
+{
+       unsigned char reorder = 0;
+       unsigned int prim = cmd_header->idx.prim;
+       unsigned int skip = cmd_header->idx.skip;
+       unsigned int n = cmd_header->idx.count;
+       unsigned int vtx_size;
+       unsigned int i;
+       DMA_LOCALS;
+
+       if (!n)
+               return 0;
+
+       switch (prim) {
+       case SAVAGE_PRIM_TRILIST_201:
+               reorder = 1;
+               prim = SAVAGE_PRIM_TRILIST;
+       case SAVAGE_PRIM_TRILIST:
+               if (n % 3 != 0) {
+                       DRM_ERROR("wrong number of indices %u in TRILIST\n", n);
+                       return -EINVAL;
+               }
+               break;
+       case SAVAGE_PRIM_TRISTRIP:
+       case SAVAGE_PRIM_TRIFAN:
+               if (n < 3) {
+                       DRM_ERROR
+                           ("wrong number of indices %u in TRIFAN/STRIP\n", n);
+                       return -EINVAL;
+               }
+               break;
+       default:
+               DRM_ERROR("invalid primitive type %u\n", prim);
+               return -EINVAL;
+       }
+
+       if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) {
+               if (skip > SAVAGE_SKIP_ALL_S3D) {
+                       DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+                       return -EINVAL;
+               }
+               vtx_size = 8;   /* full vertex */
+       } else {
+               if (skip > SAVAGE_SKIP_ALL_S4) {
+                       DRM_ERROR("invalid skip flags 0x%04x\n", skip);
+                       return -EINVAL;
+               }
+               vtx_size = 10;  /* full vertex */
+       }
+
+       vtx_size -= (skip & 1) + (skip >> 1 & 1) +
+           (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) +
+           (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1);
+
+       if (vtx_size > vb_stride) {
+               DRM_ERROR("vertex size greater than vb stride (%u > %u)\n",
+                         vtx_size, vb_stride);
+               return -EINVAL;
+       }
+
+       prim <<= 25;
+       while (n != 0) {
+               /* Can emit up to 255 vertices (85 triangles) at once. */
+               unsigned int count = n > 255 ? 255 : n;
+
+               /* Check indices */
+               for (i = 0; i < count; ++i) {
+                       if (idx[i] > vb_size / (vb_stride * 4)) {
+                               DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
+                                         i, idx[i], vb_size / (vb_stride * 4));
+                               return -EINVAL;
+                       }
+               }
+
+               if (reorder) {
+                       /* Need to reorder vertices for correct flat
+                        * shading while preserving the clock sense
+                        * for correct culling. Only on Savage3D. */
+                       int reorder[3] = { 2, -1, -1 };
+
+                       BEGIN_DMA(count * vtx_size + 1);
+                       DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+                       for (i = 0; i < count; ++i) {
+                               unsigned int j = idx[i + reorder[i % 3]];
+                               DMA_COPY(&vtxbuf[vb_stride * j], vtx_size);
+                       }
+
+                       DMA_COMMIT();
+               } else {
+                       BEGIN_DMA(count * vtx_size + 1);
+                       DMA_DRAW_PRIMITIVE(count, prim, skip);
+
+                       for (i = 0; i < count; ++i) {
+                               unsigned int j = idx[i];
+                               DMA_COPY(&vtxbuf[vb_stride * j], vtx_size);
+                       }
+
+                       DMA_COMMIT();
+               }
+
+               idx += count;
+               n -= count;
+
+               prim |= BCI_CMD_DRAW_CONT;
+       }
+
+       return 0;
+}
+
+static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
+                                const drm_savage_cmd_header_t * cmd_header,
+                                const drm_savage_cmd_header_t *data,
+                                unsigned int nbox,
+                                const struct drm_clip_rect *boxes)
+{
+       unsigned int flags = cmd_header->clear0.flags;
+       unsigned int clear_cmd;
+       unsigned int i, nbufs;
+       DMA_LOCALS;
+
+       if (nbox == 0)
+               return 0;
+
+       clear_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+           BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW;
+       BCI_CMD_SET_ROP(clear_cmd, 0xCC);
+
+       nbufs = ((flags & SAVAGE_FRONT) ? 1 : 0) +
+           ((flags & SAVAGE_BACK) ? 1 : 0) + ((flags & SAVAGE_DEPTH) ? 1 : 0);
+       if (nbufs == 0)
+               return 0;
+
+       if (data->clear1.mask != 0xffffffff) {
+               /* set mask */
+               BEGIN_DMA(2);
+               DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
+               DMA_WRITE(data->clear1.mask);
+               DMA_COMMIT();
+       }
+       for (i = 0; i < nbox; ++i) {
+               unsigned int x, y, w, h;
+               unsigned int buf;
+               x = boxes[i].x1, y = boxes[i].y1;
+               w = boxes[i].x2 - boxes[i].x1;
+               h = boxes[i].y2 - boxes[i].y1;
+               BEGIN_DMA(nbufs * 6);
+               for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) {
+                       if (!(flags & buf))
+                               continue;
+                       DMA_WRITE(clear_cmd);
+                       switch (buf) {
+                       case SAVAGE_FRONT:
+                               DMA_WRITE(dev_priv->front_offset);
+                               DMA_WRITE(dev_priv->front_bd);
+                               break;
+                       case SAVAGE_BACK:
+                               DMA_WRITE(dev_priv->back_offset);
+                               DMA_WRITE(dev_priv->back_bd);
+                               break;
+                       case SAVAGE_DEPTH:
+                               DMA_WRITE(dev_priv->depth_offset);
+                               DMA_WRITE(dev_priv->depth_bd);
+                               break;
+                       }
+                       DMA_WRITE(data->clear1.value);
+                       DMA_WRITE(BCI_X_Y(x, y));
+                       DMA_WRITE(BCI_W_H(w, h));
+               }
+               DMA_COMMIT();
+       }
+       if (data->clear1.mask != 0xffffffff) {
+               /* reset mask */
+               BEGIN_DMA(2);
+               DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
+               DMA_WRITE(0xffffffff);
+               DMA_COMMIT();
+       }
+
+       return 0;
+}
+
+static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
+                               unsigned int nbox, const struct drm_clip_rect *boxes)
+{
+       unsigned int swap_cmd;
+       unsigned int i;
+       DMA_LOCALS;
+
+       if (nbox == 0)
+               return 0;
+
+       swap_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+           BCI_CMD_SRC_PBD_COLOR_NEW | BCI_CMD_DEST_GBD;
+       BCI_CMD_SET_ROP(swap_cmd, 0xCC);
+
+       for (i = 0; i < nbox; ++i) {
+               BEGIN_DMA(6);
+               DMA_WRITE(swap_cmd);
+               DMA_WRITE(dev_priv->back_offset);
+               DMA_WRITE(dev_priv->back_bd);
+               DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1));
+               DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1));
+               DMA_WRITE(BCI_W_H(boxes[i].x2 - boxes[i].x1,
+                                 boxes[i].y2 - boxes[i].y1));
+               DMA_COMMIT();
+       }
+
+       return 0;
+}
+
+static int savage_dispatch_draw(drm_savage_private_t * dev_priv,
+                               const drm_savage_cmd_header_t *start,
+                               const drm_savage_cmd_header_t *end,
+                               const struct drm_buf * dmabuf,
+                               const unsigned int *vtxbuf,
+                               unsigned int vb_size, unsigned int vb_stride,
+                               unsigned int nbox,
+                               const struct drm_clip_rect *boxes)
+{
+       unsigned int i, j;
+       int ret;
+
+       for (i = 0; i < nbox; ++i) {
+               const drm_savage_cmd_header_t *cmdbuf;
+               dev_priv->emit_clip_rect(dev_priv, &boxes[i]);
+
+               cmdbuf = start;
+               while (cmdbuf < end) {
+                       drm_savage_cmd_header_t cmd_header;
+                       cmd_header = *cmdbuf;
+                       cmdbuf++;
+                       switch (cmd_header.cmd.cmd) {
+                       case SAVAGE_CMD_DMA_PRIM:
+                               ret = savage_dispatch_dma_prim(
+                                       dev_priv, &cmd_header, dmabuf);
+                               break;
+                       case SAVAGE_CMD_VB_PRIM:
+                               ret = savage_dispatch_vb_prim(
+                                       dev_priv, &cmd_header,
+                                       vtxbuf, vb_size, vb_stride);
+                               break;
+                       case SAVAGE_CMD_DMA_IDX:
+                               j = (cmd_header.idx.count + 3) / 4;
+                               /* j was check in savage_bci_cmdbuf */
+                               ret = savage_dispatch_dma_idx(dev_priv,
+                                       &cmd_header, (const uint16_t *)cmdbuf,
+                                       dmabuf);
+                               cmdbuf += j;
+                               break;
+                       case SAVAGE_CMD_VB_IDX:
+                               j = (cmd_header.idx.count + 3) / 4;
+                               /* j was check in savage_bci_cmdbuf */
+                               ret = savage_dispatch_vb_idx(dev_priv,
+                                       &cmd_header, (const uint16_t *)cmdbuf,
+                                       (const uint32_t *)vtxbuf, vb_size,
+                                       vb_stride);
+                               cmdbuf += j;
+                               break;
+                       default:
+                               /* What's the best return code? EFAULT? */
+                               DRM_ERROR("IMPLEMENTATION ERROR: "
+                                         "non-drawing-command %d\n",
+                                         cmd_header.cmd.cmd);
+                               return -EINVAL;
+                       }
+
+                       if (ret != 0)
+                               return ret;
+               }
+       }
+
+       return 0;
+}
+
+int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_savage_private_t *dev_priv = dev->dev_private;
+       struct drm_device_dma *dma = dev->dma;
+       struct drm_buf *dmabuf;
+       drm_savage_cmdbuf_t *cmdbuf = data;
+       drm_savage_cmd_header_t *kcmd_addr = NULL;
+       drm_savage_cmd_header_t *first_draw_cmd;
+       unsigned int *kvb_addr = NULL;
+       struct drm_clip_rect *kbox_addr = NULL;
+       unsigned int i, j;
+       int ret = 0;
+
+       DRM_DEBUG("\n");
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       if (dma && dma->buflist) {
+               if (cmdbuf->dma_idx > dma->buf_count) {
+                       DRM_ERROR
+                           ("vertex buffer index %u out of range (0-%u)\n",
+                            cmdbuf->dma_idx, dma->buf_count - 1);
+                       return -EINVAL;
+               }
+               dmabuf = dma->buflist[cmdbuf->dma_idx];
+       } else {
+               dmabuf = NULL;
+       }
+
+       /* Copy the user buffers into kernel temporary areas.  This hasn't been
+        * a performance loss compared to VERIFYAREA_READ/
+        * COPY_FROM_USER_UNCHECKED when done in other drivers, and is correct
+        * for locking on FreeBSD.
+        */
+       if (cmdbuf->size) {
+               kcmd_addr = drm_alloc(cmdbuf->size * 8, DRM_MEM_DRIVER);
+               if (kcmd_addr == NULL)
+                       return -ENOMEM;
+
+               if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf->cmd_addr,
+                                      cmdbuf->size * 8))
+               {
+                       drm_free(kcmd_addr, cmdbuf->size * 8, DRM_MEM_DRIVER);
+                       return -EFAULT;
+               }
+               cmdbuf->cmd_addr = kcmd_addr;
+       }
+       if (cmdbuf->vb_size) {
+               kvb_addr = drm_alloc(cmdbuf->vb_size, DRM_MEM_DRIVER);
+               if (kvb_addr == NULL) {
+                       ret = -ENOMEM;
+                       goto done;
+               }
+
+               if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf->vb_addr,
+                                      cmdbuf->vb_size)) {
+                       ret = -EFAULT;
+                       goto done;
+               }
+               cmdbuf->vb_addr = kvb_addr;
+       }
+       if (cmdbuf->nbox) {
+               kbox_addr = drm_alloc(cmdbuf->nbox * sizeof(struct drm_clip_rect),
+                                      DRM_MEM_DRIVER);
+               if (kbox_addr == NULL) {
+                       ret = -ENOMEM;
+                       goto done;
+               }
+
+               if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf->box_addr,
+                                      cmdbuf->nbox * sizeof(struct drm_clip_rect))) {
+                       ret = -EFAULT;
+                       goto done;
+               }
+       cmdbuf->box_addr = kbox_addr;
+       }
+
+       /* Make sure writes to DMA buffers are finished before sending
+        * DMA commands to the graphics hardware. */
+       DRM_MEMORYBARRIER();
+
+       /* Coming from user space. Don't know if the Xserver has
+        * emitted wait commands. Assuming the worst. */
+       dev_priv->waiting = 1;
+
+       i = 0;
+       first_draw_cmd = NULL;
+       while (i < cmdbuf->size) {
+               drm_savage_cmd_header_t cmd_header;
+               cmd_header = *(drm_savage_cmd_header_t *)cmdbuf->cmd_addr;
+               cmdbuf->cmd_addr++;
+               i++;
+
+               /* Group drawing commands with same state to minimize
+                * iterations over clip rects. */
+               j = 0;
+               switch (cmd_header.cmd.cmd) {
+               case SAVAGE_CMD_DMA_IDX:
+               case SAVAGE_CMD_VB_IDX:
+                       j = (cmd_header.idx.count + 3) / 4;
+                       if (i + j > cmdbuf->size) {
+                               DRM_ERROR("indexed drawing command extends "
+                                         "beyond end of command buffer\n");
+                               DMA_FLUSH();
+                               return -EINVAL;
+                       }
+                       /* fall through */
+               case SAVAGE_CMD_DMA_PRIM:
+               case SAVAGE_CMD_VB_PRIM:
+                       if (!first_draw_cmd)
+                               first_draw_cmd = cmdbuf->cmd_addr - 1;
+                       cmdbuf->cmd_addr += j;
+                       i += j;
+                       break;
+               default:
+                       if (first_draw_cmd) {
+                               ret = savage_dispatch_draw(
+                                     dev_priv, first_draw_cmd,
+                                     cmdbuf->cmd_addr - 1,
+                                     dmabuf, cmdbuf->vb_addr, cmdbuf->vb_size,
+                                     cmdbuf->vb_stride,
+                                     cmdbuf->nbox, cmdbuf->box_addr);
+                               if (ret != 0)
+                                       return ret;
+                               first_draw_cmd = NULL;
+                       }
+               }
+               if (first_draw_cmd)
+                       continue;
+
+               switch (cmd_header.cmd.cmd) {
+               case SAVAGE_CMD_STATE:
+                       j = (cmd_header.state.count + 1) / 2;
+                       if (i + j > cmdbuf->size) {
+                               DRM_ERROR("command SAVAGE_CMD_STATE extends "
+                                         "beyond end of command buffer\n");
+                               DMA_FLUSH();
+                               ret = -EINVAL;
+                               goto done;
+                       }
+                       ret = savage_dispatch_state(dev_priv, &cmd_header,
+                               (const uint32_t *)cmdbuf->cmd_addr);
+                       cmdbuf->cmd_addr += j;
+                       i += j;
+                       break;
+               case SAVAGE_CMD_CLEAR:
+                       if (i + 1 > cmdbuf->size) {
+                               DRM_ERROR("command SAVAGE_CMD_CLEAR extends "
+                                         "beyond end of command buffer\n");
+                               DMA_FLUSH();
+                               ret = -EINVAL;
+                               goto done;
+                       }
+                       ret = savage_dispatch_clear(dev_priv, &cmd_header,
+                                                   cmdbuf->cmd_addr,
+                                                   cmdbuf->nbox,
+                                                   cmdbuf->box_addr);
+                       cmdbuf->cmd_addr++;
+                       i++;
+                       break;
+               case SAVAGE_CMD_SWAP:
+                       ret = savage_dispatch_swap(dev_priv, cmdbuf->nbox,
+                                                  cmdbuf->box_addr);
+                       break;
+               default:
+                       DRM_ERROR("invalid command 0x%x\n",
+                                 cmd_header.cmd.cmd);
+                       DMA_FLUSH();
+                       ret = -EINVAL;
+                       goto done;
+               }
+
+               if (ret != 0) {
+                       DMA_FLUSH();
+                       goto done;
+               }
+       }
+
+       if (first_draw_cmd) {
+               ret = savage_dispatch_draw (
+                       dev_priv, first_draw_cmd, cmdbuf->cmd_addr, dmabuf,
+                       cmdbuf->vb_addr, cmdbuf->vb_size, cmdbuf->vb_stride,
+                       cmdbuf->nbox, cmdbuf->box_addr);
+               if (ret != 0) {
+                       DMA_FLUSH();
+                       goto done;
+               }
+       }
+
+       DMA_FLUSH();
+
+       if (dmabuf && cmdbuf->discard) {
+               drm_savage_buf_priv_t *buf_priv = dmabuf->dev_private;
+               uint16_t event;
+               event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D);
+               SET_AGE(&buf_priv->age, event, dev_priv->event_wrap);
+               savage_freelist_put(dev, dmabuf);
+       }
+
+done:
+       /* If we didn't need to allocate them, these'll be NULL */
+       drm_free(kcmd_addr, cmdbuf->size * 8, DRM_MEM_DRIVER);
+       drm_free(kvb_addr, cmdbuf->vb_size, DRM_MEM_DRIVER);
+       drm_free(kbox_addr, cmdbuf->nbox * sizeof(struct drm_clip_rect),
+                DRM_MEM_DRIVER);
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/sis/Makefile b/drivers/gpu/drm/sis/Makefile
new file mode 100644 (file)
index 0000000..441c061
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y = -Iinclude/drm
+sis-y := sis_drv.o sis_mm.o
+
+obj-$(CONFIG_DRM_SIS)   += sis.o
+
+
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c
new file mode 100644 (file)
index 0000000..7dacc64
--- /dev/null
@@ -0,0 +1,117 @@
+/* sis.c -- sis driver -*- linux-c -*-
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "drmP.h"
+#include "sis_drm.h"
+#include "sis_drv.h"
+
+#include "drm_pciids.h"
+
+static struct pci_device_id pciidlist[] = {
+       sisdrv_PCI_IDS
+};
+
+static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
+{
+       drm_sis_private_t *dev_priv;
+       int ret;
+
+       dev_priv = drm_calloc(1, sizeof(drm_sis_private_t), DRM_MEM_DRIVER);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       dev->dev_private = (void *)dev_priv;
+       dev_priv->chipset = chipset;
+       ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
+       if (ret) {
+               drm_free(dev_priv, sizeof(dev_priv), DRM_MEM_DRIVER);
+       }
+
+       return ret;
+}
+
+static int sis_driver_unload(struct drm_device *dev)
+{
+       drm_sis_private_t *dev_priv = dev->dev_private;
+
+       drm_sman_takedown(&dev_priv->sman);
+       drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+
+       return 0;
+}
+
+static struct drm_driver driver = {
+       .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR,
+       .load = sis_driver_load,
+       .unload = sis_driver_unload,
+       .context_dtor = NULL,
+       .dma_quiescent = sis_idle,
+       .reclaim_buffers = NULL,
+       .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked,
+       .lastclose = sis_lastclose,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .ioctls = sis_ioctls,
+       .fops = {
+                .owner = THIS_MODULE,
+                .open = drm_open,
+                .release = drm_release,
+                .ioctl = drm_ioctl,
+                .mmap = drm_mmap,
+                .poll = drm_poll,
+                .fasync = drm_fasync,
+       },
+       .pci_driver = {
+                .name = DRIVER_NAME,
+                .id_table = pciidlist,
+       },
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int __init sis_init(void)
+{
+       driver.num_ioctls = sis_max_ioctl;
+       return drm_init(&driver);
+}
+
+static void __exit sis_exit(void)
+{
+       drm_exit(&driver);
+}
+
+module_init(sis_init);
+module_exit(sis_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/sis/sis_drv.h b/drivers/gpu/drm/sis/sis_drv.h
new file mode 100644 (file)
index 0000000..ef940ba
--- /dev/null
@@ -0,0 +1,73 @@
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _SIS_DRV_H_
+#define _SIS_DRV_H_
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR          "SIS, Tungsten Graphics"
+#define DRIVER_NAME            "sis"
+#define DRIVER_DESC            "SIS 300/630/540 and XGI V3XE/V5/V8"
+#define DRIVER_DATE            "20070626"
+#define DRIVER_MAJOR           1
+#define DRIVER_MINOR           3
+#define DRIVER_PATCHLEVEL      0
+
+enum sis_family {
+       SIS_OTHER = 0,
+       SIS_CHIP_315 = 1,
+};
+
+#include "drm_sman.h"
+
+
+#define SIS_BASE (dev_priv->mmio)
+#define SIS_READ(reg)         DRM_READ32(SIS_BASE, reg);
+#define SIS_WRITE(reg, val)   DRM_WRITE32(SIS_BASE, reg, val);
+
+typedef struct drm_sis_private {
+       drm_local_map_t *mmio;
+       unsigned int idle_fault;
+       struct drm_sman sman;
+       unsigned int chipset;
+       int vram_initialized;
+       int agp_initialized;
+       unsigned long vram_offset;
+       unsigned long agp_offset;
+} drm_sis_private_t;
+
+extern int sis_idle(struct drm_device *dev);
+extern void sis_reclaim_buffers_locked(struct drm_device *dev,
+                                      struct drm_file *file_priv);
+extern void sis_lastclose(struct drm_device *dev);
+
+extern struct drm_ioctl_desc sis_ioctls[];
+extern int sis_max_ioctl;
+
+#endif
diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c
new file mode 100644 (file)
index 0000000..b387877
--- /dev/null
@@ -0,0 +1,333 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ *    Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "drmP.h"
+#include "sis_drm.h"
+#include "sis_drv.h"
+
+#include <video/sisfb.h>
+
+#define VIDEO_TYPE 0
+#define AGP_TYPE 1
+
+
+#if defined(CONFIG_FB_SIS)
+/* fb management via fb device */
+
+#define SIS_MM_ALIGN_SHIFT 0
+#define SIS_MM_ALIGN_MASK 0
+
+static void *sis_sman_mm_allocate(void *private, unsigned long size,
+                                 unsigned alignment)
+{
+       struct sis_memreq req;
+
+       req.size = size;
+       sis_malloc(&req);
+       if (req.size == 0)
+               return NULL;
+       else
+               return (void *)~req.offset;
+}
+
+static void sis_sman_mm_free(void *private, void *ref)
+{
+       sis_free(~((unsigned long)ref));
+}
+
+static void sis_sman_mm_destroy(void *private)
+{
+       ;
+}
+
+static unsigned long sis_sman_mm_offset(void *private, void *ref)
+{
+       return ~((unsigned long)ref);
+}
+
+#else /* CONFIG_FB_SIS */
+
+#define SIS_MM_ALIGN_SHIFT 4
+#define SIS_MM_ALIGN_MASK ( (1 << SIS_MM_ALIGN_SHIFT) - 1)
+
+#endif /* CONFIG_FB_SIS */
+
+static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_sis_private_t *dev_priv = dev->dev_private;
+       drm_sis_fb_t *fb = data;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+#if defined(CONFIG_FB_SIS)
+       {
+               struct drm_sman_mm sman_mm;
+               sman_mm.private = (void *)0xFFFFFFFF;
+               sman_mm.allocate = sis_sman_mm_allocate;
+               sman_mm.free = sis_sman_mm_free;
+               sman_mm.destroy = sis_sman_mm_destroy;
+               sman_mm.offset = sis_sman_mm_offset;
+               ret =
+                   drm_sman_set_manager(&dev_priv->sman, VIDEO_TYPE, &sman_mm);
+       }
+#else
+       ret = drm_sman_set_range(&dev_priv->sman, VIDEO_TYPE, 0,
+                                fb->size >> SIS_MM_ALIGN_SHIFT);
+#endif
+
+       if (ret) {
+               DRM_ERROR("VRAM memory manager initialisation error\n");
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
+
+       dev_priv->vram_initialized = 1;
+       dev_priv->vram_offset = fb->offset;
+
+       mutex_unlock(&dev->struct_mutex);
+       DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
+
+       return 0;
+}
+
+static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file_priv,
+                        void *data, int pool)
+{
+       drm_sis_private_t *dev_priv = dev->dev_private;
+       drm_sis_mem_t *mem = data;
+       int retval = 0;
+       struct drm_memblock_item *item;
+
+       mutex_lock(&dev->struct_mutex);
+
+       if (0 == ((pool == 0) ? dev_priv->vram_initialized :
+                     dev_priv->agp_initialized)) {
+               DRM_ERROR
+                   ("Attempt to allocate from uninitialized memory manager.\n");
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
+       }
+
+       mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT;
+       item = drm_sman_alloc(&dev_priv->sman, pool, mem->size, 0,
+                             (unsigned long)file_priv);
+
+       mutex_unlock(&dev->struct_mutex);
+       if (item) {
+               mem->offset = ((pool == 0) ?
+                             dev_priv->vram_offset : dev_priv->agp_offset) +
+                   (item->mm->
+                    offset(item->mm, item->mm_info) << SIS_MM_ALIGN_SHIFT);
+               mem->free = item->user_hash.key;
+               mem->size = mem->size << SIS_MM_ALIGN_SHIFT;
+       } else {
+               mem->offset = 0;
+               mem->size = 0;
+               mem->free = 0;
+               retval = -ENOMEM;
+       }
+
+       DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size,
+                 mem->offset);
+
+       return retval;
+}
+
+static int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_sis_private_t *dev_priv = dev->dev_private;
+       drm_sis_mem_t *mem = data;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_sman_free_key(&dev_priv->sman, mem->free);
+       mutex_unlock(&dev->struct_mutex);
+       DRM_DEBUG("free = 0x%lx\n", mem->free);
+
+       return ret;
+}
+
+static int sis_fb_alloc(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       return sis_drm_alloc(dev, file_priv, data, VIDEO_TYPE);
+}
+
+static int sis_ioctl_agp_init(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv)
+{
+       drm_sis_private_t *dev_priv = dev->dev_private;
+       drm_sis_agp_t *agp = data;
+       int ret;
+       dev_priv = dev->dev_private;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_sman_set_range(&dev_priv->sman, AGP_TYPE, 0,
+                                agp->size >> SIS_MM_ALIGN_SHIFT);
+
+       if (ret) {
+               DRM_ERROR("AGP memory manager initialisation error\n");
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
+
+       dev_priv->agp_initialized = 1;
+       dev_priv->agp_offset = agp->offset;
+       mutex_unlock(&dev->struct_mutex);
+
+       DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
+       return 0;
+}
+
+static int sis_ioctl_agp_alloc(struct drm_device *dev, void *data,
+                              struct drm_file *file_priv)
+{
+
+       return sis_drm_alloc(dev, file_priv, data, AGP_TYPE);
+}
+
+static drm_local_map_t *sis_reg_init(struct drm_device *dev)
+{
+       struct drm_map_list *entry;
+       drm_local_map_t *map;
+
+       list_for_each_entry(entry, &dev->maplist, head) {
+               map = entry->map;
+               if (!map)
+                       continue;
+               if (map->type == _DRM_REGISTERS) {
+                       return map;
+               }
+       }
+       return NULL;
+}
+
+int sis_idle(struct drm_device *dev)
+{
+       drm_sis_private_t *dev_priv = dev->dev_private;
+       uint32_t idle_reg;
+       unsigned long end;
+       int i;
+
+       if (dev_priv->idle_fault)
+               return 0;
+
+       if (dev_priv->mmio == NULL) {
+               dev_priv->mmio = sis_reg_init(dev);
+               if (dev_priv->mmio == NULL) {
+                       DRM_ERROR("Could not find register map.\n");
+                       return 0;
+               }
+       }
+
+       /*
+        * Implement a device switch here if needed
+        */
+
+       if (dev_priv->chipset != SIS_CHIP_315)
+               return 0;
+
+       /*
+        * Timeout after 3 seconds. We cannot use DRM_WAIT_ON here
+        * because its polling frequency is too low.
+        */
+
+       end = jiffies + (DRM_HZ * 3);
+
+       for (i=0; i<4; ++i) {
+               do {
+                       idle_reg = SIS_READ(0x85cc);
+               } while ( !time_after_eq(jiffies, end) &&
+                         ((idle_reg & 0x80000000) != 0x80000000));
+       }
+
+       if (time_after_eq(jiffies, end)) {
+               DRM_ERROR("Graphics engine idle timeout. "
+                         "Disabling idle check\n");
+               dev_priv->idle_fault = 1;
+       }
+
+       /*
+        * The caller never sees an error code. It gets trapped
+        * in libdrm.
+        */
+
+       return 0;
+}
+
+
+void sis_lastclose(struct drm_device *dev)
+{
+       drm_sis_private_t *dev_priv = dev->dev_private;
+
+       if (!dev_priv)
+               return;
+
+       mutex_lock(&dev->struct_mutex);
+       drm_sman_cleanup(&dev_priv->sman);
+       dev_priv->vram_initialized = 0;
+       dev_priv->agp_initialized = 0;
+       dev_priv->mmio = NULL;
+       mutex_unlock(&dev->struct_mutex);
+}
+
+void sis_reclaim_buffers_locked(struct drm_device * dev,
+                               struct drm_file *file_priv)
+{
+       drm_sis_private_t *dev_priv = dev->dev_private;
+
+       mutex_lock(&dev->struct_mutex);
+       if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) {
+               mutex_unlock(&dev->struct_mutex);
+               return;
+       }
+
+       if (dev->driver->dma_quiescent) {
+               dev->driver->dma_quiescent(dev);
+       }
+
+       drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv);
+       mutex_unlock(&dev->struct_mutex);
+       return;
+}
+
+struct drm_ioctl_desc sis_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SIS_FB_FREE, sis_drm_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
+       DRM_IOCTL_DEF(DRM_SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SIS_AGP_FREE, sis_drm_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_SIS_FB_INIT, sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY),
+};
+
+int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
diff --git a/drivers/gpu/drm/tdfx/Makefile b/drivers/gpu/drm/tdfx/Makefile
new file mode 100644 (file)
index 0000000..0379f29
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+tdfx-y := tdfx_drv.o
+
+obj-$(CONFIG_DRM_TDFX) += tdfx.o
diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c
new file mode 100644 (file)
index 0000000..012ff2e
--- /dev/null
@@ -0,0 +1,84 @@
+/* tdfx_drv.c -- tdfx driver -*- linux-c -*-
+ * Created: Thu Oct  7 10:38:32 1999 by faith@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
+ *    Daryll Strauss <daryll@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "drmP.h"
+#include "tdfx_drv.h"
+
+#include "drm_pciids.h"
+
+static struct pci_device_id pciidlist[] = {
+       tdfx_PCI_IDS
+};
+
+static struct drm_driver driver = {
+       .driver_features = DRIVER_USE_MTRR,
+       .reclaim_buffers = drm_core_reclaim_buffers,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .fops = {
+                .owner = THIS_MODULE,
+                .open = drm_open,
+                .release = drm_release,
+                .ioctl = drm_ioctl,
+                .mmap = drm_mmap,
+                .poll = drm_poll,
+                .fasync = drm_fasync,
+       },
+       .pci_driver = {
+                .name = DRIVER_NAME,
+                .id_table = pciidlist,
+       },
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int __init tdfx_init(void)
+{
+       return drm_init(&driver);
+}
+
+static void __exit tdfx_exit(void)
+{
+       drm_exit(&driver);
+}
+
+module_init(tdfx_init);
+module_exit(tdfx_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.h b/drivers/gpu/drm/tdfx/tdfx_drv.h
new file mode 100644 (file)
index 0000000..84204ec
--- /dev/null
@@ -0,0 +1,47 @@
+/* tdfx.h -- 3dfx DRM template customization -*- linux-c -*-
+ * Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com
+ */
+/*
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __TDFX_H__
+#define __TDFX_H__
+
+/* General customization:
+ */
+
+#define DRIVER_AUTHOR          "VA Linux Systems Inc."
+
+#define DRIVER_NAME            "tdfx"
+#define DRIVER_DESC            "3dfx Banshee/Voodoo3+"
+#define DRIVER_DATE            "20010216"
+
+#define DRIVER_MAJOR           1
+#define DRIVER_MINOR           0
+#define DRIVER_PATCHLEVEL      0
+
+#endif
diff --git a/drivers/gpu/drm/via/Makefile b/drivers/gpu/drm/via/Makefile
new file mode 100644 (file)
index 0000000..d59e258
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for the drm device driver.  This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+ccflags-y := -Iinclude/drm
+via-y    := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o
+
+obj-$(CONFIG_DRM_VIA)  +=via.o
diff --git a/drivers/gpu/drm/via/via_3d_reg.h b/drivers/gpu/drm/via/via_3d_reg.h
new file mode 100644 (file)
index 0000000..462375d
--- /dev/null
@@ -0,0 +1,1650 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VIA_3D_REG_H
+#define VIA_3D_REG_H
+#define HC_REG_BASE             0x0400
+
+#define HC_REG_TRANS_SPACE      0x0040
+
+#define HC_ParaN_MASK           0xffffffff
+#define HC_Para_MASK            0x00ffffff
+#define HC_SubA_MASK            0xff000000
+#define HC_SubA_SHIFT           24
+/* Transmission Setting
+ */
+#define HC_REG_TRANS_SET        0x003c
+#define HC_ParaSubType_MASK     0xff000000
+#define HC_ParaType_MASK        0x00ff0000
+#define HC_ParaOS_MASK          0x0000ff00
+#define HC_ParaAdr_MASK         0x000000ff
+#define HC_ParaSubType_SHIFT    24
+#define HC_ParaType_SHIFT       16
+#define HC_ParaOS_SHIFT         8
+#define HC_ParaAdr_SHIFT        0
+
+#define HC_ParaType_CmdVdata    0x0000
+#define HC_ParaType_NotTex      0x0001
+#define HC_ParaType_Tex         0x0002
+#define HC_ParaType_Palette     0x0003
+#define HC_ParaType_PreCR       0x0010
+#define HC_ParaType_Auto        0x00fe
+
+/* Transmission Space
+ */
+#define HC_REG_Hpara0           0x0040
+#define HC_REG_HpataAF          0x02fc
+
+/* Read
+ */
+#define HC_REG_HREngSt          0x0000
+#define HC_REG_HRFIFOempty      0x0004
+#define HC_REG_HRFIFOfull       0x0008
+#define HC_REG_HRErr            0x000c
+#define HC_REG_FIFOstatus       0x0010
+/* HC_REG_HREngSt          0x0000
+ */
+#define HC_HDASZC_MASK          0x00010000
+#define HC_HSGEMI_MASK          0x0000f000
+#define HC_HLGEMISt_MASK        0x00000f00
+#define HC_HCRSt_MASK           0x00000080
+#define HC_HSE0St_MASK          0x00000040
+#define HC_HSE1St_MASK          0x00000020
+#define HC_HPESt_MASK           0x00000010
+#define HC_HXESt_MASK           0x00000008
+#define HC_HBESt_MASK           0x00000004
+#define HC_HE2St_MASK           0x00000002
+#define HC_HE3St_MASK           0x00000001
+/* HC_REG_HRFIFOempty      0x0004
+ */
+#define HC_HRZDempty_MASK       0x00000010
+#define HC_HRTXAempty_MASK      0x00000008
+#define HC_HRTXDempty_MASK      0x00000004
+#define HC_HWZDempty_MASK       0x00000002
+#define HC_HWCDempty_MASK       0x00000001
+/* HC_REG_HRFIFOfull       0x0008
+ */
+#define HC_HRZDfull_MASK        0x00000010
+#define HC_HRTXAfull_MASK       0x00000008
+#define HC_HRTXDfull_MASK       0x00000004
+#define HC_HWZDfull_MASK        0x00000002
+#define HC_HWCDfull_MASK        0x00000001
+/* HC_REG_HRErr            0x000c
+ */
+#define HC_HAGPCMErr_MASK       0x80000000
+#define HC_HAGPCMErrC_MASK      0x70000000
+/* HC_REG_FIFOstatus       0x0010
+ */
+#define HC_HRFIFOATall_MASK     0x80000000
+#define HC_HRFIFOATbusy_MASK    0x40000000
+#define HC_HRATFGMDo_MASK       0x00000100
+#define HC_HRATFGMDi_MASK       0x00000080
+#define HC_HRATFRZD_MASK        0x00000040
+#define HC_HRATFRTXA_MASK       0x00000020
+#define HC_HRATFRTXD_MASK       0x00000010
+#define HC_HRATFWZD_MASK        0x00000008
+#define HC_HRATFWCD_MASK        0x00000004
+#define HC_HRATTXTAG_MASK       0x00000002
+#define HC_HRATTXCH_MASK        0x00000001
+
+/* AGP Command Setting
+ */
+#define HC_SubA_HAGPBstL        0x0060
+#define HC_SubA_HAGPBendL       0x0061
+#define HC_SubA_HAGPCMNT        0x0062
+#define HC_SubA_HAGPBpL         0x0063
+#define HC_SubA_HAGPBpH         0x0064
+/* HC_SubA_HAGPCMNT        0x0062
+ */
+#define HC_HAGPCMNT_MASK        0x00800000
+#define HC_HCmdErrClr_MASK      0x00400000
+#define HC_HAGPBendH_MASK       0x0000ff00
+#define HC_HAGPBstH_MASK        0x000000ff
+#define HC_HAGPBendH_SHIFT      8
+#define HC_HAGPBstH_SHIFT       0
+/* HC_SubA_HAGPBpL         0x0063
+ */
+#define HC_HAGPBpL_MASK         0x00fffffc
+#define HC_HAGPBpID_MASK        0x00000003
+#define HC_HAGPBpID_PAUSE       0x00000000
+#define HC_HAGPBpID_JUMP        0x00000001
+#define HC_HAGPBpID_STOP        0x00000002
+/* HC_SubA_HAGPBpH         0x0064
+ */
+#define HC_HAGPBpH_MASK         0x00ffffff
+
+/* Miscellaneous Settings
+ */
+#define HC_SubA_HClipTB         0x0070
+#define HC_SubA_HClipLR         0x0071
+#define HC_SubA_HFPClipTL       0x0072
+#define HC_SubA_HFPClipBL       0x0073
+#define HC_SubA_HFPClipLL       0x0074
+#define HC_SubA_HFPClipRL       0x0075
+#define HC_SubA_HFPClipTBH      0x0076
+#define HC_SubA_HFPClipLRH      0x0077
+#define HC_SubA_HLP             0x0078
+#define HC_SubA_HLPRF           0x0079
+#define HC_SubA_HSolidCL        0x007a
+#define HC_SubA_HPixGC          0x007b
+#define HC_SubA_HSPXYOS         0x007c
+#define HC_SubA_HVertexCNT      0x007d
+
+#define HC_HClipT_MASK          0x00fff000
+#define HC_HClipT_SHIFT         12
+#define HC_HClipB_MASK          0x00000fff
+#define HC_HClipB_SHIFT         0
+#define HC_HClipL_MASK          0x00fff000
+#define HC_HClipL_SHIFT         12
+#define HC_HClipR_MASK          0x00000fff
+#define HC_HClipR_SHIFT         0
+#define HC_HFPClipBH_MASK       0x0000ff00
+#define HC_HFPClipBH_SHIFT      8
+#define HC_HFPClipTH_MASK       0x000000ff
+#define HC_HFPClipTH_SHIFT      0
+#define HC_HFPClipRH_MASK       0x0000ff00
+#define HC_HFPClipRH_SHIFT      8
+#define HC_HFPClipLH_MASK       0x000000ff
+#define HC_HFPClipLH_SHIFT      0
+#define HC_HSolidCH_MASK        0x000000ff
+#define HC_HPixGC_MASK          0x00800000
+#define HC_HSPXOS_MASK          0x00fff000
+#define HC_HSPXOS_SHIFT         12
+#define HC_HSPYOS_MASK          0x00000fff
+
+/* Command
+ * Command A
+ */
+#define HC_HCmdHeader_MASK      0xfe000000     /*0xffe00000 */
+#define HC_HE3Fire_MASK         0x00100000
+#define HC_HPMType_MASK         0x000f0000
+#define HC_HEFlag_MASK          0x0000e000
+#define HC_HShading_MASK        0x00001c00
+#define HC_HPMValidN_MASK       0x00000200
+#define HC_HPLEND_MASK          0x00000100
+#define HC_HVCycle_MASK         0x000000ff
+#define HC_HVCycle_Style_MASK   0x000000c0
+#define HC_HVCycle_ChgA_MASK    0x00000030
+#define HC_HVCycle_ChgB_MASK    0x0000000c
+#define HC_HVCycle_ChgC_MASK    0x00000003
+#define HC_HPMType_Point        0x00000000
+#define HC_HPMType_Line         0x00010000
+#define HC_HPMType_Tri          0x00020000
+#define HC_HPMType_TriWF        0x00040000
+#define HC_HEFlag_NoAA          0x00000000
+#define HC_HEFlag_ab            0x00008000
+#define HC_HEFlag_bc            0x00004000
+#define HC_HEFlag_ca            0x00002000
+#define HC_HShading_Solid       0x00000000
+#define HC_HShading_FlatA       0x00000400
+#define HC_HShading_FlatB       0x00000800
+#define HC_HShading_FlatC       0x00000c00
+#define HC_HShading_Gouraud     0x00001000
+#define HC_HVCycle_Full         0x00000000
+#define HC_HVCycle_AFP          0x00000040
+#define HC_HVCycle_One          0x000000c0
+#define HC_HVCycle_NewA         0x00000000
+#define HC_HVCycle_AA           0x00000010
+#define HC_HVCycle_AB           0x00000020
+#define HC_HVCycle_AC           0x00000030
+#define HC_HVCycle_NewB         0x00000000
+#define HC_HVCycle_BA           0x00000004
+#define HC_HVCycle_BB           0x00000008
+#define HC_HVCycle_BC           0x0000000c
+#define HC_HVCycle_NewC         0x00000000
+#define HC_HVCycle_CA           0x00000001
+#define HC_HVCycle_CB           0x00000002
+#define HC_HVCycle_CC           0x00000003
+
+/* Command B
+ */
+#define HC_HLPrst_MASK          0x00010000
+#define HC_HLLastP_MASK         0x00008000
+#define HC_HVPMSK_MASK          0x00007f80
+#define HC_HBFace_MASK          0x00000040
+#define HC_H2nd1VT_MASK         0x0000003f
+#define HC_HVPMSK_X             0x00004000
+#define HC_HVPMSK_Y             0x00002000
+#define HC_HVPMSK_Z             0x00001000
+#define HC_HVPMSK_W             0x00000800
+#define HC_HVPMSK_Cd            0x00000400
+#define HC_HVPMSK_Cs            0x00000200
+#define HC_HVPMSK_S             0x00000100
+#define HC_HVPMSK_T             0x00000080
+
+/* Enable Setting
+ */
+#define HC_SubA_HEnable         0x0000
+#define HC_HenTXEnvMap_MASK     0x00200000
+#define HC_HenVertexCNT_MASK    0x00100000
+#define HC_HenCPUDAZ_MASK       0x00080000
+#define HC_HenDASZWC_MASK       0x00040000
+#define HC_HenFBCull_MASK       0x00020000
+#define HC_HenCW_MASK           0x00010000
+#define HC_HenAA_MASK           0x00008000
+#define HC_HenST_MASK           0x00004000
+#define HC_HenZT_MASK           0x00002000
+#define HC_HenZW_MASK           0x00001000
+#define HC_HenAT_MASK           0x00000800
+#define HC_HenAW_MASK           0x00000400
+#define HC_HenSP_MASK           0x00000200
+#define HC_HenLP_MASK           0x00000100
+#define HC_HenTXCH_MASK         0x00000080
+#define HC_HenTXMP_MASK         0x00000040
+#define HC_HenTXPP_MASK         0x00000020
+#define HC_HenTXTR_MASK         0x00000010
+#define HC_HenCS_MASK           0x00000008
+#define HC_HenFOG_MASK          0x00000004
+#define HC_HenABL_MASK          0x00000002
+#define HC_HenDT_MASK           0x00000001
+
+/* Z Setting
+ */
+#define HC_SubA_HZWBBasL        0x0010
+#define HC_SubA_HZWBBasH        0x0011
+#define HC_SubA_HZWBType        0x0012
+#define HC_SubA_HZBiasL         0x0013
+#define HC_SubA_HZWBend         0x0014
+#define HC_SubA_HZWTMD          0x0015
+#define HC_SubA_HZWCDL          0x0016
+#define HC_SubA_HZWCTAGnum      0x0017
+#define HC_SubA_HZCYNum         0x0018
+#define HC_SubA_HZWCFire        0x0019
+/* HC_SubA_HZWBType
+ */
+#define HC_HZWBType_MASK        0x00800000
+#define HC_HZBiasedWB_MASK      0x00400000
+#define HC_HZONEasFF_MASK       0x00200000
+#define HC_HZOONEasFF_MASK      0x00100000
+#define HC_HZWBFM_MASK          0x00030000
+#define HC_HZWBLoc_MASK         0x0000c000
+#define HC_HZWBPit_MASK         0x00003fff
+#define HC_HZWBFM_16            0x00000000
+#define HC_HZWBFM_32            0x00020000
+#define HC_HZWBFM_24            0x00030000
+#define HC_HZWBLoc_Local        0x00000000
+#define HC_HZWBLoc_SyS          0x00004000
+/* HC_SubA_HZWBend
+ */
+#define HC_HZWBend_MASK         0x00ffe000
+#define HC_HZBiasH_MASK         0x000000ff
+#define HC_HZWBend_SHIFT        10
+/* HC_SubA_HZWTMD
+ */
+#define HC_HZWTMD_MASK          0x00070000
+#define HC_HEBEBias_MASK        0x00007f00
+#define HC_HZNF_MASK            0x000000ff
+#define HC_HZWTMD_NeverPass     0x00000000
+#define HC_HZWTMD_LT            0x00010000
+#define HC_HZWTMD_EQ            0x00020000
+#define HC_HZWTMD_LE            0x00030000
+#define HC_HZWTMD_GT            0x00040000
+#define HC_HZWTMD_NE            0x00050000
+#define HC_HZWTMD_GE            0x00060000
+#define HC_HZWTMD_AllPass       0x00070000
+#define HC_HEBEBias_SHIFT       8
+/* HC_SubA_HZWCDL          0x0016
+ */
+#define HC_HZWCDL_MASK          0x00ffffff
+/* HC_SubA_HZWCTAGnum      0x0017
+ */
+#define HC_HZWCTAGnum_MASK      0x00ff0000
+#define HC_HZWCTAGnum_SHIFT     16
+#define HC_HZWCDH_MASK          0x000000ff
+#define HC_HZWCDH_SHIFT         0
+/* HC_SubA_HZCYNum         0x0018
+ */
+#define HC_HZCYNum_MASK         0x00030000
+#define HC_HZCYNum_SHIFT        16
+#define HC_HZWCQWnum_MASK       0x00003fff
+#define HC_HZWCQWnum_SHIFT      0
+/* HC_SubA_HZWCFire        0x0019
+ */
+#define HC_ZWCFire_MASK         0x00010000
+#define HC_HZWCQWnumLast_MASK   0x00003fff
+#define HC_HZWCQWnumLast_SHIFT  0
+
+/* Stencil Setting
+ */
+#define HC_SubA_HSTREF          0x0023
+#define HC_SubA_HSTMD           0x0024
+/* HC_SubA_HSBFM
+ */
+#define HC_HSBFM_MASK           0x00030000
+#define HC_HSBLoc_MASK          0x0000c000
+#define HC_HSBPit_MASK          0x00003fff
+/* HC_SubA_HSTREF
+ */
+#define HC_HSTREF_MASK          0x00ff0000
+#define HC_HSTOPMSK_MASK        0x0000ff00
+#define HC_HSTBMSK_MASK         0x000000ff
+#define HC_HSTREF_SHIFT         16
+#define HC_HSTOPMSK_SHIFT       8
+/* HC_SubA_HSTMD
+ */
+#define HC_HSTMD_MASK           0x00070000
+#define HC_HSTOPSF_MASK         0x000001c0
+#define HC_HSTOPSPZF_MASK       0x00000038
+#define HC_HSTOPSPZP_MASK       0x00000007
+#define HC_HSTMD_NeverPass      0x00000000
+#define HC_HSTMD_LT             0x00010000
+#define HC_HSTMD_EQ             0x00020000
+#define HC_HSTMD_LE             0x00030000
+#define HC_HSTMD_GT             0x00040000
+#define HC_HSTMD_NE             0x00050000
+#define HC_HSTMD_GE             0x00060000
+#define HC_HSTMD_AllPass        0x00070000
+#define HC_HSTOPSF_KEEP         0x00000000
+#define HC_HSTOPSF_ZERO         0x00000040
+#define HC_HSTOPSF_REPLACE      0x00000080
+#define HC_HSTOPSF_INCRSAT      0x000000c0
+#define HC_HSTOPSF_DECRSAT      0x00000100
+#define HC_HSTOPSF_INVERT       0x00000140
+#define HC_HSTOPSF_INCR         0x00000180
+#define HC_HSTOPSF_DECR         0x000001c0
+#define HC_HSTOPSPZF_KEEP       0x00000000
+#define HC_HSTOPSPZF_ZERO       0x00000008
+#define HC_HSTOPSPZF_REPLACE    0x00000010
+#define HC_HSTOPSPZF_INCRSAT    0x00000018
+#define HC_HSTOPSPZF_DECRSAT    0x00000020
+#define HC_HSTOPSPZF_INVERT     0x00000028
+#define HC_HSTOPSPZF_INCR       0x00000030
+#define HC_HSTOPSPZF_DECR       0x00000038
+#define HC_HSTOPSPZP_KEEP       0x00000000
+#define HC_HSTOPSPZP_ZERO       0x00000001
+#define HC_HSTOPSPZP_REPLACE    0x00000002
+#define HC_HSTOPSPZP_INCRSAT    0x00000003
+#define HC_HSTOPSPZP_DECRSAT    0x00000004
+#define HC_HSTOPSPZP_INVERT     0x00000005
+#define HC_HSTOPSPZP_INCR       0x00000006
+#define HC_HSTOPSPZP_DECR       0x00000007
+
+/* Alpha Setting
+ */
+#define HC_SubA_HABBasL         0x0030
+#define HC_SubA_HABBasH         0x0031
+#define HC_SubA_HABFM           0x0032
+#define HC_SubA_HATMD           0x0033
+#define HC_SubA_HABLCsat        0x0034
+#define HC_SubA_HABLCop         0x0035
+#define HC_SubA_HABLAsat        0x0036
+#define HC_SubA_HABLAop         0x0037
+#define HC_SubA_HABLRCa         0x0038
+#define HC_SubA_HABLRFCa        0x0039
+#define HC_SubA_HABLRCbias      0x003a
+#define HC_SubA_HABLRCb         0x003b
+#define HC_SubA_HABLRFCb        0x003c
+#define HC_SubA_HABLRAa         0x003d
+#define HC_SubA_HABLRAb         0x003e
+/* HC_SubA_HABFM
+ */
+#define HC_HABFM_MASK           0x00030000
+#define HC_HABLoc_MASK          0x0000c000
+#define HC_HABPit_MASK          0x000007ff
+/* HC_SubA_HATMD
+ */
+#define HC_HATMD_MASK           0x00000700
+#define HC_HATREF_MASK          0x000000ff
+#define HC_HATMD_NeverPass      0x00000000
+#define HC_HATMD_LT             0x00000100
+#define HC_HATMD_EQ             0x00000200
+#define HC_HATMD_LE             0x00000300
+#define HC_HATMD_GT             0x00000400
+#define HC_HATMD_NE             0x00000500
+#define HC_HATMD_GE             0x00000600
+#define HC_HATMD_AllPass        0x00000700
+/* HC_SubA_HABLCsat
+ */
+#define HC_HABLCsat_MASK        0x00010000
+#define HC_HABLCa_MASK          0x0000fc00
+#define HC_HABLCa_C_MASK        0x0000c000
+#define HC_HABLCa_OPC_MASK      0x00003c00
+#define HC_HABLFCa_MASK         0x000003f0
+#define HC_HABLFCa_C_MASK       0x00000300
+#define HC_HABLFCa_OPC_MASK     0x000000f0
+#define HC_HABLCbias_MASK       0x0000000f
+#define HC_HABLCbias_C_MASK     0x00000008
+#define HC_HABLCbias_OPC_MASK   0x00000007
+/*-- Define the input color.
+ */
+#define HC_XC_Csrc              0x00000000
+#define HC_XC_Cdst              0x00000001
+#define HC_XC_Asrc              0x00000002
+#define HC_XC_Adst              0x00000003
+#define HC_XC_Fog               0x00000004
+#define HC_XC_HABLRC            0x00000005
+#define HC_XC_minSrcDst         0x00000006
+#define HC_XC_maxSrcDst         0x00000007
+#define HC_XC_mimAsrcInvAdst    0x00000008
+#define HC_XC_OPC               0x00000000
+#define HC_XC_InvOPC            0x00000010
+#define HC_XC_OPCp5             0x00000020
+/*-- Define the input Alpha
+ */
+#define HC_XA_OPA               0x00000000
+#define HC_XA_InvOPA            0x00000010
+#define HC_XA_OPAp5             0x00000020
+#define HC_XA_0                 0x00000000
+#define HC_XA_Asrc              0x00000001
+#define HC_XA_Adst              0x00000002
+#define HC_XA_Fog               0x00000003
+#define HC_XA_minAsrcFog        0x00000004
+#define HC_XA_minAsrcAdst       0x00000005
+#define HC_XA_maxAsrcFog        0x00000006
+#define HC_XA_maxAsrcAdst       0x00000007
+#define HC_XA_HABLRA            0x00000008
+#define HC_XA_minAsrcInvAdst    0x00000008
+#define HC_XA_HABLFRA           0x00000009
+/*--
+ */
+#define HC_HABLCa_OPC           (HC_XC_OPC << 10)
+#define HC_HABLCa_InvOPC        (HC_XC_InvOPC << 10)
+#define HC_HABLCa_OPCp5         (HC_XC_OPCp5 << 10)
+#define HC_HABLCa_Csrc          (HC_XC_Csrc << 10)
+#define HC_HABLCa_Cdst          (HC_XC_Cdst << 10)
+#define HC_HABLCa_Asrc          (HC_XC_Asrc << 10)
+#define HC_HABLCa_Adst          (HC_XC_Adst << 10)
+#define HC_HABLCa_Fog           (HC_XC_Fog << 10)
+#define HC_HABLCa_HABLRCa       (HC_XC_HABLRC << 10)
+#define HC_HABLCa_minSrcDst     (HC_XC_minSrcDst << 10)
+#define HC_HABLCa_maxSrcDst     (HC_XC_maxSrcDst << 10)
+#define HC_HABLFCa_OPC              (HC_XC_OPC << 4)
+#define HC_HABLFCa_InvOPC           (HC_XC_InvOPC << 4)
+#define HC_HABLFCa_OPCp5            (HC_XC_OPCp5 << 4)
+#define HC_HABLFCa_Csrc             (HC_XC_Csrc << 4)
+#define HC_HABLFCa_Cdst             (HC_XC_Cdst << 4)
+#define HC_HABLFCa_Asrc             (HC_XC_Asrc << 4)
+#define HC_HABLFCa_Adst             (HC_XC_Adst << 4)
+#define HC_HABLFCa_Fog              (HC_XC_Fog << 4)
+#define HC_HABLFCa_HABLRCa          (HC_XC_HABLRC << 4)
+#define HC_HABLFCa_minSrcDst        (HC_XC_minSrcDst << 4)
+#define HC_HABLFCa_maxSrcDst        (HC_XC_maxSrcDst << 4)
+#define HC_HABLFCa_mimAsrcInvAdst   (HC_XC_mimAsrcInvAdst << 4)
+#define HC_HABLCbias_HABLRCbias 0x00000000
+#define HC_HABLCbias_Asrc       0x00000001
+#define HC_HABLCbias_Adst       0x00000002
+#define HC_HABLCbias_Fog        0x00000003
+#define HC_HABLCbias_Cin        0x00000004
+/* HC_SubA_HABLCop         0x0035
+ */
+#define HC_HABLdot_MASK         0x00010000
+#define HC_HABLCop_MASK         0x00004000
+#define HC_HABLCb_MASK          0x00003f00
+#define HC_HABLCb_C_MASK        0x00003000
+#define HC_HABLCb_OPC_MASK      0x00000f00
+#define HC_HABLFCb_MASK         0x000000fc
+#define HC_HABLFCb_C_MASK       0x000000c0
+#define HC_HABLFCb_OPC_MASK     0x0000003c
+#define HC_HABLCshift_MASK      0x00000003
+#define HC_HABLCb_OPC           (HC_XC_OPC << 8)
+#define HC_HABLCb_InvOPC        (HC_XC_InvOPC << 8)
+#define HC_HABLCb_OPCp5         (HC_XC_OPCp5 << 8)
+#define HC_HABLCb_Csrc          (HC_XC_Csrc << 8)
+#define HC_HABLCb_Cdst          (HC_XC_Cdst << 8)
+#define HC_HABLCb_Asrc          (HC_XC_Asrc << 8)
+#define HC_HABLCb_Adst          (HC_XC_Adst << 8)
+#define HC_HABLCb_Fog           (HC_XC_Fog << 8)
+#define HC_HABLCb_HABLRCa       (HC_XC_HABLRC << 8)
+#define HC_HABLCb_minSrcDst     (HC_XC_minSrcDst << 8)
+#define HC_HABLCb_maxSrcDst     (HC_XC_maxSrcDst << 8)
+#define HC_HABLFCb_OPC              (HC_XC_OPC << 2)
+#define HC_HABLFCb_InvOPC           (HC_XC_InvOPC << 2)
+#define HC_HABLFCb_OPCp5            (HC_XC_OPCp5 << 2)
+#define HC_HABLFCb_Csrc             (HC_XC_Csrc << 2)
+#define HC_HABLFCb_Cdst             (HC_XC_Cdst << 2)
+#define HC_HABLFCb_Asrc             (HC_XC_Asrc << 2)
+#define HC_HABLFCb_Adst             (HC_XC_Adst << 2)
+#define HC_HABLFCb_Fog              (HC_XC_Fog << 2)
+#define HC_HABLFCb_HABLRCb          (HC_XC_HABLRC << 2)
+#define HC_HABLFCb_minSrcDst        (HC_XC_minSrcDst << 2)
+#define HC_HABLFCb_maxSrcDst        (HC_XC_maxSrcDst << 2)
+#define HC_HABLFCb_mimAsrcInvAdst   (HC_XC_mimAsrcInvAdst << 2)
+/* HC_SubA_HABLAsat        0x0036
+ */
+#define HC_HABLAsat_MASK        0x00010000
+#define HC_HABLAa_MASK          0x0000fc00
+#define HC_HABLAa_A_MASK        0x0000c000
+#define HC_HABLAa_OPA_MASK      0x00003c00
+#define HC_HABLFAa_MASK         0x000003f0
+#define HC_HABLFAa_A_MASK       0x00000300
+#define HC_HABLFAa_OPA_MASK     0x000000f0
+#define HC_HABLAbias_MASK       0x0000000f
+#define HC_HABLAbias_A_MASK     0x00000008
+#define HC_HABLAbias_OPA_MASK   0x00000007
+#define HC_HABLAa_OPA           (HC_XA_OPA << 10)
+#define HC_HABLAa_InvOPA        (HC_XA_InvOPA << 10)
+#define HC_HABLAa_OPAp5         (HC_XA_OPAp5 << 10)
+#define HC_HABLAa_0             (HC_XA_0 << 10)
+#define HC_HABLAa_Asrc          (HC_XA_Asrc << 10)
+#define HC_HABLAa_Adst          (HC_XA_Adst << 10)
+#define HC_HABLAa_Fog           (HC_XA_Fog << 10)
+#define HC_HABLAa_minAsrcFog    (HC_XA_minAsrcFog << 10)
+#define HC_HABLAa_minAsrcAdst   (HC_XA_minAsrcAdst << 10)
+#define HC_HABLAa_maxAsrcFog    (HC_XA_maxAsrcFog << 10)
+#define HC_HABLAa_maxAsrcAdst   (HC_XA_maxAsrcAdst << 10)
+#define HC_HABLAa_HABLRA        (HC_XA_HABLRA << 10)
+#define HC_HABLFAa_OPA          (HC_XA_OPA << 4)
+#define HC_HABLFAa_InvOPA       (HC_XA_InvOPA << 4)
+#define HC_HABLFAa_OPAp5        (HC_XA_OPAp5 << 4)
+#define HC_HABLFAa_0            (HC_XA_0 << 4)
+#define HC_HABLFAa_Asrc         (HC_XA_Asrc << 4)
+#define HC_HABLFAa_Adst         (HC_XA_Adst << 4)
+#define HC_HABLFAa_Fog          (HC_XA_Fog << 4)
+#define HC_HABLFAa_minAsrcFog   (HC_XA_minAsrcFog << 4)
+#define HC_HABLFAa_minAsrcAdst  (HC_XA_minAsrcAdst << 4)
+#define HC_HABLFAa_maxAsrcFog   (HC_XA_maxAsrcFog << 4)
+#define HC_HABLFAa_maxAsrcAdst  (HC_XA_maxAsrcAdst << 4)
+#define HC_HABLFAa_minAsrcInvAdst   (HC_XA_minAsrcInvAdst << 4)
+#define HC_HABLFAa_HABLFRA          (HC_XA_HABLFRA << 4)
+#define HC_HABLAbias_HABLRAbias 0x00000000
+#define HC_HABLAbias_Asrc       0x00000001
+#define HC_HABLAbias_Adst       0x00000002
+#define HC_HABLAbias_Fog        0x00000003
+#define HC_HABLAbias_Aaa        0x00000004
+/* HC_SubA_HABLAop         0x0037
+ */
+#define HC_HABLAop_MASK         0x00004000
+#define HC_HABLAb_MASK          0x00003f00
+#define HC_HABLAb_OPA_MASK      0x00000f00
+#define HC_HABLFAb_MASK         0x000000fc
+#define HC_HABLFAb_OPA_MASK     0x0000003c
+#define HC_HABLAshift_MASK      0x00000003
+#define HC_HABLAb_OPA           (HC_XA_OPA << 8)
+#define HC_HABLAb_InvOPA        (HC_XA_InvOPA << 8)
+#define HC_HABLAb_OPAp5         (HC_XA_OPAp5 << 8)
+#define HC_HABLAb_0             (HC_XA_0 << 8)
+#define HC_HABLAb_Asrc          (HC_XA_Asrc << 8)
+#define HC_HABLAb_Adst          (HC_XA_Adst << 8)
+#define HC_HABLAb_Fog           (HC_XA_Fog << 8)
+#define HC_HABLAb_minAsrcFog    (HC_XA_minAsrcFog << 8)
+#define HC_HABLAb_minAsrcAdst   (HC_XA_minAsrcAdst << 8)
+#define HC_HABLAb_maxAsrcFog    (HC_XA_maxAsrcFog << 8)
+#define HC_HABLAb_maxAsrcAdst   (HC_XA_maxAsrcAdst << 8)
+#define HC_HABLAb_HABLRA        (HC_XA_HABLRA << 8)
+#define HC_HABLFAb_OPA          (HC_XA_OPA << 2)
+#define HC_HABLFAb_InvOPA       (HC_XA_InvOPA << 2)
+#define HC_HABLFAb_OPAp5        (HC_XA_OPAp5 << 2)
+#define HC_HABLFAb_0            (HC_XA_0 << 2)
+#define HC_HABLFAb_Asrc         (HC_XA_Asrc << 2)
+#define HC_HABLFAb_Adst         (HC_XA_Adst << 2)
+#define HC_HABLFAb_Fog          (HC_XA_Fog << 2)
+#define HC_HABLFAb_minAsrcFog   (HC_XA_minAsrcFog << 2)
+#define HC_HABLFAb_minAsrcAdst  (HC_XA_minAsrcAdst << 2)
+#define HC_HABLFAb_maxAsrcFog   (HC_XA_maxAsrcFog << 2)
+#define HC_HABLFAb_maxAsrcAdst  (HC_XA_maxAsrcAdst << 2)
+#define HC_HABLFAb_minAsrcInvAdst   (HC_XA_minAsrcInvAdst << 2)
+#define HC_HABLFAb_HABLFRA          (HC_XA_HABLFRA << 2)
+/* HC_SubA_HABLRAa         0x003d
+ */
+#define HC_HABLRAa_MASK         0x00ff0000
+#define HC_HABLRFAa_MASK        0x0000ff00
+#define HC_HABLRAbias_MASK      0x000000ff
+#define HC_HABLRAa_SHIFT        16
+#define HC_HABLRFAa_SHIFT       8
+/* HC_SubA_HABLRAb         0x003e
+ */
+#define HC_HABLRAb_MASK         0x0000ff00
+#define HC_HABLRFAb_MASK        0x000000ff
+#define HC_HABLRAb_SHIFT        8
+
+/* Destination Setting
+ */
+#define HC_SubA_HDBBasL         0x0040
+#define HC_SubA_HDBBasH         0x0041
+#define HC_SubA_HDBFM           0x0042
+#define HC_SubA_HFBBMSKL        0x0043
+#define HC_SubA_HROP            0x0044
+/* HC_SubA_HDBFM           0x0042
+ */
+#define HC_HDBFM_MASK           0x001f0000
+#define HC_HDBLoc_MASK          0x0000c000
+#define HC_HDBPit_MASK          0x00003fff
+#define HC_HDBFM_RGB555         0x00000000
+#define HC_HDBFM_RGB565         0x00010000
+#define HC_HDBFM_ARGB4444       0x00020000
+#define HC_HDBFM_ARGB1555       0x00030000
+#define HC_HDBFM_BGR555         0x00040000
+#define HC_HDBFM_BGR565         0x00050000
+#define HC_HDBFM_ABGR4444       0x00060000
+#define HC_HDBFM_ABGR1555       0x00070000
+#define HC_HDBFM_ARGB0888       0x00080000
+#define HC_HDBFM_ARGB8888       0x00090000
+#define HC_HDBFM_ABGR0888       0x000a0000
+#define HC_HDBFM_ABGR8888       0x000b0000
+#define HC_HDBLoc_Local         0x00000000
+#define HC_HDBLoc_Sys           0x00004000
+/* HC_SubA_HROP            0x0044
+ */
+#define HC_HROP_MASK            0x00000f00
+#define HC_HFBBMSKH_MASK        0x000000ff
+#define HC_HROP_BLACK           0x00000000
+#define HC_HROP_DPon            0x00000100
+#define HC_HROP_DPna            0x00000200
+#define HC_HROP_Pn              0x00000300
+#define HC_HROP_PDna            0x00000400
+#define HC_HROP_Dn              0x00000500
+#define HC_HROP_DPx             0x00000600
+#define HC_HROP_DPan            0x00000700
+#define HC_HROP_DPa             0x00000800
+#define HC_HROP_DPxn            0x00000900
+#define HC_HROP_D               0x00000a00
+#define HC_HROP_DPno            0x00000b00
+#define HC_HROP_P               0x00000c00
+#define HC_HROP_PDno            0x00000d00
+#define HC_HROP_DPo             0x00000e00
+#define HC_HROP_WHITE           0x00000f00
+
+/* Fog Setting
+ */
+#define HC_SubA_HFogLF          0x0050
+#define HC_SubA_HFogCL          0x0051
+#define HC_SubA_HFogCH          0x0052
+#define HC_SubA_HFogStL         0x0053
+#define HC_SubA_HFogStH         0x0054
+#define HC_SubA_HFogOOdMF       0x0055
+#define HC_SubA_HFogOOdEF       0x0056
+#define HC_SubA_HFogEndL        0x0057
+#define HC_SubA_HFogDenst       0x0058
+/* HC_SubA_FogLF           0x0050
+ */
+#define HC_FogLF_MASK           0x00000010
+#define HC_FogEq_MASK           0x00000008
+#define HC_FogMD_MASK           0x00000007
+#define HC_FogMD_LocalFog        0x00000000
+#define HC_FogMD_LinearFog       0x00000002
+#define HC_FogMD_ExponentialFog  0x00000004
+#define HC_FogMD_Exponential2Fog 0x00000005
+/* #define HC_FogMD_FogTable       0x00000003 */
+
+/* HC_SubA_HFogDenst        0x0058
+ */
+#define HC_FogDenst_MASK        0x001fff00
+#define HC_FogEndL_MASK         0x000000ff
+
+/* Texture subtype definitions
+ */
+#define HC_SubType_Tex0         0x00000000
+#define HC_SubType_Tex1         0x00000001
+#define HC_SubType_TexGeneral   0x000000fe
+
+/* Attribute of texture n
+ */
+#define HC_SubA_HTXnL0BasL      0x0000
+#define HC_SubA_HTXnL1BasL      0x0001
+#define HC_SubA_HTXnL2BasL      0x0002
+#define HC_SubA_HTXnL3BasL      0x0003
+#define HC_SubA_HTXnL4BasL      0x0004
+#define HC_SubA_HTXnL5BasL      0x0005
+#define HC_SubA_HTXnL6BasL      0x0006
+#define HC_SubA_HTXnL7BasL      0x0007
+#define HC_SubA_HTXnL8BasL      0x0008
+#define HC_SubA_HTXnL9BasL      0x0009
+#define HC_SubA_HTXnLaBasL      0x000a
+#define HC_SubA_HTXnLbBasL      0x000b
+#define HC_SubA_HTXnLcBasL      0x000c
+#define HC_SubA_HTXnLdBasL      0x000d
+#define HC_SubA_HTXnLeBasL      0x000e
+#define HC_SubA_HTXnLfBasL      0x000f
+#define HC_SubA_HTXnL10BasL     0x0010
+#define HC_SubA_HTXnL11BasL     0x0011
+#define HC_SubA_HTXnL012BasH    0x0020
+#define HC_SubA_HTXnL345BasH    0x0021
+#define HC_SubA_HTXnL678BasH    0x0022
+#define HC_SubA_HTXnL9abBasH    0x0023
+#define HC_SubA_HTXnLcdeBasH    0x0024
+#define HC_SubA_HTXnLf1011BasH  0x0025
+#define HC_SubA_HTXnL0Pit       0x002b
+#define HC_SubA_HTXnL1Pit       0x002c
+#define HC_SubA_HTXnL2Pit       0x002d
+#define HC_SubA_HTXnL3Pit       0x002e
+#define HC_SubA_HTXnL4Pit       0x002f
+#define HC_SubA_HTXnL5Pit       0x0030
+#define HC_SubA_HTXnL6Pit       0x0031
+#define HC_SubA_HTXnL7Pit       0x0032
+#define HC_SubA_HTXnL8Pit       0x0033
+#define HC_SubA_HTXnL9Pit       0x0034
+#define HC_SubA_HTXnLaPit       0x0035
+#define HC_SubA_HTXnLbPit       0x0036
+#define HC_SubA_HTXnLcPit       0x0037
+#define HC_SubA_HTXnLdPit       0x0038
+#define HC_SubA_HTXnLePit       0x0039
+#define HC_SubA_HTXnLfPit       0x003a
+#define HC_SubA_HTXnL10Pit      0x003b
+#define HC_SubA_HTXnL11Pit      0x003c
+#define HC_SubA_HTXnL0_5WE      0x004b
+#define HC_SubA_HTXnL6_bWE      0x004c
+#define HC_SubA_HTXnLc_11WE     0x004d
+#define HC_SubA_HTXnL0_5HE      0x0051
+#define HC_SubA_HTXnL6_bHE      0x0052
+#define HC_SubA_HTXnLc_11HE     0x0053
+#define HC_SubA_HTXnL0OS        0x0077
+#define HC_SubA_HTXnTB          0x0078
+#define HC_SubA_HTXnMPMD        0x0079
+#define HC_SubA_HTXnCLODu       0x007a
+#define HC_SubA_HTXnFM          0x007b
+#define HC_SubA_HTXnTRCH        0x007c
+#define HC_SubA_HTXnTRCL        0x007d
+#define HC_SubA_HTXnTBC         0x007e
+#define HC_SubA_HTXnTRAH        0x007f
+#define HC_SubA_HTXnTBLCsat     0x0080
+#define HC_SubA_HTXnTBLCop      0x0081
+#define HC_SubA_HTXnTBLMPfog    0x0082
+#define HC_SubA_HTXnTBLAsat     0x0083
+#define HC_SubA_HTXnTBLRCa      0x0085
+#define HC_SubA_HTXnTBLRCb      0x0086
+#define HC_SubA_HTXnTBLRCc      0x0087
+#define HC_SubA_HTXnTBLRCbias   0x0088
+#define HC_SubA_HTXnTBLRAa      0x0089
+#define HC_SubA_HTXnTBLRFog     0x008a
+#define HC_SubA_HTXnBumpM00     0x0090
+#define HC_SubA_HTXnBumpM01     0x0091
+#define HC_SubA_HTXnBumpM10     0x0092
+#define HC_SubA_HTXnBumpM11     0x0093
+#define HC_SubA_HTXnLScale      0x0094
+#define HC_SubA_HTXSMD          0x0000
+/* HC_SubA_HTXnL012BasH    0x0020
+ */
+#define HC_HTXnL0BasH_MASK      0x000000ff
+#define HC_HTXnL1BasH_MASK      0x0000ff00
+#define HC_HTXnL2BasH_MASK      0x00ff0000
+#define HC_HTXnL1BasH_SHIFT     8
+#define HC_HTXnL2BasH_SHIFT     16
+/* HC_SubA_HTXnL345BasH    0x0021
+ */
+#define HC_HTXnL3BasH_MASK      0x000000ff
+#define HC_HTXnL4BasH_MASK      0x0000ff00
+#define HC_HTXnL5BasH_MASK      0x00ff0000
+#define HC_HTXnL4BasH_SHIFT     8
+#define HC_HTXnL5BasH_SHIFT     16
+/* HC_SubA_HTXnL678BasH    0x0022
+ */
+#define HC_HTXnL6BasH_MASK      0x000000ff
+#define HC_HTXnL7BasH_MASK      0x0000ff00
+#define HC_HTXnL8BasH_MASK      0x00ff0000
+#define HC_HTXnL7BasH_SHIFT     8
+#define HC_HTXnL8BasH_SHIFT     16
+/* HC_SubA_HTXnL9abBasH    0x0023
+ */
+#define HC_HTXnL9BasH_MASK      0x000000ff
+#define HC_HTXnLaBasH_MASK      0x0000ff00
+#define HC_HTXnLbBasH_MASK      0x00ff0000
+#define HC_HTXnLaBasH_SHIFT     8
+#define HC_HTXnLbBasH_SHIFT     16
+/* HC_SubA_HTXnLcdeBasH    0x0024
+ */
+#define HC_HTXnLcBasH_MASK      0x000000ff
+#define HC_HTXnLdBasH_MASK      0x0000ff00
+#define HC_HTXnLeBasH_MASK      0x00ff0000
+#define HC_HTXnLdBasH_SHIFT     8
+#define HC_HTXnLeBasH_SHIFT     16
+/* HC_SubA_HTXnLcdeBasH    0x0025
+ */
+#define HC_HTXnLfBasH_MASK      0x000000ff
+#define HC_HTXnL10BasH_MASK      0x0000ff00
+#define HC_HTXnL11BasH_MASK      0x00ff0000
+#define HC_HTXnL10BasH_SHIFT     8
+#define HC_HTXnL11BasH_SHIFT     16
+/* HC_SubA_HTXnL0Pit       0x002b
+ */
+#define HC_HTXnLnPit_MASK       0x00003fff
+#define HC_HTXnEnPit_MASK       0x00080000
+#define HC_HTXnLnPitE_MASK      0x00f00000
+#define HC_HTXnLnPitE_SHIFT     20
+/* HC_SubA_HTXnL0_5WE      0x004b
+ */
+#define HC_HTXnL0WE_MASK        0x0000000f
+#define HC_HTXnL1WE_MASK        0x000000f0
+#define HC_HTXnL2WE_MASK        0x00000f00
+#define HC_HTXnL3WE_MASK        0x0000f000
+#define HC_HTXnL4WE_MASK        0x000f0000
+#define HC_HTXnL5WE_MASK        0x00f00000
+#define HC_HTXnL1WE_SHIFT       4
+#define HC_HTXnL2WE_SHIFT       8
+#define HC_HTXnL3WE_SHIFT       12
+#define HC_HTXnL4WE_SHIFT       16
+#define HC_HTXnL5WE_SHIFT       20
+/* HC_SubA_HTXnL6_bWE      0x004c
+ */
+#define HC_HTXnL6WE_MASK        0x0000000f
+#define HC_HTXnL7WE_MASK        0x000000f0
+#define HC_HTXnL8WE_MASK        0x00000f00
+#define HC_HTXnL9WE_MASK        0x0000f000
+#define HC_HTXnLaWE_MASK        0x000f0000
+#define HC_HTXnLbWE_MASK        0x00f00000
+#define HC_HTXnL7WE_SHIFT       4
+#define HC_HTXnL8WE_SHIFT       8
+#define HC_HTXnL9WE_SHIFT       12
+#define HC_HTXnLaWE_SHIFT       16
+#define HC_HTXnLbWE_SHIFT       20
+/* HC_SubA_HTXnLc_11WE      0x004d
+ */
+#define HC_HTXnLcWE_MASK        0x0000000f
+#define HC_HTXnLdWE_MASK        0x000000f0
+#define HC_HTXnLeWE_MASK        0x00000f00
+#define HC_HTXnLfWE_MASK        0x0000f000
+#define HC_HTXnL10WE_MASK       0x000f0000
+#define HC_HTXnL11WE_MASK       0x00f00000
+#define HC_HTXnLdWE_SHIFT       4
+#define HC_HTXnLeWE_SHIFT       8
+#define HC_HTXnLfWE_SHIFT       12
+#define HC_HTXnL10WE_SHIFT      16
+#define HC_HTXnL11WE_SHIFT      20
+/* HC_SubA_HTXnL0_5HE      0x0051
+ */
+#define HC_HTXnL0HE_MASK        0x0000000f
+#define HC_HTXnL1HE_MASK        0x000000f0
+#define HC_HTXnL2HE_MASK        0x00000f00
+#define HC_HTXnL3HE_MASK        0x0000f000
+#define HC_HTXnL4HE_MASK        0x000f0000
+#define HC_HTXnL5HE_MASK        0x00f00000
+#define HC_HTXnL1HE_SHIFT       4
+#define HC_HTXnL2HE_SHIFT       8
+#define HC_HTXnL3HE_SHIFT       12
+#define HC_HTXnL4HE_SHIFT       16
+#define HC_HTXnL5HE_SHIFT       20
+/* HC_SubA_HTXnL6_bHE      0x0052
+ */
+#define HC_HTXnL6HE_MASK        0x0000000f
+#define HC_HTXnL7HE_MASK        0x000000f0
+#define HC_HTXnL8HE_MASK        0x00000f00
+#define HC_HTXnL9HE_MASK        0x0000f000
+#define HC_HTXnLaHE_MASK        0x000f0000
+#define HC_HTXnLbHE_MASK        0x00f00000
+#define HC_HTXnL7HE_SHIFT       4
+#define HC_HTXnL8HE_SHIFT       8
+#define HC_HTXnL9HE_SHIFT       12
+#define HC_HTXnLaHE_SHIFT       16
+#define HC_HTXnLbHE_SHIFT       20
+/* HC_SubA_HTXnLc_11HE      0x0053
+ */
+#define HC_HTXnLcHE_MASK        0x0000000f
+#define HC_HTXnLdHE_MASK        0x000000f0
+#define HC_HTXnLeHE_MASK        0x00000f00
+#define HC_HTXnLfHE_MASK        0x0000f000
+#define HC_HTXnL10HE_MASK       0x000f0000
+#define HC_HTXnL11HE_MASK       0x00f00000
+#define HC_HTXnLdHE_SHIFT       4
+#define HC_HTXnLeHE_SHIFT       8
+#define HC_HTXnLfHE_SHIFT       12
+#define HC_HTXnL10HE_SHIFT      16
+#define HC_HTXnL11HE_SHIFT      20
+/* HC_SubA_HTXnL0OS        0x0077
+ */
+#define HC_HTXnL0OS_MASK        0x003ff000
+#define HC_HTXnLVmax_MASK       0x00000fc0
+#define HC_HTXnLVmin_MASK       0x0000003f
+#define HC_HTXnL0OS_SHIFT       12
+#define HC_HTXnLVmax_SHIFT      6
+/* HC_SubA_HTXnTB          0x0078
+ */
+#define HC_HTXnTB_MASK          0x00f00000
+#define HC_HTXnFLSe_MASK        0x0000e000
+#define HC_HTXnFLSs_MASK        0x00001c00
+#define HC_HTXnFLTe_MASK        0x00000380
+#define HC_HTXnFLTs_MASK        0x00000070
+#define HC_HTXnFLDs_MASK        0x0000000f
+#define HC_HTXnTB_NoTB          0x00000000
+#define HC_HTXnTB_TBC_S         0x00100000
+#define HC_HTXnTB_TBC_T         0x00200000
+#define HC_HTXnTB_TB_S          0x00400000
+#define HC_HTXnTB_TB_T          0x00800000
+#define HC_HTXnFLSe_Nearest     0x00000000
+#define HC_HTXnFLSe_Linear      0x00002000
+#define HC_HTXnFLSe_NonLinear   0x00004000
+#define HC_HTXnFLSe_Sharp       0x00008000
+#define HC_HTXnFLSe_Flat_Gaussian_Cubic 0x0000c000
+#define HC_HTXnFLSs_Nearest     0x00000000
+#define HC_HTXnFLSs_Linear      0x00000400
+#define HC_HTXnFLSs_NonLinear   0x00000800
+#define HC_HTXnFLSs_Flat_Gaussian_Cubic 0x00001800
+#define HC_HTXnFLTe_Nearest     0x00000000
+#define HC_HTXnFLTe_Linear      0x00000080
+#define HC_HTXnFLTe_NonLinear   0x00000100
+#define HC_HTXnFLTe_Sharp       0x00000180
+#define HC_HTXnFLTe_Flat_Gaussian_Cubic 0x00000300
+#define HC_HTXnFLTs_Nearest     0x00000000
+#define HC_HTXnFLTs_Linear      0x00000010
+#define HC_HTXnFLTs_NonLinear   0x00000020
+#define HC_HTXnFLTs_Flat_Gaussian_Cubic 0x00000060
+#define HC_HTXnFLDs_Tex0        0x00000000
+#define HC_HTXnFLDs_Nearest     0x00000001
+#define HC_HTXnFLDs_Linear      0x00000002
+#define HC_HTXnFLDs_NonLinear   0x00000003
+#define HC_HTXnFLDs_Dither      0x00000004
+#define HC_HTXnFLDs_ConstLOD    0x00000005
+#define HC_HTXnFLDs_Ani         0x00000006
+#define HC_HTXnFLDs_AniDither   0x00000007
+/* HC_SubA_HTXnMPMD        0x0079
+ */
+#define HC_HTXnMPMD_SMASK       0x00070000
+#define HC_HTXnMPMD_TMASK       0x00380000
+#define HC_HTXnLODDTf_MASK      0x00000007
+#define HC_HTXnXY2ST_MASK       0x00000008
+#define HC_HTXnMPMD_Tsingle     0x00000000
+#define HC_HTXnMPMD_Tclamp      0x00080000
+#define HC_HTXnMPMD_Trepeat     0x00100000
+#define HC_HTXnMPMD_Tmirror     0x00180000
+#define HC_HTXnMPMD_Twrap       0x00200000
+#define HC_HTXnMPMD_Ssingle     0x00000000
+#define HC_HTXnMPMD_Sclamp      0x00010000
+#define HC_HTXnMPMD_Srepeat     0x00020000
+#define HC_HTXnMPMD_Smirror     0x00030000
+#define HC_HTXnMPMD_Swrap       0x00040000
+/* HC_SubA_HTXnCLODu       0x007a
+ */
+#define HC_HTXnCLODu_MASK       0x000ffc00
+#define HC_HTXnCLODd_MASK       0x000003ff
+#define HC_HTXnCLODu_SHIFT      10
+/* HC_SubA_HTXnFM          0x007b
+ */
+#define HC_HTXnFM_MASK          0x00ff0000
+#define HC_HTXnLoc_MASK         0x00000003
+#define HC_HTXnFM_INDEX         0x00000000
+#define HC_HTXnFM_Intensity     0x00080000
+#define HC_HTXnFM_Lum           0x00100000
+#define HC_HTXnFM_Alpha         0x00180000
+#define HC_HTXnFM_DX            0x00280000
+#define HC_HTXnFM_ARGB16        0x00880000
+#define HC_HTXnFM_ARGB32        0x00980000
+#define HC_HTXnFM_ABGR16        0x00a80000
+#define HC_HTXnFM_ABGR32        0x00b80000
+#define HC_HTXnFM_RGBA16        0x00c80000
+#define HC_HTXnFM_RGBA32        0x00d80000
+#define HC_HTXnFM_BGRA16        0x00e80000
+#define HC_HTXnFM_BGRA32        0x00f80000
+#define HC_HTXnFM_BUMPMAP       0x00380000
+#define HC_HTXnFM_Index1        (HC_HTXnFM_INDEX     | 0x00000000)
+#define HC_HTXnFM_Index2        (HC_HTXnFM_INDEX     | 0x00010000)
+#define HC_HTXnFM_Index4        (HC_HTXnFM_INDEX     | 0x00020000)
+#define HC_HTXnFM_Index8        (HC_HTXnFM_INDEX     | 0x00030000)
+#define HC_HTXnFM_T1            (HC_HTXnFM_Intensity | 0x00000000)
+#define HC_HTXnFM_T2            (HC_HTXnFM_Intensity | 0x00010000)
+#define HC_HTXnFM_T4            (HC_HTXnFM_Intensity | 0x00020000)
+#define HC_HTXnFM_T8            (HC_HTXnFM_Intensity | 0x00030000)
+#define HC_HTXnFM_L1            (HC_HTXnFM_Lum       | 0x00000000)
+#define HC_HTXnFM_L2            (HC_HTXnFM_Lum       | 0x00010000)
+#define HC_HTXnFM_L4            (HC_HTXnFM_Lum       | 0x00020000)
+#define HC_HTXnFM_L8            (HC_HTXnFM_Lum       | 0x00030000)
+#define HC_HTXnFM_AL44          (HC_HTXnFM_Lum       | 0x00040000)
+#define HC_HTXnFM_AL88          (HC_HTXnFM_Lum       | 0x00050000)
+#define HC_HTXnFM_A1            (HC_HTXnFM_Alpha     | 0x00000000)
+#define HC_HTXnFM_A2            (HC_HTXnFM_Alpha     | 0x00010000)
+#define HC_HTXnFM_A4            (HC_HTXnFM_Alpha     | 0x00020000)
+#define HC_HTXnFM_A8            (HC_HTXnFM_Alpha     | 0x00030000)
+#define HC_HTXnFM_DX1           (HC_HTXnFM_DX        | 0x00010000)
+#define HC_HTXnFM_DX23          (HC_HTXnFM_DX        | 0x00020000)
+#define HC_HTXnFM_DX45          (HC_HTXnFM_DX        | 0x00030000)
+#define HC_HTXnFM_RGB555        (HC_HTXnFM_ARGB16    | 0x00000000)
+#define HC_HTXnFM_RGB565        (HC_HTXnFM_ARGB16    | 0x00010000)
+#define HC_HTXnFM_ARGB1555      (HC_HTXnFM_ARGB16    | 0x00020000)
+#define HC_HTXnFM_ARGB4444      (HC_HTXnFM_ARGB16    | 0x00030000)
+#define HC_HTXnFM_ARGB0888      (HC_HTXnFM_ARGB32    | 0x00000000)
+#define HC_HTXnFM_ARGB8888      (HC_HTXnFM_ARGB32    | 0x00010000)
+#define HC_HTXnFM_BGR555        (HC_HTXnFM_ABGR16    | 0x00000000)
+#define HC_HTXnFM_BGR565        (HC_HTXnFM_ABGR16    | 0x00010000)
+#define HC_HTXnFM_ABGR1555      (HC_HTXnFM_ABGR16    | 0x00020000)
+#define HC_HTXnFM_ABGR4444      (HC_HTXnFM_ABGR16    | 0x00030000)
+#define HC_HTXnFM_ABGR0888      (HC_HTXnFM_ABGR32    | 0x00000000)
+#define HC_HTXnFM_ABGR8888      (HC_HTXnFM_ABGR32    | 0x00010000)
+#define HC_HTXnFM_RGBA5550      (HC_HTXnFM_RGBA16    | 0x00000000)
+#define HC_HTXnFM_RGBA5551      (HC_HTXnFM_RGBA16    | 0x00020000)
+#define HC_HTXnFM_RGBA4444      (HC_HTXnFM_RGBA16    | 0x00030000)
+#define HC_HTXnFM_RGBA8880      (HC_HTXnFM_RGBA32    | 0x00000000)
+#define HC_HTXnFM_RGBA8888      (HC_HTXnFM_RGBA32    | 0x00010000)
+#define HC_HTXnFM_BGRA5550      (HC_HTXnFM_BGRA16    | 0x00000000)
+#define HC_HTXnFM_BGRA5551      (HC_HTXnFM_BGRA16    | 0x00020000)
+#define HC_HTXnFM_BGRA4444      (HC_HTXnFM_BGRA16    | 0x00030000)
+#define HC_HTXnFM_BGRA8880      (HC_HTXnFM_BGRA32    | 0x00000000)
+#define HC_HTXnFM_BGRA8888      (HC_HTXnFM_BGRA32    | 0x00010000)
+#define HC_HTXnFM_VU88          (HC_HTXnFM_BUMPMAP   | 0x00000000)
+#define HC_HTXnFM_LVU655        (HC_HTXnFM_BUMPMAP   | 0x00010000)
+#define HC_HTXnFM_LVU888        (HC_HTXnFM_BUMPMAP   | 0x00020000)
+#define HC_HTXnLoc_Local        0x00000000
+#define HC_HTXnLoc_Sys          0x00000002
+#define HC_HTXnLoc_AGP          0x00000003
+/* HC_SubA_HTXnTRAH        0x007f
+ */
+#define HC_HTXnTRAH_MASK        0x00ff0000
+#define HC_HTXnTRAL_MASK        0x0000ff00
+#define HC_HTXnTBA_MASK         0x000000ff
+#define HC_HTXnTRAH_SHIFT       16
+#define HC_HTXnTRAL_SHIFT       8
+/* HC_SubA_HTXnTBLCsat     0x0080
+ *-- Define the input texture.
+ */
+#define HC_XTC_TOPC             0x00000000
+#define HC_XTC_InvTOPC          0x00000010
+#define HC_XTC_TOPCp5           0x00000020
+#define HC_XTC_Cbias            0x00000000
+#define HC_XTC_InvCbias         0x00000010
+#define HC_XTC_0                0x00000000
+#define HC_XTC_Dif              0x00000001
+#define HC_XTC_Spec             0x00000002
+#define HC_XTC_Tex              0x00000003
+#define HC_XTC_Cur              0x00000004
+#define HC_XTC_Adif             0x00000005
+#define HC_XTC_Fog              0x00000006
+#define HC_XTC_Atex             0x00000007
+#define HC_XTC_Acur             0x00000008
+#define HC_XTC_HTXnTBLRC        0x00000009
+#define HC_XTC_Ctexnext         0x0000000a
+/*--
+ */
+#define HC_HTXnTBLCsat_MASK     0x00800000
+#define HC_HTXnTBLCa_MASK       0x000fc000
+#define HC_HTXnTBLCb_MASK       0x00001f80
+#define HC_HTXnTBLCc_MASK       0x0000003f
+#define HC_HTXnTBLCa_TOPC       (HC_XTC_TOPC << 14)
+#define HC_HTXnTBLCa_InvTOPC    (HC_XTC_InvTOPC << 14)
+#define HC_HTXnTBLCa_TOPCp5     (HC_XTC_TOPCp5 << 14)
+#define HC_HTXnTBLCa_0          (HC_XTC_0 << 14)
+#define HC_HTXnTBLCa_Dif        (HC_XTC_Dif << 14)
+#define HC_HTXnTBLCa_Spec       (HC_XTC_Spec << 14)
+#define HC_HTXnTBLCa_Tex        (HC_XTC_Tex << 14)
+#define HC_HTXnTBLCa_Cur        (HC_XTC_Cur << 14)
+#define HC_HTXnTBLCa_Adif       (HC_XTC_Adif << 14)
+#define HC_HTXnTBLCa_Fog        (HC_XTC_Fog << 14)
+#define HC_HTXnTBLCa_Atex       (HC_XTC_Atex << 14)
+#define HC_HTXnTBLCa_Acur       (HC_XTC_Acur << 14)
+#define HC_HTXnTBLCa_HTXnTBLRC  (HC_XTC_HTXnTBLRC << 14)
+#define HC_HTXnTBLCa_Ctexnext   (HC_XTC_Ctexnext << 14)
+#define HC_HTXnTBLCb_TOPC       (HC_XTC_TOPC << 7)
+#define HC_HTXnTBLCb_InvTOPC    (HC_XTC_InvTOPC << 7)
+#define HC_HTXnTBLCb_TOPCp5     (HC_XTC_TOPCp5 << 7)
+#define HC_HTXnTBLCb_0          (HC_XTC_0 << 7)
+#define HC_HTXnTBLCb_Dif        (HC_XTC_Dif << 7)
+#define HC_HTXnTBLCb_Spec       (HC_XTC_Spec << 7)
+#define HC_HTXnTBLCb_Tex        (HC_XTC_Tex << 7)
+#define HC_HTXnTBLCb_Cur        (HC_XTC_Cur << 7)
+#define HC_HTXnTBLCb_Adif       (HC_XTC_Adif << 7)
+#define HC_HTXnTBLCb_Fog        (HC_XTC_Fog << 7)
+#define HC_HTXnTBLCb_Atex       (HC_XTC_Atex << 7)
+#define HC_HTXnTBLCb_Acur       (HC_XTC_Acur << 7)
+#define HC_HTXnTBLCb_HTXnTBLRC  (HC_XTC_HTXnTBLRC << 7)
+#define HC_HTXnTBLCb_Ctexnext   (HC_XTC_Ctexnext << 7)
+#define HC_HTXnTBLCc_TOPC       (HC_XTC_TOPC << 0)
+#define HC_HTXnTBLCc_InvTOPC    (HC_XTC_InvTOPC << 0)
+#define HC_HTXnTBLCc_TOPCp5     (HC_XTC_TOPCp5 << 0)
+#define HC_HTXnTBLCc_0          (HC_XTC_0 << 0)
+#define HC_HTXnTBLCc_Dif        (HC_XTC_Dif << 0)
+#define HC_HTXnTBLCc_Spec       (HC_XTC_Spec << 0)
+#define HC_HTXnTBLCc_Tex        (HC_XTC_Tex << 0)
+#define HC_HTXnTBLCc_Cur        (HC_XTC_Cur << 0)
+#define HC_HTXnTBLCc_Adif       (HC_XTC_Adif << 0)
+#define HC_HTXnTBLCc_Fog        (HC_XTC_Fog << 0)
+#define HC_HTXnTBLCc_Atex       (HC_XTC_Atex << 0)
+#define HC_HTXnTBLCc_Acur       (HC_XTC_Acur << 0)
+#define HC_HTXnTBLCc_HTXnTBLRC  (HC_XTC_HTXnTBLRC << 0)
+#define HC_HTXnTBLCc_Ctexnext   (HC_XTC_Ctexnext << 0)
+/* HC_SubA_HTXnTBLCop      0x0081
+ */
+#define HC_HTXnTBLdot_MASK      0x00c00000
+#define HC_HTXnTBLCop_MASK      0x00380000
+#define HC_HTXnTBLCbias_MASK    0x0007c000
+#define HC_HTXnTBLCshift_MASK   0x00001800
+#define HC_HTXnTBLAop_MASK      0x00000380
+#define HC_HTXnTBLAbias_MASK    0x00000078
+#define HC_HTXnTBLAshift_MASK   0x00000003
+#define HC_HTXnTBLCop_Add       0x00000000
+#define HC_HTXnTBLCop_Sub       0x00080000
+#define HC_HTXnTBLCop_Min       0x00100000
+#define HC_HTXnTBLCop_Max       0x00180000
+#define HC_HTXnTBLCop_Mask      0x00200000
+#define HC_HTXnTBLCbias_Cbias           (HC_XTC_Cbias << 14)
+#define HC_HTXnTBLCbias_InvCbias        (HC_XTC_InvCbias << 14)
+#define HC_HTXnTBLCbias_0               (HC_XTC_0 << 14)
+#define HC_HTXnTBLCbias_Dif             (HC_XTC_Dif << 14)
+#define HC_HTXnTBLCbias_Spec            (HC_XTC_Spec << 14)
+#define HC_HTXnTBLCbias_Tex             (HC_XTC_Tex << 14)
+#define HC_HTXnTBLCbias_Cur             (HC_XTC_Cur << 14)
+#define HC_HTXnTBLCbias_Adif            (HC_XTC_Adif << 14)
+#define HC_HTXnTBLCbias_Fog             (HC_XTC_Fog << 14)
+#define HC_HTXnTBLCbias_Atex            (HC_XTC_Atex << 14)
+#define HC_HTXnTBLCbias_Acur            (HC_XTC_Acur << 14)
+#define HC_HTXnTBLCbias_HTXnTBLRC       (HC_XTC_HTXnTBLRC << 14)
+#define HC_HTXnTBLCshift_1      0x00000000
+#define HC_HTXnTBLCshift_2      0x00000800
+#define HC_HTXnTBLCshift_No     0x00001000
+#define HC_HTXnTBLCshift_DotP   0x00001800
+/*=* John Sheng [2003.7.18] texture combine *=*/
+#define HC_HTXnTBLDOT3   0x00080000
+#define HC_HTXnTBLDOT4   0x000C0000
+
+#define HC_HTXnTBLAop_Add       0x00000000
+#define HC_HTXnTBLAop_Sub       0x00000080
+#define HC_HTXnTBLAop_Min       0x00000100
+#define HC_HTXnTBLAop_Max       0x00000180
+#define HC_HTXnTBLAop_Mask      0x00000200
+#define HC_HTXnTBLAbias_Inv             0x00000040
+#define HC_HTXnTBLAbias_Adif            0x00000000
+#define HC_HTXnTBLAbias_Fog             0x00000008
+#define HC_HTXnTBLAbias_Acur            0x00000010
+#define HC_HTXnTBLAbias_HTXnTBLRAbias   0x00000018
+#define HC_HTXnTBLAbias_Atex            0x00000020
+#define HC_HTXnTBLAshift_1      0x00000000
+#define HC_HTXnTBLAshift_2      0x00000001
+#define HC_HTXnTBLAshift_No     0x00000002
+/* #define HC_HTXnTBLAshift_DotP   0x00000003 */
+/* HC_SubA_HTXnTBLMPFog    0x0082
+ */
+#define HC_HTXnTBLMPfog_MASK    0x00e00000
+#define HC_HTXnTBLMPfog_0       0x00000000
+#define HC_HTXnTBLMPfog_Adif    0x00200000
+#define HC_HTXnTBLMPfog_Fog     0x00400000
+#define HC_HTXnTBLMPfog_Atex    0x00600000
+#define HC_HTXnTBLMPfog_Acur    0x00800000
+#define HC_HTXnTBLMPfog_GHTXnTBLRFog    0x00a00000
+/* HC_SubA_HTXnTBLAsat     0x0083
+ *-- Define the texture alpha input.
+ */
+#define HC_XTA_TOPA             0x00000000
+#define HC_XTA_InvTOPA          0x00000008
+#define HC_XTA_TOPAp5           0x00000010
+#define HC_XTA_Adif             0x00000000
+#define HC_XTA_Fog              0x00000001
+#define HC_XTA_Acur             0x00000002
+#define HC_XTA_HTXnTBLRA        0x00000003
+#define HC_XTA_Atex             0x00000004
+#define HC_XTA_Atexnext         0x00000005
+/*--
+ */
+#define HC_HTXnTBLAsat_MASK     0x00800000
+#define HC_HTXnTBLAMB_MASK      0x00700000
+#define HC_HTXnTBLAa_MASK       0x0007c000
+#define HC_HTXnTBLAb_MASK       0x00000f80
+#define HC_HTXnTBLAc_MASK       0x0000001f
+#define HC_HTXnTBLAMB_SHIFT     20
+#define HC_HTXnTBLAa_TOPA       (HC_XTA_TOPA << 14)
+#define HC_HTXnTBLAa_InvTOPA    (HC_XTA_InvTOPA << 14)
+#define HC_HTXnTBLAa_TOPAp5     (HC_XTA_TOPAp5 << 14)
+#define HC_HTXnTBLAa_Adif       (HC_XTA_Adif << 14)
+#define HC_HTXnTBLAa_Fog        (HC_XTA_Fog << 14)
+#define HC_HTXnTBLAa_Acur       (HC_XTA_Acur << 14)
+#define HC_HTXnTBLAa_HTXnTBLRA  (HC_XTA_HTXnTBLRA << 14)
+#define HC_HTXnTBLAa_Atex       (HC_XTA_Atex << 14)
+#define HC_HTXnTBLAa_Atexnext   (HC_XTA_Atexnext << 14)
+#define HC_HTXnTBLAb_TOPA       (HC_XTA_TOPA << 7)
+#define HC_HTXnTBLAb_InvTOPA    (HC_XTA_InvTOPA << 7)
+#define HC_HTXnTBLAb_TOPAp5     (HC_XTA_TOPAp5 << 7)
+#define HC_HTXnTBLAb_Adif       (HC_XTA_Adif << 7)
+#define HC_HTXnTBLAb_Fog        (HC_XTA_Fog << 7)
+#define HC_HTXnTBLAb_Acur       (HC_XTA_Acur << 7)
+#define HC_HTXnTBLAb_HTXnTBLRA  (HC_XTA_HTXnTBLRA << 7)
+#define HC_HTXnTBLAb_Atex       (HC_XTA_Atex << 7)
+#define HC_HTXnTBLAb_Atexnext   (HC_XTA_Atexnext << 7)
+#define HC_HTXnTBLAc_TOPA       (HC_XTA_TOPA << 0)
+#define HC_HTXnTBLAc_InvTOPA    (HC_XTA_InvTOPA << 0)
+#define HC_HTXnTBLAc_TOPAp5     (HC_XTA_TOPAp5 << 0)
+#define HC_HTXnTBLAc_Adif       (HC_XTA_Adif << 0)
+#define HC_HTXnTBLAc_Fog        (HC_XTA_Fog << 0)
+#define HC_HTXnTBLAc_Acur       (HC_XTA_Acur << 0)
+#define HC_HTXnTBLAc_HTXnTBLRA  (HC_XTA_HTXnTBLRA << 0)
+#define HC_HTXnTBLAc_Atex       (HC_XTA_Atex << 0)
+#define HC_HTXnTBLAc_Atexnext   (HC_XTA_Atexnext << 0)
+/* HC_SubA_HTXnTBLRAa      0x0089
+ */
+#define HC_HTXnTBLRAa_MASK      0x00ff0000
+#define HC_HTXnTBLRAb_MASK      0x0000ff00
+#define HC_HTXnTBLRAc_MASK      0x000000ff
+#define HC_HTXnTBLRAa_SHIFT     16
+#define HC_HTXnTBLRAb_SHIFT     8
+#define HC_HTXnTBLRAc_SHIFT     0
+/* HC_SubA_HTXnTBLRFog     0x008a
+ */
+#define HC_HTXnTBLRFog_MASK     0x0000ff00
+#define HC_HTXnTBLRAbias_MASK   0x000000ff
+#define HC_HTXnTBLRFog_SHIFT    8
+#define HC_HTXnTBLRAbias_SHIFT  0
+/* HC_SubA_HTXnLScale      0x0094
+ */
+#define HC_HTXnLScale_MASK      0x0007fc00
+#define HC_HTXnLOff_MASK        0x000001ff
+#define HC_HTXnLScale_SHIFT     10
+/* HC_SubA_HTXSMD          0x0000
+ */
+#define HC_HTXSMD_MASK          0x00000080
+#define HC_HTXTMD_MASK          0x00000040
+#define HC_HTXNum_MASK          0x00000038
+#define HC_HTXTRMD_MASK         0x00000006
+#define HC_HTXCHCLR_MASK        0x00000001
+#define HC_HTXNum_SHIFT         3
+
+/* Texture Palette n
+ */
+#define HC_SubType_TexPalette0  0x00000000
+#define HC_SubType_TexPalette1  0x00000001
+#define HC_SubType_FogTable     0x00000010
+#define HC_SubType_Stipple      0x00000014
+/* HC_SubA_TexPalette0     0x0000
+ */
+#define HC_HTPnA_MASK           0xff000000
+#define HC_HTPnR_MASK           0x00ff0000
+#define HC_HTPnG_MASK           0x0000ff00
+#define HC_HTPnB_MASK           0x000000ff
+/* HC_SubA_FogTable        0x0010
+ */
+#define HC_HFPn3_MASK           0xff000000
+#define HC_HFPn2_MASK           0x00ff0000
+#define HC_HFPn1_MASK           0x0000ff00
+#define HC_HFPn_MASK            0x000000ff
+#define HC_HFPn3_SHIFT          24
+#define HC_HFPn2_SHIFT          16
+#define HC_HFPn1_SHIFT          8
+
+/* Auto Testing & Security
+ */
+#define HC_SubA_HenFIFOAT       0x0000
+#define HC_SubA_HFBDrawFirst    0x0004
+#define HC_SubA_HFBBasL         0x0005
+#define HC_SubA_HFBDst          0x0006
+/* HC_SubA_HenFIFOAT       0x0000
+ */
+#define HC_HenFIFOAT_MASK       0x00000020
+#define HC_HenGEMILock_MASK     0x00000010
+#define HC_HenFBASwap_MASK      0x00000008
+#define HC_HenOT_MASK           0x00000004
+#define HC_HenCMDQ_MASK         0x00000002
+#define HC_HenTXCTSU_MASK       0x00000001
+/* HC_SubA_HFBDrawFirst    0x0004
+ */
+#define HC_HFBDrawFirst_MASK    0x00000800
+#define HC_HFBQueue_MASK        0x00000400
+#define HC_HFBLock_MASK         0x00000200
+#define HC_HEOF_MASK            0x00000100
+#define HC_HFBBasH_MASK         0x000000ff
+
+/* GEMI Setting
+ */
+#define HC_SubA_HTArbRCM        0x0008
+#define HC_SubA_HTArbRZ         0x000a
+#define HC_SubA_HTArbWZ         0x000b
+#define HC_SubA_HTArbRTX        0x000c
+#define HC_SubA_HTArbRCW        0x000d
+#define HC_SubA_HTArbE2         0x000e
+#define HC_SubA_HArbRQCM        0x0010
+#define HC_SubA_HArbWQCM        0x0011
+#define HC_SubA_HGEMITout       0x0020
+#define HC_SubA_HFthRTXD        0x0040
+#define HC_SubA_HFthRTXA        0x0044
+#define HC_SubA_HCMDQstL        0x0050
+#define HC_SubA_HCMDQendL       0x0051
+#define HC_SubA_HCMDQLen        0x0052
+/* HC_SubA_HTArbRCM        0x0008
+ */
+#define HC_HTArbRCM_MASK        0x0000ffff
+/* HC_SubA_HTArbRZ         0x000a
+ */
+#define HC_HTArbRZ_MASK         0x0000ffff
+/* HC_SubA_HTArbWZ         0x000b
+ */
+#define HC_HTArbWZ_MASK         0x0000ffff
+/* HC_SubA_HTArbRTX        0x000c
+ */
+#define HC_HTArbRTX_MASK        0x0000ffff
+/* HC_SubA_HTArbRCW        0x000d
+ */
+#define HC_HTArbRCW_MASK        0x0000ffff
+/* HC_SubA_HTArbE2         0x000e
+ */
+#define HC_HTArbE2_MASK         0x0000ffff
+/* HC_SubA_HArbRQCM        0x0010
+ */
+#define HC_HTArbRQCM_MASK       0x0000ffff
+/* HC_SubA_HArbWQCM        0x0011
+ */
+#define HC_HArbWQCM_MASK        0x0000ffff
+/* HC_SubA_HGEMITout       0x0020
+ */
+#define HC_HGEMITout_MASK       0x000f0000
+#define HC_HNPArbZC_MASK        0x0000ffff
+#define HC_HGEMITout_SHIFT      16
+/* HC_SubA_HFthRTXD        0x0040
+ */
+#define HC_HFthRTXD_MASK        0x00ff0000
+#define HC_HFthRZD_MASK         0x0000ff00
+#define HC_HFthWZD_MASK         0x000000ff
+#define HC_HFthRTXD_SHIFT       16
+#define HC_HFthRZD_SHIFT        8
+/* HC_SubA_HFthRTXA        0x0044
+ */
+#define HC_HFthRTXA_MASK        0x000000ff
+
+/******************************************************************************
+** Define the Halcyon Internal register access constants. For simulator only.
+******************************************************************************/
+#define HC_SIMA_HAGPBstL        0x0000
+#define HC_SIMA_HAGPBendL       0x0001
+#define HC_SIMA_HAGPCMNT        0x0002
+#define HC_SIMA_HAGPBpL         0x0003
+#define HC_SIMA_HAGPBpH         0x0004
+#define HC_SIMA_HClipTB         0x0005
+#define HC_SIMA_HClipLR         0x0006
+#define HC_SIMA_HFPClipTL       0x0007
+#define HC_SIMA_HFPClipBL       0x0008
+#define HC_SIMA_HFPClipLL       0x0009
+#define HC_SIMA_HFPClipRL       0x000a
+#define HC_SIMA_HFPClipTBH      0x000b
+#define HC_SIMA_HFPClipLRH      0x000c
+#define HC_SIMA_HLP             0x000d
+#define HC_SIMA_HLPRF           0x000e
+#define HC_SIMA_HSolidCL        0x000f
+#define HC_SIMA_HPixGC          0x0010
+#define HC_SIMA_HSPXYOS         0x0011
+#define HC_SIMA_HCmdA           0x0012
+#define HC_SIMA_HCmdB           0x0013
+#define HC_SIMA_HEnable         0x0014
+#define HC_SIMA_HZWBBasL        0x0015
+#define HC_SIMA_HZWBBasH        0x0016
+#define HC_SIMA_HZWBType        0x0017
+#define HC_SIMA_HZBiasL         0x0018
+#define HC_SIMA_HZWBend         0x0019
+#define HC_SIMA_HZWTMD          0x001a
+#define HC_SIMA_HZWCDL          0x001b
+#define HC_SIMA_HZWCTAGnum      0x001c
+#define HC_SIMA_HZCYNum         0x001d
+#define HC_SIMA_HZWCFire        0x001e
+/* #define HC_SIMA_HSBBasL         0x001d */
+/* #define HC_SIMA_HSBBasH         0x001e */
+/* #define HC_SIMA_HSBFM           0x001f */
+#define HC_SIMA_HSTREF          0x0020
+#define HC_SIMA_HSTMD           0x0021
+#define HC_SIMA_HABBasL         0x0022
+#define HC_SIMA_HABBasH         0x0023
+#define HC_SIMA_HABFM           0x0024
+#define HC_SIMA_HATMD           0x0025
+#define HC_SIMA_HABLCsat        0x0026
+#define HC_SIMA_HABLCop         0x0027
+#define HC_SIMA_HABLAsat        0x0028
+#define HC_SIMA_HABLAop         0x0029
+#define HC_SIMA_HABLRCa         0x002a
+#define HC_SIMA_HABLRFCa        0x002b
+#define HC_SIMA_HABLRCbias      0x002c
+#define HC_SIMA_HABLRCb         0x002d
+#define HC_SIMA_HABLRFCb        0x002e
+#define HC_SIMA_HABLRAa         0x002f
+#define HC_SIMA_HABLRAb         0x0030
+#define HC_SIMA_HDBBasL         0x0031
+#define HC_SIMA_HDBBasH         0x0032
+#define HC_SIMA_HDBFM           0x0033
+#define HC_SIMA_HFBBMSKL        0x0034
+#define HC_SIMA_HROP            0x0035
+#define HC_SIMA_HFogLF          0x0036
+#define HC_SIMA_HFogCL          0x0037
+#define HC_SIMA_HFogCH          0x0038
+#define HC_SIMA_HFogStL         0x0039
+#define HC_SIMA_HFogStH         0x003a
+#define HC_SIMA_HFogOOdMF       0x003b
+#define HC_SIMA_HFogOOdEF       0x003c
+#define HC_SIMA_HFogEndL        0x003d
+#define HC_SIMA_HFogDenst       0x003e
+/*---- start of texture 0 setting ----
+ */
+#define HC_SIMA_HTX0L0BasL      0x0040
+#define HC_SIMA_HTX0L1BasL      0x0041
+#define HC_SIMA_HTX0L2BasL      0x0042
+#define HC_SIMA_HTX0L3BasL      0x0043
+#define HC_SIMA_HTX0L4BasL      0x0044
+#define HC_SIMA_HTX0L5BasL      0x0045
+#define HC_SIMA_HTX0L6BasL      0x0046
+#define HC_SIMA_HTX0L7BasL      0x0047
+#define HC_SIMA_HTX0L8BasL      0x0048
+#define HC_SIMA_HTX0L9BasL      0x0049
+#define HC_SIMA_HTX0LaBasL      0x004a
+#define HC_SIMA_HTX0LbBasL      0x004b
+#define HC_SIMA_HTX0LcBasL      0x004c
+#define HC_SIMA_HTX0LdBasL      0x004d
+#define HC_SIMA_HTX0LeBasL      0x004e
+#define HC_SIMA_HTX0LfBasL      0x004f
+#define HC_SIMA_HTX0L10BasL     0x0050
+#define HC_SIMA_HTX0L11BasL     0x0051
+#define HC_SIMA_HTX0L012BasH    0x0052
+#define HC_SIMA_HTX0L345BasH    0x0053
+#define HC_SIMA_HTX0L678BasH    0x0054
+#define HC_SIMA_HTX0L9abBasH    0x0055
+#define HC_SIMA_HTX0LcdeBasH    0x0056
+#define HC_SIMA_HTX0Lf1011BasH  0x0057
+#define HC_SIMA_HTX0L0Pit       0x0058
+#define HC_SIMA_HTX0L1Pit       0x0059
+#define HC_SIMA_HTX0L2Pit       0x005a
+#define HC_SIMA_HTX0L3Pit       0x005b
+#define HC_SIMA_HTX0L4Pit       0x005c
+#define HC_SIMA_HTX0L5Pit       0x005d
+#define HC_SIMA_HTX0L6Pit       0x005e
+#define HC_SIMA_HTX0L7Pit       0x005f
+#define HC_SIMA_HTX0L8Pit       0x0060
+#define HC_SIMA_HTX0L9Pit       0x0061
+#define HC_SIMA_HTX0LaPit       0x0062
+#define HC_SIMA_HTX0LbPit       0x0063
+#define HC_SIMA_HTX0LcPit       0x0064
+#define HC_SIMA_HTX0LdPit       0x0065
+#define HC_SIMA_HTX0LePit       0x0066
+#define HC_SIMA_HTX0LfPit       0x0067
+#define HC_SIMA_HTX0L10Pit      0x0068
+#define HC_SIMA_HTX0L11Pit      0x0069
+#define HC_SIMA_HTX0L0_5WE      0x006a
+#define HC_SIMA_HTX0L6_bWE      0x006b
+#define HC_SIMA_HTX0Lc_11WE     0x006c
+#define HC_SIMA_HTX0L0_5HE      0x006d
+#define HC_SIMA_HTX0L6_bHE      0x006e
+#define HC_SIMA_HTX0Lc_11HE     0x006f
+#define HC_SIMA_HTX0L0OS        0x0070
+#define HC_SIMA_HTX0TB          0x0071
+#define HC_SIMA_HTX0MPMD        0x0072
+#define HC_SIMA_HTX0CLODu       0x0073
+#define HC_SIMA_HTX0FM          0x0074
+#define HC_SIMA_HTX0TRCH        0x0075
+#define HC_SIMA_HTX0TRCL        0x0076
+#define HC_SIMA_HTX0TBC         0x0077
+#define HC_SIMA_HTX0TRAH        0x0078
+#define HC_SIMA_HTX0TBLCsat     0x0079
+#define HC_SIMA_HTX0TBLCop      0x007a
+#define HC_SIMA_HTX0TBLMPfog    0x007b
+#define HC_SIMA_HTX0TBLAsat     0x007c
+#define HC_SIMA_HTX0TBLRCa      0x007d
+#define HC_SIMA_HTX0TBLRCb      0x007e
+#define HC_SIMA_HTX0TBLRCc      0x007f
+#define HC_SIMA_HTX0TBLRCbias   0x0080
+#define HC_SIMA_HTX0TBLRAa      0x0081
+#define HC_SIMA_HTX0TBLRFog     0x0082
+#define HC_SIMA_HTX0BumpM00     0x0083
+#define HC_SIMA_HTX0BumpM01     0x0084
+#define HC_SIMA_HTX0BumpM10     0x0085
+#define HC_SIMA_HTX0BumpM11     0x0086
+#define HC_SIMA_HTX0LScale      0x0087
+/*---- end of texture 0 setting ----      0x008f
+ */
+#define HC_SIMA_TX0TX1_OFF      0x0050
+/*---- start of texture 1 setting ----
+ */
+#define HC_SIMA_HTX1L0BasL      (HC_SIMA_HTX0L0BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L1BasL      (HC_SIMA_HTX0L1BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L2BasL      (HC_SIMA_HTX0L2BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L3BasL      (HC_SIMA_HTX0L3BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L4BasL      (HC_SIMA_HTX0L4BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L5BasL      (HC_SIMA_HTX0L5BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L6BasL      (HC_SIMA_HTX0L6BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L7BasL      (HC_SIMA_HTX0L7BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L8BasL      (HC_SIMA_HTX0L8BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L9BasL      (HC_SIMA_HTX0L9BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LaBasL      (HC_SIMA_HTX0LaBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LbBasL      (HC_SIMA_HTX0LbBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LcBasL      (HC_SIMA_HTX0LcBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LdBasL      (HC_SIMA_HTX0LdBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LeBasL      (HC_SIMA_HTX0LeBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LfBasL      (HC_SIMA_HTX0LfBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L10BasL     (HC_SIMA_HTX0L10BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L11BasL     (HC_SIMA_HTX0L11BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L012BasH    (HC_SIMA_HTX0L012BasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L345BasH    (HC_SIMA_HTX0L345BasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L678BasH    (HC_SIMA_HTX0L678BasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L9abBasH    (HC_SIMA_HTX0L9abBasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LcdeBasH    (HC_SIMA_HTX0LcdeBasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1Lf1011BasH  (HC_SIMA_HTX0Lf1011BasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0Pit       (HC_SIMA_HTX0L0Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L1Pit       (HC_SIMA_HTX0L1Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L2Pit       (HC_SIMA_HTX0L2Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L3Pit       (HC_SIMA_HTX0L3Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L4Pit       (HC_SIMA_HTX0L4Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L5Pit       (HC_SIMA_HTX0L5Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L6Pit       (HC_SIMA_HTX0L6Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L7Pit       (HC_SIMA_HTX0L7Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L8Pit       (HC_SIMA_HTX0L8Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L9Pit       (HC_SIMA_HTX0L9Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LaPit       (HC_SIMA_HTX0LaPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LbPit       (HC_SIMA_HTX0LbPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LcPit       (HC_SIMA_HTX0LcPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LdPit       (HC_SIMA_HTX0LdPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LePit       (HC_SIMA_HTX0LePit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LfPit       (HC_SIMA_HTX0LfPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L10Pit      (HC_SIMA_HTX0L10Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L11Pit      (HC_SIMA_HTX0L11Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0_5WE      (HC_SIMA_HTX0L0_5WE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L6_bWE      (HC_SIMA_HTX0L6_bWE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1Lc_11WE     (HC_SIMA_HTX0Lc_11WE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0_5HE      (HC_SIMA_HTX0L0_5HE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L6_bHE      (HC_SIMA_HTX0L6_bHE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1Lc_11HE      (HC_SIMA_HTX0Lc_11HE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0OS        (HC_SIMA_HTX0L0OS + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TB          (HC_SIMA_HTX0TB + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1MPMD        (HC_SIMA_HTX0MPMD + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1CLODu       (HC_SIMA_HTX0CLODu + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1FM          (HC_SIMA_HTX0FM + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TRCH        (HC_SIMA_HTX0TRCH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TRCL        (HC_SIMA_HTX0TRCL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBC         (HC_SIMA_HTX0TBC + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TRAH        (HC_SIMA_HTX0TRAH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LTC         (HC_SIMA_HTX0LTC + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LTA         (HC_SIMA_HTX0LTA + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLCsat     (HC_SIMA_HTX0TBLCsat + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLCop      (HC_SIMA_HTX0TBLCop + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLMPfog    (HC_SIMA_HTX0TBLMPfog + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLAsat     (HC_SIMA_HTX0TBLAsat + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRCa      (HC_SIMA_HTX0TBLRCa + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRCb      (HC_SIMA_HTX0TBLRCb + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRCc      (HC_SIMA_HTX0TBLRCc + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRCbias   (HC_SIMA_HTX0TBLRCbias + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRAa      (HC_SIMA_HTX0TBLRAa + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRFog     (HC_SIMA_HTX0TBLRFog + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1BumpM00     (HC_SIMA_HTX0BumpM00 + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1BumpM01     (HC_SIMA_HTX0BumpM01 + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1BumpM10     (HC_SIMA_HTX0BumpM10 + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1BumpM11     (HC_SIMA_HTX0BumpM11 + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LScale      (HC_SIMA_HTX0LScale + HC_SIMA_TX0TX1_OFF)
+/*---- end of texture 1 setting ---- 0xaf
+ */
+#define HC_SIMA_HTXSMD          0x00b0
+#define HC_SIMA_HenFIFOAT       0x00b1
+#define HC_SIMA_HFBDrawFirst    0x00b2
+#define HC_SIMA_HFBBasL         0x00b3
+#define HC_SIMA_HTArbRCM        0x00b4
+#define HC_SIMA_HTArbRZ         0x00b5
+#define HC_SIMA_HTArbWZ         0x00b6
+#define HC_SIMA_HTArbRTX        0x00b7
+#define HC_SIMA_HTArbRCW        0x00b8
+#define HC_SIMA_HTArbE2         0x00b9
+#define HC_SIMA_HGEMITout       0x00ba
+#define HC_SIMA_HFthRTXD        0x00bb
+#define HC_SIMA_HFthRTXA        0x00bc
+/* Define the texture palette 0
+ */
+#define HC_SIMA_HTP0            0x0100
+#define HC_SIMA_HTP1            0x0200
+#define HC_SIMA_FOGTABLE        0x0300
+#define HC_SIMA_STIPPLE         0x0400
+#define HC_SIMA_HE3Fire         0x0440
+#define HC_SIMA_TRANS_SET       0x0441
+#define HC_SIMA_HREngSt         0x0442
+#define HC_SIMA_HRFIFOempty     0x0443
+#define HC_SIMA_HRFIFOfull      0x0444
+#define HC_SIMA_HRErr           0x0445
+#define HC_SIMA_FIFOstatus      0x0446
+
+/******************************************************************************
+** Define the AGP command header.
+******************************************************************************/
+#define HC_ACMD_MASK            0xfe000000
+#define HC_ACMD_SUB_MASK        0x0c000000
+#define HC_ACMD_HCmdA           0xee000000
+#define HC_ACMD_HCmdB           0xec000000
+#define HC_ACMD_HCmdC           0xea000000
+#define HC_ACMD_H1              0xf0000000
+#define HC_ACMD_H2              0xf2000000
+#define HC_ACMD_H3              0xf4000000
+#define HC_ACMD_H4              0xf6000000
+
+#define HC_ACMD_H1IO_MASK       0x000001ff
+#define HC_ACMD_H2IO1_MASK      0x001ff000
+#define HC_ACMD_H2IO2_MASK      0x000001ff
+#define HC_ACMD_H2IO1_SHIFT     12
+#define HC_ACMD_H2IO2_SHIFT     0
+#define HC_ACMD_H3IO_MASK       0x000001ff
+#define HC_ACMD_H3COUNT_MASK    0x01fff000
+#define HC_ACMD_H3COUNT_SHIFT   12
+#define HC_ACMD_H4ID_MASK       0x000001ff
+#define HC_ACMD_H4COUNT_MASK    0x01fffe00
+#define HC_ACMD_H4COUNT_SHIFT   9
+
+/********************************************************************************
+** Define Header
+********************************************************************************/
+#define HC_HEADER2             0xF210F110
+
+/********************************************************************************
+** Define Dummy Value
+********************************************************************************/
+#define HC_DUMMY               0xCCCCCCCC
+/********************************************************************************
+** Define for DMA use
+********************************************************************************/
+#define HALCYON_HEADER2     0XF210F110
+#define HALCYON_FIRECMD     0XEE100000
+#define HALCYON_FIREMASK    0XFFF00000
+#define HALCYON_CMDB        0XEC000000
+#define HALCYON_CMDBMASK    0XFFFE0000
+#define HALCYON_SUB_ADDR0   0X00000000
+#define HALCYON_HEADER1MASK 0XFFFFFC00
+#define HALCYON_HEADER1     0XF0000000
+#define HC_SubA_HAGPBstL        0x0060
+#define HC_SubA_HAGPBendL       0x0061
+#define HC_SubA_HAGPCMNT        0x0062
+#define HC_SubA_HAGPBpL         0x0063
+#define HC_SubA_HAGPBpH         0x0064
+#define HC_HAGPCMNT_MASK        0x00800000
+#define HC_HCmdErrClr_MASK      0x00400000
+#define HC_HAGPBendH_MASK       0x0000ff00
+#define HC_HAGPBstH_MASK        0x000000ff
+#define HC_HAGPBendH_SHIFT      8
+#define HC_HAGPBstH_SHIFT       0
+#define HC_HAGPBpL_MASK         0x00fffffc
+#define HC_HAGPBpID_MASK        0x00000003
+#define HC_HAGPBpID_PAUSE       0x00000000
+#define HC_HAGPBpID_JUMP        0x00000001
+#define HC_HAGPBpID_STOP        0x00000002
+#define HC_HAGPBpH_MASK         0x00ffffff
+
+#define VIA_VIDEO_HEADER5       0xFE040000
+#define VIA_VIDEO_HEADER6       0xFE050000
+#define VIA_VIDEO_HEADER7       0xFE060000
+#define VIA_VIDEOMASK           0xFFFF0000
+#endif
diff --git a/drivers/gpu/drm/via/via_dma.c b/drivers/gpu/drm/via/via_dma.c
new file mode 100644 (file)
index 0000000..7a339db
--- /dev/null
@@ -0,0 +1,755 @@
+/* via_dma.c -- DMA support for the VIA Unichrome/Pro
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A.
+ * All Rights Reserved.
+ *
+ * Copyright 2004 The Unichrome project.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Tungsten Graphics,
+ *    Erdi Chen,
+ *    Thomas Hellstrom.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "via_drm.h"
+#include "via_drv.h"
+#include "via_3d_reg.h"
+
+#define CMDBUF_ALIGNMENT_SIZE   (0x100)
+#define CMDBUF_ALIGNMENT_MASK   (0x0ff)
+
+/* defines for VIA 3D registers */
+#define VIA_REG_STATUS          0x400
+#define VIA_REG_TRANSET         0x43C
+#define VIA_REG_TRANSPACE       0x440
+
+/* VIA_REG_STATUS(0x400): Engine Status */
+#define VIA_CMD_RGTR_BUSY       0x00000080     /* Command Regulator is busy */
+#define VIA_2D_ENG_BUSY         0x00000001     /* 2D Engine is busy */
+#define VIA_3D_ENG_BUSY         0x00000002     /* 3D Engine is busy */
+#define VIA_VR_QUEUE_BUSY       0x00020000     /* Virtual Queue is busy */
+
+#define SetReg2DAGP(nReg, nData) {                             \
+       *((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1;  \
+       *((uint32_t *)(vb) + 1) = (nData);                      \
+       vb = ((uint32_t *)vb) + 2;                              \
+       dev_priv->dma_low +=8;                                  \
+}
+
+#define via_flush_write_combine() DRM_MEMORYBARRIER()
+
+#define VIA_OUT_RING_QW(w1,w2)                 \
+       *vb++ = (w1);                           \
+       *vb++ = (w2);                           \
+       dev_priv->dma_low += 8;
+
+static void via_cmdbuf_start(drm_via_private_t * dev_priv);
+static void via_cmdbuf_pause(drm_via_private_t * dev_priv);
+static void via_cmdbuf_reset(drm_via_private_t * dev_priv);
+static void via_cmdbuf_rewind(drm_via_private_t * dev_priv);
+static int via_wait_idle(drm_via_private_t * dev_priv);
+static void via_pad_cache(drm_via_private_t * dev_priv, int qwords);
+
+/*
+ * Free space in command buffer.
+ */
+
+static uint32_t via_cmdbuf_space(drm_via_private_t * dev_priv)
+{
+       uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+       uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
+
+       return ((hw_addr <= dev_priv->dma_low) ?
+               (dev_priv->dma_high + hw_addr - dev_priv->dma_low) :
+               (hw_addr - dev_priv->dma_low));
+}
+
+/*
+ * How much does the command regulator lag behind?
+ */
+
+static uint32_t via_cmdbuf_lag(drm_via_private_t * dev_priv)
+{
+       uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+       uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
+
+       return ((hw_addr <= dev_priv->dma_low) ?
+               (dev_priv->dma_low - hw_addr) :
+               (dev_priv->dma_wrap + dev_priv->dma_low - hw_addr));
+}
+
+/*
+ * Check that the given size fits in the buffer, otherwise wait.
+ */
+
+static inline int
+via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size)
+{
+       uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+       uint32_t cur_addr, hw_addr, next_addr;
+       volatile uint32_t *hw_addr_ptr;
+       uint32_t count;
+       hw_addr_ptr = dev_priv->hw_addr_ptr;
+       cur_addr = dev_priv->dma_low;
+       next_addr = cur_addr + size + 512 * 1024;
+       count = 1000000;
+       do {
+               hw_addr = *hw_addr_ptr - agp_base;
+               if (count-- == 0) {
+                       DRM_ERROR
+                           ("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n",
+                            hw_addr, cur_addr, next_addr);
+                       return -1;
+               }
+               if  ((cur_addr < hw_addr) && (next_addr >= hw_addr))
+                       msleep(1);
+       } while ((cur_addr < hw_addr) && (next_addr >= hw_addr));
+       return 0;
+}
+
+/*
+ * Checks whether buffer head has reach the end. Rewind the ring buffer
+ * when necessary.
+ *
+ * Returns virtual pointer to ring buffer.
+ */
+
+static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv,
+                                     unsigned int size)
+{
+       if ((dev_priv->dma_low + size + 4 * CMDBUF_ALIGNMENT_SIZE) >
+           dev_priv->dma_high) {
+               via_cmdbuf_rewind(dev_priv);
+       }
+       if (via_cmdbuf_wait(dev_priv, size) != 0) {
+               return NULL;
+       }
+
+       return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
+}
+
+int via_dma_cleanup(struct drm_device * dev)
+{
+       if (dev->dev_private) {
+               drm_via_private_t *dev_priv =
+                   (drm_via_private_t *) dev->dev_private;
+
+               if (dev_priv->ring.virtual_start) {
+                       via_cmdbuf_reset(dev_priv);
+
+                       drm_core_ioremapfree(&dev_priv->ring.map, dev);
+                       dev_priv->ring.virtual_start = NULL;
+               }
+
+       }
+
+       return 0;
+}
+
+static int via_initialize(struct drm_device * dev,
+                         drm_via_private_t * dev_priv,
+                         drm_via_dma_init_t * init)
+{
+       if (!dev_priv || !dev_priv->mmio) {
+               DRM_ERROR("via_dma_init called before via_map_init\n");
+               return -EFAULT;
+       }
+
+       if (dev_priv->ring.virtual_start != NULL) {
+               DRM_ERROR("called again without calling cleanup\n");
+               return -EFAULT;
+       }
+
+       if (!dev->agp || !dev->agp->base) {
+               DRM_ERROR("called with no agp memory available\n");
+               return -EFAULT;
+       }
+
+       if (dev_priv->chipset == VIA_DX9_0) {
+               DRM_ERROR("AGP DMA is not supported on this chip\n");
+               return -EINVAL;
+       }
+
+       dev_priv->ring.map.offset = dev->agp->base + init->offset;
+       dev_priv->ring.map.size = init->size;
+       dev_priv->ring.map.type = 0;
+       dev_priv->ring.map.flags = 0;
+       dev_priv->ring.map.mtrr = 0;
+
+       drm_core_ioremap(&dev_priv->ring.map, dev);
+
+       if (dev_priv->ring.map.handle == NULL) {
+               via_dma_cleanup(dev);
+               DRM_ERROR("can not ioremap virtual address for"
+                         " ring buffer\n");
+               return -ENOMEM;
+       }
+
+       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+
+       dev_priv->dma_ptr = dev_priv->ring.virtual_start;
+       dev_priv->dma_low = 0;
+       dev_priv->dma_high = init->size;
+       dev_priv->dma_wrap = init->size;
+       dev_priv->dma_offset = init->offset;
+       dev_priv->last_pause_ptr = NULL;
+       dev_priv->hw_addr_ptr =
+               (volatile uint32_t *)((char *)dev_priv->mmio->handle +
+               init->reg_pause_addr);
+
+       via_cmdbuf_start(dev_priv);
+
+       return 0;
+}
+
+static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       drm_via_dma_init_t *init = data;
+       int retcode = 0;
+
+       switch (init->func) {
+       case VIA_INIT_DMA:
+               if (!DRM_SUSER(DRM_CURPROC))
+                       retcode = -EPERM;
+               else
+                       retcode = via_initialize(dev, dev_priv, init);
+               break;
+       case VIA_CLEANUP_DMA:
+               if (!DRM_SUSER(DRM_CURPROC))
+                       retcode = -EPERM;
+               else
+                       retcode = via_dma_cleanup(dev);
+               break;
+       case VIA_DMA_INITIALIZED:
+               retcode = (dev_priv->ring.virtual_start != NULL) ?
+                       0 : -EFAULT;
+               break;
+       default:
+               retcode = -EINVAL;
+               break;
+       }
+
+       return retcode;
+}
+
+static int via_dispatch_cmdbuffer(struct drm_device * dev, drm_via_cmdbuffer_t * cmd)
+{
+       drm_via_private_t *dev_priv;
+       uint32_t *vb;
+       int ret;
+
+       dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       if (dev_priv->ring.virtual_start == NULL) {
+               DRM_ERROR("called without initializing AGP ring buffer.\n");
+               return -EFAULT;
+       }
+
+       if (cmd->size > VIA_PCI_BUF_SIZE) {
+               return -ENOMEM;
+       }
+
+       if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+               return -EFAULT;
+
+       /*
+        * Running this function on AGP memory is dead slow. Therefore
+        * we run it on a temporary cacheable system memory buffer and
+        * copy it to AGP memory when ready.
+        */
+
+       if ((ret =
+            via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
+                                      cmd->size, dev, 1))) {
+               return ret;
+       }
+
+       vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
+       if (vb == NULL) {
+               return -EAGAIN;
+       }
+
+       memcpy(vb, dev_priv->pci_buf, cmd->size);
+
+       dev_priv->dma_low += cmd->size;
+
+       /*
+        * Small submissions somehow stalls the CPU. (AGP cache effects?)
+        * pad to greater size.
+        */
+
+       if (cmd->size < 0x100)
+               via_pad_cache(dev_priv, (0x100 - cmd->size) >> 3);
+       via_cmdbuf_pause(dev_priv);
+
+       return 0;
+}
+
+int via_driver_dma_quiescent(struct drm_device * dev)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+
+       if (!via_wait_idle(dev_priv)) {
+               return -EBUSY;
+       }
+       return 0;
+}
+
+static int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       return via_driver_dma_quiescent(dev);
+}
+
+static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_cmdbuffer_t *cmdbuf = data;
+       int ret;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size);
+
+       ret = via_dispatch_cmdbuffer(dev, cmdbuf);
+       if (ret) {
+               return ret;
+       }
+
+       return 0;
+}
+
+static int via_dispatch_pci_cmdbuffer(struct drm_device * dev,
+                                     drm_via_cmdbuffer_t * cmd)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+       int ret;
+
+       if (cmd->size > VIA_PCI_BUF_SIZE) {
+               return -ENOMEM;
+       }
+       if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
+               return -EFAULT;
+
+       if ((ret =
+            via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
+                                      cmd->size, dev, 0))) {
+               return ret;
+       }
+
+       ret =
+           via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf,
+                                    cmd->size);
+       return ret;
+}
+
+static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_cmdbuffer_t *cmdbuf = data;
+       int ret;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size);
+
+       ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf);
+       if (ret) {
+               return ret;
+       }
+
+       return 0;
+}
+
+static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv,
+                                        uint32_t * vb, int qw_count)
+{
+       for (; qw_count > 0; --qw_count) {
+               VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY);
+       }
+       return vb;
+}
+
+/*
+ * This function is used internally by ring buffer management code.
+ *
+ * Returns virtual pointer to ring buffer.
+ */
+static inline uint32_t *via_get_dma(drm_via_private_t * dev_priv)
+{
+       return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
+}
+
+/*
+ * Hooks a segment of data into the tail of the ring-buffer by
+ * modifying the pause address stored in the buffer itself. If
+ * the regulator has already paused, restart it.
+ */
+static int via_hook_segment(drm_via_private_t * dev_priv,
+                           uint32_t pause_addr_hi, uint32_t pause_addr_lo,
+                           int no_pci_fire)
+{
+       int paused, count;
+       volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
+       uint32_t reader,ptr;
+       uint32_t diff;
+
+       paused = 0;
+       via_flush_write_combine();
+       (void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1);
+
+       *paused_at = pause_addr_lo;
+       via_flush_write_combine();
+       (void) *paused_at;
+
+       reader = *(dev_priv->hw_addr_ptr);
+       ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
+               dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+
+       dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
+
+       /*
+        * If there is a possibility that the command reader will 
+        * miss the new pause address and pause on the old one,
+        * In that case we need to program the new start address
+        * using PCI.
+        */
+
+       diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
+       count = 10000000;
+       while(diff == 0 && count--) {
+               paused = (VIA_READ(0x41c) & 0x80000000);
+               if (paused) 
+                       break;
+               reader = *(dev_priv->hw_addr_ptr);
+               diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
+       }
+
+       paused = VIA_READ(0x41c) & 0x80000000;
+
+       if (paused && !no_pci_fire) {
+               reader = *(dev_priv->hw_addr_ptr);
+               diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
+               diff &= (dev_priv->dma_high - 1);
+               if (diff != 0 && diff < (dev_priv->dma_high >> 1)) {
+                       DRM_ERROR("Paused at incorrect address. "
+                                 "0x%08x, 0x%08x 0x%08x\n",
+                                 ptr, reader, dev_priv->dma_diff);
+               } else if (diff == 0) {
+                       /*
+                        * There is a concern that these writes may stall the PCI bus
+                        * if the GPU is not idle. However, idling the GPU first
+                        * doesn't make a difference.
+                        */
+
+                       VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
+                       VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
+                       VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
+                       VIA_READ(VIA_REG_TRANSPACE);
+               }
+       }
+       return paused;
+}
+
+static int via_wait_idle(drm_via_private_t * dev_priv)
+{
+       int count = 10000000;
+
+       while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--);
+
+       while (count-- && (VIA_READ(VIA_REG_STATUS) &
+                          (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
+                           VIA_3D_ENG_BUSY))) ;
+       return count;
+}
+
+static uint32_t *via_align_cmd(drm_via_private_t * dev_priv, uint32_t cmd_type,
+                              uint32_t addr, uint32_t * cmd_addr_hi,
+                              uint32_t * cmd_addr_lo, int skip_wait)
+{
+       uint32_t agp_base;
+       uint32_t cmd_addr, addr_lo, addr_hi;
+       uint32_t *vb;
+       uint32_t qw_pad_count;
+
+       if (!skip_wait)
+               via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE);
+
+       vb = via_get_dma(dev_priv);
+       VIA_OUT_RING_QW(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
+                       (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16);
+       agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+       qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
+           ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
+
+       cmd_addr = (addr) ? addr :
+           agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
+       addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) |
+                  (cmd_addr & HC_HAGPBpL_MASK));
+       addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24));
+
+       vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1);
+       VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi, *cmd_addr_lo = addr_lo);
+       return vb;
+}
+
+static void via_cmdbuf_start(drm_via_private_t * dev_priv)
+{
+       uint32_t pause_addr_lo, pause_addr_hi;
+       uint32_t start_addr, start_addr_lo;
+       uint32_t end_addr, end_addr_lo;
+       uint32_t command;
+       uint32_t agp_base;
+       uint32_t ptr;
+       uint32_t reader;
+       int count;
+
+       dev_priv->dma_low = 0;
+
+       agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+       start_addr = agp_base;
+       end_addr = agp_base + dev_priv->dma_high;
+
+       start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF));
+       end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF));
+       command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
+                  ((end_addr & 0xff000000) >> 16));
+
+       dev_priv->last_pause_ptr =
+           via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0,
+                         &pause_addr_hi, &pause_addr_lo, 1) - 1;
+
+       via_flush_write_combine();
+       (void) *(volatile uint32_t *)dev_priv->last_pause_ptr;
+
+       VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
+       VIA_WRITE(VIA_REG_TRANSPACE, command);
+       VIA_WRITE(VIA_REG_TRANSPACE, start_addr_lo);
+       VIA_WRITE(VIA_REG_TRANSPACE, end_addr_lo);
+
+       VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
+       VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
+       DRM_WRITEMEMORYBARRIER();
+       VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
+       VIA_READ(VIA_REG_TRANSPACE);
+
+       dev_priv->dma_diff = 0;
+
+       count = 10000000;
+       while (!(VIA_READ(0x41c) & 0x80000000) && count--);
+
+       reader = *(dev_priv->hw_addr_ptr);
+       ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
+           dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+
+       /*
+        * This is the difference between where we tell the
+        * command reader to pause and where it actually pauses.
+        * This differs between hw implementation so we need to
+        * detect it.
+        */
+
+       dev_priv->dma_diff = ptr - reader;
+}
+
+static void via_pad_cache(drm_via_private_t * dev_priv, int qwords)
+{
+       uint32_t *vb;
+
+       via_cmdbuf_wait(dev_priv, qwords + 2);
+       vb = via_get_dma(dev_priv);
+       VIA_OUT_RING_QW(HC_HEADER2, HC_ParaType_NotTex << 16);
+       via_align_buffer(dev_priv, vb, qwords);
+}
+
+static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
+{
+       uint32_t *vb = via_get_dma(dev_priv);
+       SetReg2DAGP(0x0C, (0 | (0 << 16)));
+       SetReg2DAGP(0x10, 0 | (0 << 16));
+       SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
+}
+
+static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
+{
+       uint32_t agp_base;
+       uint32_t pause_addr_lo, pause_addr_hi;
+       uint32_t jump_addr_lo, jump_addr_hi;
+       volatile uint32_t *last_pause_ptr;
+       uint32_t dma_low_save1, dma_low_save2;
+
+       agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+       via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
+                     &jump_addr_lo, 0);
+
+       dev_priv->dma_wrap = dev_priv->dma_low;
+
+       /*
+        * Wrap command buffer to the beginning.
+        */
+
+       dev_priv->dma_low = 0;
+       if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) {
+               DRM_ERROR("via_cmdbuf_jump failed\n");
+       }
+
+       via_dummy_bitblt(dev_priv);
+       via_dummy_bitblt(dev_priv);
+
+       last_pause_ptr =
+           via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+                         &pause_addr_lo, 0) - 1;
+       via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+                     &pause_addr_lo, 0);
+
+       *last_pause_ptr = pause_addr_lo;
+       dma_low_save1 = dev_priv->dma_low;
+
+       /*
+        * Now, set a trap that will pause the regulator if it tries to rerun the old
+        * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
+        * and reissues the jump command over PCI, while the regulator has already taken the jump
+        * and actually paused at the current buffer end).
+        * There appears to be no other way to detect this condition, since the hw_addr_pointer
+        * does not seem to get updated immediately when a jump occurs.
+        */
+
+       last_pause_ptr =
+               via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+                             &pause_addr_lo, 0) - 1;
+       via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+                     &pause_addr_lo, 0);
+       *last_pause_ptr = pause_addr_lo;
+
+       dma_low_save2 = dev_priv->dma_low;
+       dev_priv->dma_low = dma_low_save1;
+       via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0);
+       dev_priv->dma_low = dma_low_save2;
+       via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
+}
+
+
+static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
+{
+       via_cmdbuf_jump(dev_priv);
+}
+
+static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
+{
+       uint32_t pause_addr_lo, pause_addr_hi;
+
+       via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0);
+       via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
+}
+
+static void via_cmdbuf_pause(drm_via_private_t * dev_priv)
+{
+       via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE);
+}
+
+static void via_cmdbuf_reset(drm_via_private_t * dev_priv)
+{
+       via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP);
+       via_wait_idle(dev_priv);
+}
+
+/*
+ * User interface to the space and lag functions.
+ */
+
+static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_cmdbuf_size_t *d_siz = data;
+       int ret = 0;
+       uint32_t tmp_size, count;
+       drm_via_private_t *dev_priv;
+
+       DRM_DEBUG("\n");
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       if (dev_priv->ring.virtual_start == NULL) {
+               DRM_ERROR("called without initializing AGP ring buffer.\n");
+               return -EFAULT;
+       }
+
+       count = 1000000;
+       tmp_size = d_siz->size;
+       switch (d_siz->func) {
+       case VIA_CMDBUF_SPACE:
+               while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size)
+                      && count--) {
+                       if (!d_siz->wait) {
+                               break;
+                       }
+               }
+               if (!count) {
+                       DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n");
+                       ret = -EAGAIN;
+               }
+               break;
+       case VIA_CMDBUF_LAG:
+               while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size)
+                      && count--) {
+                       if (!d_siz->wait) {
+                               break;
+                       }
+               }
+               if (!count) {
+                       DRM_ERROR("VIA_CMDBUF_LAG timed out.\n");
+                       ret = -EAGAIN;
+               }
+               break;
+       default:
+               ret = -EFAULT;
+       }
+       d_siz->size = tmp_size;
+
+       return ret;
+}
+
+struct drm_ioctl_desc via_ioctls[] = {
+       DRM_IOCTL_DEF(DRM_VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_FREEMEM, via_mem_free, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF(DRM_VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_DMA_INIT, via_dma_init, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_FLUSH, via_flush_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_DMA_BLIT, via_dma_blit, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH)
+};
+
+int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls);
diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c
new file mode 100644 (file)
index 0000000..409e00a
--- /dev/null
@@ -0,0 +1,816 @@
+/* via_dmablit.c -- PCI DMA BitBlt support for the VIA Unichrome/Pro
+ *
+ * Copyright (C) 2005 Thomas Hellstrom, All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Thomas Hellstrom.
+ *    Partially based on code obtained from Digeo Inc.
+ */
+
+
+/*
+ * Unmaps the DMA mappings.
+ * FIXME: Is this a NoOp on x86? Also
+ * FIXME: What happens if this one is called and a pending blit has previously done
+ * the same DMA mappings?
+ */
+
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+#include "via_dmablit.h"
+
+#include <linux/pagemap.h>
+
+#define VIA_PGDN(x)         (((unsigned long)(x)) & PAGE_MASK)
+#define VIA_PGOFF(x)       (((unsigned long)(x)) & ~PAGE_MASK)
+#define VIA_PFN(x)           ((unsigned long)(x) >> PAGE_SHIFT)
+
+typedef struct _drm_via_descriptor {
+       uint32_t mem_addr;
+       uint32_t dev_addr;
+       uint32_t size;
+       uint32_t next;
+} drm_via_descriptor_t;
+
+
+/*
+ * Unmap a DMA mapping.
+ */
+
+
+
+static void
+via_unmap_blit_from_device(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
+{
+       int num_desc = vsg->num_desc;
+       unsigned cur_descriptor_page = num_desc / vsg->descriptors_per_page;
+       unsigned descriptor_this_page = num_desc % vsg->descriptors_per_page;
+       drm_via_descriptor_t *desc_ptr = vsg->desc_pages[cur_descriptor_page] +
+               descriptor_this_page;
+       dma_addr_t next = vsg->chain_start;
+
+       while(num_desc--) {
+               if (descriptor_this_page-- == 0) {
+                       cur_descriptor_page--;
+                       descriptor_this_page = vsg->descriptors_per_page - 1;
+                       desc_ptr = vsg->desc_pages[cur_descriptor_page] +
+                               descriptor_this_page;
+               }
+               dma_unmap_single(&pdev->dev, next, sizeof(*desc_ptr), DMA_TO_DEVICE);
+               dma_unmap_page(&pdev->dev, desc_ptr->mem_addr, desc_ptr->size, vsg->direction);
+               next = (dma_addr_t) desc_ptr->next;
+               desc_ptr--;
+       }
+}
+
+/*
+ * If mode = 0, count how many descriptors are needed.
+ * If mode = 1, Map the DMA pages for the device, put together and map also the descriptors.
+ * Descriptors are run in reverse order by the hardware because we are not allowed to update the
+ * 'next' field without syncing calls when the descriptor is already mapped.
+ */
+
+static void
+via_map_blit_for_device(struct pci_dev *pdev,
+                  const drm_via_dmablit_t *xfer,
+                  drm_via_sg_info_t *vsg,
+                  int mode)
+{
+       unsigned cur_descriptor_page = 0;
+       unsigned num_descriptors_this_page = 0;
+       unsigned char *mem_addr = xfer->mem_addr;
+       unsigned char *cur_mem;
+       unsigned char *first_addr = (unsigned char *)VIA_PGDN(mem_addr);
+       uint32_t fb_addr = xfer->fb_addr;
+       uint32_t cur_fb;
+       unsigned long line_len;
+       unsigned remaining_len;
+       int num_desc = 0;
+       int cur_line;
+       dma_addr_t next = 0 | VIA_DMA_DPR_EC;
+       drm_via_descriptor_t *desc_ptr = NULL;
+
+       if (mode == 1)
+               desc_ptr = vsg->desc_pages[cur_descriptor_page];
+
+       for (cur_line = 0; cur_line < xfer->num_lines; ++cur_line) {
+
+               line_len = xfer->line_length;
+               cur_fb = fb_addr;
+               cur_mem = mem_addr;
+
+               while (line_len > 0) {
+
+                       remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len);
+                       line_len -= remaining_len;
+
+                       if (mode == 1) {
+                               desc_ptr->mem_addr =
+                                       dma_map_page(&pdev->dev,
+                                                    vsg->pages[VIA_PFN(cur_mem) -
+                                                               VIA_PFN(first_addr)],
+                                                    VIA_PGOFF(cur_mem), remaining_len,
+                                                    vsg->direction);
+                               desc_ptr->dev_addr = cur_fb;
+
+                               desc_ptr->size = remaining_len;
+                               desc_ptr->next = (uint32_t) next;
+                               next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr),
+                                                     DMA_TO_DEVICE);
+                               desc_ptr++;
+                               if (++num_descriptors_this_page >= vsg->descriptors_per_page) {
+                                       num_descriptors_this_page = 0;
+                                       desc_ptr = vsg->desc_pages[++cur_descriptor_page];
+                               }
+                       }
+
+                       num_desc++;
+                       cur_mem += remaining_len;
+                       cur_fb += remaining_len;
+               }
+
+               mem_addr += xfer->mem_stride;
+               fb_addr += xfer->fb_stride;
+       }
+
+       if (mode == 1) {
+               vsg->chain_start = next;
+               vsg->state = dr_via_device_mapped;
+       }
+       vsg->num_desc = num_desc;
+}
+
+/*
+ * Function that frees up all resources for a blit. It is usable even if the
+ * blit info has only been partially built as long as the status enum is consistent
+ * with the actual status of the used resources.
+ */
+
+
+static void
+via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
+{
+       struct page *page;
+       int i;
+
+       switch(vsg->state) {
+       case dr_via_device_mapped:
+               via_unmap_blit_from_device(pdev, vsg);
+       case dr_via_desc_pages_alloc:
+               for (i=0; i<vsg->num_desc_pages; ++i) {
+                       if (vsg->desc_pages[i] != NULL)
+                         free_page((unsigned long)vsg->desc_pages[i]);
+               }
+               kfree(vsg->desc_pages);
+       case dr_via_pages_locked:
+               for (i=0; i<vsg->num_pages; ++i) {
+                       if ( NULL != (page = vsg->pages[i])) {
+                               if (! PageReserved(page) && (DMA_FROM_DEVICE == vsg->direction))
+                                       SetPageDirty(page);
+                               page_cache_release(page);
+                       }
+               }
+       case dr_via_pages_alloc:
+               vfree(vsg->pages);
+       default:
+               vsg->state = dr_via_sg_init;
+       }
+       if (vsg->bounce_buffer) {
+               vfree(vsg->bounce_buffer);
+               vsg->bounce_buffer = NULL;
+       }
+       vsg->free_on_sequence = 0;
+}
+
+/*
+ * Fire a blit engine.
+ */
+
+static void
+via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+
+       VIA_WRITE(VIA_PCI_DMA_MAR0 + engine*0x10, 0);
+       VIA_WRITE(VIA_PCI_DMA_DAR0 + engine*0x10, 0);
+       VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD |
+                 VIA_DMA_CSR_DE);
+       VIA_WRITE(VIA_PCI_DMA_MR0  + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);
+       VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0);
+       VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);
+       DRM_WRITEMEMORYBARRIER();
+       VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);
+       VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04);
+}
+
+/*
+ * Obtain a page pointer array and lock all pages into system memory. A segmentation violation will
+ * occur here if the calling user does not have access to the submitted address.
+ */
+
+static int
+via_lock_all_dma_pages(drm_via_sg_info_t *vsg,  drm_via_dmablit_t *xfer)
+{
+       int ret;
+       unsigned long first_pfn = VIA_PFN(xfer->mem_addr);
+       vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride -1)) -
+               first_pfn + 1;
+
+       if (NULL == (vsg->pages = vmalloc(sizeof(struct page *) * vsg->num_pages)))
+               return -ENOMEM;
+       memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages);
+       down_read(&current->mm->mmap_sem);
+       ret = get_user_pages(current, current->mm,
+                            (unsigned long)xfer->mem_addr,
+                            vsg->num_pages,
+                            (vsg->direction == DMA_FROM_DEVICE),
+                            0, vsg->pages, NULL);
+
+       up_read(&current->mm->mmap_sem);
+       if (ret != vsg->num_pages) {
+               if (ret < 0)
+                       return ret;
+               vsg->state = dr_via_pages_locked;
+               return -EINVAL;
+       }
+       vsg->state = dr_via_pages_locked;
+       DRM_DEBUG("DMA pages locked\n");
+       return 0;
+}
+
+/*
+ * Allocate DMA capable memory for the blit descriptor chain, and an array that keeps track of the
+ * pages we allocate. We don't want to use kmalloc for the descriptor chain because it may be
+ * quite large for some blits, and pages don't need to be contingous.
+ */
+
+static int
+via_alloc_desc_pages(drm_via_sg_info_t *vsg)
+{
+       int i;
+
+       vsg->descriptors_per_page = PAGE_SIZE / sizeof( drm_via_descriptor_t);
+       vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) /
+               vsg->descriptors_per_page;
+
+       if (NULL ==  (vsg->desc_pages = kcalloc(vsg->num_desc_pages, sizeof(void *), GFP_KERNEL)))
+               return -ENOMEM;
+
+       vsg->state = dr_via_desc_pages_alloc;
+       for (i=0; i<vsg->num_desc_pages; ++i) {
+               if (NULL == (vsg->desc_pages[i] =
+                            (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL)))
+                       return -ENOMEM;
+       }
+       DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages,
+                 vsg->num_desc);
+       return 0;
+}
+
+static void
+via_abort_dmablit(struct drm_device *dev, int engine)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+
+       VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA);
+}
+
+static void
+via_dmablit_engine_off(struct drm_device *dev, int engine)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+
+       VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD);
+}
+
+
+
+/*
+ * The dmablit part of the IRQ handler. Trying to do only reasonably fast things here.
+ * The rest, like unmapping and freeing memory for done blits is done in a separate workqueue
+ * task. Basically the task of the interrupt handler is to submit a new blit to the engine, while
+ * the workqueue task takes care of processing associated with the old blit.
+ */
+
+void
+via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+       drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
+       int cur;
+       int done_transfer;
+       unsigned long irqsave=0;
+       uint32_t status = 0;
+
+       DRM_DEBUG("DMA blit handler called. engine = %d, from_irq = %d, blitq = 0x%lx\n",
+                 engine, from_irq, (unsigned long) blitq);
+
+       if (from_irq) {
+               spin_lock(&blitq->blit_lock);
+       } else {
+               spin_lock_irqsave(&blitq->blit_lock, irqsave);
+       }
+
+       done_transfer = blitq->is_active &&
+         (( status = VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD);
+       done_transfer = done_transfer || ( blitq->aborting && !(status & VIA_DMA_CSR_DE));
+
+       cur = blitq->cur;
+       if (done_transfer) {
+
+               blitq->blits[cur]->aborted = blitq->aborting;
+               blitq->done_blit_handle++;
+               DRM_WAKEUP(blitq->blit_queue + cur);
+
+               cur++;
+               if (cur >= VIA_NUM_BLIT_SLOTS)
+                       cur = 0;
+               blitq->cur = cur;
+
+               /*
+                * Clear transfer done flag.
+                */
+
+               VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04,  VIA_DMA_CSR_TD);
+
+               blitq->is_active = 0;
+               blitq->aborting = 0;
+               schedule_work(&blitq->wq);
+
+       } else if (blitq->is_active && time_after_eq(jiffies, blitq->end)) {
+
+               /*
+                * Abort transfer after one second.
+                */
+
+               via_abort_dmablit(dev, engine);
+               blitq->aborting = 1;
+               blitq->end = jiffies + DRM_HZ;
+       }
+
+       if (!blitq->is_active) {
+               if (blitq->num_outstanding) {
+                       via_fire_dmablit(dev, blitq->blits[cur], engine);
+                       blitq->is_active = 1;
+                       blitq->cur = cur;
+                       blitq->num_outstanding--;
+                       blitq->end = jiffies + DRM_HZ;
+                       if (!timer_pending(&blitq->poll_timer))
+                               mod_timer(&blitq->poll_timer, jiffies + 1);
+               } else {
+                       if (timer_pending(&blitq->poll_timer)) {
+                               del_timer(&blitq->poll_timer);
+                       }
+                       via_dmablit_engine_off(dev, engine);
+               }
+       }
+
+       if (from_irq) {
+               spin_unlock(&blitq->blit_lock);
+       } else {
+               spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+       }
+}
+
+
+
+/*
+ * Check whether this blit is still active, performing necessary locking.
+ */
+
+static int
+via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_queue_head_t **queue)
+{
+       unsigned long irqsave;
+       uint32_t slot;
+       int active;
+
+       spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+       /*
+        * Allow for handle wraparounds.
+        */
+
+       active = ((blitq->done_blit_handle - handle) > (1 << 23)) &&
+               ((blitq->cur_blit_handle - handle) <= (1 << 23));
+
+       if (queue && active) {
+               slot = handle - blitq->done_blit_handle + blitq->cur -1;
+               if (slot >= VIA_NUM_BLIT_SLOTS) {
+                       slot -= VIA_NUM_BLIT_SLOTS;
+               }
+               *queue = blitq->blit_queue + slot;
+       }
+
+       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+       return active;
+}
+
+/*
+ * Sync. Wait for at least three seconds for the blit to be performed.
+ */
+
+static int
+via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine)
+{
+
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+       drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
+       wait_queue_head_t *queue;
+       int ret = 0;
+
+       if (via_dmablit_active(blitq, engine, handle, &queue)) {
+               DRM_WAIT_ON(ret, *queue, 3 * DRM_HZ,
+                           !via_dmablit_active(blitq, engine, handle, NULL));
+       }
+       DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n",
+                 handle, engine, ret);
+
+       return ret;
+}
+
+
+/*
+ * A timer that regularly polls the blit engine in cases where we don't have interrupts:
+ * a) Broken hardware (typically those that don't have any video capture facility).
+ * b) Blit abort. The hardware doesn't send an interrupt when a blit is aborted.
+ * The timer and hardware IRQ's can and do work in parallel. If the hardware has
+ * irqs, it will shorten the latency somewhat.
+ */
+
+
+
+static void
+via_dmablit_timer(unsigned long data)
+{
+       drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;
+       struct drm_device *dev = blitq->dev;
+       int engine = (int)
+               (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues);
+
+       DRM_DEBUG("Polling timer called for engine %d, jiffies %lu\n", engine,
+                 (unsigned long) jiffies);
+
+       via_dmablit_handler(dev, engine, 0);
+
+       if (!timer_pending(&blitq->poll_timer)) {
+               mod_timer(&blitq->poll_timer, jiffies + 1);
+
+              /*
+               * Rerun handler to delete timer if engines are off, and
+               * to shorten abort latency. This is a little nasty.
+               */
+
+              via_dmablit_handler(dev, engine, 0);
+
+       }
+}
+
+
+
+
+/*
+ * Workqueue task that frees data and mappings associated with a blit.
+ * Also wakes up waiting processes. Each of these tasks handles one
+ * blit engine only and may not be called on each interrupt.
+ */
+
+
+static void
+via_dmablit_workqueue(struct work_struct *work)
+{
+       drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq);
+       struct drm_device *dev = blitq->dev;
+       unsigned long irqsave;
+       drm_via_sg_info_t *cur_sg;
+       int cur_released;
+
+
+       DRM_DEBUG("Workqueue task called for blit engine %ld\n",(unsigned long)
+                 (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues));
+
+       spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+       while(blitq->serviced != blitq->cur) {
+
+               cur_released = blitq->serviced++;
+
+               DRM_DEBUG("Releasing blit slot %d\n", cur_released);
+
+               if (blitq->serviced >= VIA_NUM_BLIT_SLOTS)
+                       blitq->serviced = 0;
+
+               cur_sg = blitq->blits[cur_released];
+               blitq->num_free++;
+
+               spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+               DRM_WAKEUP(&blitq->busy_queue);
+
+               via_free_sg_info(dev->pdev, cur_sg);
+               kfree(cur_sg);
+
+               spin_lock_irqsave(&blitq->blit_lock, irqsave);
+       }
+
+       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+}
+
+
+/*
+ * Init all blit engines. Currently we use two, but some hardware have 4.
+ */
+
+
+void
+via_init_dmablit(struct drm_device *dev)
+{
+       int i,j;
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+       drm_via_blitq_t *blitq;
+
+       pci_set_master(dev->pdev);
+
+       for (i=0; i< VIA_NUM_BLIT_ENGINES; ++i) {
+               blitq = dev_priv->blit_queues + i;
+               blitq->dev = dev;
+               blitq->cur_blit_handle = 0;
+               blitq->done_blit_handle = 0;
+               blitq->head = 0;
+               blitq->cur = 0;
+               blitq->serviced = 0;
+               blitq->num_free = VIA_NUM_BLIT_SLOTS - 1;
+               blitq->num_outstanding = 0;
+               blitq->is_active = 0;
+               blitq->aborting = 0;
+               spin_lock_init(&blitq->blit_lock);
+               for (j=0; j<VIA_NUM_BLIT_SLOTS; ++j) {
+                       DRM_INIT_WAITQUEUE(blitq->blit_queue + j);
+               }
+               DRM_INIT_WAITQUEUE(&blitq->busy_queue);
+               INIT_WORK(&blitq->wq, via_dmablit_workqueue);
+               setup_timer(&blitq->poll_timer, via_dmablit_timer,
+                               (unsigned long)blitq);
+       }
+}
+
+/*
+ * Build all info and do all mappings required for a blit.
+ */
+
+
+static int
+via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
+{
+       int draw = xfer->to_fb;
+       int ret = 0;
+
+       vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+       vsg->bounce_buffer = NULL;
+
+       vsg->state = dr_via_sg_init;
+
+       if (xfer->num_lines <= 0 || xfer->line_length <= 0) {
+               DRM_ERROR("Zero size bitblt.\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Below check is a driver limitation, not a hardware one. We
+        * don't want to lock unused pages, and don't want to incoporate the
+        * extra logic of avoiding them. Make sure there are no.
+        * (Not a big limitation anyway.)
+        */
+
+       if ((xfer->mem_stride - xfer->line_length) > 2*PAGE_SIZE) {
+               DRM_ERROR("Too large system memory stride. Stride: %d, "
+                         "Length: %d\n", xfer->mem_stride, xfer->line_length);
+               return -EINVAL;
+       }
+
+       if ((xfer->mem_stride == xfer->line_length) &&
+          (xfer->fb_stride == xfer->line_length)) {
+               xfer->mem_stride *= xfer->num_lines;
+               xfer->line_length = xfer->mem_stride;
+               xfer->fb_stride = xfer->mem_stride;
+               xfer->num_lines = 1;
+       }
+
+       /*
+        * Don't lock an arbitrary large number of pages, since that causes a
+        * DOS security hole.
+        */
+
+       if (xfer->num_lines > 2048 || (xfer->num_lines*xfer->mem_stride > (2048*2048*4))) {
+               DRM_ERROR("Too large PCI DMA bitblt.\n");
+               return -EINVAL;
+       }
+
+       /*
+        * we allow a negative fb stride to allow flipping of images in
+        * transfer.
+        */
+
+       if (xfer->mem_stride < xfer->line_length ||
+               abs(xfer->fb_stride) < xfer->line_length) {
+               DRM_ERROR("Invalid frame-buffer / memory stride.\n");
+               return -EINVAL;
+       }
+
+       /*
+        * A hardware bug seems to be worked around if system memory addresses start on
+        * 16 byte boundaries. This seems a bit restrictive however. VIA is contacted
+        * about this. Meanwhile, impose the following restrictions:
+        */
+
+#ifdef VIA_BUGFREE
+       if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) ||
+           ((xfer->num_lines > 1) && ((xfer->mem_stride & 3) != (xfer->fb_stride & 3)))) {
+               DRM_ERROR("Invalid DRM bitblt alignment.\n");
+               return -EINVAL;
+       }
+#else
+       if ((((unsigned long)xfer->mem_addr & 15) ||
+             ((unsigned long)xfer->fb_addr & 3)) ||
+          ((xfer->num_lines > 1) &&
+          ((xfer->mem_stride & 15) || (xfer->fb_stride & 3)))) {
+               DRM_ERROR("Invalid DRM bitblt alignment.\n");
+               return -EINVAL;
+       }
+#endif
+
+       if (0 != (ret = via_lock_all_dma_pages(vsg, xfer))) {
+               DRM_ERROR("Could not lock DMA pages.\n");
+               via_free_sg_info(dev->pdev, vsg);
+               return ret;
+       }
+
+       via_map_blit_for_device(dev->pdev, xfer, vsg, 0);
+       if (0 != (ret = via_alloc_desc_pages(vsg))) {
+               DRM_ERROR("Could not allocate DMA descriptor pages.\n");
+               via_free_sg_info(dev->pdev, vsg);
+               return ret;
+       }
+       via_map_blit_for_device(dev->pdev, xfer, vsg, 1);
+
+       return 0;
+}
+
+
+/*
+ * Reserve one free slot in the blit queue. Will wait for one second for one
+ * to become available. Otherwise -EBUSY is returned.
+ */
+
+static int
+via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine)
+{
+       int ret=0;
+       unsigned long irqsave;
+
+       DRM_DEBUG("Num free is %d\n", blitq->num_free);
+       spin_lock_irqsave(&blitq->blit_lock, irqsave);
+       while(blitq->num_free == 0) {
+               spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+               DRM_WAIT_ON(ret, blitq->busy_queue, DRM_HZ, blitq->num_free > 0);
+               if (ret) {
+                       return (-EINTR == ret) ? -EAGAIN : ret;
+               }
+
+               spin_lock_irqsave(&blitq->blit_lock, irqsave);
+       }
+
+       blitq->num_free--;
+       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+       return 0;
+}
+
+/*
+ * Hand back a free slot if we changed our mind.
+ */
+
+static void
+via_dmablit_release_slot(drm_via_blitq_t *blitq)
+{
+       unsigned long irqsave;
+
+       spin_lock_irqsave(&blitq->blit_lock, irqsave);
+       blitq->num_free++;
+       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+       DRM_WAKEUP( &blitq->busy_queue );
+}
+
+/*
+ * Grab a free slot. Build blit info and queue a blit.
+ */
+
+
+static int
+via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+       drm_via_sg_info_t *vsg;
+       drm_via_blitq_t *blitq;
+       int ret;
+       int engine;
+       unsigned long irqsave;
+
+       if (dev_priv == NULL) {
+               DRM_ERROR("Called without initialization.\n");
+               return -EINVAL;
+       }
+
+       engine = (xfer->to_fb) ? 0 : 1;
+       blitq = dev_priv->blit_queues + engine;
+       if (0 != (ret = via_dmablit_grab_slot(blitq, engine))) {
+               return ret;
+       }
+       if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) {
+               via_dmablit_release_slot(blitq);
+               return -ENOMEM;
+       }
+       if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) {
+               via_dmablit_release_slot(blitq);
+               kfree(vsg);
+               return ret;
+       }
+       spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+       blitq->blits[blitq->head++] = vsg;
+       if (blitq->head >= VIA_NUM_BLIT_SLOTS)
+               blitq->head = 0;
+       blitq->num_outstanding++;
+       xfer->sync.sync_handle = ++blitq->cur_blit_handle;
+
+       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+       xfer->sync.engine = engine;
+
+       via_dmablit_handler(dev, engine, 0);
+
+       return 0;
+}
+
+/*
+ * Sync on a previously submitted blit. Note that the X server use signals extensively, and
+ * that there is a very big probability that this IOCTL will be interrupted by a signal. In that
+ * case it returns with -EAGAIN for the signal to be delivered.
+ * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock().
+ */
+
+int
+via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_priv )
+{
+       drm_via_blitsync_t *sync = data;
+       int err;
+
+       if (sync->engine >= VIA_NUM_BLIT_ENGINES)
+               return -EINVAL;
+
+       err = via_dmablit_sync(dev, sync->sync_handle, sync->engine);
+
+       if (-EINTR == err)
+               err = -EAGAIN;
+
+       return err;
+}
+
+
+/*
+ * Queue a blit and hand back a handle to be used for sync. This IOCTL may be interrupted by a signal
+ * while waiting for a free slot in the blit queue. In that case it returns with -EAGAIN and should
+ * be reissued. See the above IOCTL code.
+ */
+
+int
+via_dma_blit( struct drm_device *dev, void *data, struct drm_file *file_priv )
+{
+       drm_via_dmablit_t *xfer = data;
+       int err;
+
+       err = via_dmablit(dev, xfer);
+
+       return err;
+}
diff --git a/drivers/gpu/drm/via/via_dmablit.h b/drivers/gpu/drm/via/via_dmablit.h
new file mode 100644 (file)
index 0000000..7408a54
--- /dev/null
@@ -0,0 +1,140 @@
+/* via_dmablit.h -- PCI DMA BitBlt support for the VIA Unichrome/Pro
+ *
+ * Copyright 2005 Thomas Hellstrom.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Thomas Hellstrom.
+ *    Register info from Digeo Inc.
+ */
+
+#ifndef _VIA_DMABLIT_H
+#define _VIA_DMABLIT_H
+
+#include <linux/dma-mapping.h>
+
+#define VIA_NUM_BLIT_ENGINES 2
+#define VIA_NUM_BLIT_SLOTS 8
+
+struct _drm_via_descriptor;
+
+typedef struct _drm_via_sg_info {
+       struct page **pages;
+       unsigned long num_pages;
+       struct _drm_via_descriptor **desc_pages;
+       int num_desc_pages;
+       int num_desc;
+       enum dma_data_direction direction;
+       unsigned char *bounce_buffer;
+        dma_addr_t chain_start;
+       uint32_t free_on_sequence;
+        unsigned int descriptors_per_page;
+       int aborted;
+       enum {
+               dr_via_device_mapped,
+               dr_via_desc_pages_alloc,
+               dr_via_pages_locked,
+               dr_via_pages_alloc,
+               dr_via_sg_init
+       } state;
+} drm_via_sg_info_t;
+
+typedef struct _drm_via_blitq {
+       struct drm_device *dev;
+       uint32_t cur_blit_handle;
+       uint32_t done_blit_handle;
+       unsigned serviced;
+       unsigned head;
+       unsigned cur;
+       unsigned num_free;
+       unsigned num_outstanding;
+       unsigned long end;
+        int aborting;
+       int is_active;
+       drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS];
+       spinlock_t blit_lock;
+       wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS];
+       wait_queue_head_t busy_queue;
+       struct work_struct wq;
+       struct timer_list poll_timer;
+} drm_via_blitq_t;
+
+
+/*
+ *  PCI DMA Registers
+ *  Channels 2 & 3 don't seem to be implemented in hardware.
+ */
+
+#define VIA_PCI_DMA_MAR0            0xE40   /* Memory Address Register of Channel 0 */
+#define VIA_PCI_DMA_DAR0            0xE44   /* Device Address Register of Channel 0 */
+#define VIA_PCI_DMA_BCR0            0xE48   /* Byte Count Register of Channel 0 */
+#define VIA_PCI_DMA_DPR0            0xE4C   /* Descriptor Pointer Register of Channel 0 */
+
+#define VIA_PCI_DMA_MAR1            0xE50   /* Memory Address Register of Channel 1 */
+#define VIA_PCI_DMA_DAR1            0xE54   /* Device Address Register of Channel 1 */
+#define VIA_PCI_DMA_BCR1            0xE58   /* Byte Count Register of Channel 1 */
+#define VIA_PCI_DMA_DPR1            0xE5C   /* Descriptor Pointer Register of Channel 1 */
+
+#define VIA_PCI_DMA_MAR2            0xE60   /* Memory Address Register of Channel 2 */
+#define VIA_PCI_DMA_DAR2            0xE64   /* Device Address Register of Channel 2 */
+#define VIA_PCI_DMA_BCR2            0xE68   /* Byte Count Register of Channel 2 */
+#define VIA_PCI_DMA_DPR2            0xE6C   /* Descriptor Pointer Register of Channel 2 */
+
+#define VIA_PCI_DMA_MAR3            0xE70   /* Memory Address Register of Channel 3 */
+#define VIA_PCI_DMA_DAR3            0xE74   /* Device Address Register of Channel 3 */
+#define VIA_PCI_DMA_BCR3            0xE78   /* Byte Count Register of Channel 3 */
+#define VIA_PCI_DMA_DPR3            0xE7C   /* Descriptor Pointer Register of Channel 3 */
+
+#define VIA_PCI_DMA_MR0             0xE80   /* Mode Register of Channel 0 */
+#define VIA_PCI_DMA_MR1             0xE84   /* Mode Register of Channel 1 */
+#define VIA_PCI_DMA_MR2             0xE88   /* Mode Register of Channel 2 */
+#define VIA_PCI_DMA_MR3             0xE8C   /* Mode Register of Channel 3 */
+
+#define VIA_PCI_DMA_CSR0            0xE90   /* Command/Status Register of Channel 0 */
+#define VIA_PCI_DMA_CSR1            0xE94   /* Command/Status Register of Channel 1 */
+#define VIA_PCI_DMA_CSR2            0xE98   /* Command/Status Register of Channel 2 */
+#define VIA_PCI_DMA_CSR3            0xE9C   /* Command/Status Register of Channel 3 */
+
+#define VIA_PCI_DMA_PTR             0xEA0   /* Priority Type Register */
+
+/* Define for DMA engine */
+/* DPR */
+#define VIA_DMA_DPR_EC         (1<<1)  /* end of chain */
+#define VIA_DMA_DPR_DDIE       (1<<2)  /* descriptor done interrupt enable */
+#define VIA_DMA_DPR_DT         (1<<3)  /* direction of transfer (RO) */
+
+/* MR */
+#define VIA_DMA_MR_CM          (1<<0)  /* chaining mode */
+#define VIA_DMA_MR_TDIE                (1<<1)  /* transfer done interrupt enable */
+#define VIA_DMA_MR_HENDMACMD           (1<<7) /* ? */
+
+/* CSR */
+#define VIA_DMA_CSR_DE         (1<<0)  /* DMA enable */
+#define VIA_DMA_CSR_TS         (1<<1)  /* transfer start */
+#define VIA_DMA_CSR_TA         (1<<2)  /* transfer abort */
+#define VIA_DMA_CSR_TD         (1<<3)  /* transfer done */
+#define VIA_DMA_CSR_DD         (1<<4)  /* descriptor done */
+#define VIA_DMA_DPR_EC          (1<<1)  /* end of chain */
+
+
+
+#endif
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
new file mode 100644 (file)
index 0000000..80c01cd
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+#include "drm_pciids.h"
+
+static int dri_library_name(struct drm_device *dev, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "unichrome");
+}
+
+static struct pci_device_id pciidlist[] = {
+       viadrv_PCI_IDS
+};
+
+static struct drm_driver driver = {
+       .driver_features =
+           DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
+           DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+       .load = via_driver_load,
+       .unload = via_driver_unload,
+       .context_dtor = via_final_context,
+       .vblank_wait = via_driver_vblank_wait,
+       .irq_preinstall = via_driver_irq_preinstall,
+       .irq_postinstall = via_driver_irq_postinstall,
+       .irq_uninstall = via_driver_irq_uninstall,
+       .irq_handler = via_driver_irq_handler,
+       .dma_quiescent = via_driver_dma_quiescent,
+       .dri_library_name = dri_library_name,
+       .reclaim_buffers = drm_core_reclaim_buffers,
+       .reclaim_buffers_locked = NULL,
+       .reclaim_buffers_idlelocked = via_reclaim_buffers_locked,
+       .lastclose = via_lastclose,
+       .get_map_ofs = drm_core_get_map_ofs,
+       .get_reg_ofs = drm_core_get_reg_ofs,
+       .ioctls = via_ioctls,
+       .fops = {
+                .owner = THIS_MODULE,
+                .open = drm_open,
+                .release = drm_release,
+                .ioctl = drm_ioctl,
+                .mmap = drm_mmap,
+                .poll = drm_poll,
+                .fasync = drm_fasync,
+       },
+       .pci_driver = {
+                .name = DRIVER_NAME,
+                .id_table = pciidlist,
+       },
+
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static int __init via_init(void)
+{
+       driver.num_ioctls = via_max_ioctl;
+       via_init_command_verifier();
+       return drm_init(&driver);
+}
+
+static void __exit via_exit(void)
+{
+       drm_exit(&driver);
+}
+
+module_init(via_init);
+module_exit(via_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h
new file mode 100644 (file)
index 0000000..2daae81
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _VIA_DRV_H_
+#define _VIA_DRV_H_
+
+#include "drm_sman.h"
+#define DRIVER_AUTHOR  "Various"
+
+#define DRIVER_NAME            "via"
+#define DRIVER_DESC            "VIA Unichrome / Pro"
+#define DRIVER_DATE            "20070202"
+
+#define DRIVER_MAJOR           2
+#define DRIVER_MINOR           11
+#define DRIVER_PATCHLEVEL      1
+
+#include "via_verifier.h"
+
+#include "via_dmablit.h"
+
+#define VIA_PCI_BUF_SIZE 60000
+#define VIA_FIRE_BUF_SIZE  1024
+#define VIA_NUM_IRQS 4
+
+typedef struct drm_via_ring_buffer {
+       drm_local_map_t map;
+       char *virtual_start;
+} drm_via_ring_buffer_t;
+
+typedef uint32_t maskarray_t[5];
+
+typedef struct drm_via_irq {
+       atomic_t irq_received;
+       uint32_t pending_mask;
+       uint32_t enable_mask;
+       wait_queue_head_t irq_queue;
+} drm_via_irq_t;
+
+typedef struct drm_via_private {
+       drm_via_sarea_t *sarea_priv;
+       drm_local_map_t *sarea;
+       drm_local_map_t *fb;
+       drm_local_map_t *mmio;
+       unsigned long agpAddr;
+       wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
+       char *dma_ptr;
+       unsigned int dma_low;
+       unsigned int dma_high;
+       unsigned int dma_offset;
+       uint32_t dma_wrap;
+       volatile uint32_t *last_pause_ptr;
+       volatile uint32_t *hw_addr_ptr;
+       drm_via_ring_buffer_t ring;
+       struct timeval last_vblank;
+       int last_vblank_valid;
+       unsigned usec_per_vblank;
+       drm_via_state_t hc_state;
+       char pci_buf[VIA_PCI_BUF_SIZE];
+       const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
+       uint32_t num_fire_offsets;
+       int chipset;
+       drm_via_irq_t via_irqs[VIA_NUM_IRQS];
+       unsigned num_irqs;
+       maskarray_t *irq_masks;
+       uint32_t irq_enable_mask;
+       uint32_t irq_pending_mask;
+       int *irq_map;
+       unsigned int idle_fault;
+       struct drm_sman sman;
+       int vram_initialized;
+       int agp_initialized;
+       unsigned long vram_offset;
+       unsigned long agp_offset;
+       drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
+       uint32_t dma_diff;
+} drm_via_private_t;
+
+enum via_family {
+  VIA_OTHER = 0,     /* Baseline */
+  VIA_PRO_GROUP_A,   /* Another video engine and DMA commands */
+  VIA_DX9_0          /* Same video as pro_group_a, but 3D is unsupported */
+};
+
+/* VIA MMIO register access */
+#define VIA_BASE ((dev_priv->mmio))
+
+#define VIA_READ(reg)          DRM_READ32(VIA_BASE, reg)
+#define VIA_WRITE(reg,val)     DRM_WRITE32(VIA_BASE, reg, val)
+#define VIA_READ8(reg)         DRM_READ8(VIA_BASE, reg)
+#define VIA_WRITE8(reg,val)    DRM_WRITE8(VIA_BASE, reg, val)
+
+extern struct drm_ioctl_desc via_ioctls[];
+extern int via_max_ioctl;
+
+extern int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv);
+extern int via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_priv );
+extern int via_dma_blit( struct drm_device *dev, void *data, struct drm_file *file_priv );
+
+extern int via_driver_load(struct drm_device *dev, unsigned long chipset);
+extern int via_driver_unload(struct drm_device *dev);
+
+extern int via_init_context(struct drm_device * dev, int context);
+extern int via_final_context(struct drm_device * dev, int context);
+
+extern int via_do_cleanup_map(struct drm_device * dev);
+extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+
+extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
+extern void via_driver_irq_preinstall(struct drm_device * dev);
+extern void via_driver_irq_postinstall(struct drm_device * dev);
+extern void via_driver_irq_uninstall(struct drm_device * dev);
+
+extern int via_dma_cleanup(struct drm_device * dev);
+extern void via_init_command_verifier(void);
+extern int via_driver_dma_quiescent(struct drm_device * dev);
+extern void via_init_futex(drm_via_private_t * dev_priv);
+extern void via_cleanup_futex(drm_via_private_t * dev_priv);
+extern void via_release_futex(drm_via_private_t * dev_priv, int context);
+
+extern void via_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file_priv);
+extern void via_lastclose(struct drm_device *dev);
+
+extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
+extern void via_init_dmablit(struct drm_device *dev);
+
+#endif
diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c
new file mode 100644 (file)
index 0000000..c6bb978
--- /dev/null
@@ -0,0 +1,377 @@
+/* via_irq.c
+ *
+ * Copyright 2004 BEAM Ltd.
+ * Copyright 2002 Tungsten Graphics, Inc.
+ * Copyright 2005 Thomas Hellstrom.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BEAM LTD, TUNGSTEN GRAPHICS  AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Terry Barnaby <terry1@beam.ltd.uk>
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Thomas Hellstrom <unichrome@shipmail.org>
+ *
+ * This code provides standard DRM access to the Via Unichrome / Pro Vertical blank
+ * interrupt, as well as an infrastructure to handle other interrupts of the chip.
+ * The refresh rate is also calculated for video playback sync purposes.
+ */
+
+#include "drmP.h"
+#include "drm.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+#define VIA_REG_INTERRUPT       0x200
+
+/* VIA_REG_INTERRUPT */
+#define VIA_IRQ_GLOBAL          (1 << 31)
+#define VIA_IRQ_VBLANK_ENABLE   (1 << 19)
+#define VIA_IRQ_VBLANK_PENDING  (1 << 3)
+#define VIA_IRQ_HQV0_ENABLE     (1 << 11)
+#define VIA_IRQ_HQV1_ENABLE     (1 << 25)
+#define VIA_IRQ_HQV0_PENDING    (1 << 9)
+#define VIA_IRQ_HQV1_PENDING    (1 << 10)
+#define VIA_IRQ_DMA0_DD_ENABLE  (1 << 20)
+#define VIA_IRQ_DMA0_TD_ENABLE  (1 << 21)
+#define VIA_IRQ_DMA1_DD_ENABLE  (1 << 22)
+#define VIA_IRQ_DMA1_TD_ENABLE  (1 << 23)
+#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
+#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
+#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
+#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
+
+
+/*
+ * Device-specific IRQs go here. This type might need to be extended with
+ * the register if there are multiple IRQ control registers.
+ * Currently we activate the HQV interrupts of  Unichrome Pro group A.
+ */
+
+static maskarray_t via_pro_group_a_irqs[] = {
+       {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
+        0x00000000},
+       {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
+        0x00000000},
+       {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
+        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+       {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
+        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+};
+static int via_num_pro_group_a =
+    sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);
+static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
+
+static maskarray_t via_unichrome_irqs[] = {
+       {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
+        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+       {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
+        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
+};
+static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);
+static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
+
+static unsigned time_diff(struct timeval *now, struct timeval *then)
+{
+       return (now->tv_usec >= then->tv_usec) ?
+           now->tv_usec - then->tv_usec :
+           1000000 - (then->tv_usec - now->tv_usec);
+}
+
+irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       u32 status;
+       int handled = 0;
+       struct timeval cur_vblank;
+       drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+       int i;
+
+       status = VIA_READ(VIA_REG_INTERRUPT);
+       if (status & VIA_IRQ_VBLANK_PENDING) {
+               atomic_inc(&dev->vbl_received);
+               if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
+                       do_gettimeofday(&cur_vblank);
+                       if (dev_priv->last_vblank_valid) {
+                               dev_priv->usec_per_vblank =
+                                   time_diff(&cur_vblank,
+                                             &dev_priv->last_vblank) >> 4;
+                       }
+                       dev_priv->last_vblank = cur_vblank;
+                       dev_priv->last_vblank_valid = 1;
+               }
+               if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
+                       DRM_DEBUG("US per vblank is: %u\n",
+                                 dev_priv->usec_per_vblank);
+               }
+               DRM_WAKEUP(&dev->vbl_queue);
+               drm_vbl_send_signals(dev);
+               handled = 1;
+       }
+
+       for (i = 0; i < dev_priv->num_irqs; ++i) {
+               if (status & cur_irq->pending_mask) {
+                       atomic_inc(&cur_irq->irq_received);
+                       DRM_WAKEUP(&cur_irq->irq_queue);
+                       handled = 1;
+                       if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) {
+                               via_dmablit_handler(dev, 0, 1);
+                       } else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) {
+                               via_dmablit_handler(dev, 1, 1);
+                       }
+               }
+               cur_irq++;
+       }
+
+       /* Acknowlege interrupts */
+       VIA_WRITE(VIA_REG_INTERRUPT, status);
+
+       if (handled)
+               return IRQ_HANDLED;
+       else
+               return IRQ_NONE;
+}
+
+static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
+{
+       u32 status;
+
+       if (dev_priv) {
+               /* Acknowlege interrupts */
+               status = VIA_READ(VIA_REG_INTERRUPT);
+               VIA_WRITE(VIA_REG_INTERRUPT, status |
+                         dev_priv->irq_pending_mask);
+       }
+}
+
+int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       unsigned int cur_vblank;
+       int ret = 0;
+
+       DRM_DEBUG("\n");
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       viadrv_acknowledge_irqs(dev_priv);
+
+       /* Assume that the user has missed the current sequence number
+        * by about a day rather than she wants to wait for years
+        * using vertical blanks...
+        */
+
+       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+                   (((cur_vblank = atomic_read(&dev->vbl_received)) -
+                     *sequence) <= (1 << 23)));
+
+       *sequence = cur_vblank;
+       return ret;
+}
+
+static int
+via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequence,
+                   unsigned int *sequence)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       unsigned int cur_irq_sequence;
+       drm_via_irq_t *cur_irq;
+       int ret = 0;
+       maskarray_t *masks;
+       int real_irq;
+
+       DRM_DEBUG("\n");
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       if (irq >= drm_via_irq_num) {
+               DRM_ERROR("Trying to wait on unknown irq %d\n", irq);
+               return -EINVAL;
+       }
+
+       real_irq = dev_priv->irq_map[irq];
+
+       if (real_irq < 0) {
+               DRM_ERROR("Video IRQ %d not available on this hardware.\n",
+                         irq);
+               return -EINVAL;
+       }
+
+       masks = dev_priv->irq_masks;
+       cur_irq = dev_priv->via_irqs + real_irq;
+
+       if (masks[real_irq][2] && !force_sequence) {
+               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+                           ((VIA_READ(masks[irq][2]) & masks[irq][3]) ==
+                            masks[irq][4]));
+               cur_irq_sequence = atomic_read(&cur_irq->irq_received);
+       } else {
+               DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
+                           (((cur_irq_sequence =
+                              atomic_read(&cur_irq->irq_received)) -
+                             *sequence) <= (1 << 23)));
+       }
+       *sequence = cur_irq_sequence;
+       return ret;
+}
+
+/*
+ * drm_dma.h hooks
+ */
+
+void via_driver_irq_preinstall(struct drm_device * dev)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       u32 status;
+       drm_via_irq_t *cur_irq;
+       int i;
+
+       DRM_DEBUG("dev_priv: %p\n", dev_priv);
+       if (dev_priv) {
+               cur_irq = dev_priv->via_irqs;
+
+               dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
+               dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
+
+               if (dev_priv->chipset == VIA_PRO_GROUP_A ||
+                   dev_priv->chipset == VIA_DX9_0) {
+                       dev_priv->irq_masks = via_pro_group_a_irqs;
+                       dev_priv->num_irqs = via_num_pro_group_a;
+                       dev_priv->irq_map = via_irqmap_pro_group_a;
+               } else {
+                       dev_priv->irq_masks = via_unichrome_irqs;
+                       dev_priv->num_irqs = via_num_unichrome;
+                       dev_priv->irq_map = via_irqmap_unichrome;
+               }
+
+               for (i = 0; i < dev_priv->num_irqs; ++i) {
+                       atomic_set(&cur_irq->irq_received, 0);
+                       cur_irq->enable_mask = dev_priv->irq_masks[i][0];
+                       cur_irq->pending_mask = dev_priv->irq_masks[i][1];
+                       DRM_INIT_WAITQUEUE(&cur_irq->irq_queue);
+                       dev_priv->irq_enable_mask |= cur_irq->enable_mask;
+                       dev_priv->irq_pending_mask |= cur_irq->pending_mask;
+                       cur_irq++;
+
+                       DRM_DEBUG("Initializing IRQ %d\n", i);
+               }
+
+               dev_priv->last_vblank_valid = 0;
+
+               /* Clear VSync interrupt regs */
+               status = VIA_READ(VIA_REG_INTERRUPT);
+               VIA_WRITE(VIA_REG_INTERRUPT, status &
+                         ~(dev_priv->irq_enable_mask));
+
+               /* Clear bits if they're already high */
+               viadrv_acknowledge_irqs(dev_priv);
+       }
+}
+
+void via_driver_irq_postinstall(struct drm_device * dev)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       u32 status;
+
+       DRM_DEBUG("\n");
+       if (dev_priv) {
+               status = VIA_READ(VIA_REG_INTERRUPT);
+               VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
+                         | dev_priv->irq_enable_mask);
+
+               /* Some magic, oh for some data sheets ! */
+
+               VIA_WRITE8(0x83d4, 0x11);
+               VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
+
+       }
+}
+
+void via_driver_irq_uninstall(struct drm_device * dev)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       u32 status;
+
+       DRM_DEBUG("\n");
+       if (dev_priv) {
+
+               /* Some more magic, oh for some data sheets ! */
+
+               VIA_WRITE8(0x83d4, 0x11);
+               VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
+
+               status = VIA_READ(VIA_REG_INTERRUPT);
+               VIA_WRITE(VIA_REG_INTERRUPT, status &
+                         ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
+       }
+}
+
+int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_irqwait_t *irqwait = data;
+       struct timeval now;
+       int ret = 0;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+       int force_sequence;
+
+       if (!dev->irq)
+               return -EINVAL;
+
+       if (irqwait->request.irq >= dev_priv->num_irqs) {
+               DRM_ERROR("Trying to wait on unknown irq %d\n",
+                         irqwait->request.irq);
+               return -EINVAL;
+       }
+
+       cur_irq += irqwait->request.irq;
+
+       switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) {
+       case VIA_IRQ_RELATIVE:
+               irqwait->request.sequence += atomic_read(&cur_irq->irq_received);
+               irqwait->request.type &= ~_DRM_VBLANK_RELATIVE;
+       case VIA_IRQ_ABSOLUTE:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (irqwait->request.type & VIA_IRQ_SIGNAL) {
+               DRM_ERROR("Signals on Via IRQs not implemented yet.\n");
+               return -EINVAL;
+       }
+
+       force_sequence = (irqwait->request.type & VIA_IRQ_FORCE_SEQUENCE);
+
+       ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence,
+                                 &irqwait->request.sequence);
+       do_gettimeofday(&now);
+       irqwait->reply.tval_sec = now.tv_sec;
+       irqwait->reply.tval_usec = now.tv_usec;
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c
new file mode 100644 (file)
index 0000000..a967556
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+static int via_do_init_map(struct drm_device * dev, drm_via_init_t * init)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+
+       dev_priv->sarea = drm_getsarea(dev);
+       if (!dev_priv->sarea) {
+               DRM_ERROR("could not find sarea!\n");
+               dev->dev_private = (void *)dev_priv;
+               via_do_cleanup_map(dev);
+               return -EINVAL;
+       }
+
+       dev_priv->fb = drm_core_findmap(dev, init->fb_offset);
+       if (!dev_priv->fb) {
+               DRM_ERROR("could not find framebuffer!\n");
+               dev->dev_private = (void *)dev_priv;
+               via_do_cleanup_map(dev);
+               return -EINVAL;
+       }
+       dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
+       if (!dev_priv->mmio) {
+               DRM_ERROR("could not find mmio region!\n");
+               dev->dev_private = (void *)dev_priv;
+               via_do_cleanup_map(dev);
+               return -EINVAL;
+       }
+
+       dev_priv->sarea_priv =
+           (drm_via_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+                                init->sarea_priv_offset);
+
+       dev_priv->agpAddr = init->agpAddr;
+
+       via_init_futex(dev_priv);
+
+       via_init_dmablit(dev);
+
+       dev->dev_private = (void *)dev_priv;
+       return 0;
+}
+
+int via_do_cleanup_map(struct drm_device * dev)
+{
+       via_dma_cleanup(dev);
+
+       return 0;
+}
+
+int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_init_t *init = data;
+
+       DRM_DEBUG("\n");
+
+       switch (init->func) {
+       case VIA_INIT_MAP:
+               return via_do_init_map(dev, init);
+       case VIA_CLEANUP_MAP:
+               return via_do_cleanup_map(dev);
+       }
+
+       return -EINVAL;
+}
+
+int via_driver_load(struct drm_device *dev, unsigned long chipset)
+{
+       drm_via_private_t *dev_priv;
+       int ret = 0;
+
+       dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       dev->dev_private = (void *)dev_priv;
+
+       dev_priv->chipset = chipset;
+
+       ret = drm_sman_init(&dev_priv->sman, 2, 12, 8);
+       if (ret) {
+               drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+       }
+       return ret;
+}
+
+int via_driver_unload(struct drm_device *dev)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+
+       drm_sman_takedown(&dev_priv->sman);
+
+       drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+
+       return 0;
+}
diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c
new file mode 100644 (file)
index 0000000..e640949
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+/*
+ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+#include "drm_sman.h"
+
+#define VIA_MM_ALIGN_SHIFT 4
+#define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1)
+
+int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_agp_t *agp = data;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0,
+                                agp->size >> VIA_MM_ALIGN_SHIFT);
+
+       if (ret) {
+               DRM_ERROR("AGP memory manager initialisation error\n");
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
+
+       dev_priv->agp_initialized = 1;
+       dev_priv->agp_offset = agp->offset;
+       mutex_unlock(&dev->struct_mutex);
+
+       DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
+       return 0;
+}
+
+int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_fb_t *fb = data;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0,
+                                fb->size >> VIA_MM_ALIGN_SHIFT);
+
+       if (ret) {
+               DRM_ERROR("VRAM memory manager initialisation error\n");
+               mutex_unlock(&dev->struct_mutex);
+               return ret;
+       }
+
+       dev_priv->vram_initialized = 1;
+       dev_priv->vram_offset = fb->offset;
+
+       mutex_unlock(&dev->struct_mutex);
+       DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
+
+       return 0;
+
+}
+
+int via_final_context(struct drm_device *dev, int context)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       via_release_futex(dev_priv, context);
+
+       /* Linux specific until context tracking code gets ported to BSD */
+       /* Last context, perform cleanup */
+       if (dev->ctx_count == 1 && dev->dev_private) {
+               DRM_DEBUG("Last Context\n");
+               if (dev->irq)
+                       drm_irq_uninstall(dev);
+               via_cleanup_futex(dev_priv);
+               via_do_cleanup_map(dev);
+       }
+       return 1;
+}
+
+void via_lastclose(struct drm_device *dev)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       if (!dev_priv)
+               return;
+
+       mutex_lock(&dev->struct_mutex);
+       drm_sman_cleanup(&dev_priv->sman);
+       dev_priv->vram_initialized = 0;
+       dev_priv->agp_initialized = 0;
+       mutex_unlock(&dev->struct_mutex);
+}
+
+int via_mem_alloc(struct drm_device *dev, void *data,
+                 struct drm_file *file_priv)
+{
+       drm_via_mem_t *mem = data;
+       int retval = 0;
+       struct drm_memblock_item *item;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       unsigned long tmpSize;
+
+       if (mem->type > VIA_MEM_AGP) {
+               DRM_ERROR("Unknown memory type allocation\n");
+               return -EINVAL;
+       }
+       mutex_lock(&dev->struct_mutex);
+       if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
+                     dev_priv->agp_initialized)) {
+               DRM_ERROR
+                   ("Attempt to allocate from uninitialized memory manager.\n");
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
+       }
+
+       tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
+       item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0,
+                             (unsigned long)file_priv);
+       mutex_unlock(&dev->struct_mutex);
+       if (item) {
+               mem->offset = ((mem->type == VIA_MEM_VIDEO) ?
+                             dev_priv->vram_offset : dev_priv->agp_offset) +
+                   (item->mm->
+                    offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT);
+               mem->index = item->user_hash.key;
+       } else {
+               mem->offset = 0;
+               mem->size = 0;
+               mem->index = 0;
+               DRM_DEBUG("Video memory allocation failed\n");
+               retval = -ENOMEM;
+       }
+
+       return retval;
+}
+
+int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+       drm_via_mem_t *mem = data;
+       int ret;
+
+       mutex_lock(&dev->struct_mutex);
+       ret = drm_sman_free_key(&dev_priv->sman, mem->index);
+       mutex_unlock(&dev->struct_mutex);
+       DRM_DEBUG("free = 0x%lx\n", mem->index);
+
+       return ret;
+}
+
+
+void via_reclaim_buffers_locked(struct drm_device * dev,
+                               struct drm_file *file_priv)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+
+       mutex_lock(&dev->struct_mutex);
+       if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) {
+               mutex_unlock(&dev->struct_mutex);
+               return;
+       }
+
+       if (dev->driver->dma_quiescent) {
+               dev->driver->dma_quiescent(dev);
+       }
+
+       drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv);
+       mutex_unlock(&dev->struct_mutex);
+       return;
+}
diff --git a/drivers/gpu/drm/via/via_verifier.c b/drivers/gpu/drm/via/via_verifier.c
new file mode 100644 (file)
index 0000000..46a5791
--- /dev/null
@@ -0,0 +1,1116 @@
+/*
+ * Copyright 2004 The Unichrome Project. All Rights Reserved.
+ * Copyright 2005 Thomas Hellstrom. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Thomas Hellstrom 2004, 2005.
+ * This code was written using docs obtained under NDA from VIA Inc.
+ *
+ * Don't run this code directly on an AGP buffer. Due to cache problems it will
+ * be very slow.
+ */
+
+#include "via_3d_reg.h"
+#include "drmP.h"
+#include "drm.h"
+#include "via_drm.h"
+#include "via_verifier.h"
+#include "via_drv.h"
+
+typedef enum {
+       state_command,
+       state_header2,
+       state_header1,
+       state_vheader5,
+       state_vheader6,
+       state_error
+} verifier_state_t;
+
+typedef enum {
+       no_check = 0,
+       check_for_header2,
+       check_for_header1,
+       check_for_header2_err,
+       check_for_header1_err,
+       check_for_fire,
+       check_z_buffer_addr0,
+       check_z_buffer_addr1,
+       check_z_buffer_addr_mode,
+       check_destination_addr0,
+       check_destination_addr1,
+       check_destination_addr_mode,
+       check_for_dummy,
+       check_for_dd,
+       check_texture_addr0,
+       check_texture_addr1,
+       check_texture_addr2,
+       check_texture_addr3,
+       check_texture_addr4,
+       check_texture_addr5,
+       check_texture_addr6,
+       check_texture_addr7,
+       check_texture_addr8,
+       check_texture_addr_mode,
+       check_for_vertex_count,
+       check_number_texunits,
+       forbidden_command
+} hazard_t;
+
+/*
+ * Associates each hazard above with a possible multi-command
+ * sequence. For example an address that is split over multiple
+ * commands and that needs to be checked at the first command
+ * that does not include any part of the address.
+ */
+
+static drm_via_sequence_t seqs[] = {
+       no_sequence,
+       no_sequence,
+       no_sequence,
+       no_sequence,
+       no_sequence,
+       no_sequence,
+       z_address,
+       z_address,
+       z_address,
+       dest_address,
+       dest_address,
+       dest_address,
+       no_sequence,
+       no_sequence,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       no_sequence
+};
+
+typedef struct {
+       unsigned int code;
+       hazard_t hz;
+} hz_init_t;
+
+static hz_init_t init_table1[] = {
+       {0xf2, check_for_header2_err},
+       {0xf0, check_for_header1_err},
+       {0xee, check_for_fire},
+       {0xcc, check_for_dummy},
+       {0xdd, check_for_dd},
+       {0x00, no_check},
+       {0x10, check_z_buffer_addr0},
+       {0x11, check_z_buffer_addr1},
+       {0x12, check_z_buffer_addr_mode},
+       {0x13, no_check},
+       {0x14, no_check},
+       {0x15, no_check},
+       {0x23, no_check},
+       {0x24, no_check},
+       {0x33, no_check},
+       {0x34, no_check},
+       {0x35, no_check},
+       {0x36, no_check},
+       {0x37, no_check},
+       {0x38, no_check},
+       {0x39, no_check},
+       {0x3A, no_check},
+       {0x3B, no_check},
+       {0x3C, no_check},
+       {0x3D, no_check},
+       {0x3E, no_check},
+       {0x40, check_destination_addr0},
+       {0x41, check_destination_addr1},
+       {0x42, check_destination_addr_mode},
+       {0x43, no_check},
+       {0x44, no_check},
+       {0x50, no_check},
+       {0x51, no_check},
+       {0x52, no_check},
+       {0x53, no_check},
+       {0x54, no_check},
+       {0x55, no_check},
+       {0x56, no_check},
+       {0x57, no_check},
+       {0x58, no_check},
+       {0x70, no_check},
+       {0x71, no_check},
+       {0x78, no_check},
+       {0x79, no_check},
+       {0x7A, no_check},
+       {0x7B, no_check},
+       {0x7C, no_check},
+       {0x7D, check_for_vertex_count}
+};
+
+static hz_init_t init_table2[] = {
+       {0xf2, check_for_header2_err},
+       {0xf0, check_for_header1_err},
+       {0xee, check_for_fire},
+       {0xcc, check_for_dummy},
+       {0x00, check_texture_addr0},
+       {0x01, check_texture_addr0},
+       {0x02, check_texture_addr0},
+       {0x03, check_texture_addr0},
+       {0x04, check_texture_addr0},
+       {0x05, check_texture_addr0},
+       {0x06, check_texture_addr0},
+       {0x07, check_texture_addr0},
+       {0x08, check_texture_addr0},
+       {0x09, check_texture_addr0},
+       {0x20, check_texture_addr1},
+       {0x21, check_texture_addr1},
+       {0x22, check_texture_addr1},
+       {0x23, check_texture_addr4},
+       {0x2B, check_texture_addr3},
+       {0x2C, check_texture_addr3},
+       {0x2D, check_texture_addr3},
+       {0x2E, check_texture_addr3},
+       {0x2F, check_texture_addr3},
+       {0x30, check_texture_addr3},
+       {0x31, check_texture_addr3},
+       {0x32, check_texture_addr3},
+       {0x33, check_texture_addr3},
+       {0x34, check_texture_addr3},
+       {0x4B, check_texture_addr5},
+       {0x4C, check_texture_addr6},
+       {0x51, check_texture_addr7},
+       {0x52, check_texture_addr8},
+       {0x77, check_texture_addr2},
+       {0x78, no_check},
+       {0x79, no_check},
+       {0x7A, no_check},
+       {0x7B, check_texture_addr_mode},
+       {0x7C, no_check},
+       {0x7D, no_check},
+       {0x7E, no_check},
+       {0x7F, no_check},
+       {0x80, no_check},
+       {0x81, no_check},
+       {0x82, no_check},
+       {0x83, no_check},
+       {0x85, no_check},
+       {0x86, no_check},
+       {0x87, no_check},
+       {0x88, no_check},
+       {0x89, no_check},
+       {0x8A, no_check},
+       {0x90, no_check},
+       {0x91, no_check},
+       {0x92, no_check},
+       {0x93, no_check}
+};
+
+static hz_init_t init_table3[] = {
+       {0xf2, check_for_header2_err},
+       {0xf0, check_for_header1_err},
+       {0xcc, check_for_dummy},
+       {0x00, check_number_texunits}
+};
+
+static hazard_t table1[256];
+static hazard_t table2[256];
+static hazard_t table3[256];
+
+static __inline__ int
+eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
+{
+       if ((buf_end - *buf) >= num_words) {
+               *buf += num_words;
+               return 0;
+       }
+       DRM_ERROR("Illegal termination of DMA command buffer\n");
+       return 1;
+}
+
+/*
+ * Partially stolen from drm_memory.h
+ */
+
+static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
+                                                   unsigned long offset,
+                                                   unsigned long size,
+                                                   struct drm_device * dev)
+{
+       struct drm_map_list *r_list;
+       drm_local_map_t *map = seq->map_cache;
+
+       if (map && map->offset <= offset
+           && (offset + size) <= (map->offset + map->size)) {
+               return map;
+       }
+
+       list_for_each_entry(r_list, &dev->maplist, head) {
+               map = r_list->map;
+               if (!map)
+                       continue;
+               if (map->offset <= offset
+                   && (offset + size) <= (map->offset + map->size)
+                   && !(map->flags & _DRM_RESTRICTED)
+                   && (map->type == _DRM_AGP)) {
+                       seq->map_cache = map;
+                       return map;
+               }
+       }
+       return NULL;
+}
+
+/*
+ * Require that all AGP texture levels reside in the same AGP map which should
+ * be mappable by the client. This is not a big restriction.
+ * FIXME: To actually enforce this security policy strictly, drm_rmmap
+ * would have to wait for dma quiescent before removing an AGP map.
+ * The via_drm_lookup_agp_map call in reality seems to take
+ * very little CPU time.
+ */
+
+static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
+{
+       switch (cur_seq->unfinished) {
+       case z_address:
+               DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
+               break;
+       case dest_address:
+               DRM_DEBUG("Destination start address is 0x%x\n",
+                         cur_seq->d_addr);
+               break;
+       case tex_address:
+               if (cur_seq->agp_texture) {
+                       unsigned start =
+                           cur_seq->tex_level_lo[cur_seq->texture];
+                       unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
+                       unsigned long lo = ~0, hi = 0, tmp;
+                       uint32_t *addr, *pitch, *height, tex;
+                       unsigned i;
+                       int npot;
+
+                       if (end > 9)
+                               end = 9;
+                       if (start > 9)
+                               start = 9;
+
+                       addr =
+                           &(cur_seq->t_addr[tex = cur_seq->texture][start]);
+                       pitch = &(cur_seq->pitch[tex][start]);
+                       height = &(cur_seq->height[tex][start]);
+                       npot = cur_seq->tex_npot[tex];
+                       for (i = start; i <= end; ++i) {
+                               tmp = *addr++;
+                               if (tmp < lo)
+                                       lo = tmp;
+                               if (i == 0 && npot)
+                                       tmp += (*height++ * *pitch++);
+                               else
+                                       tmp += (*height++ << *pitch++);
+                               if (tmp > hi)
+                                       hi = tmp;
+                       }
+
+                       if (!via_drm_lookup_agp_map
+                           (cur_seq, lo, hi - lo, cur_seq->dev)) {
+                               DRM_ERROR
+                                   ("AGP texture is not in allowed map\n");
+                               return 2;
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+       cur_seq->unfinished = no_sequence;
+       return 0;
+}
+
+static __inline__ int
+investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t * cur_seq)
+{
+       register uint32_t tmp, *tmp_addr;
+
+       if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
+               int ret;
+               if ((ret = finish_current_sequence(cur_seq)))
+                       return ret;
+       }
+
+       switch (hz) {
+       case check_for_header2:
+               if (cmd == HALCYON_HEADER2)
+                       return 1;
+               return 0;
+       case check_for_header1:
+               if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+                       return 1;
+               return 0;
+       case check_for_header2_err:
+               if (cmd == HALCYON_HEADER2)
+                       return 1;
+               DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
+               break;
+       case check_for_header1_err:
+               if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+                       return 1;
+               DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
+               break;
+       case check_for_fire:
+               if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD)
+                       return 1;
+               DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
+               break;
+       case check_for_dummy:
+               if (HC_DUMMY == cmd)
+                       return 0;
+               DRM_ERROR("Illegal DMA HC_DUMMY command\n");
+               break;
+       case check_for_dd:
+               if (0xdddddddd == cmd)
+                       return 0;
+               DRM_ERROR("Illegal DMA 0xdddddddd command\n");
+               break;
+       case check_z_buffer_addr0:
+               cur_seq->unfinished = z_address;
+               cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
+                   (cmd & 0x00FFFFFF);
+               return 0;
+       case check_z_buffer_addr1:
+               cur_seq->unfinished = z_address;
+               cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
+                   ((cmd & 0xFF) << 24);
+               return 0;
+       case check_z_buffer_addr_mode:
+               cur_seq->unfinished = z_address;
+               if ((cmd & 0x0000C000) == 0)
+                       return 0;
+               DRM_ERROR("Attempt to place Z buffer in system memory\n");
+               return 2;
+       case check_destination_addr0:
+               cur_seq->unfinished = dest_address;
+               cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
+                   (cmd & 0x00FFFFFF);
+               return 0;
+       case check_destination_addr1:
+               cur_seq->unfinished = dest_address;
+               cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
+                   ((cmd & 0xFF) << 24);
+               return 0;
+       case check_destination_addr_mode:
+               cur_seq->unfinished = dest_address;
+               if ((cmd & 0x0000C000) == 0)
+                       return 0;
+               DRM_ERROR
+                   ("Attempt to place 3D drawing buffer in system memory\n");
+               return 2;
+       case check_texture_addr0:
+               cur_seq->unfinished = tex_address;
+               tmp = (cmd >> 24);
+               tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
+               *tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF);
+               return 0;
+       case check_texture_addr1:
+               cur_seq->unfinished = tex_address;
+               tmp = ((cmd >> 24) - 0x20);
+               tmp += tmp << 1;
+               tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
+               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
+               tmp_addr++;
+               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16);
+               tmp_addr++;
+               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8);
+               return 0;
+       case check_texture_addr2:
+               cur_seq->unfinished = tex_address;
+               cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F;
+               cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6;
+               return 0;
+       case check_texture_addr3:
+               cur_seq->unfinished = tex_address;
+               tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit);
+               if (tmp == 0 &&
+                   (cmd & HC_HTXnEnPit_MASK)) {
+                       cur_seq->pitch[cur_seq->texture][tmp] =
+                               (cmd & HC_HTXnLnPit_MASK);
+                       cur_seq->tex_npot[cur_seq->texture] = 1;
+               } else {
+                       cur_seq->pitch[cur_seq->texture][tmp] =
+                               (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT;
+                       cur_seq->tex_npot[cur_seq->texture] = 0;
+                       if (cmd & 0x000FFFFF) {
+                               DRM_ERROR
+                                       ("Unimplemented texture level 0 pitch mode.\n");
+                               return 2;
+                       }
+               }
+               return 0;
+       case check_texture_addr4:
+               cur_seq->unfinished = tex_address;
+               tmp_addr = &cur_seq->t_addr[cur_seq->texture][9];
+               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
+               return 0;
+       case check_texture_addr5:
+       case check_texture_addr6:
+               cur_seq->unfinished = tex_address;
+               /*
+                * Texture width. We don't care since we have the pitch.
+                */
+               return 0;
+       case check_texture_addr7:
+               cur_seq->unfinished = tex_address;
+               tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
+               tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20);
+               tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16);
+               tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12);
+               tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8);
+               tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4);
+               tmp_addr[0] = 1 << (cmd & 0x0000000F);
+               return 0;
+       case check_texture_addr8:
+               cur_seq->unfinished = tex_address;
+               tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
+               tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
+               tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
+               tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
+               tmp_addr[6] = 1 << (cmd & 0x0000000F);
+               return 0;
+       case check_texture_addr_mode:
+               cur_seq->unfinished = tex_address;
+               if (2 == (tmp = cmd & 0x00000003)) {
+                       DRM_ERROR
+                           ("Attempt to fetch texture from system memory.\n");
+                       return 2;
+               }
+               cur_seq->agp_texture = (tmp == 3);
+               cur_seq->tex_palette_size[cur_seq->texture] =
+                   (cmd >> 16) & 0x000000007;
+               return 0;
+       case check_for_vertex_count:
+               cur_seq->vertex_count = cmd & 0x0000FFFF;
+               return 0;
+       case check_number_texunits:
+               cur_seq->multitex = (cmd >> 3) & 1;
+               return 0;
+       default:
+               DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
+               return 2;
+       }
+       return 2;
+}
+
+static __inline__ int
+via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,
+                   drm_via_state_t * cur_seq)
+{
+       drm_via_private_t *dev_priv =
+           (drm_via_private_t *) cur_seq->dev->dev_private;
+       uint32_t a_fire, bcmd, dw_count;
+       int ret = 0;
+       int have_fire;
+       const uint32_t *buf = *buffer;
+
+       while (buf < buf_end) {
+               have_fire = 0;
+               if ((buf_end - buf) < 2) {
+                       DRM_ERROR
+                           ("Unexpected termination of primitive list.\n");
+                       ret = 1;
+                       break;
+               }
+               if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB)
+                       break;
+               bcmd = *buf++;
+               if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
+                       DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
+                                 *buf);
+                       ret = 1;
+                       break;
+               }
+               a_fire =
+                   *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK |
+                   HC_HE3Fire_MASK;
+
+               /*
+                * How many dwords per vertex ?
+                */
+
+               if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
+                       DRM_ERROR("Illegal B command vertex data for AGP.\n");
+                       ret = 1;
+                       break;
+               }
+
+               dw_count = 0;
+               if (bcmd & (1 << 7))
+                       dw_count += (cur_seq->multitex) ? 2 : 1;
+               if (bcmd & (1 << 8))
+                       dw_count += (cur_seq->multitex) ? 2 : 1;
+               if (bcmd & (1 << 9))
+                       dw_count++;
+               if (bcmd & (1 << 10))
+                       dw_count++;
+               if (bcmd & (1 << 11))
+                       dw_count++;
+               if (bcmd & (1 << 12))
+                       dw_count++;
+               if (bcmd & (1 << 13))
+                       dw_count++;
+               if (bcmd & (1 << 14))
+                       dw_count++;
+
+               while (buf < buf_end) {
+                       if (*buf == a_fire) {
+                               if (dev_priv->num_fire_offsets >=
+                                   VIA_FIRE_BUF_SIZE) {
+                                       DRM_ERROR("Fire offset buffer full.\n");
+                                       ret = 1;
+                                       break;
+                               }
+                               dev_priv->fire_offsets[dev_priv->
+                                                      num_fire_offsets++] =
+                                   buf;
+                               have_fire = 1;
+                               buf++;
+                               if (buf < buf_end && *buf == a_fire)
+                                       buf++;
+                               break;
+                       }
+                       if ((*buf == HALCYON_HEADER2) ||
+                           ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
+                               DRM_ERROR("Missing Vertex Fire command, "
+                                         "Stray Vertex Fire command  or verifier "
+                                         "lost sync.\n");
+                               ret = 1;
+                               break;
+                       }
+                       if ((ret = eat_words(&buf, buf_end, dw_count)))
+                               break;
+               }
+               if (buf >= buf_end && !have_fire) {
+                       DRM_ERROR("Missing Vertex Fire command or verifier "
+                                 "lost sync.\n");
+                       ret = 1;
+                       break;
+               }
+               if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) {
+                       DRM_ERROR("AGP Primitive list end misaligned.\n");
+                       ret = 1;
+                       break;
+               }
+       }
+       *buffer = buf;
+       return ret;
+}
+
+static __inline__ verifier_state_t
+via_check_header2(uint32_t const **buffer, const uint32_t * buf_end,
+                 drm_via_state_t * hc_state)
+{
+       uint32_t cmd;
+       int hz_mode;
+       hazard_t hz;
+       const uint32_t *buf = *buffer;
+       const hazard_t *hz_table;
+
+       if ((buf_end - buf) < 2) {
+               DRM_ERROR
+                   ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
+               return state_error;
+       }
+       buf++;
+       cmd = (*buf++ & 0xFFFF0000) >> 16;
+
+       switch (cmd) {
+       case HC_ParaType_CmdVdata:
+               if (via_check_prim_list(&buf, buf_end, hc_state))
+                       return state_error;
+               *buffer = buf;
+               return state_command;
+       case HC_ParaType_NotTex:
+               hz_table = table1;
+               break;
+       case HC_ParaType_Tex:
+               hc_state->texture = 0;
+               hz_table = table2;
+               break;
+       case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)):
+               hc_state->texture = 1;
+               hz_table = table2;
+               break;
+       case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)):
+               hz_table = table3;
+               break;
+       case HC_ParaType_Auto:
+               if (eat_words(&buf, buf_end, 2))
+                       return state_error;
+               *buffer = buf;
+               return state_command;
+       case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)):
+               if (eat_words(&buf, buf_end, 32))
+                       return state_error;
+               *buffer = buf;
+               return state_command;
+       case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)):
+       case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)):
+               DRM_ERROR("Texture palettes are rejected because of "
+                         "lack of info how to determine their size.\n");
+               return state_error;
+       case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)):
+               DRM_ERROR("Fog factor palettes are rejected because of "
+                         "lack of info how to determine their size.\n");
+               return state_error;
+       default:
+
+               /*
+                * There are some unimplemented HC_ParaTypes here, that
+                * need to be implemented if the Mesa driver is extended.
+                */
+
+               DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
+                         "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
+                         cmd, *(buf - 2));
+               *buffer = buf;
+               return state_error;
+       }
+
+       while (buf < buf_end) {
+               cmd = *buf++;
+               if ((hz = hz_table[cmd >> 24])) {
+                       if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
+                               if (hz_mode == 1) {
+                                       buf--;
+                                       break;
+                               }
+                               return state_error;
+                       }
+               } else if (hc_state->unfinished &&
+                          finish_current_sequence(hc_state)) {
+                       return state_error;
+               }
+       }
+       if (hc_state->unfinished && finish_current_sequence(hc_state)) {
+               return state_error;
+       }
+       *buffer = buf;
+       return state_command;
+}
+
+static __inline__ verifier_state_t
+via_parse_header2(drm_via_private_t * dev_priv, uint32_t const **buffer,
+                 const uint32_t * buf_end, int *fire_count)
+{
+       uint32_t cmd;
+       const uint32_t *buf = *buffer;
+       const uint32_t *next_fire;
+       int burst = 0;
+
+       next_fire = dev_priv->fire_offsets[*fire_count];
+       buf++;
+       cmd = (*buf & 0xFFFF0000) >> 16;
+       VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
+       switch (cmd) {
+       case HC_ParaType_CmdVdata:
+               while ((buf < buf_end) &&
+                      (*fire_count < dev_priv->num_fire_offsets) &&
+                      (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
+                       while (buf <= next_fire) {
+                               VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
+                                         (burst & 63), *buf++);
+                               burst += 4;
+                       }
+                       if ((buf < buf_end)
+                           && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
+                               buf++;
+
+                       if (++(*fire_count) < dev_priv->num_fire_offsets)
+                               next_fire = dev_priv->fire_offsets[*fire_count];
+               }
+               break;
+       default:
+               while (buf < buf_end) {
+
+                       if (*buf == HC_HEADER2 ||
+                           (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
+                           (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
+                           (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+                               break;
+
+                       VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE +
+                                 (burst & 63), *buf++);
+                       burst += 4;
+               }
+       }
+       *buffer = buf;
+       return state_command;
+}
+
+static __inline__ int verify_mmio_address(uint32_t address)
+{
+       if ((address > 0x3FF) && (address < 0xC00)) {
+               DRM_ERROR("Invalid VIDEO DMA command. "
+                         "Attempt to access 3D- or command burst area.\n");
+               return 1;
+       } else if ((address > 0xCFF) && (address < 0x1300)) {
+               DRM_ERROR("Invalid VIDEO DMA command. "
+                         "Attempt to access PCI DMA area.\n");
+               return 1;
+       } else if (address > 0x13FF) {
+               DRM_ERROR("Invalid VIDEO DMA command. "
+                         "Attempt to access VGA registers.\n");
+               return 1;
+       }
+       return 0;
+}
+
+static __inline__ int
+verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,
+                 uint32_t dwords)
+{
+       const uint32_t *buf = *buffer;
+
+       if (buf_end - buf < dwords) {
+               DRM_ERROR("Illegal termination of video command.\n");
+               return 1;
+       }
+       while (dwords--) {
+               if (*buf++) {
+                       DRM_ERROR("Illegal video command tail.\n");
+                       return 1;
+               }
+       }
+       *buffer = buf;
+       return 0;
+}
+
+static __inline__ verifier_state_t
+via_check_header1(uint32_t const **buffer, const uint32_t * buf_end)
+{
+       uint32_t cmd;
+       const uint32_t *buf = *buffer;
+       verifier_state_t ret = state_command;
+
+       while (buf < buf_end) {
+               cmd = *buf;
+               if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
+                   (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
+                       if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+                               break;
+                       DRM_ERROR("Invalid HALCYON_HEADER1 command. "
+                                 "Attempt to access 3D- or command burst area.\n");
+                       ret = state_error;
+                       break;
+               } else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
+                       if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+                               break;
+                       DRM_ERROR("Invalid HALCYON_HEADER1 command. "
+                                 "Attempt to access VGA registers.\n");
+                       ret = state_error;
+                       break;
+               } else {
+                       buf += 2;
+               }
+       }
+       *buffer = buf;
+       return ret;
+}
+
+static __inline__ verifier_state_t
+via_parse_header1(drm_via_private_t * dev_priv, uint32_t const **buffer,
+                 const uint32_t * buf_end)
+{
+       register uint32_t cmd;
+       const uint32_t *buf = *buffer;
+
+       while (buf < buf_end) {
+               cmd = *buf;
+               if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+                       break;
+               VIA_WRITE((cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
+               buf++;
+       }
+       *buffer = buf;
+       return state_command;
+}
+
+static __inline__ verifier_state_t
+via_check_vheader5(uint32_t const **buffer, const uint32_t * buf_end)
+{
+       uint32_t data;
+       const uint32_t *buf = *buffer;
+
+       if (buf_end - buf < 4) {
+               DRM_ERROR("Illegal termination of video header5 command\n");
+               return state_error;
+       }
+
+       data = *buf++ & ~VIA_VIDEOMASK;
+       if (verify_mmio_address(data))
+               return state_error;
+
+       data = *buf++;
+       if (*buf++ != 0x00F50000) {
+               DRM_ERROR("Illegal header5 header data\n");
+               return state_error;
+       }
+       if (*buf++ != 0x00000000) {
+               DRM_ERROR("Illegal header5 header data\n");
+               return state_error;
+       }
+       if (eat_words(&buf, buf_end, data))
+               return state_error;
+       if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
+               return state_error;
+       *buffer = buf;
+       return state_command;
+
+}
+
+static __inline__ verifier_state_t
+via_parse_vheader5(drm_via_private_t * dev_priv, uint32_t const **buffer,
+                  const uint32_t * buf_end)
+{
+       uint32_t addr, count, i;
+       const uint32_t *buf = *buffer;
+
+       addr = *buf++ & ~VIA_VIDEOMASK;
+       i = count = *buf;
+       buf += 3;
+       while (i--) {
+               VIA_WRITE(addr, *buf++);
+       }
+       if (count & 3)
+               buf += 4 - (count & 3);
+       *buffer = buf;
+       return state_command;
+}
+
+static __inline__ verifier_state_t
+via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)
+{
+       uint32_t data;
+       const uint32_t *buf = *buffer;
+       uint32_t i;
+
+       if (buf_end - buf < 4) {
+               DRM_ERROR("Illegal termination of video header6 command\n");
+               return state_error;
+       }
+       buf++;
+       data = *buf++;
+       if (*buf++ != 0x00F60000) {
+               DRM_ERROR("Illegal header6 header data\n");
+               return state_error;
+       }
+       if (*buf++ != 0x00000000) {
+               DRM_ERROR("Illegal header6 header data\n");
+               return state_error;
+       }
+       if ((buf_end - buf) < (data << 1)) {
+               DRM_ERROR("Illegal termination of video header6 command\n");
+               return state_error;
+       }
+       for (i = 0; i < data; ++i) {
+               if (verify_mmio_address(*buf++))
+                       return state_error;
+               buf++;
+       }
+       data <<= 1;
+       if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
+               return state_error;
+       *buffer = buf;
+       return state_command;
+}
+
+static __inline__ verifier_state_t
+via_parse_vheader6(drm_via_private_t * dev_priv, uint32_t const **buffer,
+                  const uint32_t * buf_end)
+{
+
+       uint32_t addr, count, i;
+       const uint32_t *buf = *buffer;
+
+       i = count = *++buf;
+       buf += 3;
+       while (i--) {
+               addr = *buf++;
+               VIA_WRITE(addr, *buf++);
+       }
+       count <<= 1;
+       if (count & 3)
+               buf += 4 - (count & 3);
+       *buffer = buf;
+       return state_command;
+}
+
+int
+via_verify_command_stream(const uint32_t * buf, unsigned int size,
+                         struct drm_device * dev, int agp)
+{
+
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       drm_via_state_t *hc_state = &dev_priv->hc_state;
+       drm_via_state_t saved_state = *hc_state;
+       uint32_t cmd;
+       const uint32_t *buf_end = buf + (size >> 2);
+       verifier_state_t state = state_command;
+       int cme_video;
+       int supported_3d;
+
+       cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A ||
+                    dev_priv->chipset == VIA_DX9_0);
+
+       supported_3d = dev_priv->chipset != VIA_DX9_0;
+
+       hc_state->dev = dev;
+       hc_state->unfinished = no_sequence;
+       hc_state->map_cache = NULL;
+       hc_state->agp = agp;
+       hc_state->buf_start = buf;
+       dev_priv->num_fire_offsets = 0;
+
+       while (buf < buf_end) {
+
+               switch (state) {
+               case state_header2:
+                       state = via_check_header2(&buf, buf_end, hc_state);
+                       break;
+               case state_header1:
+                       state = via_check_header1(&buf, buf_end);
+                       break;
+               case state_vheader5:
+                       state = via_check_vheader5(&buf, buf_end);
+                       break;
+               case state_vheader6:
+                       state = via_check_vheader6(&buf, buf_end);
+                       break;
+               case state_command:
+                       if ((HALCYON_HEADER2 == (cmd = *buf)) &&
+                           supported_3d)
+                               state = state_header2;
+                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+                               state = state_header1;
+                       else if (cme_video
+                                && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
+                               state = state_vheader5;
+                       else if (cme_video
+                                && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+                               state = state_vheader6;
+                       else if ((cmd == HALCYON_HEADER2) && !supported_3d) {
+                               DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n");
+                               state = state_error;
+                       } else {
+                               DRM_ERROR
+                                   ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
+                                    cmd);
+                               state = state_error;
+                       }
+                       break;
+               case state_error:
+               default:
+                       *hc_state = saved_state;
+                       return -EINVAL;
+               }
+       }
+       if (state == state_error) {
+               *hc_state = saved_state;
+               return -EINVAL;
+       }
+       return 0;
+}
+
+int
+via_parse_command_stream(struct drm_device * dev, const uint32_t * buf,
+                        unsigned int size)
+{
+
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       uint32_t cmd;
+       const uint32_t *buf_end = buf + (size >> 2);
+       verifier_state_t state = state_command;
+       int fire_count = 0;
+
+       while (buf < buf_end) {
+
+               switch (state) {
+               case state_header2:
+                       state =
+                           via_parse_header2(dev_priv, &buf, buf_end,
+                                             &fire_count);
+                       break;
+               case state_header1:
+                       state = via_parse_header1(dev_priv, &buf, buf_end);
+                       break;
+               case state_vheader5:
+                       state = via_parse_vheader5(dev_priv, &buf, buf_end);
+                       break;
+               case state_vheader6:
+                       state = via_parse_vheader6(dev_priv, &buf, buf_end);
+                       break;
+               case state_command:
+                       if (HALCYON_HEADER2 == (cmd = *buf))
+                               state = state_header2;
+                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+                               state = state_header1;
+                       else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
+                               state = state_vheader5;
+                       else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+                               state = state_vheader6;
+                       else {
+                               DRM_ERROR
+                                   ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
+                                    cmd);
+                               state = state_error;
+                       }
+                       break;
+               case state_error:
+               default:
+                       return -EINVAL;
+               }
+       }
+       if (state == state_error) {
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void
+setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
+{
+       int i;
+
+       for (i = 0; i < 256; ++i) {
+               table[i] = forbidden_command;
+       }
+
+       for (i = 0; i < size; ++i) {
+               table[init_table[i].code] = init_table[i].hz;
+       }
+}
+
+void via_init_command_verifier(void)
+{
+       setup_hazard_table(init_table1, table1,
+                          sizeof(init_table1) / sizeof(hz_init_t));
+       setup_hazard_table(init_table2, table2,
+                          sizeof(init_table2) / sizeof(hz_init_t));
+       setup_hazard_table(init_table3, table3,
+                          sizeof(init_table3) / sizeof(hz_init_t));
+}
diff --git a/drivers/gpu/drm/via/via_verifier.h b/drivers/gpu/drm/via/via_verifier.h
new file mode 100644 (file)
index 0000000..d6f8214
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2004 The Unichrome Project. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE UNICHROME PROJECT, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Thomas Hellström 2004.
+ */
+
+#ifndef _VIA_VERIFIER_H_
+#define _VIA_VERIFIER_H_
+
+typedef enum {
+       no_sequence = 0,
+       z_address,
+       dest_address,
+       tex_address
+} drm_via_sequence_t;
+
+typedef struct {
+       unsigned texture;
+       uint32_t z_addr;
+       uint32_t d_addr;
+       uint32_t t_addr[2][10];
+       uint32_t pitch[2][10];
+       uint32_t height[2][10];
+       uint32_t tex_level_lo[2];
+       uint32_t tex_level_hi[2];
+       uint32_t tex_palette_size[2];
+       uint32_t tex_npot[2];
+       drm_via_sequence_t unfinished;
+       int agp_texture;
+       int multitex;
+       struct drm_device *dev;
+       drm_local_map_t *map_cache;
+       uint32_t vertex_count;
+       int agp;
+       const uint32_t *buf_start;
+} drm_via_state_t;
+
+extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,
+                                    struct drm_device * dev, int agp);
+extern int via_parse_command_stream(struct drm_device *dev, const uint32_t *buf,
+                                   unsigned int size);
+
+#endif
diff --git a/drivers/gpu/drm/via/via_video.c b/drivers/gpu/drm/via/via_video.c
new file mode 100644 (file)
index 0000000..6ec04ac
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2005 Thomas Hellstrom. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Thomas Hellstrom 2005.
+ *
+ * Video and XvMC related functions.
+ */
+
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+
+void via_init_futex(drm_via_private_t * dev_priv)
+{
+       unsigned int i;
+
+       DRM_DEBUG("\n");
+
+       for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
+               DRM_INIT_WAITQUEUE(&(dev_priv->decoder_queue[i]));
+               XVMCLOCKPTR(dev_priv->sarea_priv, i)->lock = 0;
+       }
+}
+
+void via_cleanup_futex(drm_via_private_t * dev_priv)
+{
+}
+
+void via_release_futex(drm_via_private_t * dev_priv, int context)
+{
+       unsigned int i;
+       volatile int *lock;
+
+       if (!dev_priv->sarea_priv)
+               return;
+
+       for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
+               lock = (volatile int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);
+               if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {
+                       if (_DRM_LOCK_IS_HELD(*lock)
+                           && (*lock & _DRM_LOCK_CONT)) {
+                               DRM_WAKEUP(&(dev_priv->decoder_queue[i]));
+                       }
+                       *lock = 0;
+               }
+       }
+}
+
+int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_futex_t *fx = data;
+       volatile int *lock;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       drm_via_sarea_t *sAPriv = dev_priv->sarea_priv;
+       int ret = 0;
+
+       DRM_DEBUG("\n");
+
+       if (fx->lock > VIA_NR_XVMC_LOCKS)
+               return -EFAULT;
+
+       lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx->lock);
+
+       switch (fx->func) {
+       case VIA_FUTEX_WAIT:
+               DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock],
+                           (fx->ms / 10) * (DRM_HZ / 100), *lock != fx->val);
+               return ret;
+       case VIA_FUTEX_WAKE:
+               DRM_WAKEUP(&(dev_priv->decoder_queue[fx->lock]));
+               return 0;
+       }
+       return 0;
+}
index 26df06f840eb4d16a08f4f4d9e8170c8bac5f241..50f22690d6114a51518f40003083a578693c11f9 100644 (file)
@@ -516,17 +516,23 @@ static struct dmi_system_id __initdata hdaps_whitelist[] = {
        HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"),
        HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"),
        HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61i"),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61"),
        HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p"),
        HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"),
        HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p"),
        HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"),
        HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"),
        HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60"),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61p"),
        HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61"),
        HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"),
        HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X41"),
        HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60"),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61s"),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61"),
        HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61m"),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61p"),
        { .ident = NULL }
 };
 
index 1305ef190fc10dfbee90b1f52705885731935071..9e8c875437bec533ec4e32579602f31f4336bbe9 100644 (file)
@@ -290,12 +290,12 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
                 * bus, or started a new i2c message
                 */
                
-               if (iicstat  & S3C2410_IICSTAT_LASTBIT &&
+               if (iicstat & S3C2410_IICSTAT_LASTBIT &&
                    !(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
                        /* ack was not received... */
 
                        dev_dbg(i2c->dev, "ack was not received\n");
-                       s3c24xx_i2c_stop(i2c, -EREMOTEIO);
+                       s3c24xx_i2c_stop(i2c, -ENXIO);
                        goto out_ack;
                }
 
@@ -305,7 +305,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
                        i2c->state = STATE_WRITE;
 
                /* terminate the transfer if there is nothing to do
-                * (used by the i2c probe to find devices */
+                * as this is used by the i2c probe to find devices. */
 
                if (is_lastmsg(i2c) && i2c->msg->len == 0) {
                        s3c24xx_i2c_stop(i2c, 0);
@@ -323,7 +323,17 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
                 * end of the message, and if so, work out what to do
                 */
 
+               if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
+                       if (iicstat & S3C2410_IICSTAT_LASTBIT) {
+                               dev_dbg(i2c->dev, "WRITE: No Ack\n");
+
+                               s3c24xx_i2c_stop(i2c, -ECONNREFUSED);
+                               goto out_ack;
+                       }
+               }
+
        retry_write:
+
                if (!is_msgend(i2c)) {
                        byte = i2c->msg->buf[i2c->msg_ptr++];
                        writeb(byte, i2c->regs + S3C2410_IICDS);
@@ -377,17 +387,6 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
                 * going to do any more read/write
                 */
 
-               if (!(i2c->msg->flags & I2C_M_IGNORE_NAK) &&
-                   !(is_msglast(i2c) && is_lastmsg(i2c))) {
-
-                       if (iicstat & S3C2410_IICSTAT_LASTBIT) {
-                               dev_dbg(i2c->dev, "READ: No Ack\n");
-
-                               s3c24xx_i2c_stop(i2c, -ECONNREFUSED);
-                               goto out_ack;
-                       }
-               }
-
                byte = readb(i2c->regs + S3C2410_IICDS);
                i2c->msg->buf[i2c->msg_ptr++] = byte;
 
@@ -949,3 +948,4 @@ MODULE_DESCRIPTION("S3C24XX I2C Bus driver");
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:s3c2410-i2c");
+MODULE_ALIAS("platform:s3c2440-i2c");
index 8e07de23d220911988d811f121bcd2b8d17e6699..1607536ff5fb3ec7da44b500157c1631703b3604 100644 (file)
@@ -823,6 +823,13 @@ config BLK_DEV_IDE_RAPIDE
          Say Y here if you want to support the Yellowstone RapIDE controller
          manufactured for use with Acorn computers.
 
+config BLK_DEV_IDE_BAST
+       tristate "Simtec BAST / Thorcom VR1000 IDE support"
+       depends on ARM && (ARCH_BAST || MACH_VR1000)
+       help
+         Say Y here if you want to support the onboard IDE channels on the
+         Simtec BAST or the Thorcom VR1000
+
 config IDE_H8300
        tristate "H8300 IDE support"
        depends on H8300
index 5bc26053afa609c83e05426edc3d999cdef8d3a7..936e7b0237f5499fe0305845679c12a96d025d16 100644 (file)
@@ -1,6 +1,7 @@
 
 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)       += icside.o
 obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)       += rapide.o
+obj-$(CONFIG_BLK_DEV_IDE_BAST)         += bast-ide.o
 obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710)  += palm_bk3710.o
 
 ifeq ($(CONFIG_IDE_ARM), m)
diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c
new file mode 100644 (file)
index 0000000..8e8c281
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2003-2004 Simtec Electronics
+ *  Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/arch/map.h>
+#include <asm/arch/bast-map.h>
+#include <asm/arch/bast-irq.h>
+
+#define DRV_NAME "bast-ide"
+
+static int __init bastide_register(unsigned int base, unsigned int aux, int irq)
+{
+       ide_hwif_t *hwif;
+       hw_regs_t hw;
+       int i;
+       u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+
+       memset(&hw, 0, sizeof(hw));
+
+       base += BAST_IDE_CS;
+       aux  += BAST_IDE_CS;
+
+       for (i = 0; i <= 7; i++) {
+               hw.io_ports_array[i] = (unsigned long)base;
+               base += 0x20;
+       }
+
+       hw.io_ports.ctl_addr = aux + (6 * 0x20);
+       hw.irq = irq;
+       hw.chipset = ide_generic;
+
+       hwif = ide_find_port();
+       if (hwif == NULL)
+               goto out;
+
+       i = hwif->index;
+
+       ide_init_port_data(hwif, i);
+       ide_init_port_hw(hwif, &hw);
+       hwif->port_ops = NULL;
+
+       idx[0] = i;
+
+       ide_device_add(idx, NULL);
+out:
+       return 0;
+}
+
+static int __init bastide_init(void)
+{
+       unsigned long base = BAST_VA_IDEPRI + BAST_IDE_CS;
+
+       /* we can treat the VR1000 and the BAST the same */
+
+       if (!(machine_is_bast() || machine_is_vr1000()))
+               return 0;
+
+       printk("BAST: IDE driver, (c) 2003-2004 Simtec Electronics\n");
+
+       if (!request_mem_region(base, 0x400000, DRV_NAME)) {
+               printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
+               return -EBUSY;
+       }
+
+       bastide_register(BAST_VA_IDEPRI, BAST_VA_IDEPRIAUX, IRQ_IDE0);
+       bastide_register(BAST_VA_IDESEC, BAST_VA_IDESECAUX, IRQ_IDE1);
+
+       return 0;
+}
+
+module_init(bastide_init);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Simtec BAST / Thorcom VR1000 IDE driver");
index cc24803fadff72c45ecff00010888d7161ed7cf7..2f2b4f4cf229f9e046b3dec3b83e367fd0038efd 100644 (file)
@@ -76,7 +76,7 @@ struct palm_bk3710_udmatiming {
 
 #include "../ide-timing.h"
 
-static long ide_palm_clk;
+static unsigned ideclk_period; /* in nanoseconds */
 
 static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
        {160, 240},             /* UDMA Mode 0 */
@@ -86,8 +86,6 @@ static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
        {85,  60},              /* UDMA Mode 4 */
 };
 
-static struct clk *ideclkp;
-
 static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
                                    unsigned int mode)
 {
@@ -97,10 +95,10 @@ static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
 
        /* DMA Data Setup */
        t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime,
-                         ide_palm_clk) - 1;
-       tenv = DIV_ROUND_UP(20, ide_palm_clk) - 1;
+                         ideclk_period) - 1;
+       tenv = DIV_ROUND_UP(20, ideclk_period) - 1;
        trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime,
-                          ide_palm_clk) - 1;
+                          ideclk_period) - 1;
 
        /* udmatim Register */
        val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
@@ -141,8 +139,8 @@ static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
        cycletime = max_t(int, t->cycle, min_cycle);
 
        /* DMA Data Setup */
-       t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
-       td = DIV_ROUND_UP(t->active, ide_palm_clk);
+       t0 = DIV_ROUND_UP(cycletime, ideclk_period);
+       td = DIV_ROUND_UP(t->active, ideclk_period);
        tkw = t0 - td - 1;
        td -= 1;
 
@@ -168,9 +166,9 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
        struct ide_timing *t;
 
        /* PIO Data Setup */
-       t0 = DIV_ROUND_UP(cycletime, ide_palm_clk);
+       t0 = DIV_ROUND_UP(cycletime, ideclk_period);
        t2 = DIV_ROUND_UP(ide_timing_find_mode(XFER_PIO_0 + mode)->active,
-                         ide_palm_clk);
+                         ideclk_period);
 
        t2i = t0 - t2 - 1;
        t2 -= 1;
@@ -192,8 +190,8 @@ static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
 
        /* TASKFILE Setup */
        t = ide_timing_find_mode(XFER_PIO_0 + mode);
-       t0 = DIV_ROUND_UP(t->cyc8b, ide_palm_clk);
-       t2 = DIV_ROUND_UP(t->act8b, ide_palm_clk);
+       t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
+       t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
 
        t2i = t0 - t2 - 1;
        t2 -= 1;
@@ -350,22 +348,22 @@ static const struct ide_port_info __devinitdata palm_bk3710_port_info = {
 
 static int __devinit palm_bk3710_probe(struct platform_device *pdev)
 {
-       struct clk *clkp;
+       struct clk *clk;
        struct resource *mem, *irq;
        ide_hwif_t *hwif;
-       unsigned long base;
+       unsigned long base, rate;
        int i;
        hw_regs_t hw;
        u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
 
-       clkp = clk_get(NULL, "IDECLK");
-       if (IS_ERR(clkp))
+       clk = clk_get(NULL, "IDECLK");
+       if (IS_ERR(clk))
                return -ENODEV;
 
-       ideclkp = clkp;
-       clk_enable(ideclkp);
-       ide_palm_clk = clk_get_rate(ideclkp)/100000;
-       ide_palm_clk = (10000/ide_palm_clk) + 1;
+       clk_enable(clk);
+       rate = clk_get_rate(clk);
+       ideclk_period = 1000000000UL / rate;
+
        /* Register the IDE interface with Linux ATA Interface */
        memset(&hw, 0, sizeof(hw));
 
index 380fa0c8cc84d40f2f9897d0b41d234815bc6a92..26e68b65b7cf554c09869f65eba2e8940489238e 100644 (file)
@@ -646,8 +646,6 @@ static int ide_register_port(ide_hwif_t *hwif)
                goto out;
        }
 
-       get_device(&hwif->gendev);
-
        hwif->portdev = device_create_drvdata(ide_port_class, &hwif->gendev,
                                              MKDEV(0, 0), hwif, hwif->name);
        if (IS_ERR(hwif->portdev)) {
@@ -1220,16 +1218,12 @@ static void drive_release_dev (struct device *dev)
        complete(&drive->gendev_rel_comp);
 }
 
-#ifndef ide_default_irq
-#define ide_default_irq(irq) 0
-#endif
-
 static int hwif_init(ide_hwif_t *hwif)
 {
        int old_irq;
 
        if (!hwif->irq) {
-               hwif->irq = ide_default_irq(hwif->io_ports.data_addr);
+               hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
                if (!hwif->irq) {
                        printk("%s: DISABLED, NO IRQ\n", hwif->name);
                        return 0;
@@ -1259,7 +1253,7 @@ static int hwif_init(ide_hwif_t *hwif)
         *      It failed to initialise. Find the default IRQ for 
         *      this port and try that.
         */
-       hwif->irq = ide_default_irq(hwif->io_ports.data_addr);
+       hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
        if (!hwif->irq) {
                printk("%s: Disabled unable to get IRQ %d.\n",
                        hwif->name, old_irq);
index 55ec7f798772d6d60a7d704371eca12c5854616f..8af88bf0969bde8bf41926e1e5834deed20022f6 100644 (file)
@@ -76,7 +76,7 @@ static int proc_ide_read_mate
        ide_hwif_t      *hwif = (ide_hwif_t *) data;
        int             len;
 
-       if (hwif && hwif->mate && hwif->mate->present)
+       if (hwif && hwif->mate)
                len = sprintf(page, "%s\n", hwif->mate->name);
        else
                len = sprintf(page, "(none)\n");
index c758dcb13b14209a97bfdca02ef056ee113712a7..300431d080a97310ca829beff00f8b7dd49bb3aa 100644 (file)
@@ -315,13 +315,14 @@ void ide_unregister(ide_hwif_t *hwif)
 
        BUG_ON(in_interrupt());
        BUG_ON(irqs_disabled());
+
        mutex_lock(&ide_cfg_mtx);
-       spin_lock_irq(&ide_lock);
-       if (!hwif->present)
-               goto abort;
-       __ide_port_unregister_devices(hwif);
-       hwif->present = 0;
 
+       spin_lock_irq(&ide_lock);
+       if (hwif->present) {
+               __ide_port_unregister_devices(hwif);
+               hwif->present = 0;
+       }
        spin_unlock_irq(&ide_lock);
 
        ide_proc_unregister_port(hwif);
@@ -351,16 +352,15 @@ void ide_unregister(ide_hwif_t *hwif)
        blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS);
        kfree(hwif->sg_table);
        unregister_blkdev(hwif->major, hwif->name);
-       spin_lock_irq(&ide_lock);
 
        if (hwif->dma_base)
                ide_release_dma_engine(hwif);
 
+       spin_lock_irq(&ide_lock);
        /* restore hwif data to pristine status */
        ide_init_port_data(hwif, hwif->index);
-
-abort:
        spin_unlock_irq(&ide_lock);
+
        mutex_unlock(&ide_cfg_mtx);
 }
 
@@ -1094,13 +1094,6 @@ struct bus_type ide_bus_type = {
 
 EXPORT_SYMBOL_GPL(ide_bus_type);
 
-static void ide_port_class_release(struct device *portdev)
-{
-       ide_hwif_t *hwif = dev_get_drvdata(portdev);
-
-       put_device(&hwif->gendev);
-}
-
 int ide_vlb_clk;
 EXPORT_SYMBOL_GPL(ide_vlb_clk);
 
@@ -1305,7 +1298,6 @@ static int __init ide_init(void)
                ret = PTR_ERR(ide_port_class);
                goto out_port_class;
        }
-       ide_port_class->dev_release = ide_port_class_release;
 
        init_ide_data();
 
index 3381424d70a195ed70bb3525e0160d96c18af033..8dbf4d9b6447cdd6e6bf2add89382b1f55ec0213 100644 (file)
@@ -63,11 +63,11 @@ MODULE_LICENSE("Dual MPL/GPL");
 
 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
 
-#ifdef PCMCIA_DEBUG
-INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
+#ifdef CONFIG_PCMCIA_DEBUG
+INT_MODULE_PARM(pc_debug, 0);
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
-static char *version =
-"ide-cs.c 1.3 2002/10/26 05:45:31 (David Hinds)";
+/*static char *version =
+"ide-cs.c 1.3 2002/10/26 05:45:31 (David Hinds)";*/
 #else
 #define DEBUG(n, args...)
 #endif
@@ -375,7 +375,7 @@ failed:
 
 ======================================================================*/
 
-void ide_release(struct pcmcia_device *link)
+static void ide_release(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
     ide_hwif_t *hwif = info->hwif;
index 9053c8771e6ec792304c49b9e509fd450d994437..2b71bdf74e73a2557c1f2c033bfb5306c684cbdc 100644 (file)
@@ -184,8 +184,7 @@ static const struct ide_port_info it8213_chipsets[] __devinitdata = {
 
 static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       ide_setup_pci_device(dev, &it8213_chipsets[id->driver_data]);
-       return 0;
+       return ide_setup_pci_device(dev, &it8213_chipsets[id->driver_data]);
 }
 
 static const struct pci_device_id it8213_pci_tbl[] = {
index fec4955f449b0fa9bcc08ad57a203e81684ad73b..a7a41bb827783b7946ada332583e042a1c23338a 100644 (file)
@@ -225,10 +225,6 @@ static int ns87415_dma_setup(ide_drive_t *drive)
        return 1;
 }
 
-#ifndef ide_default_irq
-#define ide_default_irq(irq) 0
-#endif
-
 static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
 {
        struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -288,7 +284,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
        }
 
        if (!using_inta)
-               hwif->irq = ide_default_irq(hwif->io_ports.data_addr);
+               hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
        else if (!hwif->irq && hwif->mate && hwif->mate->irq)
                hwif->irq = hwif->mate->irq;    /* share IRQ with mate */
 
index 8934178a23ee6d615ed2a7badfd1758c3aab3f6b..95f82cfb6c54de3b95a3a98a0e303e9c8f2321a3 100644 (file)
@@ -1096,7 +1096,9 @@ static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, ch
        struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
 
        PDBG("%s dev 0x%p\n", __func__, dev);
+       rtnl_lock();
        lldev->ethtool_ops->get_drvinfo(lldev, &info);
+       rtnl_unlock();
        return sprintf(buf, "%s\n", info.fw_version);
 }
 
@@ -1109,7 +1111,9 @@ static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
        struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
 
        PDBG("%s dev 0x%p\n", __func__, dev);
+       rtnl_lock();
        lldev->ethtool_ops->get_drvinfo(lldev, &info);
+       rtnl_unlock();
        return sprintf(buf, "%s\n", info.driver);
 }
 
index eebc72465fc9beb44d2ecfa77a78d24cbd31f891..72c63e5dd630709ddffccf8dc945147857bf41ba 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/sched.h>
 
 /*
  * Check that the effect_id is a valid effect and whether the user
@@ -166,8 +167,10 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
        if (ret)
                goto out;
 
+       spin_lock_irq(&dev->event_lock);
        ff->effects[id] = *effect;
        ff->effect_owners[id] = file;
+       spin_unlock_irq(&dev->event_lock);
 
  out:
        mutex_unlock(&ff->mutex);
@@ -189,16 +192,22 @@ static int erase_effect(struct input_dev *dev, int effect_id,
        if (error)
                return error;
 
+       spin_lock_irq(&dev->event_lock);
        ff->playback(dev, effect_id, 0);
+       ff->effect_owners[effect_id] = NULL;
+       spin_unlock_irq(&dev->event_lock);
 
        if (ff->erase) {
                error = ff->erase(dev, effect_id);
-               if (error)
+               if (error) {
+                       spin_lock_irq(&dev->event_lock);
+                       ff->effect_owners[effect_id] = file;
+                       spin_unlock_irq(&dev->event_lock);
+
                        return error;
+               }
        }
 
-       ff->effect_owners[effect_id] = NULL;
-
        return 0;
 }
 
@@ -263,8 +272,6 @@ int input_ff_event(struct input_dev *dev, unsigned int type,
        if (type != EV_FF)
                return 0;
 
-       mutex_lock(&ff->mutex);
-
        switch (code) {
        case FF_GAIN:
                if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffff)
@@ -286,7 +293,6 @@ int input_ff_event(struct input_dev *dev, unsigned int type,
                break;
        }
 
-       mutex_unlock(&ff->mutex);
        return 0;
 }
 EXPORT_SYMBOL_GPL(input_ff_event);
index 0f3c66de69bcec511b89b9c72265ada93b2bc3c2..8d8c6b736167c63427e5c013c6ae81aae3744589 100644 (file)
@@ -1977,8 +1977,10 @@ isdn_writebuf_stub(int drvidx, int chan, const u_char __user * buf, int len)
        if (!skb)
                return -ENOMEM;
        skb_reserve(skb, hl);
-       if (copy_from_user(skb_put(skb, len), buf, len))
+       if (copy_from_user(skb_put(skb, len), buf, len)) {
+               dev_kfree_skb(skb);
                return -EFAULT;
+       }
        ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);
        if (ret <= 0)
                dev_kfree_skb(skb);
index 835def11419d36d7b56e0e216028714d384ad0f9..ab6a61db63ce2248b5553ec43678fab61642e9a7 100644 (file)
@@ -432,6 +432,7 @@ static int crypt_convert(struct crypt_config *cc,
                case 0:
                        atomic_dec(&ctx->pending);
                        ctx->sector++;
+                       cond_resched();
                        continue;
 
                /* error */
index 10748240cb2fde2bd8942dbb19e300cc6c32961c..6a866d7c8ae5885e3a0f75970106b1e76efca652 100644 (file)
@@ -50,17 +50,19 @@ 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
  *     @q: request queue
- *     @bio: the buffer head that's been built up so far
+ *     @bvm: properties of new bio
  *     @biovec: the request that could be merged to it.
  *
  *     Return amount of bytes we can take at this offset
  */
-static int linear_mergeable_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *biovec)
+static int linear_mergeable_bvec(struct request_queue *q,
+                                struct bvec_merge_data *bvm,
+                                struct bio_vec *biovec)
 {
        mddev_t *mddev = q->queuedata;
        dev_info_t *dev0;
-       unsigned long maxsectors, bio_sectors = bio->bi_size >> 9;
-       sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
+       unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9;
+       sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
 
        dev0 = which_dev(mddev, sector);
        maxsectors = (dev0->size << 1) - (sector - (dev0->offset<<1));
index 7cf512a34ccfc1ecd84c5264aff7d44184a14d95..2580ac1b9b0ff06f34d37f12ea829682017e5ef1 100644 (file)
@@ -3897,8 +3897,10 @@ static void autorun_devices(int part)
 
                md_probe(dev, NULL, NULL);
                mddev = mddev_find(dev);
-               if (!mddev) {
-                       printk(KERN_ERR 
+               if (!mddev || !mddev->gendisk) {
+                       if (mddev)
+                               mddev_put(mddev);
+                       printk(KERN_ERR
                                "md: cannot allocate memory for md drive.\n");
                        break;
                }
index 914c04ddec7c64690cdb24a4b77c83172d4d38ab..bcbb82594a193c275dd4db15fadc46fd4a6494d6 100644 (file)
@@ -241,18 +241,20 @@ static int create_strip_zones (mddev_t *mddev)
 /**
  *     raid0_mergeable_bvec -- tell bio layer if a two requests can be merged
  *     @q: request queue
- *     @bio: the buffer head that's been built up so far
+ *     @bvm: properties of new bio
  *     @biovec: the request that could be merged to it.
  *
  *     Return amount of bytes we can accept at this offset
  */
-static int raid0_mergeable_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *biovec)
+static int raid0_mergeable_bvec(struct request_queue *q,
+                               struct bvec_merge_data *bvm,
+                               struct bio_vec *biovec)
 {
        mddev_t *mddev = q->queuedata;
-       sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
+       sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
        int max;
        unsigned int chunk_sectors = mddev->chunk_size >> 9;
-       unsigned int bio_sectors = bio->bi_size >> 9;
+       unsigned int bio_sectors = bvm->bi_size >> 9;
 
        max =  (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
        if (max < 0) max = 0; /* bio_add cannot handle a negative return */
index 1de17da34a956e8383efb1b42474c3c4d3d15dbe..22bb2b1b886d96887948f25fd8efbc199b3b3079 100644 (file)
@@ -439,26 +439,27 @@ static sector_t raid10_find_virt(conf_t *conf, sector_t sector, int dev)
 /**
  *     raid10_mergeable_bvec -- tell bio layer if a two requests can be merged
  *     @q: request queue
- *     @bio: the buffer head that's been built up so far
+ *     @bvm: properties of new bio
  *     @biovec: the request that could be merged to it.
  *
  *     Return amount of bytes we can accept at this offset
  *      If near_copies == raid_disk, there are no striping issues,
  *      but in that case, the function isn't called at all.
  */
-static int raid10_mergeable_bvec(struct request_queue *q, struct bio *bio,
-                               struct bio_vec *bio_vec)
+static int raid10_mergeable_bvec(struct request_queue *q,
+                                struct bvec_merge_data *bvm,
+                                struct bio_vec *biovec)
 {
        mddev_t *mddev = q->queuedata;
-       sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
+       sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
        int max;
        unsigned int chunk_sectors = mddev->chunk_size >> 9;
-       unsigned int bio_sectors = bio->bi_size >> 9;
+       unsigned int bio_sectors = bvm->bi_size >> 9;
 
        max =  (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
        if (max < 0) max = 0; /* bio_add cannot handle a negative return */
-       if (max <= bio_vec->bv_len && bio_sectors == 0)
-               return bio_vec->bv_len;
+       if (max <= biovec->bv_len && bio_sectors == 0)
+               return biovec->bv_len;
        else
                return max;
 }
@@ -2137,6 +2138,8 @@ static int run(mddev_t *mddev)
                    !test_bit(In_sync, &disk->rdev->flags)) {
                        disk->head_position = 0;
                        mddev->degraded++;
+                       if (disk->rdev)
+                               conf->fullsync = 1;
                }
        }
 
index c37e256b117603f8f68aed3de3a40db9328e70f6..9ce7154845c67eb4acffc441462667b9a152f468 100644 (file)
@@ -2017,12 +2017,7 @@ static int __handle_issuing_new_read_requests5(struct stripe_head *sh,
                         */
                        s->uptodate++;
                        return 0; /* uptodate + compute == disks */
-               } else if ((s->uptodate < disks - 1) &&
-                       test_bit(R5_Insync, &dev->flags)) {
-                       /* Note: we hold off compute operations while checks are
-                        * in flight, but we still prefer 'compute' over 'read'
-                        * hence we only read if (uptodate < * disks-1)
-                        */
+               } else if (test_bit(R5_Insync, &dev->flags)) {
                        set_bit(R5_LOCKED, &dev->flags);
                        set_bit(R5_Wantread, &dev->flags);
                        if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
@@ -2898,6 +2893,8 @@ static void handle_stripe5(struct stripe_head *sh)
 
                for (i = conf->raid_disks; i--; ) {
                        set_bit(R5_Wantwrite, &sh->dev[i].flags);
+                       set_bit(R5_LOCKED, &dev->flags);
+                       s.locked++;
                        if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
                                sh->ops.count++;
                }
@@ -2911,6 +2908,7 @@ static void handle_stripe5(struct stripe_head *sh)
                        conf->raid_disks);
                s.locked += handle_write_operations5(sh, 1, 1);
        } else if (s.expanded &&
+                  s.locked == 0 &&
                !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
                clear_bit(STRIPE_EXPAND_READY, &sh->state);
                atomic_dec(&conf->reshape_stripes);
@@ -3316,15 +3314,17 @@ static int raid5_congested(void *data, int bits)
 /* We want read requests to align with chunks where possible,
  * but write requests don't need to.
  */
-static int raid5_mergeable_bvec(struct request_queue *q, struct bio *bio, struct bio_vec *biovec)
+static int raid5_mergeable_bvec(struct request_queue *q,
+                               struct bvec_merge_data *bvm,
+                               struct bio_vec *biovec)
 {
        mddev_t *mddev = q->queuedata;
-       sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev);
+       sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
        int max;
        unsigned int chunk_sectors = mddev->chunk_size >> 9;
-       unsigned int bio_sectors = bio->bi_size >> 9;
+       unsigned int bio_sectors = bvm->bi_size >> 9;
 
-       if (bio_data_dir(bio) == WRITE)
+       if ((bvm->bi_rw & 1) == WRITE)
                return biovec->bv_len; /* always allow writes to be mergeable */
 
        max =  (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9;
@@ -4305,7 +4305,9 @@ static int run(mddev_t *mddev)
                                " disk %d\n", bdevname(rdev->bdev,b),
                                raid_disk);
                        working_disks++;
-               }
+               } else
+                       /* Cannot rely on bitmap to complete recovery */
+                       conf->fullsync = 1;
        }
 
        /*
index a3485817e46c9e06b765bda262fdd9f8215b7168..8fa91f846d591bcd35d544d87aec42edbbfc5b96 100644 (file)
@@ -2201,3 +2201,41 @@ IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = {
        [0x25] = KEY_POWER,             /* power */
 };
 EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel);
+
+IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = {
+       [0x20] = KEY_LIST,
+       [0x00] = KEY_POWER,
+       [0x28] = KEY_1,
+       [0x18] = KEY_2,
+       [0x38] = KEY_3,
+       [0x24] = KEY_4,
+       [0x14] = KEY_5,
+       [0x34] = KEY_6,
+       [0x2c] = KEY_7,
+       [0x1c] = KEY_8,
+       [0x3c] = KEY_9,
+       [0x12] = KEY_SUBTITLE,
+       [0x22] = KEY_0,
+       [0x32] = KEY_REWIND,
+       [0x3a] = KEY_SHUFFLE,
+       [0x02] = KEY_PRINT,
+       [0x11] = KEY_CHANNELDOWN,
+       [0x31] = KEY_CHANNELUP,
+       [0x0c] = KEY_ZOOM,
+       [0x1e] = KEY_VOLUMEDOWN,
+       [0x3e] = KEY_VOLUMEUP,
+       [0x0a] = KEY_MUTE,
+       [0x04] = KEY_AUDIO,
+       [0x26] = KEY_RECORD,
+       [0x06] = KEY_PLAY,
+       [0x36] = KEY_STOP,
+       [0x16] = KEY_PAUSE,
+       [0x2e] = KEY_REWIND,
+       [0x0e] = KEY_FASTFORWARD,
+       [0x30] = KEY_TEXT,
+       [0x21] = KEY_GREEN,
+       [0x01] = KEY_BLUE,
+       [0x08] = KEY_EPG,
+       [0x2a] = KEY_MENU,
+};
+EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d);
index f1894fec32b930343d69f0665a698ed267b8e731..6fb5b45865690b3a4279e891d09cf43e222a7dee 100644 (file)
@@ -649,9 +649,17 @@ int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq)
        u8 val;
 
        int ret = tda18271_lookup_map(fe, RF_CAL, freq, &val);
+       /* The TDA18271HD/C1 rf_cal map lookup is expected to go out of range
+        * for frequencies above 61.1 MHz.  In these cases, the internal RF
+        * tracking filters calibration mechanism is used.
+        *
+        * There is no need to warn the user about this.
+        */
+       if (ret < 0)
+               goto fail;
 
        regs[R_EB14] = val;
-
+fail:
        return ret;
 }
 
index 89c01fb1f85981c5cbfa909e1579c2f75212cf07..93063c6fbbf634e42aac29b3502de2b66104e232 100644 (file)
@@ -45,6 +45,21 @@ static inline int charge_pump_source(struct dvb_frontend *fe, int force)
                                           TDA18271_MAIN_PLL, force);
 }
 
+static inline void tda18271_set_if_notch(struct dvb_frontend *fe)
+{
+       struct tda18271_priv *priv = fe->tuner_priv;
+       unsigned char *regs = priv->tda18271_regs;
+
+       switch (priv->mode) {
+       case TDA18271_ANALOG:
+               regs[R_MPD]  &= ~0x80; /* IF notch = 0 */
+               break;
+       case TDA18271_DIGITAL:
+               regs[R_MPD]  |= 0x80; /* IF notch = 1 */
+               break;
+       }
+}
+
 static int tda18271_channel_configuration(struct dvb_frontend *fe,
                                          struct tda18271_std_map_item *map,
                                          u32 freq, u32 bw)
@@ -60,25 +75,18 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
        regs[R_EP3]  &= ~0x1f; /* clear std bits */
        regs[R_EP3]  |= (map->agc_mode << 3) | map->std;
 
-       /* set rfagc to high speed mode */
-       regs[R_EP3] &= ~0x04;
+       if (priv->id == TDA18271HDC2) {
+               /* set rfagc to high speed mode */
+               regs[R_EP3] &= ~0x04;
+       }
 
        /* set cal mode to normal */
        regs[R_EP4]  &= ~0x03;
 
-       /* update IF output level & IF notch frequency */
+       /* update IF output level */
        regs[R_EP4]  &= ~0x1c; /* clear if level bits */
        regs[R_EP4]  |= (map->if_lvl << 2);
 
-       switch (priv->mode) {
-       case TDA18271_ANALOG:
-               regs[R_MPD]  &= ~0x80; /* IF notch = 0 */
-               break;
-       case TDA18271_DIGITAL:
-               regs[R_MPD]  |= 0x80; /* IF notch = 1 */
-               break;
-       }
-
        /* update FM_RFn */
        regs[R_EP4]  &= ~0x80;
        regs[R_EP4]  |= map->fm_rfn << 7;
@@ -95,6 +103,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
        /* disable Power Level Indicator */
        regs[R_EP1]  |= 0x40;
 
+       /* make sure thermometer is off */
+       regs[R_TM]   &= ~0x10;
+
        /* frequency dependent parameters */
 
        tda18271_calc_ir_measure(fe, &freq);
@@ -135,6 +146,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
        switch (priv->role) {
        case TDA18271_MASTER:
                tda18271_calc_main_pll(fe, N);
+               tda18271_set_if_notch(fe);
                tda18271_write_regs(fe, R_MPD, 4);
                break;
        case TDA18271_SLAVE:
@@ -142,6 +154,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
                tda18271_write_regs(fe, R_CPD, 4);
 
                regs[R_MPD] = regs[R_CPD] & 0x7f;
+               tda18271_set_if_notch(fe);
                tda18271_write_regs(fe, R_MPD, 1);
                break;
        }
@@ -160,12 +173,14 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
 
        msleep(20);
 
-       /* set rfagc to normal speed mode */
-       if (map->fm_rfn)
-               regs[R_EP3] &= ~0x04;
-       else
-               regs[R_EP3] |= 0x04;
-       ret = tda18271_write_regs(fe, R_EP3, 1);
+       if (priv->id == TDA18271HDC2) {
+               /* set rfagc to normal speed mode */
+               if (map->fm_rfn)
+                       regs[R_EP3] &= ~0x04;
+               else
+                       regs[R_EP3] |= 0x04;
+               ret = tda18271_write_regs(fe, R_EP3, 1);
+       }
 fail:
        return ret;
 }
@@ -507,7 +522,7 @@ static int tda18271_powerscan_init(struct dvb_frontend *fe)
        /* set cal mode to normal */
        regs[R_EP4]  &= ~0x03;
 
-       /* update IF output level & IF notch frequency */
+       /* update IF output level */
        regs[R_EP4]  &= ~0x1c; /* clear if level bits */
 
        ret = tda18271_write_regs(fe, R_EP3, 2);
index ceae6db901ecaa9543f5e4ef4bcd727e3d10cc42..7cf4f5bdb2ecef54de97f6af81407bb098964932 100644 (file)
@@ -177,6 +177,7 @@ static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
        {"FM Radio-INPUT1",   0x0208, 0x9002}
 };
 
+static int  xc5000_is_firmware_loaded(struct dvb_frontend *fe);
 static int  xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len);
 static int  xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len);
 static void xc5000_TunerReset(struct dvb_frontend *fe);
@@ -352,7 +353,7 @@ static int xc_SetTVStandard(struct xc5000_priv *priv,
 
 static int xc_shutdown(struct xc5000_priv *priv)
 {
-       return 0;
+       return XC_RESULT_SUCCESS;
        /* Fixme: cannot bring tuner back alive once shutdown
         *        without reloading the driver modules.
         *    return xc_write_reg(priv, XREG_POWER_DOWN, 0);
@@ -685,6 +686,25 @@ static int xc5000_set_params(struct dvb_frontend *fe,
        return 0;
 }
 
+static int xc5000_is_firmware_loaded(struct dvb_frontend *fe)
+{
+       struct xc5000_priv *priv = fe->tuner_priv;
+       int ret;
+       u16 id;
+
+       ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id);
+       if (ret == XC_RESULT_SUCCESS) {
+               if (id == XC_PRODUCT_ID_FW_NOT_LOADED)
+                       ret = XC_RESULT_RESET_FAILURE;
+               else
+                       ret = XC_RESULT_SUCCESS;
+       }
+
+       dprintk(1, "%s() returns %s id = 0x%x\n", __func__,
+               ret == XC_RESULT_SUCCESS ? "True" : "False", id);
+       return ret;
+}
+
 static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
 
 static int xc5000_set_analog_params(struct dvb_frontend *fe,
@@ -693,7 +713,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
        struct xc5000_priv *priv = fe->tuner_priv;
        int ret;
 
-       if(priv->fwloaded == 0)
+       if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
                xc_load_fw_and_init_tuner(fe);
 
        dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
@@ -808,11 +828,10 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
        struct xc5000_priv *priv = fe->tuner_priv;
        int ret = 0;
 
-       if (priv->fwloaded == 0) {
+       if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
                ret = xc5000_fwupload(fe);
                if (ret != XC_RESULT_SUCCESS)
                        return ret;
-               priv->fwloaded = 1;
        }
 
        /* Start the tuner self-calibration process */
@@ -852,7 +871,6 @@ static int xc5000_sleep(struct dvb_frontend *fe)
                return -EREMOTEIO;
        }
        else {
-               /* priv->fwloaded = 0; */
                return XC_RESULT_SUCCESS;
        }
 }
@@ -933,7 +951,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
                        cfg->i2c_address);
                printk(KERN_INFO
                        "xc5000: Firmware has been loaded previously\n");
-               priv->fwloaded = 1;
                break;
        case XC_PRODUCT_ID_FW_NOT_LOADED:
                printk(KERN_INFO
@@ -941,7 +958,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
                        cfg->i2c_address);
                printk(KERN_INFO
                        "xc5000: Firmware has not been loaded previously\n");
-               priv->fwloaded = 0;
                break;
        default:
                printk(KERN_ERR
index ecebfe4745adcadf30e3f2a82d31b00c3b21210e..a72a9887fe7ffeab488da51193be130ba7d98767 100644 (file)
@@ -30,7 +30,6 @@ struct xc5000_priv {
        u32 bandwidth;
        u8  video_standard;
        u8  rf_mode;
-       u8  fwloaded;
 
        void *devptr;
 };
index 0a8ac64a4e33a6a345cd6eea538b7397a33c6536..037f7ffb47b297e6696fd167b8849143cac654f6 100644 (file)
@@ -47,6 +47,8 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
                return -EINVAL;
        }
 
+       msleep(1); /* avoid I2C errors */
+
        return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type,
                               value, index, rbuf, rlen, 2000);
 }
@@ -92,16 +94,6 @@ static struct i2c_algorithm gl861_i2c_algo = {
 };
 
 /* Callbacks for DVB USB */
-static int gl861_identify_state(struct usb_device *udev,
-                               struct dvb_usb_device_properties *props,
-                               struct dvb_usb_device_description **desc,
-                               int *cold)
-{
-       *cold = 0;
-
-       return 0;
-}
-
 static struct zl10353_config gl861_zl10353_config = {
        .demod_address = 0x0f,
        .no_tuner = 1,
@@ -172,7 +164,6 @@ static struct dvb_usb_device_properties gl861_properties = {
 
        .size_of_priv     = 0,
 
-       .identify_state   = gl861_identify_state,
        .num_adapters = 1,
        .adapter = {{
 
@@ -194,13 +185,15 @@ static struct dvb_usb_device_properties gl861_properties = {
 
        .num_device_descs = 2,
        .devices = {
-               {   "MSI Mega Sky 55801 DVB-T USB2.0",
-                       { &gl861_table[0], NULL },
-                       { NULL },
+               {
+                       .name = "MSI Mega Sky 55801 DVB-T USB2.0",
+                       .cold_ids = { NULL },
+                       .warm_ids = { &gl861_table[0], NULL },
                },
-               {   "A-LINK DTU DVB-T USB2.0",
-                       { &gl861_table[1], NULL },
-                       { NULL },
+               {
+                       .name = "A-LINK DTU DVB-T USB2.0",
+                       .cold_ids = { NULL },
+                       .warm_ids = { &gl861_table[1], NULL },
                },
        }
 };
index 9e7653bb3b660bc4c44985db551cf94e0f65ee5e..118aab1a3e540943e7a325f5836999e4c4819d5f 100644 (file)
@@ -107,7 +107,7 @@ static struct dvb_usb_device_properties umt_properties = {
                        /* parameter for the MPEG2-data transfer */
                        .stream = {
                                .type = USB_BULK,
-                               .count = 20,
+                               .count = MAX_NO_URBS_FOR_DATA_STREAM,
                                .endpoint = 0x06,
                                .u = {
                                        .bulk = {
index 084a280c2d7f97cbf6835e1f6e5bf73cf363f8d3..03900d241a76da067545aaba61916d4c88385291 100644 (file)
@@ -463,10 +463,13 @@ static int au8522_set_frontend(struct dvb_frontend *fe,
                               struct dvb_frontend_parameters *p)
 {
        struct au8522_state *state = fe->demodulator_priv;
+       int ret = -EINVAL;
 
        dprintk("%s(frequency=%d)\n", __func__, p->frequency);
 
-       state->current_frequency = p->frequency;
+       if ((state->current_frequency == p->frequency) &&
+           (state->current_modulation == p->u.vsb.modulation))
+               return 0;
 
        au8522_enable_modulation(fe, p->u.vsb.modulation);
 
@@ -476,11 +479,16 @@ static int au8522_set_frontend(struct dvb_frontend *fe,
        if (fe->ops.tuner_ops.set_params) {
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 1);
-               fe->ops.tuner_ops.set_params(fe, p);
+               ret = fe->ops.tuner_ops.set_params(fe, p);
                if (fe->ops.i2c_gate_ctrl)
                        fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
+       if (ret < 0)
+               return ret;
+
+       state->current_frequency = p->frequency;
+
        return 0;
 }
 
@@ -498,6 +506,16 @@ static int au8522_init(struct dvb_frontend *fe)
        return 0;
 }
 
+static int au8522_sleep(struct dvb_frontend *fe)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+       dprintk("%s()\n", __func__);
+
+       state->current_frequency = 0;
+
+       return 0;
+}
+
 static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
        struct au8522_state *state = fe->demodulator_priv;
@@ -509,10 +527,8 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
        if (state->current_modulation == VSB_8) {
                dprintk("%s() Checking VSB_8\n", __func__);
                reg = au8522_readreg(state, 0x4088);
-               if (reg & 0x01)
-                       *status |= FE_HAS_VITERBI;
-               if (reg & 0x02)
-                       *status |= FE_HAS_LOCK | FE_HAS_SYNC;
+               if ((reg & 0x03) == 0x03)
+                       *status |= FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
        } else {
                dprintk("%s() Checking QAM\n", __func__);
                reg = au8522_readreg(state, 0x4541);
@@ -672,6 +688,7 @@ static struct dvb_frontend_ops au8522_ops = {
        },
 
        .init                 = au8522_init,
+       .sleep                = au8522_sleep,
        .i2c_gate_ctrl        = au8522_i2c_gate_ctrl,
        .set_frontend         = au8522_set_frontend,
        .get_frontend         = au8522_get_frontend,
index 17556183e871629c2ae4fabc116c598ce233ea70..35435bef8e7992af4e1e8648a8c408b0f2d62f18 100644 (file)
@@ -63,6 +63,7 @@ struct stv0299_state {
        u32 symbol_rate;
        fe_code_rate_t fec_inner;
        int errmode;
+       u32 ucblocks;
 };
 
 #define STATUS_BER 0
@@ -501,8 +502,10 @@ 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;
-       *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
+       if (state->errmode != STATUS_BER)
+               return -ENOSYS;
+
+       *ber = stv0299_readreg(state, 0x1e) | (stv0299_readreg(state, 0x1d) << 8);
 
        return 0;
 }
@@ -540,8 +543,12 @@ 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);
+       if (state->errmode != STATUS_UCBLOCKS)
+               return -ENOSYS;
+
+       state->ucblocks += stv0299_readreg(state, 0x1e);
+       state->ucblocks += (stv0299_readreg(state, 0x1d) << 8);
+       *ucblocks = state->ucblocks;
 
        return 0;
 }
index 0727b80bc4d296a83f56317b9266fdbac705f562..c6ff5b82ff80d481e58151cbe47ee336fe76868d 100644 (file)
@@ -116,9 +116,12 @@ static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
        int ret;
 
        ret = i2c_transfer (state->i2c, msg, 2);
-       if (ret != 2)
-               printk("DVB: TDA10023: %s: readreg error (ret == %i)\n",
-                                __func__, ret);
+       if (ret != 2) {
+               int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
+               printk(KERN_ERR "DVB: TDA10023(%d): %s: readreg error "
+                       "(reg == 0x%02x, ret == %i)\n",
+                       num, __func__, reg, ret);
+       }
        return b1[0];
 }
 
@@ -129,11 +132,12 @@ static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data)
        int ret;
 
        ret = i2c_transfer (state->i2c, &msg, 1);
-       if (ret != 1)
-               printk("DVB: TDA10023(%d): %s, writereg error "
+       if (ret != 1) {
+               int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
+               printk(KERN_ERR "DVB: TDA10023(%d): %s, writereg error "
                        "(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-                       state->frontend.dvb->num, __func__, reg, data, ret);
-
+                       num, __func__, reg, data, ret);
+       }
        return (ret != 1) ? -EREMOTEIO : 0;
 }
 
@@ -464,7 +468,7 @@ struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
        int i;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct tda10023_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct tda10023_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
index 49973846373e843b5fc4d64e6aa97b14922f3a45..a0d6386535673223f557c8d068e233e9a900a239 100644 (file)
@@ -1248,11 +1248,14 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
                                     struct i2c_adapter* i2c)
 {
        struct tda1004x_state *state;
+       int id;
 
        /* allocate memory for the internal state */
        state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
-       if (!state)
+       if (!state) {
+               printk(KERN_ERR "Can't alocate memory for tda10045 state\n");
                return NULL;
+       }
 
        /* setup the state */
        state->config = config;
@@ -1260,7 +1263,15 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
        state->demod_type = TDA1004X_DEMOD_TDA10045;
 
        /* check if the demod is there */
-       if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x25) {
+       id = tda1004x_read_byte(state, TDA1004X_CHIPID);
+       if (id < 0) {
+               printk(KERN_ERR "tda10045: chip is not answering. Giving up.\n");
+               kfree(state);
+               return NULL;
+       }
+
+       if (id != 0x25) {
+               printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id);
                kfree(state);
                return NULL;
        }
@@ -1307,11 +1318,14 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
                                     struct i2c_adapter* i2c)
 {
        struct tda1004x_state *state;
+       int id;
 
        /* allocate memory for the internal state */
        state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
-       if (!state)
+       if (!state) {
+               printk(KERN_ERR "Can't alocate memory for tda10046 state\n");
                return NULL;
+       }
 
        /* setup the state */
        state->config = config;
@@ -1319,7 +1333,14 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
        state->demod_type = TDA1004X_DEMOD_TDA10046;
 
        /* check if the demod is there */
-       if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) {
+       id = tda1004x_read_byte(state, TDA1004X_CHIPID);
+       if (id < 0) {
+               printk(KERN_ERR "tda10046: chip is not answering. Giving up.\n");
+               kfree(state);
+               return NULL;
+       }
+       if (id != 0x46) {
+               printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id);
                kfree(state);
                return NULL;
        }
index d4339b1b3b6872e905532852ef31c4403158950b..07643e01009340cada617b9979a2837ad7747965 100644 (file)
@@ -101,6 +101,7 @@ config DVB_BUDGET
 config DVB_BUDGET_CI
        tristate "Budget cards with onboard CI connector"
        depends on DVB_BUDGET_CORE && I2C
+       depends on INPUT # due to IR
        select DVB_STV0297 if !DVB_FE_CUSTOMISE
        select DVB_STV0299 if !DVB_FE_CUSTOMISE
        select DVB_TDA1004X if !DVB_FE_CUSTOMISE
index 9d81074b31dfe7b2b3ca105234f3d518c2c8d3d8..3a3f5279e927287e68e326c1c7d91721ff704335 100644 (file)
@@ -427,6 +427,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
                        if (err) {
                                printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
                                        __func__, type);
+                               av7110->arm_errors++;
                                return -ETIMEDOUT;
                        }
                        msleep(1);
@@ -853,10 +854,8 @@ static osd_raw_window_t bpp2bit[8] = {
 
 static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
 {
-       int ret = wait_event_interruptible_timeout(av7110->bmpq,
+       int ret = wait_event_timeout(av7110->bmpq,
                                av7110->bmp_state != BMP_LOADING, 10*HZ);
-       if (ret == -ERESTARTSYS)
-               return ret;
        if (ret == 0) {
                printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
                       ret, av7110->bmp_state);
index 3b26fbd3e5589e5203ca0c99c96bf4e5fbb5e91c..5ccb0aeca8ccde50c4a605a42c3574c46358a045 100644 (file)
@@ -793,6 +793,14 @@ menuconfig V4L_USB_DRIVERS
 
 if V4L_USB_DRIVERS && USB
 
+config USB_VIDEO_CLASS
+       tristate "USB Video Class (UVC)"
+       ---help---
+         Support for the USB Video Class (UVC).  Currently only video
+         input devices, such as webcams, are supported.
+
+         For more information see: <http://linux-uvc.berlios.de/>
+
 source "drivers/media/video/pvrusb2/Kconfig"
 
 source "drivers/media/video/em28xx/Kconfig"
index dff0d6abe917f35ecb79eb7b381802361237ecde..ecbbfaab24d506daf49920a1755ef549277f4334 100644 (file)
@@ -136,6 +136,8 @@ obj-$(CONFIG_SOC_CAMERA_MT9V022)    += mt9v022.o
 
 obj-$(CONFIG_VIDEO_AU0828) += au0828/
 
+obj-$(CONFIG_USB_VIDEO_CLASS)  += uvc/
+
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
 EXTRA_CFLAGS += -Idrivers/media/common/tuners
index a2a6983444fa0d8fe146ceadcaabab3378e6d28f..898e12395e7c26e1f829beff5f773c85cd5671f8 100644 (file)
@@ -77,8 +77,14 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
 
        /* Make sure we support the board model */
        switch (tv.model) {
+       case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */
        case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */
+       case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */
+       case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */
+       case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */
+       case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and basic analog video */
        case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */
+       case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */
                break;
        default:
                printk(KERN_WARNING "%s: warning: "
@@ -175,6 +181,18 @@ struct usb_device_id au0828_usb_id_table [] = {
                .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 },
        { USB_DEVICE(0x0fe9, 0xd620),
                .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 },
+       { USB_DEVICE(0x2040, 0x7210),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x7217),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x721b),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x721f),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x7280),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x0fd9, 0x0008),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
        { },
 };
 
index 5f942690570c2079626c15c113cdaa02538d3e05..9aefdc5ea79a960983c9c78d5c3cd5e4348e1311 100644 (file)
@@ -10,8 +10,8 @@ config VIDEO_CX18
        select VIDEO_TVEEPROM
        select VIDEO_CX2341X
        select VIDEO_CS5345
-       select DVB_S5H1409
-       select MEDIA_TUNER_MXL5005S
+       select DVB_S5H1409 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE
        ---help---
          This is a video4linux driver for Conexant cx23418 based
          PCI combo video recorder devices.
index 9a26751615c618d6dcf1d5d42e36d02ecda29ef5..faca43eb940f7aa17bfbb552c038e0ad2ecd07f3 100644 (file)
@@ -69,6 +69,58 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
                             or_value);
 }
 
+int cx18_av_write_no_acfg(struct cx18 *cx, u16 addr, u8 value, int no_acfg_mask)
+{
+       int retval;
+       u32 saved_reg[8] = {0};
+
+       if (no_acfg_mask & CXADEC_NO_ACFG_AFE) {
+               saved_reg[0] = cx18_av_read4(cx, CXADEC_CHIP_CTRL);
+               saved_reg[1] = cx18_av_read4(cx, CXADEC_AFE_CTRL);
+       }
+
+       if (no_acfg_mask & CXADEC_NO_ACFG_PLL) {
+               saved_reg[2] = cx18_av_read4(cx, CXADEC_PLL_CTRL1);
+               saved_reg[3] = cx18_av_read4(cx, CXADEC_VID_PLL_FRAC);
+       }
+
+       if (no_acfg_mask & CXADEC_NO_ACFG_VID) {
+               saved_reg[4] = cx18_av_read4(cx, CXADEC_HORIZ_TIM_CTRL);
+               saved_reg[5] = cx18_av_read4(cx, CXADEC_VERT_TIM_CTRL);
+               saved_reg[6] = cx18_av_read4(cx, CXADEC_SRC_COMB_CFG);
+               saved_reg[7] = cx18_av_read4(cx, CXADEC_CHROMA_VBIOFF_CFG);
+       }
+
+       retval = cx18_av_write(cx, addr, value);
+
+       if (no_acfg_mask & CXADEC_NO_ACFG_AFE) {
+               cx18_av_write4(cx, CXADEC_CHIP_CTRL, saved_reg[0]);
+               cx18_av_write4(cx, CXADEC_AFE_CTRL,  saved_reg[1]);
+       }
+
+       if (no_acfg_mask & CXADEC_NO_ACFG_PLL) {
+               cx18_av_write4(cx, CXADEC_PLL_CTRL1,    saved_reg[2]);
+               cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, saved_reg[3]);
+       }
+
+       if (no_acfg_mask & CXADEC_NO_ACFG_VID) {
+               cx18_av_write4(cx, CXADEC_HORIZ_TIM_CTRL,    saved_reg[4]);
+               cx18_av_write4(cx, CXADEC_VERT_TIM_CTRL,     saved_reg[5]);
+               cx18_av_write4(cx, CXADEC_SRC_COMB_CFG,      saved_reg[6]);
+               cx18_av_write4(cx, CXADEC_CHROMA_VBIOFF_CFG, saved_reg[7]);
+       }
+
+       return retval;
+}
+
+int cx18_av_and_or_no_acfg(struct cx18 *cx, u16 addr, unsigned and_mask,
+                          u8 or_value, int no_acfg_mask)
+{
+       return cx18_av_write_no_acfg(cx, addr,
+                                    (cx18_av_read(cx, addr) & and_mask) |
+                                    or_value, no_acfg_mask);
+}
+
 /* ----------------------------------------------------------------------- */
 
 static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
@@ -170,13 +222,15 @@ static void input_change(struct cx18 *cx)
 
        /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */
        if (std & V4L2_STD_SECAM)
-               cx18_av_write(cx, 0x402, 0);
+               cx18_av_write_no_acfg(cx, 0x402, 0, CXADEC_NO_ACFG_ALL);
        else {
-               cx18_av_write(cx, 0x402, 0x04);
+               cx18_av_write_no_acfg(cx, 0x402, 0x04, CXADEC_NO_ACFG_ALL);
                cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
        }
-       cx18_av_and_or(cx, 0x401, ~0x60, 0);
-       cx18_av_and_or(cx, 0x401, ~0x60, 0x60);
+       cx18_av_and_or_no_acfg(cx, 0x401, ~0x60, 0,
+                               CXADEC_NO_ACFG_PLL | CXADEC_NO_ACFG_VID);
+       cx18_av_and_or_no_acfg(cx, 0x401, ~0x60, 0x60,
+                               CXADEC_NO_ACFG_PLL | CXADEC_NO_ACFG_VID);
 
        if (std & V4L2_STD_525_60) {
                if (std == V4L2_STD_NTSC_M_JP) {
@@ -228,7 +282,7 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
 
                if ((vid_input & ~0xff0) ||
                    luma < CX18_AV_SVIDEO_LUMA1 ||
-                   luma > CX18_AV_SVIDEO_LUMA4 ||
+                   luma > CX18_AV_SVIDEO_LUMA8 ||
                    chroma < CX18_AV_SVIDEO_CHROMA4 ||
                    chroma > CX18_AV_SVIDEO_CHROMA8) {
                        CX18_ERR("0x%04x is not a valid video input!\n",
@@ -262,7 +316,8 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
 
        cx18_av_write(cx, 0x103, reg);
        /* Set INPUT_MODE to Composite (0) or S-Video (1) */
-       cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02);
+       cx18_av_and_or_no_acfg(cx, 0x401, ~0x6, is_composite ? 0 : 0x02,
+                               CXADEC_NO_ACFG_PLL | CXADEC_NO_ACFG_VID);
        /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
        cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
        /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
@@ -318,12 +373,12 @@ static int set_v4lstd(struct cx18 *cx)
           This happens for example with the Yuan MPC622. */
        if (fmt >= 4 && fmt < 8) {
                /* Set format to NTSC-M */
-               cx18_av_and_or(cx, 0x400, ~0xf, 1);
+               cx18_av_and_or_no_acfg(cx, 0x400, ~0xf, 1, CXADEC_NO_ACFG_AFE);
                /* Turn off LCOMB */
                cx18_av_and_or(cx, 0x47b, ~6, 0);
        }
-       cx18_av_and_or(cx, 0x400, ~0xf, fmt);
-       cx18_av_and_or(cx, 0x403, ~0x3, pal_m);
+       cx18_av_and_or_no_acfg(cx, 0x400, ~0xf, fmt, CXADEC_NO_ACFG_AFE);
+       cx18_av_and_or_no_acfg(cx, 0x403, ~0x3, pal_m, CXADEC_NO_ACFG_ALL);
        cx18_av_vbi_setup(cx);
        input_change(cx);
        return 0;
index 786901d72e9a84f96d2a48ae1607a90f15e497bb..c172823ce1d8801a93f384fbd5063057a1b6d2a3 100644 (file)
@@ -37,12 +37,16 @@ enum cx18_av_video_input {
        CX18_AV_COMPOSITE7,
        CX18_AV_COMPOSITE8,
 
-       /* S-Video inputs consist of one luma input (In1-In4) ORed with one
+       /* S-Video inputs consist of one luma input (In1-In8) ORed with one
           chroma input (In5-In8) */
        CX18_AV_SVIDEO_LUMA1 = 0x10,
        CX18_AV_SVIDEO_LUMA2 = 0x20,
        CX18_AV_SVIDEO_LUMA3 = 0x30,
        CX18_AV_SVIDEO_LUMA4 = 0x40,
+       CX18_AV_SVIDEO_LUMA5 = 0x50,
+       CX18_AV_SVIDEO_LUMA6 = 0x60,
+       CX18_AV_SVIDEO_LUMA7 = 0x70,
+       CX18_AV_SVIDEO_LUMA8 = 0x80,
        CX18_AV_SVIDEO_CHROMA4 = 0x400,
        CX18_AV_SVIDEO_CHROMA5 = 0x500,
        CX18_AV_SVIDEO_CHROMA6 = 0x600,
@@ -291,14 +295,24 @@ struct cx18_av_state {
 #define CXADEC_SELECT_AUDIO_STANDARD_FM    0xF9  /* FM radio */
 #define CXADEC_SELECT_AUDIO_STANDARD_AUTO  0xFF  /* Auto detect */
 
+/* Flags on what to preserve on write to 0x400-0x403 with cx18_av_.*_no_acfg()*/
+#define CXADEC_NO_ACFG_AFE     0x01 /* Preserve 0x100-0x107 */
+#define CXADEC_NO_ACFG_PLL     0x02 /* Preserve 0x108-0x10f */
+#define CXADEC_NO_ACFG_VID     0x04 /* Preserve 0x470-0x47f */
+#define CXADEC_NO_ACFG_ALL     0x07
+
 /* ----------------------------------------------------------------------- */
 /* cx18_av-core.c                                                         */
 int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
 int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
+int cx18_av_write_no_acfg(struct cx18 *cx, u16 addr, u8 value,
+                               int no_acfg_mask);
 u8 cx18_av_read(struct cx18 *cx, u16 addr);
 u32 cx18_av_read4(struct cx18 *cx, u16 addr);
 int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
 int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
+int cx18_av_and_or_no_acfg(struct cx18 *cx, u16 addr, unsigned mask, u8 value,
+                               int no_acfg_mask);
 int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg);
 
 /* ----------------------------------------------------------------------- */
index baccd079243d9682efbe949ee11a6a69bfc419bb..c26e0ef5b07583927c5d5ddd80fee3c304557741 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "cx18-driver.h"
 #include "cx18-cards.h"
+#include "cx18-av-core.h"
 #include "cx18-i2c.h"
 #include <media/cs5345.h>
 
@@ -54,22 +55,22 @@ static const struct cx18_card cx18_card_hvr1600_esmt = {
        .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER |
                  CX18_HW_CS5345 | CX18_HW_DVB,
        .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX23418_COMPOSITE7 },
-               { CX18_CARD_INPUT_SVIDEO1,    1, CX23418_SVIDEO1    },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 },
-               { CX18_CARD_INPUT_SVIDEO2,    2, CX23418_SVIDEO2    },
-               { CX18_CARD_INPUT_COMPOSITE2, 2, CX23418_COMPOSITE4 },
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
+               { CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+               { CX18_CARD_INPUT_SVIDEO2,    2, CX18_AV_SVIDEO2    },
+               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
        },
        .audio_inputs = {
                { CX18_CARD_INPUT_AUD_TUNER,
-                 CX23418_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+                 CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
                { CX18_CARD_INPUT_LINE_IN1,
-                 CX23418_AUDIO_SERIAL, CS5345_IN_2 },
+                 CX18_AV_AUDIO_SERIAL, CS5345_IN_2 },
                { CX18_CARD_INPUT_LINE_IN2,
-                 CX23418_AUDIO_SERIAL, CS5345_IN_2 },
+                 CX18_AV_AUDIO_SERIAL, CS5345_IN_3 },
        },
        .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
-                        CX23418_AUDIO_SERIAL, 0 },
+                        CX18_AV_AUDIO_SERIAL, CS5345_IN_4 },
        .ddr = {
                /* ESMT M13S128324A-5B memory */
                .chip_config = 0x003,
@@ -81,6 +82,11 @@ static const struct cx18_card cx18_card_hvr1600_esmt = {
        },
        .gpio_init.initial_value = 0x3001,
        .gpio_init.direction = 0x3001,
+       .gpio_i2c_slave_reset = {
+               .active_lo_mask = 0x3001,
+               .msecs_asserted = 10,
+               .msecs_recovery = 40,
+       },
        .i2c = &cx18_i2c_std,
 };
 
@@ -94,22 +100,22 @@ static const struct cx18_card cx18_card_hvr1600_samsung = {
        .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER |
                  CX18_HW_CS5345 | CX18_HW_DVB,
        .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX23418_COMPOSITE7 },
-               { CX18_CARD_INPUT_SVIDEO1,    1, CX23418_SVIDEO1    },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 },
-               { CX18_CARD_INPUT_SVIDEO2,    2, CX23418_SVIDEO2    },
-               { CX18_CARD_INPUT_COMPOSITE2, 2, CX23418_COMPOSITE4 },
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
+               { CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+               { CX18_CARD_INPUT_SVIDEO2,    2, CX18_AV_SVIDEO2    },
+               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
        },
        .audio_inputs = {
                { CX18_CARD_INPUT_AUD_TUNER,
-                 CX23418_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+                 CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
                { CX18_CARD_INPUT_LINE_IN1,
-                 CX23418_AUDIO_SERIAL, CS5345_IN_2 },
+                 CX18_AV_AUDIO_SERIAL, CS5345_IN_2 },
                { CX18_CARD_INPUT_LINE_IN2,
-                 CX23418_AUDIO_SERIAL, CS5345_IN_2 },
+                 CX18_AV_AUDIO_SERIAL, CS5345_IN_3 },
        },
        .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
-                        CX23418_AUDIO_SERIAL, 0 },
+                        CX18_AV_AUDIO_SERIAL, CS5345_IN_4 },
        .ddr = {
                /* Samsung K4D263238G-VC33 memory */
                .chip_config = 0x003,
@@ -121,6 +127,11 @@ static const struct cx18_card cx18_card_hvr1600_samsung = {
        },
        .gpio_init.initial_value = 0x3001,
        .gpio_init.direction = 0x3001,
+       .gpio_i2c_slave_reset = {
+               .active_lo_mask = 0x3001,
+               .msecs_asserted = 10,
+               .msecs_recovery = 40,
+       },
        .i2c = &cx18_i2c_std,
 };
 
@@ -141,19 +152,19 @@ static const struct cx18_card cx18_card_h900 = {
        .hw_audio_ctrl = CX18_HW_CX23418,
        .hw_all = CX18_HW_TUNER,
        .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX23418_COMPOSITE2 },
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
                { CX18_CARD_INPUT_SVIDEO1,    1,
-                       CX23418_SVIDEO_LUMA3 | CX23418_SVIDEO_CHROMA4 },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE1 },
+                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
        },
        .audio_inputs = {
                { CX18_CARD_INPUT_AUD_TUNER,
-                 CX23418_AUDIO8, 0 },
+                 CX18_AV_AUDIO8, 0 },
                { CX18_CARD_INPUT_LINE_IN1,
-                 CX23418_AUDIO_SERIAL, 0 },
+                 CX18_AV_AUDIO_SERIAL, 0 },
        },
        .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
-                        CX23418_AUDIO_SERIAL, 0 },
+                        CX18_AV_AUDIO_SERIAL, 0 },
        .tuners = {
                { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
        },
@@ -183,23 +194,26 @@ static const struct cx18_card_pci_info cx18_pci_mpc718[] = {
 static const struct cx18_card cx18_card_mpc718 = {
        .type = CX18_CARD_YUAN_MPC718,
        .name = "Yuan MPC718",
-       .comment = "Not yet supported!\n",
-       .v4l2_capabilities = 0,
+       .comment = "Some Composite and S-Video inputs are currently working.\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
        .hw_audio_ctrl = CX18_HW_CX23418,
        .hw_all = CX18_HW_TUNER,
        .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX23418_COMPOSITE7 },
-               { CX18_CARD_INPUT_SVIDEO1,    1, CX23418_SVIDEO1    },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 },
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+               { CX18_CARD_INPUT_SVIDEO1,    1,
+                               CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+               { CX18_CARD_INPUT_SVIDEO2,    2,
+                               CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
+               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
+               { CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 },
        },
        .audio_inputs = {
-               { CX18_CARD_INPUT_AUD_TUNER,
-                 CX23418_AUDIO8, 0 },
-               { CX18_CARD_INPUT_LINE_IN1,
-                 CX23418_AUDIO_SERIAL, 0 },
+               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,       0 },
+               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL, 0 },
+               { CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL, 0 },
        },
-       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
-                        CX23418_AUDIO_SERIAL, 0 },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL, 0 },
        .tuners = {
                /* XC3028 tuner */
                { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
index bccb67f0db16415a1efd6ffef20909b9d42cd46d..dc2dd945d4c3be4aefd2b324a6d4f368b8825c8c 100644 (file)
 #define        CX18_CARD_INPUT_COMPOSITE2      5
 #define        CX18_CARD_INPUT_COMPOSITE3      6
 
-enum cx34180_video_input {
-       /* Composite video inputs In1-In8 */
-       CX23418_COMPOSITE1 = 1,
-       CX23418_COMPOSITE2,
-       CX23418_COMPOSITE3,
-       CX23418_COMPOSITE4,
-       CX23418_COMPOSITE5,
-       CX23418_COMPOSITE6,
-       CX23418_COMPOSITE7,
-       CX23418_COMPOSITE8,
-
-       /* S-Video inputs consist of one luma input (In1-In4) ORed with one
-          chroma input (In5-In8) */
-       CX23418_SVIDEO_LUMA1 = 0x10,
-       CX23418_SVIDEO_LUMA2 = 0x20,
-       CX23418_SVIDEO_LUMA3 = 0x30,
-       CX23418_SVIDEO_LUMA4 = 0x40,
-       CX23418_SVIDEO_CHROMA4 = 0x400,
-       CX23418_SVIDEO_CHROMA5 = 0x500,
-       CX23418_SVIDEO_CHROMA6 = 0x600,
-       CX23418_SVIDEO_CHROMA7 = 0x700,
-       CX23418_SVIDEO_CHROMA8 = 0x800,
-
-       /* S-Video aliases for common luma/chroma combinations */
-       CX23418_SVIDEO1 = 0x510,
-       CX23418_SVIDEO2 = 0x620,
-       CX23418_SVIDEO3 = 0x730,
-       CX23418_SVIDEO4 = 0x840,
-};
-
 /* audio inputs */
 #define        CX18_CARD_INPUT_AUD_TUNER       1
 #define        CX18_CARD_INPUT_LINE_IN1        2
@@ -75,16 +45,6 @@ enum cx34180_video_input {
 #define CX18_CARD_MAX_AUDIO_INPUTS 3
 #define CX18_CARD_MAX_TUNERS      2
 
-enum cx23418_audio_input {
-       /* Audio inputs: serial or In4-In8 */
-       CX23418_AUDIO_SERIAL,
-       CX23418_AUDIO4 = 4,
-       CX23418_AUDIO5,
-       CX23418_AUDIO6,
-       CX23418_AUDIO7,
-       CX23418_AUDIO8,
-};
-
 /* V4L2 capability aliases */
 #define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
                          V4L2_CAP_AUDIO | V4L2_CAP_READWRITE)
@@ -118,6 +78,13 @@ struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */
        u32 initial_value;
 };
 
+struct cx18_gpio_i2c_slave_reset {
+       u32 active_lo_mask; /* GPIO outputs that reset i2c chips when low */
+       u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */
+       int msecs_asserted; /* time period reset must remain asserted */
+       int msecs_recovery; /* time after deassert for chips to be ready */
+};
+
 struct cx18_card_tuner {
        v4l2_std_id std;        /* standard for which the tuner is suitable */
        int         tuner;      /* tuner ID (from tuner.h) */
@@ -154,7 +121,8 @@ struct cx18_card {
 
        /* GPIO card-specific settings */
        u8 xceive_pin;          /* XCeive tuner GPIO reset pin */
-       struct cx18_gpio_init           gpio_init;
+       struct cx18_gpio_init            gpio_init;
+       struct cx18_gpio_i2c_slave_reset gpio_i2c_slave_reset;
 
        struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS];
        struct cx18_card_tuner_i2c *i2c;
index c9744173f9692d635455d844beb7a2f9aef2020a..cae38985b1313a306f4dedbe8c656f6208b737ca 100644 (file)
@@ -69,11 +69,21 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
        struct dvb_demux *demux = feed->demux;
        struct cx18_stream *stream = (struct cx18_stream *) demux->priv;
        struct cx18 *cx = stream->cx;
-       int ret = -EINVAL;
+       int ret;
        u32 v;
 
        CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n",
                        feed->pid, feed->index);
+
+       mutex_lock(&cx->serialize_lock);
+       ret = cx18_init_on_first_open(cx);
+       mutex_unlock(&cx->serialize_lock);
+       if (ret) {
+               CX18_ERR("Failed to initialize firmware starting DVB feed\n");
+               return ret;
+       }
+       ret = -EINVAL;
+
        switch (cx->card->type) {
        case CX18_CARD_HVR_1600_ESMT:
        case CX18_CARD_HVR_1600_SAMSUNG:
@@ -101,6 +111,11 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
                if (stream->dvb.feeding++ == 0) {
                        CX18_DEBUG_INFO("Starting Transport DMA\n");
                        ret = cx18_start_v4l2_encode_stream(stream);
+                       if (ret < 0) {
+                               CX18_DEBUG_INFO(
+                                       "Failed to start Transport DMA\n");
+                               stream->dvb.feeding--;
+                       }
                } else
                        ret = 0;
                mutex_unlock(&stream->dvb.feedlock);
index ceb63653c926f71e6b8dae4ce39e00e4e03314ea..b302833f6f9dd8d8250f4e716ed5fa9084d515d6 100644 (file)
@@ -53,10 +53,34 @@ static void gpio_write(struct cx18 *cx)
        write_reg(((dir & 0xffff) << 16) | (val & 0xffff),
                        CX18_REG_GPIO_OUT1);
        write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2);
-       write_reg((dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
+       write_reg_sync((dir & 0xffff0000) | ((val & 0xffff0000) >> 16),
                        CX18_REG_GPIO_OUT2);
 }
 
+void cx18_reset_i2c_slaves_gpio(struct cx18 *cx)
+{
+       const struct cx18_gpio_i2c_slave_reset *p;
+
+       p = &cx->card->gpio_i2c_slave_reset;
+
+       if ((p->active_lo_mask | p->active_hi_mask) == 0)
+               return;
+
+       /* Assuming that the masks are a subset of the bits in gpio_dir */
+
+       /* Assert */
+       cx->gpio_val =
+               (cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask);
+       gpio_write(cx);
+       schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
+
+       /* Deassert */
+       cx->gpio_val =
+               (cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask);
+       gpio_write(cx);
+       schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
+}
+
 void cx18_gpio_init(struct cx18 *cx)
 {
        cx->gpio_dir = cx->card->gpio_init.direction;
index 41bac8856b50e050871d85ee655082e2408ee886..525c328f748a3d0f677863bdc4fdde9ae4bdc0fb 100644 (file)
@@ -21,4 +21,5 @@
  */
 
 void cx18_gpio_init(struct cx18 *cx);
+void cx18_reset_i2c_slaves_gpio(struct cx18 *cx);
 int cx18_reset_tuner_gpio(void *dev, int cmd, int value);
index 1d6c51a753137652028763005bc3c318404e4011..680bc4e35b79a3c67d38e072af2471fb30e35e2d 100644 (file)
@@ -405,6 +405,8 @@ int init_cx18_i2c(struct cx18 *cx)
        cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
        cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
 
+       cx18_reset_i2c_slaves_gpio(cx);
+
        return i2c_bit_add_bus(&cx->i2c_adap[0]) ||
                i2c_bit_add_bus(&cx->i2c_adap[1]);
 }
index 607efdcd22f8d0eeae68ba7a57b01c2c171293cd..1da6f134888d6d524ee375d345c75574981706bc 100644 (file)
@@ -433,7 +433,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
                int chroma = vid_input & 0xf00;
 
                if ((vid_input & ~0xff0) ||
-                   luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA4 ||
+                   luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA8 ||
                    chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) {
                        v4l_err(client, "0x%04x is not a valid video input!\n",
                                vid_input);
index e976fc6bef7ccc7c6ec747fc5594f7a720aff505..80c8883e54b5c6ef853d5e8560da3424044376e3 100644 (file)
@@ -332,6 +332,12 @@ static int snd_cx88_pcm_open(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        int err;
 
+       if (!chip) {
+               printk(KERN_ERR "BUG: cx88 can't find device struct."
+                               " Can't proceed with open\n");
+               return -ENODEV;
+       }
+
        err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
        if (err < 0)
                goto _error;
index 92b2a6db4fdc15edea12a61ccbdcfa522da7a534..3c006103c1eb369c4817fd74522ef7ffebc91e61 100644 (file)
@@ -268,6 +268,12 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
 
        dprintk("opening device and trying to acquire exclusive lock\n");
 
+       if (!dev) {
+               printk(KERN_ERR "BUG: em28xx can't find device struct."
+                               " Can't proceed with open\n");
+               return -ENODEV;
+       }
+
        /* Sets volume, mute, etc */
 
        dev->mute = 0;
@@ -415,6 +421,12 @@ static int em28xx_audio_init(struct em28xx *dev)
        static int          devnr;
        int                 ret, err;
 
+       if (dev->has_audio_class) {
+               /* This device does not support the extension (in this case
+                  the device is expecting the snd-usb-audio module */
+               return 0;
+       }
+
        printk(KERN_INFO "em28xx-audio.c: probing for em28x1 "
                         "non standard usbaudio\n");
        printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
@@ -458,6 +470,12 @@ static int em28xx_audio_fini(struct em28xx *dev)
        if (dev == NULL)
                return 0;
 
+       if (dev->has_audio_class) {
+               /* This device does not support the extension (in this case
+                  the device is expecting the snd-usb-audio module */
+               return 0;
+       }
+
        if (dev->adev) {
                snd_card_free(dev->adev->sndcard);
                kfree(dev->adev);
index 3e4f3c7e92e78ee62231feaebde1628d0cae27ff..8cbda43727c3de59ba73a9427706b0961f7d80b1 100644 (file)
@@ -157,6 +157,7 @@ struct em28xx_board em28xx_boards[] = {
                .tda9887_conf = TDA9887_PRESENT,
                .tuner_type   = TUNER_XC2028,
                .mts_firmware = 1,
+               .has_dvb        = 1,
                .decoder      = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -524,6 +525,9 @@ void em28xx_pre_card_setup(struct em28xx *dev)
        rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
        if (rc > 0) {
                switch (rc) {
+               case CHIP_ID_EM2860:
+                       em28xx_info("chip ID is em2860\n");
+                       break;
                case CHIP_ID_EM2883:
                        em28xx_info("chip ID is em2882/em2883\n");
                        dev->wait_after_write = 0;
index 8cf4983f0039602ce617fbe929a1edad032baa26..0b2333ee07f8ea6c3bbf7200cd70f47b89c3a61f 100644 (file)
@@ -382,6 +382,11 @@ static int dvb_init(struct em28xx *dev)
        int result = 0;
        struct em28xx_dvb *dvb;
 
+       if (!dev->has_dvb) {
+               /* This device does not support the extension */
+               return 0;
+       }
+
        dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
 
        if (dvb == NULL) {
@@ -444,6 +449,11 @@ out_free:
 
 static int dvb_fini(struct em28xx *dev)
 {
+       if (!dev->has_dvb) {
+               /* This device does not support the extension */
+               return 0;
+       }
+
        if (dev->dvb) {
                unregister_dvb(dev->dvb);
                dev->dvb = NULL;
index 9058bed07953d839fc69fd2a44042061cb0c5b3a..fac1ab23f6216dd74d4fcbc0a65fd26868d0fcd6 100644 (file)
@@ -84,5 +84,6 @@
 
 /* FIXME: Need to be populated with the other chip ID's */
 enum em28xx_chip_id {
+       CHIP_ID_EM2860 = 34,
        CHIP_ID_EM2883 = 36,
 };
index fb163ecd921684a4014b69e4de056512fa22904e..285bc62bbe4670f203cde0e08c2c14e1e00743bc 100644 (file)
@@ -1848,32 +1848,28 @@ static DEFINE_MUTEX(em28xx_extension_devlist_lock);
 
 int em28xx_register_extension(struct em28xx_ops *ops)
 {
-       struct em28xx *h, *dev = NULL;
-
-       list_for_each_entry(h, &em28xx_devlist, devlist)
-               dev = h;
+       struct em28xx *dev = NULL;
 
        mutex_lock(&em28xx_extension_devlist_lock);
        list_add_tail(&ops->next, &em28xx_extension_devlist);
-       if (dev)
-               ops->init(dev);
-
+       list_for_each_entry(dev, &em28xx_devlist, devlist) {
+               if (dev)
+                       ops->init(dev);
+       }
        printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
        mutex_unlock(&em28xx_extension_devlist_lock);
-
        return 0;
 }
 EXPORT_SYMBOL(em28xx_register_extension);
 
 void em28xx_unregister_extension(struct em28xx_ops *ops)
 {
-       struct em28xx *h, *dev = NULL;
-
-       list_for_each_entry(h, &em28xx_devlist, devlist)
-               dev = h;
+       struct em28xx *dev = NULL;
 
-       if (dev)
-               ops->fini(dev);
+       list_for_each_entry(dev, &em28xx_devlist, devlist) {
+               if (dev)
+                       ops->fini(dev);
+       }
 
        mutex_lock(&em28xx_extension_devlist_lock);
        printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
index 2bc6bdc9c1f2c50eb966aa2fd127a13cc2d8090d..d7bfd30f74a9bed8455d8c69859f83becc4f2471 100644 (file)
@@ -406,8 +406,10 @@ static int ov7670_read(struct i2c_client *c, unsigned char reg,
        int ret;
 
        ret = i2c_smbus_read_byte_data(c, reg);
-       if (ret >= 0)
+       if (ret >= 0) {
                *value = (unsigned char) ret;
+               ret = 0;
+       }
        return ret;
 }
 
index 7cc8e9b19fb794fb57139515692de6d460afbd96..5ec5bb9a94d2e848095d8e737eb2936e6803b14d 100644 (file)
@@ -1019,12 +1019,12 @@ static int pxa_camera_probe(struct platform_device *pdev)
        struct pxa_camera_dev *pcdev;
        struct resource *res;
        void __iomem *base;
-       unsigned int irq;
+       int irq;
        int err = 0;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_irq(pdev, 0);
-       if (!res || !irq) {
+       if (!res || irq < 0) {
                err = -ENODEV;
                goto exit;
        }
index ba3082422a01915dce20bce15832c495e9555d89..f118de6e36722950b43b5cb21d64520a32386f1f 100644 (file)
@@ -613,9 +613,15 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        snd_card_saa7134_pcm_t *pcm;
        snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
-       struct saa7134_dev *dev = saa7134->dev;
+       struct saa7134_dev *dev;
        int amux, err;
 
+       if (!saa7134) {
+               printk(KERN_ERR "BUG: saa7134 can't find device struct."
+                               " Can't proceed with open\n");
+               return -ENODEV;
+       }
+       dev = saa7134->dev;
        mutex_lock(&dev->dmasound.lock);
 
        dev->dmasound.read_count  = 0;
index b111903aa322cd287a4d5ca0041396242b7e6c43..2618cfa592e7067287407a403f9501213575b8d0 100644 (file)
@@ -4114,11 +4114,7 @@ struct saa7134_board saa7134_boards[] = {
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
-                /*
-                   TODO:
                 .mpeg           = SAA7134_MPEG_DVB,
-                */
-
                 .inputs         = {{
                         .name = name_tv,
                         .vmux = 1,
@@ -4157,7 +4153,7 @@ struct saa7134_board saa7134_boards[] = {
                } },
                .radio = {
                        .name = name_radio,
-                       .amux = LINE1,
+                       .amux = TV,
                },
        },
        [SAA7134_BOARD_AVERMEDIA_M115] = {
@@ -4167,6 +4163,7 @@ struct saa7134_board saa7134_boards[] = {
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
                .inputs         = {{
                        .name = name_tv,
                        .vmux = 1,
@@ -5351,22 +5348,21 @@ static int saa7134_xc2028_callback(struct saa7134_dev *dev,
 {
        switch (command) {
        case XC2028_TUNER_RESET:
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
-               mdelay(250);
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0);
-               mdelay(250);
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
-               mdelay(250);
-               saa_andorl(SAA7133_ANALOG_IO_SELECT >> 2, 0x02, 0x02);
-               saa_andorl(SAA7134_ANALOG_IN_CTRL1 >> 2, 0x81, 0x81);
-               saa_andorl(SAA7134_AUDIO_CLOCK0 >> 2, 0x03187de7, 0x03187de7);
-               saa_andorl(SAA7134_AUDIO_PLL_CTRL >> 2, 0x03, 0x03);
-               saa_andorl(SAA7134_AUDIO_CLOCKS_PER_FIELD0 >> 2,
-                          0x0001e000, 0x0001e000);
-               return 0;
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00000000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000);
+               switch (dev->board) {
+               case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+                       saa7134_set_gpio(dev, 23, 0);
+                       msleep(10);
+                       saa7134_set_gpio(dev, 23, 1);
+               break;
+               case SAA7134_BOARD_AVERMEDIA_A16D:
+                       saa7134_set_gpio(dev, 21, 0);
+                       msleep(10);
+                       saa7134_set_gpio(dev, 21, 1);
+               break;
+               }
+       return 0;
        }
        return -EINVAL;
 }
@@ -5553,9 +5549,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
                saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000);
                break;
        case SAA7134_BOARD_AVERMEDIA_CARDBUS:
-       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
        case SAA7134_BOARD_AVERMEDIA_M115:
-       case SAA7134_BOARD_AVERMEDIA_A16D:
                /* power-down tuner chip */
                saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0xffffffff, 0);
                saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0);
@@ -5565,6 +5559,18 @@ int saa7134_board_init1(struct saa7134_dev *dev)
                saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff);
                msleep(10);
                break;
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+               saa7134_set_gpio(dev, 23, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 23, 1);
+               break;
+       case SAA7134_BOARD_AVERMEDIA_A16D:
+               saa7134_set_gpio(dev, 21, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 21, 1);
+               msleep(1);
+               dev->has_remote = SAA7134_REMOTE_GPIO;
+               break;
        case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
                /* power-down tuner chip */
                saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x000A8004, 0x000A8004);
@@ -5615,7 +5621,8 @@ int saa7134_board_init1(struct saa7134_dev *dev)
                saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x80040100, 0x80040100);
                saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100);
                printk("%s: %s: hybrid analog/dvb card\n"
-                      "%s: Sorry, only the analog inputs are supported for now.\n",
+                      "%s: Sorry, only analog s-video and composite input "
+                      "are supported for now.\n",
                        dev->name, card(dev).name, dev->name);
                break;
        }
@@ -5675,6 +5682,7 @@ static void saa7134_tuner_setup(struct saa7134_dev *dev)
 
                switch (dev->board) {
                case SAA7134_BOARD_AVERMEDIA_A16D:
+               case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
                        ctl.demod = XC3028_FE_ZARLINK456;
                        break;
                default:
index 469f93aac0083a1e049cb55bc27ed985ca31596d..341b101b0357d457003438ecaa210d16640dc580 100644 (file)
@@ -153,12 +153,12 @@ static int mt352_aver777_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int mt352_aver_a16d_init(struct dvb_frontend *fe)
+static int mt352_avermedia_xc3028_init(struct dvb_frontend *fe)
 {
-       static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x2d };
-       static u8 reset []         = { RESET,      0x80 };
-       static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
-       static u8 agc_cfg []       = { AGC_TARGET, 0x28, 0xa0 };
+       static u8 clock_config []  = { CLOCK_CTL, 0x38, 0x2d };
+       static u8 reset []         = { RESET, 0x80 };
+       static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+       static u8 agc_cfg []       = { AGC_TARGET, 0xe };
        static u8 capt_range_cfg[] = { CAPT_RANGE, 0x33 };
 
        mt352_write(fe, clock_config,   sizeof(clock_config));
@@ -167,12 +167,9 @@ static int mt352_aver_a16d_init(struct dvb_frontend *fe)
        mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
        mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
        mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
-
        return 0;
 }
 
-
-
 static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
                                           struct dvb_frontend_parameters* params)
 {
@@ -215,14 +212,10 @@ static struct mt352_config avermedia_777 = {
        .demod_init    = mt352_aver777_init,
 };
 
-static struct mt352_config avermedia_16d = {
-       .demod_address = 0xf,
-       .demod_init    = mt352_aver_a16d_init,
-};
-
-static struct mt352_config avermedia_e506r_mt352_dev = {
+static struct mt352_config avermedia_xc3028_mt352_dev = {
        .demod_address   = (0x1e >> 1),
        .no_tuner        = 1,
+       .demod_init      = mt352_avermedia_xc3028_init,
 };
 
 /* ==================================================================
@@ -975,9 +968,10 @@ static int dvb_init(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_AVERMEDIA_A16D:
-               dprintk("avertv A16D dvb setup\n");
-               dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_16d,
-                                              &dev->i2c_adap);
+               dprintk("AverMedia A16D dvb setup\n");
+               dev->dvb.frontend = dvb_attach(mt352_attach,
+                                               &avermedia_xc3028_mt352_dev,
+                                               &dev->i2c_adap);
                attach_xc3028 = 1;
                break;
        case SAA7134_BOARD_MD7134:
@@ -1091,7 +1085,8 @@ static int dvb_init(struct saa7134_dev *dev)
                                        ads_tech_duo_config.tuner_address);
                                goto dettach_frontend;
                        }
-               }
+               } else
+                       wprintk("failed to attach tda10046\n");
                break;
        case SAA7134_BOARD_TEVION_DVBT_220RF:
                if (configure_tda827x_fe(dev, &tevion_dvbt220rf_config,
@@ -1260,11 +1255,14 @@ static int dvb_init(struct saa7134_dev *dev)
                        goto dettach_frontend;
                break;
        case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+               dprintk("AverMedia E506R dvb setup\n");
+               saa7134_set_gpio(dev, 25, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 25, 1);
                dev->dvb.frontend = dvb_attach(mt352_attach,
-                                              &avermedia_e506r_mt352_dev,
-                                              &dev->i2c_adap);
+                                               &avermedia_xc3028_mt352_dev,
+                                               &dev->i2c_adap);
                attach_xc3028 = 1;
-               break;
        case SAA7134_BOARD_MD7134_BRIDGE_2:
                dev->dvb.frontend = dvb_attach(tda10086_attach,
                                                &sd1878_4m, &dev->i2c_adap);
@@ -1338,7 +1336,8 @@ static int dvb_init(struct saa7134_dev *dev)
        return ret;
 
 dettach_frontend:
-       dvb_frontend_detach(dev->dvb.frontend);
+       if (dev->dvb.frontend)
+               dvb_frontend_detach(dev->dvb.frontend);
        dev->dvb.frontend = NULL;
 
        return -1;
index 81431ee418426894f5c285fdfef6f4609f2294a5..3ae71a3408223800ce442efc413c8589bb18ae4a 100644 (file)
@@ -110,9 +110,10 @@ static int ts_release(struct inode *inode, struct file *file)
 {
        struct saa7134_dev *dev = file->private_data;
 
+       mutex_lock(&dev->empress_tsq.vb_lock);
+
        videobuf_stop(&dev->empress_tsq);
        videobuf_mmap_free(&dev->empress_tsq);
-       dev->empress_users--;
 
        /* stop the encoder */
        ts_reset_encoder(dev);
@@ -121,6 +122,10 @@ static int ts_release(struct inode *inode, struct file *file)
        saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
                saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
 
+       dev->empress_users--;
+
+       mutex_unlock(&dev->empress_tsq.vb_lock);
+
        return 0;
 }
 
@@ -218,8 +223,7 @@ static int empress_enum_fmt_cap(struct file *file, void  *priv,
 static int empress_g_fmt_cap(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_dev *dev = file->private_data;
 
        saa7134_i2c_call_clients(dev, VIDIOC_G_FMT, f);
 
@@ -232,8 +236,7 @@ static int empress_g_fmt_cap(struct file *file, void *priv,
 static int empress_s_fmt_cap(struct file *file, void *priv,
                                struct v4l2_format *f)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_dev *dev = file->private_data;
 
        saa7134_i2c_call_clients(dev, VIDIOC_S_FMT, f);
 
@@ -247,8 +250,7 @@ static int empress_s_fmt_cap(struct file *file, void *priv,
 static int empress_reqbufs(struct file *file, void *priv,
                                        struct v4l2_requestbuffers *p)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_dev *dev = file->private_data;
 
        return videobuf_reqbufs(&dev->empress_tsq, p);
 }
@@ -256,24 +258,21 @@ static int empress_reqbufs(struct file *file, void *priv,
 static int empress_querybuf(struct file *file, void *priv,
                                        struct v4l2_buffer *b)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_dev *dev = file->private_data;
 
        return videobuf_querybuf(&dev->empress_tsq, b);
 }
 
 static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_dev *dev = file->private_data;
 
        return videobuf_qbuf(&dev->empress_tsq, b);
 }
 
 static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_dev *dev = file->private_data;
 
        return videobuf_dqbuf(&dev->empress_tsq, b,
                                file->f_flags & O_NONBLOCK);
@@ -282,8 +281,7 @@ static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 static int empress_streamon(struct file *file, void *priv,
                                        enum v4l2_buf_type type)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_dev *dev = file->private_data;
 
        return videobuf_streamon(&dev->empress_tsq);
 }
@@ -291,8 +289,7 @@ static int empress_streamon(struct file *file, void *priv,
 static int empress_streamoff(struct file *file, void *priv,
                                        enum v4l2_buf_type type)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_dev *dev = file->private_data;
 
        return videobuf_streamoff(&dev->empress_tsq);
 }
@@ -300,8 +297,7 @@ static int empress_streamoff(struct file *file, void *priv,
 static int empress_s_ext_ctrls(struct file *file, void *priv,
                               struct v4l2_ext_controls *ctrls)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_dev *dev = file->private_data;
 
        /* count == 0 is abused in saa6752hs.c, so that special
                case is handled here explicitly. */
@@ -320,8 +316,7 @@ static int empress_s_ext_ctrls(struct file *file, void *priv,
 static int empress_g_ext_ctrls(struct file *file, void *priv,
                               struct v4l2_ext_controls *ctrls)
 {
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_dev *dev = file->private_data;
 
        if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
                return -EINVAL;
index 919632b10aae0ed20510fc68c2d89e944117b00c..76e6501d238d0d31ddaf68305484de9faa9c6368 100644 (file)
@@ -323,6 +323,15 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
                saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
                break;
+       case SAA7134_BOARD_AVERMEDIA_A16D:
+               ir_codes     = ir_codes_avermedia_a16d;
+               mask_keycode = 0x02F200;
+               mask_keydown = 0x000400;
+               polling      = 50; /* ms */
+               /* Without this we won't receive key up events */
+               saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
+               saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
+               break;
        case SAA7134_BOARD_KWORLD_TERMINATOR:
                ir_codes     = ir_codes_pixelview;
                mask_keycode = 0x00001f;
index a1b92446c8b4ac78052a4849e23a9f428ccba2c1..d015bfe00950c5fcf1a943154cb6413ce8db60f5 100644 (file)
@@ -763,15 +763,6 @@ static struct device_driver ic_drv = {
        .owner  = THIS_MODULE,
 };
 
-/*
- * Image capture host - this is a host device, not a bus device, so,
- * no bus reference, no probing.
- */
-static struct class soc_camera_host_class = {
-       .owner          = THIS_MODULE,
-       .name           = "camera_host",
-};
-
 static void dummy_release(struct device *dev)
 {
 }
@@ -801,7 +792,6 @@ int soc_camera_host_register(struct soc_camera_host *ici)
 
        /* Number might be equal to the platform device ID */
        sprintf(ici->dev.bus_id, "camera_host%d", ici->nr);
-       ici->dev.class = &soc_camera_host_class;
 
        mutex_lock(&list_lock);
        list_for_each_entry(ix, &hosts, list) {
@@ -1003,14 +993,9 @@ static int __init soc_camera_init(void)
        ret = driver_register(&ic_drv);
        if (ret)
                goto edrvr;
-       ret = class_register(&soc_camera_host_class);
-       if (ret)
-               goto eclr;
 
        return 0;
 
-eclr:
-       driver_unregister(&ic_drv);
 edrvr:
        bus_unregister(&soc_camera_bus_type);
        return ret;
@@ -1018,7 +1003,6 @@ edrvr:
 
 static void __exit soc_camera_exit(void)
 {
-       class_unregister(&soc_camera_host_class);
        driver_unregister(&ic_drv);
        bus_unregister(&soc_camera_bus_type);
 }
diff --git a/drivers/media/video/uvc/Makefile b/drivers/media/video/uvc/Makefile
new file mode 100644 (file)
index 0000000..968c199
--- /dev/null
@@ -0,0 +1,3 @@
+uvcvideo-objs  := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \
+                 uvc_status.o uvc_isight.o
+obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
new file mode 100644 (file)
index 0000000..f0ee46d
--- /dev/null
@@ -0,0 +1,1256 @@
+/*
+ *      uvc_ctrl.c  --  USB Video Class driver - Controls
+ *
+ *      Copyright (C) 2005-2008
+ *          Laurent Pinchart (laurent.pinchart@skynet.be)
+ *
+ *      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/kernel.h>
+#include <linux/version.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+#include <asm/atomic.h>
+
+#include "uvcvideo.h"
+
+#define UVC_CTRL_NDATA         2
+#define UVC_CTRL_DATA_CURRENT  0
+#define UVC_CTRL_DATA_BACKUP   1
+
+/* ------------------------------------------------------------------------
+ * Control, formats, ...
+ */
+
+static struct uvc_control_info uvc_ctrls[] = {
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_BRIGHTNESS_CONTROL,
+               .index          = 0,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_CONTRAST_CONTROL,
+               .index          = 1,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_HUE_CONTROL,
+               .index          = 2,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_SATURATION_CONTROL,
+               .index          = 3,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_SHARPNESS_CONTROL,
+               .index          = 4,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_GAMMA_CONTROL,
+               .index          = 5,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_BACKLIGHT_COMPENSATION_CONTROL,
+               .index          = 8,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_GAIN_CONTROL,
+               .index          = 9,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_POWER_LINE_FREQUENCY_CONTROL,
+               .index          = 10,
+               .size           = 1,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_HUE_AUTO_CONTROL,
+               .index          = 11,
+               .size           = 1,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+                               | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_AE_MODE_CONTROL,
+               .index          = 1,
+               .size           = 1,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+                               | UVC_CONTROL_GET_DEF | UVC_CONTROL_GET_RES
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_AE_PRIORITY_CONTROL,
+               .index          = 2,
+               .size           = 1,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
+               .index          = 3,
+               .size           = 4,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_FOCUS_ABSOLUTE_CONTROL,
+               .index          = 5,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_FOCUS_AUTO_CONTROL,
+               .index          = 17,
+               .size           = 1,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+                               | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
+               .index          = 12,
+               .size           = 1,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+                               | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
+               .index          = 6,
+               .size           = 2,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
+               .index          = 13,
+               .size           = 1,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR
+                               | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_COMPONENT_CONTROL,
+               .index          = 7,
+               .size           = 4,
+               .flags          = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE
+                               | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE,
+       },
+};
+
+static struct uvc_menu_info power_line_frequency_controls[] = {
+       { 0, "Disabled" },
+       { 1, "50 Hz" },
+       { 2, "60 Hz" },
+};
+
+static struct uvc_menu_info exposure_auto_controls[] = {
+       { 1, "Manual Mode" },
+       { 2, "Auto Mode" },
+       { 4, "Shutter Priority Mode" },
+       { 8, "Aperture Priority Mode" },
+};
+
+static struct uvc_control_mapping uvc_ctrl_mappings[] = {
+       {
+               .id             = V4L2_CID_BRIGHTNESS,
+               .name           = "Brightness",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_BRIGHTNESS_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
+       },
+       {
+               .id             = V4L2_CID_CONTRAST,
+               .name           = "Contrast",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_CONTRAST_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_HUE,
+               .name           = "Hue",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_HUE_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
+       },
+       {
+               .id             = V4L2_CID_SATURATION,
+               .name           = "Saturation",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_SATURATION_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_SHARPNESS,
+               .name           = "Sharpness",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_SHARPNESS_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_GAMMA,
+               .name           = "Gamma",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_GAMMA_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_BACKLIGHT_COMPENSATION,
+               .name           = "Backlight Compensation",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_BACKLIGHT_COMPENSATION_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_GAIN,
+               .name           = "Gain",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_GAIN_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_POWER_LINE_FREQUENCY,
+               .name           = "Power Line Frequency",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_POWER_LINE_FREQUENCY_CONTROL,
+               .size           = 2,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_MENU,
+               .data_type      = UVC_CTRL_DATA_TYPE_ENUM,
+               .menu_info      = power_line_frequency_controls,
+               .menu_count     = ARRAY_SIZE(power_line_frequency_controls),
+       },
+       {
+               .id             = V4L2_CID_HUE_AUTO,
+               .name           = "Hue, Auto",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_HUE_AUTO_CONTROL,
+               .size           = 1,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
+               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
+       },
+       {
+               .id             = V4L2_CID_EXPOSURE_AUTO,
+               .name           = "Exposure, Auto",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_AE_MODE_CONTROL,
+               .size           = 4,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_MENU,
+               .data_type      = UVC_CTRL_DATA_TYPE_BITMASK,
+               .menu_info      = exposure_auto_controls,
+               .menu_count     = ARRAY_SIZE(exposure_auto_controls),
+       },
+       {
+               .id             = V4L2_CID_EXPOSURE_AUTO_PRIORITY,
+               .name           = "Exposure, Auto Priority",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_AE_PRIORITY_CONTROL,
+               .size           = 1,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
+               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
+       },
+       {
+               .id             = V4L2_CID_EXPOSURE_ABSOLUTE,
+               .name           = "Exposure (Absolute)",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
+               .size           = 32,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_AUTO_WHITE_BALANCE,
+               .name           = "White Balance Temperature, Auto",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
+               .size           = 1,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
+               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
+       },
+       {
+               .id             = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
+               .name           = "White Balance Temperature",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_AUTO_WHITE_BALANCE,
+               .name           = "White Balance Component, Auto",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
+               .size           = 1,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
+               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
+       },
+       {
+               .id             = V4L2_CID_BLUE_BALANCE,
+               .name           = "White Balance Blue Component",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_COMPONENT_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
+       },
+       {
+               .id             = V4L2_CID_RED_BALANCE,
+               .name           = "White Balance Red Component",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = PU_WHITE_BALANCE_COMPONENT_CONTROL,
+               .size           = 16,
+               .offset         = 16,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
+       },
+       {
+               .id             = V4L2_CID_FOCUS_ABSOLUTE,
+               .name           = "Focus (absolute)",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_FOCUS_ABSOLUTE_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_FOCUS_AUTO,
+               .name           = "Focus, Auto",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = CT_FOCUS_AUTO_CONTROL,
+               .size           = 1,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
+               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
+       },
+};
+
+/* ------------------------------------------------------------------------
+ * Utility functions
+ */
+
+static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id)
+{
+       return ctrl->data + id * ctrl->info->size;
+}
+
+static inline int uvc_get_bit(const __u8 *data, int bit)
+{
+       return (data[bit >> 3] >> (bit & 7)) & 1;
+}
+
+/* Extract the bit string specified by mapping->offset and mapping->size
+ * from the little-endian data stored at 'data' and return the result as
+ * a signed 32bit integer. Sign extension will be performed if the mapping
+ * references a signed data type.
+ */
+static __s32 uvc_get_le_value(const __u8 *data,
+       struct uvc_control_mapping *mapping)
+{
+       int bits = mapping->size;
+       int offset = mapping->offset;
+       __s32 value = 0;
+       __u8 mask;
+
+       data += offset / 8;
+       offset &= 7;
+       mask = ((1LL << bits) - 1) << offset;
+
+       for (; bits > 0; data++) {
+               __u8 byte = *data & mask;
+               value |= offset > 0 ? (byte >> offset) : (byte << (-offset));
+               bits -= 8 - (offset > 0 ? offset : 0);
+               offset -= 8;
+               mask = (1 << bits) - 1;
+       }
+
+       /* Sign-extend the value if needed */
+       if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
+               value |= -(value & (1 << (mapping->size - 1)));
+
+       return value;
+}
+
+/* Set the bit string specified by mapping->offset and mapping->size
+ * in the little-endian data stored at 'data' to the value 'value'.
+ */
+static void uvc_set_le_value(__s32 value, __u8 *data,
+       struct uvc_control_mapping *mapping)
+{
+       int bits = mapping->size;
+       int offset = mapping->offset;
+       __u8 mask;
+
+       data += offset / 8;
+       offset &= 7;
+
+       for (; bits > 0; data++) {
+               mask = ((1LL << bits) - 1) << offset;
+               *data = (*data & ~mask) | ((value << offset) & mask);
+               value >>= offset ? offset : 8;
+               bits -= 8 - offset;
+               offset = 0;
+       }
+}
+
+/* ------------------------------------------------------------------------
+ * Terminal and unit management
+ */
+
+static const __u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING;
+static const __u8 uvc_camera_guid[16] = UVC_GUID_UVC_CAMERA;
+static const __u8 uvc_media_transport_input_guid[16] =
+       UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT;
+
+static int uvc_entity_match_guid(struct uvc_entity *entity, __u8 guid[16])
+{
+       switch (UVC_ENTITY_TYPE(entity)) {
+       case ITT_CAMERA:
+               return memcmp(uvc_camera_guid, guid, 16) == 0;
+
+       case ITT_MEDIA_TRANSPORT_INPUT:
+               return memcmp(uvc_media_transport_input_guid, guid, 16) == 0;
+
+       case VC_PROCESSING_UNIT:
+               return memcmp(uvc_processing_guid, guid, 16) == 0;
+
+       case VC_EXTENSION_UNIT:
+               return memcmp(entity->extension.guidExtensionCode,
+                             guid, 16) == 0;
+
+       default:
+               return 0;
+       }
+}
+
+/* ------------------------------------------------------------------------
+ * UVC Controls
+ */
+
+static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id,
+       struct uvc_control_mapping **mapping, struct uvc_control **control,
+       int next)
+{
+       struct uvc_control *ctrl;
+       struct uvc_control_mapping *map;
+       unsigned int i;
+
+       if (entity == NULL)
+               return;
+
+       for (i = 0; i < entity->ncontrols; ++i) {
+               ctrl = &entity->controls[i];
+               if (ctrl->info == NULL)
+                       continue;
+
+               list_for_each_entry(map, &ctrl->info->mappings, list) {
+                       if ((map->id == v4l2_id) && !next) {
+                               *control = ctrl;
+                               *mapping = map;
+                               return;
+                       }
+
+                       if ((*mapping == NULL || (*mapping)->id > map->id) &&
+                           (map->id > v4l2_id) && next) {
+                               *control = ctrl;
+                               *mapping = map;
+                       }
+               }
+       }
+}
+
+struct uvc_control *uvc_find_control(struct uvc_video_device *video,
+       __u32 v4l2_id, struct uvc_control_mapping **mapping)
+{
+       struct uvc_control *ctrl = NULL;
+       struct uvc_entity *entity;
+       int next = v4l2_id & V4L2_CTRL_FLAG_NEXT_CTRL;
+
+       *mapping = NULL;
+
+       /* Mask the query flags. */
+       v4l2_id &= V4L2_CTRL_ID_MASK;
+
+       /* Find the control. */
+       __uvc_find_control(video->processing, v4l2_id, mapping, &ctrl, next);
+       if (ctrl && !next)
+               return ctrl;
+
+       list_for_each_entry(entity, &video->iterms, chain) {
+               __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
+               if (ctrl && !next)
+                       return ctrl;
+       }
+
+       list_for_each_entry(entity, &video->extensions, chain) {
+               __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
+               if (ctrl && !next)
+                       return ctrl;
+       }
+
+       if (ctrl == NULL && !next)
+               uvc_trace(UVC_TRACE_CONTROL, "Control 0x%08x not found.\n",
+                               v4l2_id);
+
+       return ctrl;
+}
+
+int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
+       struct v4l2_queryctrl *v4l2_ctrl)
+{
+       struct uvc_control *ctrl;
+       struct uvc_control_mapping *mapping;
+       struct uvc_menu_info *menu;
+       unsigned int i;
+       __u8 data[8];
+       int ret;
+
+       ctrl = uvc_find_control(video, v4l2_ctrl->id, &mapping);
+       if (ctrl == NULL)
+               return -EINVAL;
+
+       v4l2_ctrl->id = mapping->id;
+       v4l2_ctrl->type = mapping->v4l2_type;
+       strncpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name);
+       v4l2_ctrl->flags = 0;
+
+       if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR))
+               v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+       if (ctrl->info->flags & UVC_CONTROL_GET_DEF) {
+               if ((ret = uvc_query_ctrl(video->dev, GET_DEF, ctrl->entity->id,
+                               video->dev->intfnum, ctrl->info->selector,
+                               &data, ctrl->info->size)) < 0)
+                       return ret;
+               v4l2_ctrl->default_value = uvc_get_le_value(data, mapping);
+       }
+
+       if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
+               v4l2_ctrl->minimum = 0;
+               v4l2_ctrl->maximum = mapping->menu_count - 1;
+               v4l2_ctrl->step = 1;
+
+               menu = mapping->menu_info;
+               for (i = 0; i < mapping->menu_count; ++i, ++menu) {
+                       if (menu->value == v4l2_ctrl->default_value) {
+                               v4l2_ctrl->default_value = i;
+                               break;
+                       }
+               }
+
+               return 0;
+       }
+
+       if (ctrl->info->flags & UVC_CONTROL_GET_MIN) {
+               if ((ret = uvc_query_ctrl(video->dev, GET_MIN, ctrl->entity->id,
+                               video->dev->intfnum, ctrl->info->selector,
+                               &data, ctrl->info->size)) < 0)
+                       return ret;
+               v4l2_ctrl->minimum = uvc_get_le_value(data, mapping);
+       }
+       if (ctrl->info->flags & UVC_CONTROL_GET_MAX) {
+               if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id,
+                               video->dev->intfnum, ctrl->info->selector,
+                               &data, ctrl->info->size)) < 0)
+                       return ret;
+               v4l2_ctrl->maximum = uvc_get_le_value(data, mapping);
+       }
+       if (ctrl->info->flags & UVC_CONTROL_GET_RES) {
+               if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id,
+                               video->dev->intfnum, ctrl->info->selector,
+                               &data, ctrl->info->size)) < 0)
+                       return ret;
+               v4l2_ctrl->step = uvc_get_le_value(data, mapping);
+       }
+
+       return 0;
+}
+
+
+/* --------------------------------------------------------------------------
+ * Control transactions
+ *
+ * To make extended set operations as atomic as the hardware allows, controls
+ * are handled using begin/commit/rollback operations.
+ *
+ * At the beginning of a set request, uvc_ctrl_begin should be called to
+ * initialize the request. This function acquires the control lock.
+ *
+ * When setting a control, the new value is stored in the control data field
+ * at position UVC_CTRL_DATA_CURRENT. The control is then marked as dirty for
+ * later processing. If the UVC and V4L2 control sizes differ, the current
+ * value is loaded from the hardware before storing the new value in the data
+ * field.
+ *
+ * After processing all controls in the transaction, uvc_ctrl_commit or
+ * uvc_ctrl_rollback must be called to apply the pending changes to the
+ * hardware or revert them. When applying changes, all controls marked as
+ * dirty will be modified in the UVC device, and the dirty flag will be
+ * cleared. When reverting controls, the control data field
+ * UVC_CTRL_DATA_CURRENT is reverted to its previous value
+ * (UVC_CTRL_DATA_BACKUP) for all dirty controls. Both functions release the
+ * control lock.
+ */
+int uvc_ctrl_begin(struct uvc_video_device *video)
+{
+       return mutex_lock_interruptible(&video->ctrl_mutex) ? -ERESTARTSYS : 0;
+}
+
+static int uvc_ctrl_commit_entity(struct uvc_device *dev,
+       struct uvc_entity *entity, int rollback)
+{
+       struct uvc_control *ctrl;
+       unsigned int i;
+       int ret;
+
+       if (entity == NULL)
+               return 0;
+
+       for (i = 0; i < entity->ncontrols; ++i) {
+               ctrl = &entity->controls[i];
+               if (ctrl->info == NULL || !ctrl->dirty)
+                       continue;
+
+               if (!rollback)
+                       ret = uvc_query_ctrl(dev, SET_CUR, ctrl->entity->id,
+                               dev->intfnum, ctrl->info->selector,
+                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                               ctrl->info->size);
+               else
+                       ret = 0;
+
+               if (rollback || ret < 0)
+                       memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                              uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
+                              ctrl->info->size);
+
+               if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0)
+                       ctrl->loaded = 0;
+
+               ctrl->dirty = 0;
+
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+int __uvc_ctrl_commit(struct uvc_video_device *video, int rollback)
+{
+       struct uvc_entity *entity;
+       int ret = 0;
+
+       /* Find the control. */
+       ret = uvc_ctrl_commit_entity(video->dev, video->processing, rollback);
+       if (ret < 0)
+               goto done;
+
+       list_for_each_entry(entity, &video->iterms, chain) {
+               ret = uvc_ctrl_commit_entity(video->dev, entity, rollback);
+               if (ret < 0)
+                       goto done;
+       }
+
+       list_for_each_entry(entity, &video->extensions, chain) {
+               ret = uvc_ctrl_commit_entity(video->dev, entity, rollback);
+               if (ret < 0)
+                       goto done;
+       }
+
+done:
+       mutex_unlock(&video->ctrl_mutex);
+       return ret;
+}
+
+int uvc_ctrl_get(struct uvc_video_device *video,
+       struct v4l2_ext_control *xctrl)
+{
+       struct uvc_control *ctrl;
+       struct uvc_control_mapping *mapping;
+       struct uvc_menu_info *menu;
+       unsigned int i;
+       int ret;
+
+       ctrl = uvc_find_control(video, xctrl->id, &mapping);
+       if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0)
+               return -EINVAL;
+
+       if (!ctrl->loaded) {
+               ret = uvc_query_ctrl(video->dev, GET_CUR, ctrl->entity->id,
+                               video->dev->intfnum, ctrl->info->selector,
+                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                               ctrl->info->size);
+               if (ret < 0)
+                       return ret;
+
+               if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0)
+                       ctrl->loaded = 1;
+       }
+
+       xctrl->value = uvc_get_le_value(
+               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping);
+
+       if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
+               menu = mapping->menu_info;
+               for (i = 0; i < mapping->menu_count; ++i, ++menu) {
+                       if (menu->value == xctrl->value) {
+                               xctrl->value = i;
+                               break;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+int uvc_ctrl_set(struct uvc_video_device *video,
+       struct v4l2_ext_control *xctrl)
+{
+       struct uvc_control *ctrl;
+       struct uvc_control_mapping *mapping;
+       s32 value = xctrl->value;
+       int ret;
+
+       ctrl = uvc_find_control(video, xctrl->id, &mapping);
+       if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_SET_CUR) == 0)
+               return -EINVAL;
+
+       if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
+               if (value < 0 || value >= mapping->menu_count)
+                       return -EINVAL;
+               value = mapping->menu_info[value].value;
+       }
+
+       if (!ctrl->loaded && (ctrl->info->size * 8) != mapping->size) {
+               if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) {
+                       memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                               0, ctrl->info->size);
+               } else {
+                       ret = uvc_query_ctrl(video->dev, GET_CUR,
+                               ctrl->entity->id, video->dev->intfnum,
+                               ctrl->info->selector,
+                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                               ctrl->info->size);
+                       if (ret < 0)
+                               return ret;
+               }
+
+               if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0)
+                       ctrl->loaded = 1;
+       }
+
+       if (!ctrl->dirty) {
+               memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
+                      uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                      ctrl->info->size);
+       }
+
+       uvc_set_le_value(value,
+               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping);
+
+       ctrl->dirty = 1;
+       ctrl->modified = 1;
+       return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * Dynamic controls
+ */
+
+int uvc_xu_ctrl_query(struct uvc_video_device *video,
+       struct uvc_xu_control *xctrl, int set)
+{
+       struct uvc_entity *entity;
+       struct uvc_control *ctrl = NULL;
+       unsigned int i, found = 0;
+       __u8 *data;
+       int ret;
+
+       /* Find the extension unit. */
+       list_for_each_entry(entity, &video->extensions, chain) {
+               if (entity->id == xctrl->unit)
+                       break;
+       }
+
+       if (entity->id != xctrl->unit) {
+               uvc_trace(UVC_TRACE_CONTROL, "Extension unit %u not found.\n",
+                       xctrl->unit);
+               return -EINVAL;
+       }
+
+       /* Find the control. */
+       for (i = 0; i < entity->ncontrols; ++i) {
+               ctrl = &entity->controls[i];
+               if (ctrl->info == NULL)
+                       continue;
+
+               if (ctrl->info->selector == xctrl->selector) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (!found) {
+               uvc_trace(UVC_TRACE_CONTROL,
+                       "Control " UVC_GUID_FORMAT "/%u not found.\n",
+                       UVC_GUID_ARGS(entity->extension.guidExtensionCode),
+                       xctrl->selector);
+               return -EINVAL;
+       }
+
+       /* Validate control data size. */
+       if (ctrl->info->size != xctrl->size)
+               return -EINVAL;
+
+       if ((set && !(ctrl->info->flags & UVC_CONTROL_SET_CUR)) ||
+           (!set && !(ctrl->info->flags & UVC_CONTROL_GET_CUR)))
+               return -EINVAL;
+
+       if (mutex_lock_interruptible(&video->ctrl_mutex))
+               return -ERESTARTSYS;
+
+       memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
+              uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+              xctrl->size);
+       data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT);
+
+       if (set && copy_from_user(data, xctrl->data, xctrl->size)) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       ret = uvc_query_ctrl(video->dev, set ? SET_CUR : GET_CUR, xctrl->unit,
+                            video->dev->intfnum, xctrl->selector, data,
+                            xctrl->size);
+       if (ret < 0)
+               goto out;
+
+       if (!set && copy_to_user(xctrl->data, data, xctrl->size)) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+out:
+       if (ret)
+               memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                      uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
+                      xctrl->size);
+
+       mutex_unlock(&video->ctrl_mutex);
+       return ret;
+}
+
+/* --------------------------------------------------------------------------
+ * Suspend/resume
+ */
+
+/*
+ * Restore control values after resume, skipping controls that haven't been
+ * changed.
+ *
+ * TODO
+ * - Don't restore modified controls that are back to their default value.
+ * - Handle restore order (Auto-Exposure Mode should be restored before
+ *   Exposure Time).
+ */
+int uvc_ctrl_resume_device(struct uvc_device *dev)
+{
+       struct uvc_control *ctrl;
+       struct uvc_entity *entity;
+       unsigned int i;
+       int ret;
+
+       /* Walk the entities list and restore controls when possible. */
+       list_for_each_entry(entity, &dev->entities, list) {
+
+               for (i = 0; i < entity->ncontrols; ++i) {
+                       ctrl = &entity->controls[i];
+
+                       if (ctrl->info == NULL || !ctrl->modified ||
+                           (ctrl->info->flags & UVC_CONTROL_RESTORE) == 0)
+                               continue;
+
+                       printk(KERN_INFO "restoring control " UVC_GUID_FORMAT
+                               "/%u/%u\n", UVC_GUID_ARGS(ctrl->info->entity),
+                               ctrl->info->index, ctrl->info->selector);
+                       ctrl->dirty = 1;
+               }
+
+               ret = uvc_ctrl_commit_entity(dev, entity, 0);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * Control and mapping handling
+ */
+
+static void uvc_ctrl_add_ctrl(struct uvc_device *dev,
+       struct uvc_control_info *info)
+{
+       struct uvc_entity *entity;
+       struct uvc_control *ctrl = NULL;
+       int ret, found = 0;
+       unsigned int i;
+
+       list_for_each_entry(entity, &dev->entities, list) {
+               if (!uvc_entity_match_guid(entity, info->entity))
+                       continue;
+
+               for (i = 0; i < entity->ncontrols; ++i) {
+                       ctrl = &entity->controls[i];
+                       if (ctrl->index == info->index) {
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (found)
+                       break;
+       }
+
+       if (!found)
+               return;
+
+       if (UVC_ENTITY_TYPE(entity) == VC_EXTENSION_UNIT) {
+               /* Check if the device control information and length match
+                * the user supplied information.
+                */
+               __u32 flags;
+               __le16 size;
+               __u8 inf;
+
+               if ((ret = uvc_query_ctrl(dev, GET_LEN, ctrl->entity->id,
+                       dev->intfnum, info->selector, (__u8 *)&size, 2)) < 0) {
+                       uvc_trace(UVC_TRACE_CONTROL, "GET_LEN failed on "
+                               "control " UVC_GUID_FORMAT "/%u (%d).\n",
+                               UVC_GUID_ARGS(info->entity), info->selector,
+                               ret);
+                       return;
+               }
+
+               if (info->size != le16_to_cpu(size)) {
+                       uvc_trace(UVC_TRACE_CONTROL, "Control " UVC_GUID_FORMAT
+                               "/%u size doesn't match user supplied "
+                               "value.\n", UVC_GUID_ARGS(info->entity),
+                               info->selector);
+                       return;
+               }
+
+               if ((ret = uvc_query_ctrl(dev, GET_INFO, ctrl->entity->id,
+                       dev->intfnum, info->selector, &inf, 1)) < 0) {
+                       uvc_trace(UVC_TRACE_CONTROL, "GET_INFO failed on "
+                               "control " UVC_GUID_FORMAT "/%u (%d).\n",
+                               UVC_GUID_ARGS(info->entity), info->selector,
+                               ret);
+                       return;
+               }
+
+               flags = info->flags;
+               if (((flags & UVC_CONTROL_GET_CUR) && !(inf & (1 << 0))) ||
+                   ((flags & UVC_CONTROL_SET_CUR) && !(inf & (1 << 1)))) {
+                       uvc_trace(UVC_TRACE_CONTROL, "Control "
+                               UVC_GUID_FORMAT "/%u flags don't match "
+                               "supported operations.\n",
+                               UVC_GUID_ARGS(info->entity), info->selector);
+                       return;
+               }
+       }
+
+       ctrl->info = info;
+       ctrl->data = kmalloc(ctrl->info->size * UVC_CTRL_NDATA, GFP_KERNEL);
+       uvc_trace(UVC_TRACE_CONTROL, "Added control " UVC_GUID_FORMAT "/%u "
+               "to device %s entity %u\n", UVC_GUID_ARGS(ctrl->info->entity),
+               ctrl->info->selector, dev->udev->devpath, entity->id);
+}
+
+/*
+ * Add an item to the UVC control information list, and instantiate a control
+ * structure for each device that supports the control.
+ */
+int uvc_ctrl_add_info(struct uvc_control_info *info)
+{
+       struct uvc_control_info *ctrl;
+       struct uvc_device *dev;
+       int ret = 0;
+
+       /* Find matching controls by walking the devices, entities and
+        * controls list.
+        */
+       mutex_lock(&uvc_driver.ctrl_mutex);
+
+       /* First check if the list contains a control matching the new one.
+        * Bail out if it does.
+        */
+       list_for_each_entry(ctrl, &uvc_driver.controls, list) {
+               if (memcmp(ctrl->entity, info->entity, 16))
+                       continue;
+
+               if (ctrl->selector == info->selector) {
+                       uvc_trace(UVC_TRACE_CONTROL, "Control "
+                               UVC_GUID_FORMAT "/%u is already defined.\n",
+                               UVC_GUID_ARGS(info->entity), info->selector);
+                       ret = -EEXIST;
+                       goto end;
+               }
+               if (ctrl->index == info->index) {
+                       uvc_trace(UVC_TRACE_CONTROL, "Control "
+                               UVC_GUID_FORMAT "/%u would overwrite index "
+                               "%d.\n", UVC_GUID_ARGS(info->entity),
+                               info->selector, info->index);
+                       ret = -EEXIST;
+                       goto end;
+               }
+       }
+
+       list_for_each_entry(dev, &uvc_driver.devices, list)
+               uvc_ctrl_add_ctrl(dev, info);
+
+       INIT_LIST_HEAD(&info->mappings);
+       list_add_tail(&info->list, &uvc_driver.controls);
+end:
+       mutex_unlock(&uvc_driver.ctrl_mutex);
+       return ret;
+}
+
+int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping)
+{
+       struct uvc_control_info *info;
+       struct uvc_control_mapping *map;
+       int ret = -EINVAL;
+
+       if (mapping->id & ~V4L2_CTRL_ID_MASK) {
+               uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s' with "
+                       "invalid control id 0x%08x\n", mapping->name,
+                       mapping->id);
+               return -EINVAL;
+       }
+
+       mutex_lock(&uvc_driver.ctrl_mutex);
+       list_for_each_entry(info, &uvc_driver.controls, list) {
+               if (memcmp(info->entity, mapping->entity, 16) ||
+                       info->selector != mapping->selector)
+                       continue;
+
+               if (info->size * 8 < mapping->size + mapping->offset) {
+                       uvc_trace(UVC_TRACE_CONTROL, "Mapping '%s' would "
+                               "overflow control " UVC_GUID_FORMAT "/%u\n",
+                               mapping->name, UVC_GUID_ARGS(info->entity),
+                               info->selector);
+                       ret = -EOVERFLOW;
+                       goto end;
+               }
+
+               /* Check if the list contains a mapping matching the new one.
+                * Bail out if it does.
+                */
+               list_for_each_entry(map, &info->mappings, list) {
+                       if (map->id == mapping->id) {
+                               uvc_trace(UVC_TRACE_CONTROL, "Mapping '%s' is "
+                                       "already defined.\n", mapping->name);
+                               ret = -EEXIST;
+                               goto end;
+                       }
+               }
+
+               mapping->ctrl = info;
+               list_add_tail(&mapping->list, &info->mappings);
+               uvc_trace(UVC_TRACE_CONTROL, "Adding mapping %s to control "
+                       UVC_GUID_FORMAT "/%u.\n", mapping->name,
+                       UVC_GUID_ARGS(info->entity), info->selector);
+
+               ret = 0;
+               break;
+       }
+end:
+       mutex_unlock(&uvc_driver.ctrl_mutex);
+       return ret;
+}
+
+/*
+ * Initialize device controls.
+ */
+int uvc_ctrl_init_device(struct uvc_device *dev)
+{
+       struct uvc_control_info *info;
+       struct uvc_control *ctrl;
+       struct uvc_entity *entity;
+       unsigned int i;
+
+       /* Walk the entities list and instantiate controls */
+       list_for_each_entry(entity, &dev->entities, list) {
+               unsigned int bControlSize = 0, ncontrols = 0;
+               __u8 *bmControls = NULL;
+
+               if (UVC_ENTITY_TYPE(entity) == VC_EXTENSION_UNIT) {
+                       bmControls = entity->extension.bmControls;
+                       bControlSize = entity->extension.bControlSize;
+               } else if (UVC_ENTITY_TYPE(entity) == VC_PROCESSING_UNIT) {
+                       bmControls = entity->processing.bmControls;
+                       bControlSize = entity->processing.bControlSize;
+               } else if (UVC_ENTITY_TYPE(entity) == ITT_CAMERA) {
+                       bmControls = entity->camera.bmControls;
+                       bControlSize = entity->camera.bControlSize;
+               }
+
+               for (i = 0; i < bControlSize; ++i)
+                       ncontrols += hweight8(bmControls[i]);
+
+               if (ncontrols == 0)
+                       continue;
+
+               entity->controls = kzalloc(ncontrols*sizeof *ctrl, GFP_KERNEL);
+               if (entity->controls == NULL)
+                       return -ENOMEM;
+
+               entity->ncontrols = ncontrols;
+
+               ctrl = entity->controls;
+               for (i = 0; i < bControlSize * 8; ++i) {
+                       if (uvc_get_bit(bmControls, i) == 0)
+                               continue;
+
+                       ctrl->entity = entity;
+                       ctrl->index = i;
+                       ctrl++;
+               }
+       }
+
+       /* Walk the controls info list and associate them with the device
+        * controls, then add the device to the global device list. This has
+        * to be done while holding the controls lock, to make sure
+        * uvc_ctrl_add_info() will not get called in-between.
+        */
+       mutex_lock(&uvc_driver.ctrl_mutex);
+       list_for_each_entry(info, &uvc_driver.controls, list)
+               uvc_ctrl_add_ctrl(dev, info);
+
+       list_add_tail(&dev->list, &uvc_driver.devices);
+       mutex_unlock(&uvc_driver.ctrl_mutex);
+
+       return 0;
+}
+
+/*
+ * Cleanup device controls.
+ */
+void uvc_ctrl_cleanup_device(struct uvc_device *dev)
+{
+       struct uvc_entity *entity;
+       unsigned int i;
+
+       /* Remove the device from the global devices list */
+       mutex_lock(&uvc_driver.ctrl_mutex);
+       if (dev->list.next != NULL)
+               list_del(&dev->list);
+       mutex_unlock(&uvc_driver.ctrl_mutex);
+
+       list_for_each_entry(entity, &dev->entities, list) {
+               for (i = 0; i < entity->ncontrols; ++i)
+                       kfree(entity->controls[i].data);
+
+               kfree(entity->controls);
+       }
+}
+
+void uvc_ctrl_init(void)
+{
+       struct uvc_control_info *ctrl = uvc_ctrls;
+       struct uvc_control_info *cend = ctrl + ARRAY_SIZE(uvc_ctrls);
+       struct uvc_control_mapping *mapping = uvc_ctrl_mappings;
+       struct uvc_control_mapping *mend =
+               mapping + ARRAY_SIZE(uvc_ctrl_mappings);
+
+       for (; ctrl < cend; ++ctrl)
+               uvc_ctrl_add_info(ctrl);
+
+       for (; mapping < mend; ++mapping)
+               uvc_ctrl_add_mapping(mapping);
+}
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
new file mode 100644 (file)
index 0000000..60ced58
--- /dev/null
@@ -0,0 +1,1955 @@
+/*
+ *      uvc_driver.c  --  USB Video Class driver
+ *
+ *      Copyright (C) 2005-2008
+ *          Laurent Pinchart (laurent.pinchart@skynet.be)
+ *
+ *      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 driver aims to support video input devices compliant with the 'USB
+ * Video Class' specification.
+ *
+ * The driver doesn't support the deprecated v4l1 interface. It implements the
+ * mmap capture method only, and doesn't do any image format conversion in
+ * software. If your user-space application doesn't support YUYV or MJPEG, fix
+ * it :-). Please note that the MJPEG data have been stripped from their
+ * Huffman tables (DHT marker), you will need to add it back if your JPEG
+ * codec can't handle MJPEG data.
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+#include <asm/atomic.h>
+
+#include <media/v4l2-common.h>
+
+#include "uvcvideo.h"
+
+#define DRIVER_AUTHOR          "Laurent Pinchart <laurent.pinchart@skynet.be>"
+#define DRIVER_DESC            "USB Video Class driver"
+#ifndef DRIVER_VERSION
+#define DRIVER_VERSION         "v0.1.0"
+#endif
+
+static unsigned int uvc_quirks_param;
+unsigned int uvc_trace_param;
+
+/* ------------------------------------------------------------------------
+ * Control, formats, ...
+ */
+
+static struct uvc_format_desc uvc_fmts[] = {
+       {
+               .name           = "YUV 4:2:2 (YUYV)",
+               .guid           = UVC_GUID_FORMAT_YUY2,
+               .fcc            = V4L2_PIX_FMT_YUYV,
+       },
+       {
+               .name           = "YUV 4:2:0 (NV12)",
+               .guid           = UVC_GUID_FORMAT_NV12,
+               .fcc            = V4L2_PIX_FMT_NV12,
+       },
+       {
+               .name           = "MJPEG",
+               .guid           = UVC_GUID_FORMAT_MJPEG,
+               .fcc            = V4L2_PIX_FMT_MJPEG,
+       },
+       {
+               .name           = "YVU 4:2:0 (YV12)",
+               .guid           = UVC_GUID_FORMAT_YV12,
+               .fcc            = V4L2_PIX_FMT_YVU420,
+       },
+       {
+               .name           = "YUV 4:2:0 (I420)",
+               .guid           = UVC_GUID_FORMAT_I420,
+               .fcc            = V4L2_PIX_FMT_YUV420,
+       },
+       {
+               .name           = "YUV 4:2:2 (UYVY)",
+               .guid           = UVC_GUID_FORMAT_UYVY,
+               .fcc            = V4L2_PIX_FMT_UYVY,
+       },
+       {
+               .name           = "Greyscale",
+               .guid           = UVC_GUID_FORMAT_Y800,
+               .fcc            = V4L2_PIX_FMT_GREY,
+       },
+       {
+               .name           = "RGB Bayer",
+               .guid           = UVC_GUID_FORMAT_BY8,
+               .fcc            = V4L2_PIX_FMT_SBGGR8,
+       },
+};
+
+/* ------------------------------------------------------------------------
+ * Utility functions
+ */
+
+struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts,
+               __u8 epaddr)
+{
+       struct usb_host_endpoint *ep;
+       unsigned int i;
+
+       for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
+               ep = &alts->endpoint[i];
+               if (ep->desc.bEndpointAddress == epaddr)
+                       return ep;
+       }
+
+       return NULL;
+}
+
+static struct uvc_format_desc *uvc_format_by_guid(const __u8 guid[16])
+{
+       unsigned int len = ARRAY_SIZE(uvc_fmts);
+       unsigned int i;
+
+       for (i = 0; i < len; ++i) {
+               if (memcmp(guid, uvc_fmts[i].guid, 16) == 0)
+                       return &uvc_fmts[i];
+       }
+
+       return NULL;
+}
+
+static __u32 uvc_colorspace(const __u8 primaries)
+{
+       static const __u8 colorprimaries[] = {
+               0,
+               V4L2_COLORSPACE_SRGB,
+               V4L2_COLORSPACE_470_SYSTEM_M,
+               V4L2_COLORSPACE_470_SYSTEM_BG,
+               V4L2_COLORSPACE_SMPTE170M,
+               V4L2_COLORSPACE_SMPTE240M,
+       };
+
+       if (primaries < ARRAY_SIZE(colorprimaries))
+               return colorprimaries[primaries];
+
+       return 0;
+}
+
+/* Simplify a fraction using a simple continued fraction decomposition. The
+ * idea here is to convert fractions such as 333333/10000000 to 1/30 using
+ * 32 bit arithmetic only. The algorithm is not perfect and relies upon two
+ * arbitrary parameters to remove non-significative terms from the simple
+ * continued fraction decomposition. Using 8 and 333 for n_terms and threshold
+ * respectively seems to give nice results.
+ */
+void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,
+               unsigned int n_terms, unsigned int threshold)
+{
+       uint32_t *an;
+       uint32_t x, y, r;
+       unsigned int i, n;
+
+       an = kmalloc(n_terms * sizeof *an, GFP_KERNEL);
+       if (an == NULL)
+               return;
+
+       /* Convert the fraction to a simple continued fraction. See
+        * http://mathforum.org/dr.math/faq/faq.fractions.html
+        * Stop if the current term is bigger than or equal to the given
+        * threshold.
+        */
+       x = *numerator;
+       y = *denominator;
+
+       for (n = 0; n < n_terms && y != 0; ++n) {
+               an[n] = x / y;
+               if (an[n] >= threshold) {
+                       if (n < 2)
+                               n++;
+                       break;
+               }
+
+               r = x - an[n] * y;
+               x = y;
+               y = r;
+       }
+
+       /* Expand the simple continued fraction back to an integer fraction. */
+       x = 0;
+       y = 1;
+
+       for (i = n; i > 0; --i) {
+               r = y;
+               y = an[i-1] * y + x;
+               x = r;
+       }
+
+       *numerator = y;
+       *denominator = x;
+       kfree(an);
+}
+
+/* Convert a fraction to a frame interval in 100ns multiples. The idea here is
+ * to compute numerator / denominator * 10000000 using 32 bit fixed point
+ * arithmetic only.
+ */
+uint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator)
+{
+       uint32_t multiplier;
+
+       /* Saturate the result if the operation would overflow. */
+       if (denominator == 0 ||
+           numerator/denominator >= ((uint32_t)-1)/10000000)
+               return (uint32_t)-1;
+
+       /* Divide both the denominator and the multiplier by two until
+        * numerator * multiplier doesn't overflow. If anyone knows a better
+        * algorithm please let me know.
+        */
+       multiplier = 10000000;
+       while (numerator > ((uint32_t)-1)/multiplier) {
+               multiplier /= 2;
+               denominator /= 2;
+       }
+
+       return denominator ? numerator * multiplier / denominator : 0;
+}
+
+/* ------------------------------------------------------------------------
+ * Terminal and unit management
+ */
+
+static struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id)
+{
+       struct uvc_entity *entity;
+
+       list_for_each_entry(entity, &dev->entities, list) {
+               if (entity->id == id)
+                       return entity;
+       }
+
+       return NULL;
+}
+
+static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
+       int id, struct uvc_entity *entity)
+{
+       unsigned int i;
+
+       if (entity == NULL)
+               entity = list_entry(&dev->entities, struct uvc_entity, list);
+
+       list_for_each_entry_continue(entity, &dev->entities, list) {
+               switch (UVC_ENTITY_TYPE(entity)) {
+               case TT_STREAMING:
+                       if (entity->output.bSourceID == id)
+                               return entity;
+                       break;
+
+               case VC_PROCESSING_UNIT:
+                       if (entity->processing.bSourceID == id)
+                               return entity;
+                       break;
+
+               case VC_SELECTOR_UNIT:
+                       for (i = 0; i < entity->selector.bNrInPins; ++i)
+                               if (entity->selector.baSourceID[i] == id)
+                                       return entity;
+                       break;
+
+               case VC_EXTENSION_UNIT:
+                       for (i = 0; i < entity->extension.bNrInPins; ++i)
+                               if (entity->extension.baSourceID[i] == id)
+                                       return entity;
+                       break;
+               }
+       }
+
+       return NULL;
+}
+
+/* ------------------------------------------------------------------------
+ * Descriptors handling
+ */
+
+static int uvc_parse_format(struct uvc_device *dev,
+       struct uvc_streaming *streaming, struct uvc_format *format,
+       __u32 **intervals, unsigned char *buffer, int buflen)
+{
+       struct usb_interface *intf = streaming->intf;
+       struct usb_host_interface *alts = intf->cur_altsetting;
+       struct uvc_format_desc *fmtdesc;
+       struct uvc_frame *frame;
+       const unsigned char *start = buffer;
+       unsigned int interval;
+       unsigned int i, n;
+       __u8 ftype;
+
+       format->type = buffer[2];
+       format->index = buffer[3];
+
+       switch (buffer[2]) {
+       case VS_FORMAT_UNCOMPRESSED:
+       case VS_FORMAT_FRAME_BASED:
+               if (buflen < 27) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+                              "interface %d FORMAT error\n",
+                              dev->udev->devnum,
+                              alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               /* Find the format descriptor from its GUID. */
+               fmtdesc = uvc_format_by_guid(&buffer[5]);
+
+               if (fmtdesc != NULL) {
+                       strncpy(format->name, fmtdesc->name,
+                               sizeof format->name);
+                       format->fcc = fmtdesc->fcc;
+               } else {
+                       uvc_printk(KERN_INFO, "Unknown video format "
+                               UVC_GUID_FORMAT "\n",
+                               UVC_GUID_ARGS(&buffer[5]));
+                       snprintf(format->name, sizeof format->name,
+                               UVC_GUID_FORMAT, UVC_GUID_ARGS(&buffer[5]));
+                       format->fcc = 0;
+               }
+
+               format->bpp = buffer[21];
+               if (buffer[2] == VS_FORMAT_UNCOMPRESSED) {
+                       ftype = VS_FRAME_UNCOMPRESSED;
+               } else {
+                       ftype = VS_FRAME_FRAME_BASED;
+                       if (buffer[27])
+                               format->flags = UVC_FMT_FLAG_COMPRESSED;
+               }
+               break;
+
+       case VS_FORMAT_MJPEG:
+               if (buflen < 11) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+                              "interface %d FORMAT error\n",
+                              dev->udev->devnum,
+                              alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               strncpy(format->name, "MJPEG", sizeof format->name);
+               format->fcc = V4L2_PIX_FMT_MJPEG;
+               format->flags = UVC_FMT_FLAG_COMPRESSED;
+               format->bpp = 0;
+               ftype = VS_FRAME_MJPEG;
+               break;
+
+       case VS_FORMAT_DV:
+               if (buflen < 9) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+                              "interface %d FORMAT error\n",
+                              dev->udev->devnum,
+                              alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               switch (buffer[8] & 0x7f) {
+               case 0:
+                       strncpy(format->name, "SD-DV", sizeof format->name);
+                       break;
+               case 1:
+                       strncpy(format->name, "SDL-DV", sizeof format->name);
+                       break;
+               case 2:
+                       strncpy(format->name, "HD-DV", sizeof format->name);
+                       break;
+               default:
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+                              "interface %d: unknown DV format %u\n",
+                              dev->udev->devnum,
+                              alts->desc.bInterfaceNumber, buffer[8]);
+                       return -EINVAL;
+               }
+
+               strncat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
+                       sizeof format->name);
+
+               format->fcc = V4L2_PIX_FMT_DV;
+               format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM;
+               format->bpp = 0;
+               ftype = 0;
+
+               /* Create a dummy frame descriptor. */
+               frame = &format->frame[0];
+               memset(&format->frame[0], 0, sizeof format->frame[0]);
+               frame->bFrameIntervalType = 1;
+               frame->dwDefaultFrameInterval = 1;
+               frame->dwFrameInterval = *intervals;
+               *(*intervals)++ = 1;
+               format->nframes = 1;
+               break;
+
+       case VS_FORMAT_MPEG2TS:
+       case VS_FORMAT_STREAM_BASED:
+               /* Not supported yet. */
+       default:
+               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+                      "interface %d unsupported format %u\n",
+                      dev->udev->devnum, alts->desc.bInterfaceNumber,
+                      buffer[2]);
+               return -EINVAL;
+       }
+
+       uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name);
+
+       buflen -= buffer[0];
+       buffer += buffer[0];
+
+       /* Parse the frame descriptors. Only uncompressed, MJPEG and frame
+        * based formats have frame descriptors.
+        */
+       while (buflen > 2 && buffer[2] == ftype) {
+               frame = &format->frame[format->nframes];
+
+               if (ftype != VS_FRAME_FRAME_BASED)
+                       n = buflen > 25 ? buffer[25] : 0;
+               else
+                       n = buflen > 21 ? buffer[21] : 0;
+
+               n = n ? n : 3;
+
+               if (buflen < 26 + 4*n) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+                              "interface %d FRAME error\n", dev->udev->devnum,
+                              alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               frame->bFrameIndex = buffer[3];
+               frame->bmCapabilities = buffer[4];
+               frame->wWidth = le16_to_cpup((__le16 *)&buffer[5]);
+               frame->wHeight = le16_to_cpup((__le16 *)&buffer[7]);
+               frame->dwMinBitRate = le32_to_cpup((__le32 *)&buffer[9]);
+               frame->dwMaxBitRate = le32_to_cpup((__le32 *)&buffer[13]);
+               if (ftype != VS_FRAME_FRAME_BASED) {
+                       frame->dwMaxVideoFrameBufferSize =
+                               le32_to_cpup((__le32 *)&buffer[17]);
+                       frame->dwDefaultFrameInterval =
+                               le32_to_cpup((__le32 *)&buffer[21]);
+                       frame->bFrameIntervalType = buffer[25];
+               } else {
+                       frame->dwMaxVideoFrameBufferSize = 0;
+                       frame->dwDefaultFrameInterval =
+                               le32_to_cpup((__le32 *)&buffer[17]);
+                       frame->bFrameIntervalType = buffer[21];
+               }
+               frame->dwFrameInterval = *intervals;
+
+               /* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
+                * completely. Observed behaviours range from setting the
+                * value to 1.1x the actual frame size of hardwiring the
+                * 16 low bits to 0. This results in a higher than necessary
+                * memory usage as well as a wrong image size information. For
+                * uncompressed formats this can be fixed by computing the
+                * value from the frame size.
+                */
+               if (!(format->flags & UVC_FMT_FLAG_COMPRESSED))
+                       frame->dwMaxVideoFrameBufferSize = format->bpp
+                               * frame->wWidth * frame->wHeight / 8;
+
+               /* Some bogus devices report dwMinFrameInterval equal to
+                * dwMaxFrameInterval and have dwFrameIntervalStep set to
+                * zero. Setting all null intervals to 1 fixes the problem and
+                * some other divisions by zero which could happen.
+                */
+               for (i = 0; i < n; ++i) {
+                       interval = le32_to_cpup((__le32 *)&buffer[26+4*i]);
+                       *(*intervals)++ = interval ? interval : 1;
+               }
+
+               /* Make sure that the default frame interval stays between
+                * the boundaries.
+                */
+               n -= frame->bFrameIntervalType ? 1 : 2;
+               frame->dwDefaultFrameInterval =
+                       min(frame->dwFrameInterval[n],
+                           max(frame->dwFrameInterval[0],
+                               frame->dwDefaultFrameInterval));
+
+               uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n",
+                       frame->wWidth, frame->wHeight,
+                       10000000/frame->dwDefaultFrameInterval,
+                       (100000000/frame->dwDefaultFrameInterval)%10);
+
+               format->nframes++;
+               buflen -= buffer[0];
+               buffer += buffer[0];
+       }
+
+       if (buflen > 2 && buffer[2] == VS_STILL_IMAGE_FRAME) {
+               buflen -= buffer[0];
+               buffer += buffer[0];
+       }
+
+       if (buflen > 2 && buffer[2] == VS_COLORFORMAT) {
+               if (buflen < 6) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
+                              "interface %d COLORFORMAT error\n",
+                              dev->udev->devnum,
+                              alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               format->colorspace = uvc_colorspace(buffer[3]);
+
+               buflen -= buffer[0];
+               buffer += buffer[0];
+       }
+
+       return buffer - start;
+}
+
+static int uvc_parse_streaming(struct uvc_device *dev,
+       struct usb_interface *intf)
+{
+       struct uvc_streaming *streaming = NULL;
+       struct uvc_format *format;
+       struct uvc_frame *frame;
+       struct usb_host_interface *alts = &intf->altsetting[0];
+       unsigned char *_buffer, *buffer = alts->extra;
+       int _buflen, buflen = alts->extralen;
+       unsigned int nformats = 0, nframes = 0, nintervals = 0;
+       unsigned int size, i, n, p;
+       __u32 *interval;
+       __u16 psize;
+       int ret = -EINVAL;
+
+       if (intf->cur_altsetting->desc.bInterfaceSubClass
+               != SC_VIDEOSTREAMING) {
+               uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a "
+                       "video streaming interface\n", dev->udev->devnum,
+                       intf->altsetting[0].desc.bInterfaceNumber);
+               return -EINVAL;
+       }
+
+       if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) {
+               uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already "
+                       "claimed\n", dev->udev->devnum,
+                       intf->altsetting[0].desc.bInterfaceNumber);
+               return -EINVAL;
+       }
+
+       streaming = kzalloc(sizeof *streaming, GFP_KERNEL);
+       if (streaming == NULL) {
+               usb_driver_release_interface(&uvc_driver.driver, intf);
+               return -EINVAL;
+       }
+
+       mutex_init(&streaming->mutex);
+       streaming->intf = usb_get_intf(intf);
+       streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
+       /* The Pico iMage webcam has its class-specific interface descriptors
+        * after the endpoint descriptors.
+        */
+       if (buflen == 0) {
+               for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
+                       struct usb_host_endpoint *ep = &alts->endpoint[i];
+
+                       if (ep->extralen == 0)
+                               continue;
+
+                       if (ep->extralen > 2 &&
+                           ep->extra[1] == USB_DT_CS_INTERFACE) {
+                               uvc_trace(UVC_TRACE_DESCR, "trying extra data "
+                                       "from endpoint %u.\n", i);
+                               buffer = alts->endpoint[i].extra;
+                               buflen = alts->endpoint[i].extralen;
+                               break;
+                       }
+               }
+       }
+
+       /* Skip the standard interface descriptors. */
+       while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) {
+               buflen -= buffer[0];
+               buffer += buffer[0];
+       }
+
+       if (buflen <= 2) {
+               uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming "
+                       "interface descriptors found.\n");
+               goto error;
+       }
+
+       /* Parse the header descriptor. */
+       if (buffer[2] == VS_OUTPUT_HEADER) {
+               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
+                       "%d OUTPUT HEADER descriptor is not supported.\n",
+                       dev->udev->devnum, alts->desc.bInterfaceNumber);
+               goto error;
+       } else if (buffer[2] == VS_INPUT_HEADER) {
+               p = buflen >= 5 ? buffer[3] : 0;
+               n = buflen >= 12 ? buffer[12] : 0;
+
+               if (buflen < 13 + p*n || buffer[2] != VS_INPUT_HEADER) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
+                               "interface %d INPUT HEADER descriptor is "
+                               "invalid.\n", dev->udev->devnum,
+                               alts->desc.bInterfaceNumber);
+                       goto error;
+               }
+
+               streaming->header.bNumFormats = p;
+               streaming->header.bEndpointAddress = buffer[6];
+               streaming->header.bmInfo = buffer[7];
+               streaming->header.bTerminalLink = buffer[8];
+               streaming->header.bStillCaptureMethod = buffer[9];
+               streaming->header.bTriggerSupport = buffer[10];
+               streaming->header.bTriggerUsage = buffer[11];
+               streaming->header.bControlSize = n;
+
+               streaming->header.bmaControls = kmalloc(p*n, GFP_KERNEL);
+               if (streaming->header.bmaControls == NULL) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
+
+               memcpy(streaming->header.bmaControls, &buffer[13], p*n);
+       } else {
+               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
+                       "%d HEADER descriptor not found.\n", dev->udev->devnum,
+                       alts->desc.bInterfaceNumber);
+               goto error;
+       }
+
+       buflen -= buffer[0];
+       buffer += buffer[0];
+
+       _buffer = buffer;
+       _buflen = buflen;
+
+       /* Count the format and frame descriptors. */
+       while (_buflen > 2) {
+               switch (_buffer[2]) {
+               case VS_FORMAT_UNCOMPRESSED:
+               case VS_FORMAT_MJPEG:
+               case VS_FORMAT_FRAME_BASED:
+                       nformats++;
+                       break;
+
+               case VS_FORMAT_DV:
+                       /* DV format has no frame descriptor. We will create a
+                        * dummy frame descriptor with a dummy frame interval.
+                        */
+                       nformats++;
+                       nframes++;
+                       nintervals++;
+                       break;
+
+               case VS_FORMAT_MPEG2TS:
+               case VS_FORMAT_STREAM_BASED:
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
+                               "interface %d FORMAT %u is not supported.\n",
+                               dev->udev->devnum,
+                               alts->desc.bInterfaceNumber, _buffer[2]);
+                       break;
+
+               case VS_FRAME_UNCOMPRESSED:
+               case VS_FRAME_MJPEG:
+                       nframes++;
+                       if (_buflen > 25)
+                               nintervals += _buffer[25] ? _buffer[25] : 3;
+                       break;
+
+               case VS_FRAME_FRAME_BASED:
+                       nframes++;
+                       if (_buflen > 21)
+                               nintervals += _buffer[21] ? _buffer[21] : 3;
+                       break;
+               }
+
+               _buflen -= _buffer[0];
+               _buffer += _buffer[0];
+       }
+
+       if (nformats == 0) {
+               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
+                       "%d has no supported formats defined.\n",
+                       dev->udev->devnum, alts->desc.bInterfaceNumber);
+               goto error;
+       }
+
+       size = nformats * sizeof *format + nframes * sizeof *frame
+            + nintervals * sizeof *interval;
+       format = kzalloc(size, GFP_KERNEL);
+       if (format == NULL) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       frame = (struct uvc_frame *)&format[nformats];
+       interval = (__u32 *)&frame[nframes];
+
+       streaming->format = format;
+       streaming->nformats = nformats;
+
+       /* Parse the format descriptors. */
+       while (buflen > 2) {
+               switch (buffer[2]) {
+               case VS_FORMAT_UNCOMPRESSED:
+               case VS_FORMAT_MJPEG:
+               case VS_FORMAT_DV:
+               case VS_FORMAT_FRAME_BASED:
+                       format->frame = frame;
+                       ret = uvc_parse_format(dev, streaming, format,
+                               &interval, buffer, buflen);
+                       if (ret < 0)
+                               goto error;
+
+                       frame += format->nframes;
+                       format++;
+
+                       buflen -= ret;
+                       buffer += ret;
+                       continue;
+
+               default:
+                       break;
+               }
+
+               buflen -= buffer[0];
+               buffer += buffer[0];
+       }
+
+       /* Parse the alternate settings to find the maximum bandwidth. */
+       for (i = 0; i < intf->num_altsetting; ++i) {
+               struct usb_host_endpoint *ep;
+               alts = &intf->altsetting[i];
+               ep = uvc_find_endpoint(alts,
+                               streaming->header.bEndpointAddress);
+               if (ep == NULL)
+                       continue;
+
+               psize = le16_to_cpu(ep->desc.wMaxPacketSize);
+               psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+               if (psize > streaming->maxpsize)
+                       streaming->maxpsize = psize;
+       }
+
+       list_add_tail(&streaming->list, &dev->streaming);
+       return 0;
+
+error:
+       usb_driver_release_interface(&uvc_driver.driver, intf);
+       usb_put_intf(intf);
+       kfree(streaming->format);
+       kfree(streaming->header.bmaControls);
+       kfree(streaming);
+       return ret;
+}
+
+/* Parse vendor-specific extensions. */
+static int uvc_parse_vendor_control(struct uvc_device *dev,
+       const unsigned char *buffer, int buflen)
+{
+       struct usb_device *udev = dev->udev;
+       struct usb_host_interface *alts = dev->intf->cur_altsetting;
+       struct uvc_entity *unit;
+       unsigned int n, p;
+       int handled = 0;
+
+       switch (le16_to_cpu(dev->udev->descriptor.idVendor)) {
+       case 0x046d:            /* Logitech */
+               if (buffer[1] != 0x41 || buffer[2] != 0x01)
+                       break;
+
+               /* Logitech implements several vendor specific functions
+                * through vendor specific extension units (LXU).
+                *
+                * The LXU descriptors are similar to XU descriptors
+                * (see "USB Device Video Class for Video Devices", section
+                * 3.7.2.6 "Extension Unit Descriptor") with the following
+                * differences:
+                *
+                * ----------------------------------------------------------
+                * 0            bLength         1        Number
+                *      Size of this descriptor, in bytes: 24+p+n*2
+                * ----------------------------------------------------------
+                * 23+p+n       bmControlsType  N       Bitmap
+                *      Individual bits in the set are defined:
+                *      0: Absolute
+                *      1: Relative
+                *
+                *      This bitset is mapped exactly the same as bmControls.
+                * ----------------------------------------------------------
+                * 23+p+n*2     bReserved       1       Boolean
+                * ----------------------------------------------------------
+                * 24+p+n*2     iExtension      1       Index
+                *      Index of a string descriptor that describes this
+                *      extension unit.
+                * ----------------------------------------------------------
+                */
+               p = buflen >= 22 ? buffer[21] : 0;
+               n = buflen >= 25 + p ? buffer[22+p] : 0;
+
+               if (buflen < 25 + p + 2*n) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d EXTENSION_UNIT error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       break;
+               }
+
+               unit = kzalloc(sizeof *unit + p + 2*n, GFP_KERNEL);
+               if (unit == NULL)
+                       return -ENOMEM;
+
+               unit->id = buffer[3];
+               unit->type = VC_EXTENSION_UNIT;
+               memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
+               unit->extension.bNumControls = buffer[20];
+               unit->extension.bNrInPins =
+                       le16_to_cpup((__le16 *)&buffer[21]);
+               unit->extension.baSourceID = (__u8 *)unit + sizeof *unit;
+               memcpy(unit->extension.baSourceID, &buffer[22], p);
+               unit->extension.bControlSize = buffer[22+p];
+               unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p;
+               unit->extension.bmControlsType = (__u8 *)unit + sizeof *unit
+                                              + p + n;
+               memcpy(unit->extension.bmControls, &buffer[23+p], 2*n);
+
+               if (buffer[24+p+2*n] != 0)
+                       usb_string(udev, buffer[24+p+2*n], unit->name,
+                                  sizeof unit->name);
+               else
+                       sprintf(unit->name, "Extension %u", buffer[3]);
+
+               list_add_tail(&unit->list, &dev->entities);
+               handled = 1;
+               break;
+       }
+
+       return handled;
+}
+
+static int uvc_parse_standard_control(struct uvc_device *dev,
+       const unsigned char *buffer, int buflen)
+{
+       struct usb_device *udev = dev->udev;
+       struct uvc_entity *unit, *term;
+       struct usb_interface *intf;
+       struct usb_host_interface *alts = dev->intf->cur_altsetting;
+       unsigned int i, n, p, len;
+       __u16 type;
+
+       switch (buffer[2]) {
+       case VC_HEADER:
+               n = buflen >= 12 ? buffer[11] : 0;
+
+               if (buflen < 12 || buflen < 12 + n) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d HEADER error\n", udev->devnum,
+                               alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               dev->uvc_version = le16_to_cpup((__le16 *)&buffer[3]);
+               dev->clock_frequency = le32_to_cpup((__le32 *)&buffer[7]);
+
+               /* Parse all USB Video Streaming interfaces. */
+               for (i = 0; i < n; ++i) {
+                       intf = usb_ifnum_to_if(udev, buffer[12+i]);
+                       if (intf == NULL) {
+                               uvc_trace(UVC_TRACE_DESCR, "device %d "
+                                       "interface %d doesn't exists\n",
+                                       udev->devnum, i);
+                               continue;
+                       }
+
+                       uvc_parse_streaming(dev, intf);
+               }
+               break;
+
+       case VC_INPUT_TERMINAL:
+               if (buflen < 8) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d INPUT_TERMINAL error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               /* Make sure the terminal type MSB is not null, otherwise it
+                * could be confused with a unit.
+                */
+               type = le16_to_cpup((__le16 *)&buffer[4]);
+               if ((type & 0xff00) == 0) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d INPUT_TERMINAL %d has invalid "
+                               "type 0x%04x, skipping\n", udev->devnum,
+                               alts->desc.bInterfaceNumber,
+                               buffer[3], type);
+                       return 0;
+               }
+
+               n = 0;
+               p = 0;
+               len = 8;
+
+               if (type == ITT_CAMERA) {
+                       n = buflen >= 15 ? buffer[14] : 0;
+                       len = 15;
+
+               } else if (type == ITT_MEDIA_TRANSPORT_INPUT) {
+                       n = buflen >= 9 ? buffer[8] : 0;
+                       p = buflen >= 10 + n ? buffer[9+n] : 0;
+                       len = 10;
+               }
+
+               if (buflen < len + n + p) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d INPUT_TERMINAL error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               term = kzalloc(sizeof *term + n + p, GFP_KERNEL);
+               if (term == NULL)
+                       return -ENOMEM;
+
+               term->id = buffer[3];
+               term->type = type | UVC_TERM_INPUT;
+
+               if (UVC_ENTITY_TYPE(term) == ITT_CAMERA) {
+                       term->camera.bControlSize = n;
+                       term->camera.bmControls = (__u8 *)term + sizeof *term;
+                       term->camera.wObjectiveFocalLengthMin =
+                               le16_to_cpup((__le16 *)&buffer[8]);
+                       term->camera.wObjectiveFocalLengthMax =
+                               le16_to_cpup((__le16 *)&buffer[10]);
+                       term->camera.wOcularFocalLength =
+                               le16_to_cpup((__le16 *)&buffer[12]);
+                       memcpy(term->camera.bmControls, &buffer[15], n);
+               } else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT) {
+                       term->media.bControlSize = n;
+                       term->media.bmControls = (__u8 *)term + sizeof *term;
+                       term->media.bTransportModeSize = p;
+                       term->media.bmTransportModes = (__u8 *)term
+                                                    + sizeof *term + n;
+                       memcpy(term->media.bmControls, &buffer[9], n);
+                       memcpy(term->media.bmTransportModes, &buffer[10+n], p);
+               }
+
+               if (buffer[7] != 0)
+                       usb_string(udev, buffer[7], term->name,
+                                  sizeof term->name);
+               else if (UVC_ENTITY_TYPE(term) == ITT_CAMERA)
+                       sprintf(term->name, "Camera %u", buffer[3]);
+               else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT)
+                       sprintf(term->name, "Media %u", buffer[3]);
+               else
+                       sprintf(term->name, "Input %u", buffer[3]);
+
+               list_add_tail(&term->list, &dev->entities);
+               break;
+
+       case VC_OUTPUT_TERMINAL:
+               if (buflen < 9) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d OUTPUT_TERMINAL error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               /* Make sure the terminal type MSB is not null, otherwise it
+                * could be confused with a unit.
+                */
+               type = le16_to_cpup((__le16 *)&buffer[4]);
+               if ((type & 0xff00) == 0) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d OUTPUT_TERMINAL %d has invalid "
+                               "type 0x%04x, skipping\n", udev->devnum,
+                               alts->desc.bInterfaceNumber, buffer[3], type);
+                       return 0;
+               }
+
+               term = kzalloc(sizeof *term, GFP_KERNEL);
+               if (term == NULL)
+                       return -ENOMEM;
+
+               term->id = buffer[3];
+               term->type = type | UVC_TERM_OUTPUT;
+               term->output.bSourceID = buffer[7];
+
+               if (buffer[8] != 0)
+                       usb_string(udev, buffer[8], term->name,
+                                  sizeof term->name);
+               else
+                       sprintf(term->name, "Output %u", buffer[3]);
+
+               list_add_tail(&term->list, &dev->entities);
+               break;
+
+       case VC_SELECTOR_UNIT:
+               p = buflen >= 5 ? buffer[4] : 0;
+
+               if (buflen < 5 || buflen < 6 + p) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d SELECTOR_UNIT error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               unit = kzalloc(sizeof *unit + p, GFP_KERNEL);
+               if (unit == NULL)
+                       return -ENOMEM;
+
+               unit->id = buffer[3];
+               unit->type = buffer[2];
+               unit->selector.bNrInPins = buffer[4];
+               unit->selector.baSourceID = (__u8 *)unit + sizeof *unit;
+               memcpy(unit->selector.baSourceID, &buffer[5], p);
+
+               if (buffer[5+p] != 0)
+                       usb_string(udev, buffer[5+p], unit->name,
+                                  sizeof unit->name);
+               else
+                       sprintf(unit->name, "Selector %u", buffer[3]);
+
+               list_add_tail(&unit->list, &dev->entities);
+               break;
+
+       case VC_PROCESSING_UNIT:
+               n = buflen >= 8 ? buffer[7] : 0;
+               p = dev->uvc_version >= 0x0110 ? 10 : 9;
+
+               if (buflen < p + n) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d PROCESSING_UNIT error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               unit = kzalloc(sizeof *unit + n, GFP_KERNEL);
+               if (unit == NULL)
+                       return -ENOMEM;
+
+               unit->id = buffer[3];
+               unit->type = buffer[2];
+               unit->processing.bSourceID = buffer[4];
+               unit->processing.wMaxMultiplier =
+                       le16_to_cpup((__le16 *)&buffer[5]);
+               unit->processing.bControlSize = buffer[7];
+               unit->processing.bmControls = (__u8 *)unit + sizeof *unit;
+               memcpy(unit->processing.bmControls, &buffer[8], n);
+               if (dev->uvc_version >= 0x0110)
+                       unit->processing.bmVideoStandards = buffer[9+n];
+
+               if (buffer[8+n] != 0)
+                       usb_string(udev, buffer[8+n], unit->name,
+                                  sizeof unit->name);
+               else
+                       sprintf(unit->name, "Processing %u", buffer[3]);
+
+               list_add_tail(&unit->list, &dev->entities);
+               break;
+
+       case VC_EXTENSION_UNIT:
+               p = buflen >= 22 ? buffer[21] : 0;
+               n = buflen >= 24 + p ? buffer[22+p] : 0;
+
+               if (buflen < 24 + p + n) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d EXTENSION_UNIT error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               unit = kzalloc(sizeof *unit + p + n, GFP_KERNEL);
+               if (unit == NULL)
+                       return -ENOMEM;
+
+               unit->id = buffer[3];
+               unit->type = buffer[2];
+               memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
+               unit->extension.bNumControls = buffer[20];
+               unit->extension.bNrInPins =
+                       le16_to_cpup((__le16 *)&buffer[21]);
+               unit->extension.baSourceID = (__u8 *)unit + sizeof *unit;
+               memcpy(unit->extension.baSourceID, &buffer[22], p);
+               unit->extension.bControlSize = buffer[22+p];
+               unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p;
+               memcpy(unit->extension.bmControls, &buffer[23+p], n);
+
+               if (buffer[23+p+n] != 0)
+                       usb_string(udev, buffer[23+p+n], unit->name,
+                                  sizeof unit->name);
+               else
+                       sprintf(unit->name, "Extension %u", buffer[3]);
+
+               list_add_tail(&unit->list, &dev->entities);
+               break;
+
+       default:
+               uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE "
+                       "descriptor (%u)\n", buffer[2]);
+               break;
+       }
+
+       return 0;
+}
+
+static int uvc_parse_control(struct uvc_device *dev)
+{
+       struct usb_host_interface *alts = dev->intf->cur_altsetting;
+       unsigned char *buffer = alts->extra;
+       int buflen = alts->extralen;
+       int ret;
+
+       /* Parse the default alternate setting only, as the UVC specification
+        * defines a single alternate setting, the default alternate setting
+        * zero.
+        */
+
+       while (buflen > 2) {
+               if (uvc_parse_vendor_control(dev, buffer, buflen) ||
+                   buffer[1] != USB_DT_CS_INTERFACE)
+                       goto next_descriptor;
+
+               if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0)
+                       return ret;
+
+next_descriptor:
+               buflen -= buffer[0];
+               buffer += buffer[0];
+       }
+
+       /* Check if the optional status endpoint is present. */
+       if (alts->desc.bNumEndpoints == 1) {
+               struct usb_host_endpoint *ep = &alts->endpoint[0];
+               struct usb_endpoint_descriptor *desc = &ep->desc;
+
+               if (usb_endpoint_is_int_in(desc) &&
+                   le16_to_cpu(desc->wMaxPacketSize) >= 8 &&
+                   desc->bInterval != 0) {
+                       uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint "
+                               "(addr %02x).\n", desc->bEndpointAddress);
+                       dev->int_ep = ep;
+               }
+       }
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------------
+ * USB probe and disconnect
+ */
+
+/*
+ * Unregister the video devices.
+ */
+static void uvc_unregister_video(struct uvc_device *dev)
+{
+       if (dev->video.vdev) {
+               if (dev->video.vdev->minor == -1)
+                       video_device_release(dev->video.vdev);
+               else
+                       video_unregister_device(dev->video.vdev);
+               dev->video.vdev = NULL;
+       }
+}
+
+/*
+ * Scan the UVC descriptors to locate a chain starting at an Output Terminal
+ * and containing the following units:
+ *
+ * - a USB Streaming Output Terminal
+ * - zero or one Processing Unit
+ * - zero, one or mode single-input Selector Units
+ * - zero or one multiple-input Selector Units, provided all inputs are
+ *   connected to input terminals
+ * - zero, one or mode single-input Extension Units
+ * - one Camera Input Terminal, or one or more External terminals.
+ *
+ * A side forward scan is made on each detected entity to check for additional
+ * extension units.
+ */
+static int uvc_scan_chain_entity(struct uvc_video_device *video,
+       struct uvc_entity *entity)
+{
+       switch (UVC_ENTITY_TYPE(entity)) {
+       case VC_EXTENSION_UNIT:
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk(" <- XU %d", entity->id);
+
+               if (entity->extension.bNrInPins != 1) {
+                       uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more "
+                               "than 1 input pin.\n", entity->id);
+                       return -1;
+               }
+
+               list_add_tail(&entity->chain, &video->extensions);
+               break;
+
+       case VC_PROCESSING_UNIT:
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk(" <- PU %d", entity->id);
+
+               if (video->processing != NULL) {
+                       uvc_trace(UVC_TRACE_DESCR, "Found multiple "
+                               "Processing Units in chain.\n");
+                       return -1;
+               }
+
+               video->processing = entity;
+               break;
+
+       case VC_SELECTOR_UNIT:
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk(" <- SU %d", entity->id);
+
+               /* Single-input selector units are ignored. */
+               if (entity->selector.bNrInPins == 1)
+                       break;
+
+               if (video->selector != NULL) {
+                       uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector "
+                               "Units in chain.\n");
+                       return -1;
+               }
+
+               video->selector = entity;
+               break;
+
+       case ITT_VENDOR_SPECIFIC:
+       case ITT_CAMERA:
+       case ITT_MEDIA_TRANSPORT_INPUT:
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk(" <- IT %d\n", entity->id);
+
+               list_add_tail(&entity->chain, &video->iterms);
+               break;
+
+       default:
+               uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type "
+                       "0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity));
+               return -1;
+       }
+
+       return 0;
+}
+
+static int uvc_scan_chain_forward(struct uvc_video_device *video,
+       struct uvc_entity *entity, struct uvc_entity *prev)
+{
+       struct uvc_entity *forward;
+       int found;
+
+       /* Forward scan */
+       forward = NULL;
+       found = 0;
+
+       while (1) {
+               forward = uvc_entity_by_reference(video->dev, entity->id,
+                       forward);
+               if (forward == NULL)
+                       break;
+
+               if (UVC_ENTITY_TYPE(forward) != VC_EXTENSION_UNIT ||
+                   forward == prev)
+                       continue;
+
+               if (forward->extension.bNrInPins != 1) {
+                       uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has"
+                               "more than 1 input pin.\n", entity->id);
+                       return -1;
+               }
+
+               list_add_tail(&forward->chain, &video->extensions);
+               if (uvc_trace_param & UVC_TRACE_PROBE) {
+                       if (!found)
+                               printk(" (-> XU");
+
+                       printk(" %d", forward->id);
+                       found = 1;
+               }
+       }
+       if (found)
+               printk(")");
+
+       return 0;
+}
+
+static int uvc_scan_chain_backward(struct uvc_video_device *video,
+       struct uvc_entity *entity)
+{
+       struct uvc_entity *term;
+       int id = -1, i;
+
+       switch (UVC_ENTITY_TYPE(entity)) {
+       case VC_EXTENSION_UNIT:
+               id = entity->extension.baSourceID[0];
+               break;
+
+       case VC_PROCESSING_UNIT:
+               id = entity->processing.bSourceID;
+               break;
+
+       case VC_SELECTOR_UNIT:
+               /* Single-input selector units are ignored. */
+               if (entity->selector.bNrInPins == 1) {
+                       id = entity->selector.baSourceID[0];
+                       break;
+               }
+
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk(" <- IT");
+
+               video->selector = entity;
+               for (i = 0; i < entity->selector.bNrInPins; ++i) {
+                       id = entity->selector.baSourceID[i];
+                       term = uvc_entity_by_id(video->dev, id);
+                       if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {
+                               uvc_trace(UVC_TRACE_DESCR, "Selector unit %d "
+                                       "input %d isn't connected to an "
+                                       "input terminal\n", entity->id, i);
+                               return -1;
+                       }
+
+                       if (uvc_trace_param & UVC_TRACE_PROBE)
+                               printk(" %d", term->id);
+
+                       list_add_tail(&term->chain, &video->iterms);
+                       uvc_scan_chain_forward(video, term, entity);
+               }
+
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk("\n");
+
+               id = 0;
+               break;
+       }
+
+       return id;
+}
+
+static int uvc_scan_chain(struct uvc_video_device *video)
+{
+       struct uvc_entity *entity, *prev;
+       int id;
+
+       entity = video->oterm;
+       uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id);
+       id = entity->output.bSourceID;
+       while (id != 0) {
+               prev = entity;
+               entity = uvc_entity_by_id(video->dev, id);
+               if (entity == NULL) {
+                       uvc_trace(UVC_TRACE_DESCR, "Found reference to "
+                               "unknown entity %d.\n", id);
+                       return -1;
+               }
+
+               /* Process entity */
+               if (uvc_scan_chain_entity(video, entity) < 0)
+                       return -1;
+
+               /* Forward scan */
+               if (uvc_scan_chain_forward(video, entity, prev) < 0)
+                       return -1;
+
+               /* Stop when a terminal is found. */
+               if (!UVC_ENTITY_IS_UNIT(entity))
+                       break;
+
+               /* Backward scan */
+               id = uvc_scan_chain_backward(video, entity);
+               if (id < 0)
+                       return id;
+       }
+
+       /* Initialize the video buffers queue. */
+       uvc_queue_init(&video->queue);
+
+       return 0;
+}
+
+/*
+ * Register the video devices.
+ *
+ * The driver currently supports a single video device per control interface
+ * only. The terminal and units must match the following structure:
+ *
+ * ITT_CAMERA -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> TT_STREAMING
+ *
+ * The Extension Units, if present, must have a single input pin. The
+ * Processing Unit and Extension Units can be in any order. Additional
+ * Extension Units connected to the main chain as single-unit branches are
+ * also supported.
+ */
+static int uvc_register_video(struct uvc_device *dev)
+{
+       struct video_device *vdev;
+       struct uvc_entity *term;
+       int found = 0, ret;
+
+       /* Check if the control interface matches the structure we expect. */
+       list_for_each_entry(term, &dev->entities, list) {
+               struct uvc_streaming *streaming;
+
+               if (UVC_ENTITY_TYPE(term) != TT_STREAMING)
+                       continue;
+
+               memset(&dev->video, 0, sizeof dev->video);
+               mutex_init(&dev->video.ctrl_mutex);
+               INIT_LIST_HEAD(&dev->video.iterms);
+               INIT_LIST_HEAD(&dev->video.extensions);
+               dev->video.oterm = term;
+               dev->video.dev = dev;
+               if (uvc_scan_chain(&dev->video) < 0)
+                       continue;
+
+               list_for_each_entry(streaming, &dev->streaming, list) {
+                       if (streaming->header.bTerminalLink == term->id) {
+                               dev->video.streaming = streaming;
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (found)
+                       break;
+       }
+
+       if (!found) {
+               uvc_printk(KERN_INFO, "No valid video chain found.\n");
+               return -1;
+       }
+
+       if (uvc_trace_param & UVC_TRACE_PROBE) {
+               uvc_printk(KERN_INFO, "Found a valid video chain (");
+               list_for_each_entry(term, &dev->video.iterms, chain) {
+                       printk("%d", term->id);
+                       if (term->chain.next != &dev->video.iterms)
+                               printk(",");
+               }
+               printk(" -> %d).\n", dev->video.oterm->id);
+       }
+
+       /* Initialize the streaming interface with default streaming
+        * parameters.
+        */
+       if ((ret = uvc_video_init(&dev->video)) < 0) {
+               uvc_printk(KERN_ERR, "Failed to initialize the device "
+                       "(%d).\n", ret);
+               return ret;
+       }
+
+       /* Register the device with V4L. */
+       vdev = video_device_alloc();
+       if (vdev == NULL)
+               return -1;
+
+       /* We already hold a reference to dev->udev. The video device will be
+        * unregistered before the reference is released, so we don't need to
+        * get another one.
+        */
+       vdev->dev = &dev->intf->dev;
+       vdev->type = 0;
+       vdev->type2 = 0;
+       vdev->minor = -1;
+       vdev->fops = &uvc_fops;
+       vdev->release = video_device_release;
+       strncpy(vdev->name, dev->name, sizeof vdev->name);
+
+       /* Set the driver data before calling video_register_device, otherwise
+        * uvc_v4l2_open might race us.
+        *
+        * FIXME: usb_set_intfdata hasn't been called so far. Is that a
+        *        problem ? Does any function which could be called here get
+        *        a pointer to the usb_interface ?
+        */
+       dev->video.vdev = vdev;
+       video_set_drvdata(vdev, &dev->video);
+
+       if (video_register_device(vdev, VFL_TYPE_GRABBER, -1) < 0) {
+               dev->video.vdev = NULL;
+               video_device_release(vdev);
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Delete the UVC device.
+ *
+ * Called by the kernel when the last reference to the uvc_device structure
+ * is released.
+ *
+ * Unregistering the video devices is done here because every opened instance
+ * must be closed before the device can be unregistered. An alternative would
+ * have been to use another reference count for uvc_v4l2_open/uvc_release, and
+ * unregister the video devices on disconnect when that reference count drops
+ * to zero.
+ *
+ * As this function is called after or during disconnect(), all URBs have
+ * already been canceled by the USB core. There is no need to kill the
+ * interrupt URB manually.
+ */
+void uvc_delete(struct kref *kref)
+{
+       struct uvc_device *dev = container_of(kref, struct uvc_device, kref);
+       struct list_head *p, *n;
+
+       /* Unregister the video device */
+       uvc_unregister_video(dev);
+       usb_put_intf(dev->intf);
+       usb_put_dev(dev->udev);
+
+       uvc_status_cleanup(dev);
+       uvc_ctrl_cleanup_device(dev);
+
+       list_for_each_safe(p, n, &dev->entities) {
+               struct uvc_entity *entity;
+               entity = list_entry(p, struct uvc_entity, list);
+               kfree(entity);
+       }
+
+       list_for_each_safe(p, n, &dev->streaming) {
+               struct uvc_streaming *streaming;
+               streaming = list_entry(p, struct uvc_streaming, list);
+               usb_driver_release_interface(&uvc_driver.driver,
+                       streaming->intf);
+               usb_put_intf(streaming->intf);
+               kfree(streaming->format);
+               kfree(streaming->header.bmaControls);
+               kfree(streaming);
+       }
+
+       kfree(dev);
+}
+
+static int uvc_probe(struct usb_interface *intf,
+                    const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct uvc_device *dev;
+       int ret;
+
+       if (id->idVendor && id->idProduct)
+               uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s "
+                               "(%04x:%04x)\n", udev->devpath, id->idVendor,
+                               id->idProduct);
+       else
+               uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
+                               udev->devpath);
+
+       /* Allocate memory for the device and initialize it */
+       if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&dev->entities);
+       INIT_LIST_HEAD(&dev->streaming);
+       kref_init(&dev->kref);
+
+       dev->udev = usb_get_dev(udev);
+       dev->intf = usb_get_intf(intf);
+       dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
+       dev->quirks = id->driver_info | uvc_quirks_param;
+
+       if (udev->product != NULL)
+               strncpy(dev->name, udev->product, sizeof dev->name);
+       else
+               snprintf(dev->name, sizeof dev->name,
+                       "UVC Camera (%04x:%04x)",
+                       le16_to_cpu(udev->descriptor.idVendor),
+                       le16_to_cpu(udev->descriptor.idProduct));
+
+       /* Parse the Video Class control descriptor */
+       if (uvc_parse_control(dev) < 0) {
+               uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
+                       "descriptors.\n");
+               goto error;
+       }
+
+       uvc_printk(KERN_INFO, "Found UVC %u.%02u device %s (%04x:%04x)\n",
+               dev->uvc_version >> 8, dev->uvc_version & 0xff,
+               udev->product ? udev->product : "<unnamed>",
+               le16_to_cpu(udev->descriptor.idVendor),
+               le16_to_cpu(udev->descriptor.idProduct));
+
+       if (uvc_quirks_param != 0) {
+               uvc_printk(KERN_INFO, "Forcing device quirks 0x%x by module "
+                       "parameter for testing purpose.\n", uvc_quirks_param);
+               uvc_printk(KERN_INFO, "Please report required quirks to the "
+                       "linux-uvc-devel mailing list.\n");
+       }
+
+       /* Initialize controls */
+       if (uvc_ctrl_init_device(dev) < 0)
+               goto error;
+
+       /* Register the video devices */
+       if (uvc_register_video(dev) < 0)
+               goto error;
+
+       /* Save our data pointer in the interface data */
+       usb_set_intfdata(intf, dev);
+
+       /* Initialize the interrupt URB */
+       if ((ret = uvc_status_init(dev)) < 0) {
+               uvc_printk(KERN_INFO, "Unable to initialize the status "
+                       "endpoint (%d), status interrupt will not be "
+                       "supported.\n", ret);
+       }
+
+       uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
+       return 0;
+
+error:
+       kref_put(&dev->kref, uvc_delete);
+       return -ENODEV;
+}
+
+static void uvc_disconnect(struct usb_interface *intf)
+{
+       struct uvc_device *dev = usb_get_intfdata(intf);
+
+       /* Set the USB interface data to NULL. This can be done outside the
+        * lock, as there's no other reader.
+        */
+       usb_set_intfdata(intf, NULL);
+
+       if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOSTREAMING)
+               return;
+
+       /* uvc_v4l2_open() might race uvc_disconnect(). A static driver-wide
+        * lock is needed to prevent uvc_disconnect from releasing its
+        * reference to the uvc_device instance after uvc_v4l2_open() received
+        * the pointer to the device (video_devdata) but before it got the
+        * chance to increase the reference count (kref_get).
+        */
+       mutex_lock(&uvc_driver.open_mutex);
+
+       dev->state |= UVC_DEV_DISCONNECTED;
+       kref_put(&dev->kref, uvc_delete);
+
+       mutex_unlock(&uvc_driver.open_mutex);
+}
+
+static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct uvc_device *dev = usb_get_intfdata(intf);
+
+       uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n",
+               intf->cur_altsetting->desc.bInterfaceNumber);
+
+       /* Controls are cached on the fly so they don't need to be saved. */
+       if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL)
+               return uvc_status_suspend(dev);
+
+       if (dev->video.streaming->intf != intf) {
+               uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB "
+                               "interface mismatch.\n");
+               return -EINVAL;
+       }
+
+       return uvc_video_suspend(&dev->video);
+}
+
+static int uvc_resume(struct usb_interface *intf)
+{
+       struct uvc_device *dev = usb_get_intfdata(intf);
+       int ret;
+
+       uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
+               intf->cur_altsetting->desc.bInterfaceNumber);
+
+       if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) {
+               if ((ret = uvc_ctrl_resume_device(dev)) < 0)
+                       return ret;
+
+               return uvc_status_resume(dev);
+       }
+
+       if (dev->video.streaming->intf != intf) {
+               uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB "
+                               "interface mismatch.\n");
+               return -EINVAL;
+       }
+
+       return uvc_video_resume(&dev->video);
+}
+
+/* ------------------------------------------------------------------------
+ * Driver initialization and cleanup
+ */
+
+/*
+ * The Logitech cameras listed below have their interface class set to
+ * VENDOR_SPEC because they don't announce themselves as UVC devices, even
+ * though they are compliant.
+ */
+static struct usb_device_id uvc_ids[] = {
+       /* ALi M5606 (Clevo M540SR) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0402,
+         .idProduct            = 0x5606,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Creative Live! Optia */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x041e,
+         .idProduct            = 0x4057,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Microsoft Lifecam NX-6000 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x045e,
+         .idProduct            = 0x00f8,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Microsoft Lifecam VX-7000 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x045e,
+         .idProduct            = 0x0723,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Logitech Quickcam Fusion */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x046d,
+         .idProduct            = 0x08c1,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Logitech Quickcam Orbit MP */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x046d,
+         .idProduct            = 0x08c2,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Logitech Quickcam Pro for Notebook */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x046d,
+         .idProduct            = 0x08c3,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Logitech Quickcam Pro 5000 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x046d,
+         .idProduct            = 0x08c5,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Logitech Quickcam OEM Dell Notebook */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x046d,
+         .idProduct            = 0x08c6,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Logitech Quickcam OEM Cisco VT Camera II */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x046d,
+         .idProduct            = 0x08c7,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Apple Built-In iSight */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x05ac,
+         .idProduct            = 0x8501,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX
+                               | UVC_QUIRK_BUILTIN_ISIGHT },
+       /* Genesys Logic USB 2.0 PC Camera */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x05e3,
+         .idProduct            = 0x0505,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* Silicon Motion SM371 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x090c,
+         .idProduct            = 0xb371,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* MT6227 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0e8d,
+         .idProduct            = 0x0004,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Syntek (HP Spartan) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x174f,
+         .idProduct            = 0x5212,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* Syntek (Asus U3S) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x174f,
+         .idProduct            = 0x8a33,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* Ecamm Pico iMage */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x18cd,
+         .idProduct            = 0xcafe,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_EXTRAFIELDS },
+       /* Bodelin ProScopeHR */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_DEV_HI
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x19ab,
+         .idProduct            = 0x1000,
+         .bcdDevice_hi         = 0x0126,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STATUS_INTERVAL },
+       /* SiGma Micro USB Web Camera */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x1c4f,
+         .idProduct            = 0x3000,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX
+                               | UVC_QUIRK_IGNORE_SELECTOR_UNIT},
+       /* Acer OEM Webcam - Unknown vendor */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x5986,
+         .idProduct            = 0x0100,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Packard Bell OEM Webcam */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x5986,
+         .idProduct            = 0x0101,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Acer Crystal Eye webcam */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x5986,
+         .idProduct            = 0x0102,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Acer OrbiCam - Unknown vendor */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x5986,
+         .idProduct            = 0x0200,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Generic USB Video Class */
+       { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, uvc_ids);
+
+struct uvc_driver uvc_driver = {
+       .driver = {
+               .name           = "uvcvideo",
+               .probe          = uvc_probe,
+               .disconnect     = uvc_disconnect,
+               .suspend        = uvc_suspend,
+               .resume         = uvc_resume,
+               .id_table       = uvc_ids,
+               .supports_autosuspend = 1,
+       },
+};
+
+static int __init uvc_init(void)
+{
+       int result;
+
+       INIT_LIST_HEAD(&uvc_driver.devices);
+       INIT_LIST_HEAD(&uvc_driver.controls);
+       mutex_init(&uvc_driver.open_mutex);
+       mutex_init(&uvc_driver.ctrl_mutex);
+
+       uvc_ctrl_init();
+
+       result = usb_register(&uvc_driver.driver);
+       if (result == 0)
+               printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
+       return result;
+}
+
+static void __exit uvc_cleanup(void)
+{
+       usb_deregister(&uvc_driver.driver);
+}
+
+module_init(uvc_init);
+module_exit(uvc_cleanup);
+
+module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(quirks, "Forced device quirks");
+module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(trace, "Trace level bitmask");
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/media/video/uvc/uvc_isight.c b/drivers/media/video/uvc/uvc_isight.c
new file mode 100644 (file)
index 0000000..37bdefd
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *      uvc_isight.c  --  USB Video Class driver - iSight support
+ *
+ *     Copyright (C) 2006-2007
+ *             Ivan N. Zlatev <contact@i-nz.net>
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ */
+
+#include <linux/usb.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include "uvcvideo.h"
+
+/* Built-in iSight webcams implements most of UVC 1.0 except a
+ * different packet format. Instead of sending a header at the
+ * beginning of each isochronous transfer payload, the webcam sends a
+ * single header per image (on its own in a packet), followed by
+ * packets containing data only.
+ *
+ * Offset   Size (bytes)       Description
+ * ------------------------------------------------------------------
+ * 0x00        1       Header length
+ * 0x01        1       Flags (UVC-compliant)
+ * 0x02        4       Always equal to '11223344'
+ * 0x06        8       Always equal to 'deadbeefdeadface'
+ * 0x0e        16      Unknown
+ *
+ * The header can be prefixed by an optional, unknown-purpose byte.
+ */
+
+static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf,
+               const __u8 *data, unsigned int len)
+{
+       static const __u8 hdr[] = {
+               0x11, 0x22, 0x33, 0x44,
+               0xde, 0xad, 0xbe, 0xef,
+               0xde, 0xad, 0xfa, 0xce
+       };
+
+       unsigned int maxlen, nbytes;
+       __u8 *mem;
+       int is_header = 0;
+
+       if (buf == NULL)
+               return 0;
+
+       if ((len >= 14 && memcmp(&data[2], hdr, 12) == 0) ||
+           (len >= 15 && memcmp(&data[3], hdr, 12) == 0)) {
+               uvc_trace(UVC_TRACE_FRAME, "iSight header found\n");
+               is_header = 1;
+       }
+
+       /* Synchronize to the input stream by waiting for a header packet. */
+       if (buf->state != UVC_BUF_STATE_ACTIVE) {
+               if (!is_header) {
+                       uvc_trace(UVC_TRACE_FRAME, "Dropping packet (out of "
+                                 "sync).\n");
+                       return 0;
+               }
+
+               buf->state = UVC_BUF_STATE_ACTIVE;
+       }
+
+       /* Mark the buffer as done if we're at the beginning of a new frame.
+        *
+        * Empty buffers (bytesused == 0) don't trigger end of frame detection
+        * as it doesn't make sense to return an empty buffer.
+        */
+       if (is_header && buf->buf.bytesused != 0) {
+               buf->state = UVC_BUF_STATE_DONE;
+               return -EAGAIN;
+       }
+
+       /* Copy the video data to the buffer. Skip header packets, as they
+        * contain no data.
+        */
+       if (!is_header) {
+               maxlen = buf->buf.length - buf->buf.bytesused;
+               mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+               nbytes = min(len, maxlen);
+               memcpy(mem, data, nbytes);
+               buf->buf.bytesused += nbytes;
+
+               if (len > maxlen || buf->buf.bytesused == buf->buf.length) {
+                       uvc_trace(UVC_TRACE_FRAME, "Frame complete "
+                                 "(overflow).\n");
+                       buf->state = UVC_BUF_STATE_DONE;
+               }
+       }
+
+       return 0;
+}
+
+void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video,
+               struct uvc_buffer *buf)
+{
+       int ret, i;
+
+       for (i = 0; i < urb->number_of_packets; ++i) {
+               if (urb->iso_frame_desc[i].status < 0) {
+                       uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame "
+                                 "lost (%d).\n",
+                                 urb->iso_frame_desc[i].status);
+               }
+
+               /* Decode the payload packet.
+                * uvc_video_decode is entered twice when a frame transition
+                * has been detected because the end of frame can only be
+                * reliably detected when the first packet of the new frame
+                * is processed. The first pass detects the transition and
+                * closes the previous frame's buffer, the second pass
+                * processes the data of the first payload of the new frame.
+                */
+               do {
+                       ret = isight_decode(&video->queue, buf,
+                                       urb->transfer_buffer +
+                                       urb->iso_frame_desc[i].offset,
+                                       urb->iso_frame_desc[i].actual_length);
+
+                       if (buf == NULL)
+                               break;
+
+                       if (buf->state == UVC_BUF_STATE_DONE ||
+                           buf->state == UVC_BUF_STATE_ERROR)
+                               buf = uvc_queue_next_buffer(&video->queue, buf);
+               } while (ret == -EAGAIN);
+       }
+}
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
new file mode 100644 (file)
index 0000000..0923f0e
--- /dev/null
@@ -0,0 +1,477 @@
+/*
+ *      uvc_queue.c  --  USB Video Class driver - Buffers management
+ *
+ *      Copyright (C) 2005-2008
+ *          Laurent Pinchart (laurent.pinchart@skynet.be)
+ *
+ *      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/kernel.h>
+#include <linux/version.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+#include <asm/atomic.h>
+
+#include "uvcvideo.h"
+
+/* ------------------------------------------------------------------------
+ * Video buffers queue management.
+ *
+ * Video queues is initialized by uvc_queue_init(). The function performs
+ * basic initialization of the uvc_video_queue struct and never fails.
+ *
+ * Video buffer allocation and freeing are performed by uvc_alloc_buffers and
+ * uvc_free_buffers respectively. The former acquires the video queue lock,
+ * while the later must be called with the lock held (so that allocation can
+ * free previously allocated buffers). Trying to free buffers that are mapped
+ * to user space will return -EBUSY.
+ *
+ * Video buffers are managed using two queues. However, unlike most USB video
+ * drivers which use an in queue and an out queue, we use a main queue which
+ * holds all queued buffers (both 'empty' and 'done' buffers), and an irq
+ * queue which holds empty buffers. This design (copied from video-buf)
+ * minimizes locking in interrupt, as only one queue is shared between
+ * interrupt and user contexts.
+ *
+ * Use cases
+ * ---------
+ *
+ * Unless stated otherwise, all operations which modify the irq buffers queue
+ * are protected by the irq spinlock.
+ *
+ * 1. The user queues the buffers, starts streaming and dequeues a buffer.
+ *
+ *    The buffers are added to the main and irq queues. Both operations are
+ *    protected by the queue lock, and the latert is protected by the irq
+ *    spinlock as well.
+ *
+ *    The completion handler fetches a buffer from the irq queue and fills it
+ *    with video data. If no buffer is available (irq queue empty), the handler
+ *    returns immediately.
+ *
+ *    When the buffer is full, the completion handler removes it from the irq
+ *    queue, marks it as ready (UVC_BUF_STATE_DONE) and wake its wait queue.
+ *    At that point, any process waiting on the buffer will be woken up. If a
+ *    process tries to dequeue a buffer after it has been marked ready, the
+ *    dequeing will succeed immediately.
+ *
+ * 2. Buffers are queued, user is waiting on a buffer and the device gets
+ *    disconnected.
+ *
+ *    When the device is disconnected, the kernel calls the completion handler
+ *    with an appropriate status code. The handler marks all buffers in the
+ *    irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so
+ *    that any process waiting on a buffer gets woken up.
+ *
+ *    Waking up up the first buffer on the irq list is not enough, as the
+ *    process waiting on the buffer might restart the dequeue operation
+ *    immediately.
+ *
+ */
+
+void uvc_queue_init(struct uvc_video_queue *queue)
+{
+       mutex_init(&queue->mutex);
+       spin_lock_init(&queue->irqlock);
+       INIT_LIST_HEAD(&queue->mainqueue);
+       INIT_LIST_HEAD(&queue->irqqueue);
+}
+
+/*
+ * Allocate the video buffers.
+ *
+ * Pages are reserved to make sure they will not be swaped, as they will be
+ * filled in URB completion handler.
+ *
+ * Buffers will be individually mapped, so they must all be page aligned.
+ */
+int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
+               unsigned int buflength)
+{
+       unsigned int bufsize = PAGE_ALIGN(buflength);
+       unsigned int i;
+       void *mem = NULL;
+       int ret;
+
+       if (nbuffers > UVC_MAX_VIDEO_BUFFERS)
+               nbuffers = UVC_MAX_VIDEO_BUFFERS;
+
+       mutex_lock(&queue->mutex);
+
+       if ((ret = uvc_free_buffers(queue)) < 0)
+               goto done;
+
+       /* Bail out if no buffers should be allocated. */
+       if (nbuffers == 0)
+               goto done;
+
+       /* Decrement the number of buffers until allocation succeeds. */
+       for (; nbuffers > 0; --nbuffers) {
+               mem = vmalloc_32(nbuffers * bufsize);
+               if (mem != NULL)
+                       break;
+       }
+
+       if (mem == NULL) {
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       for (i = 0; i < nbuffers; ++i) {
+               memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);
+               queue->buffer[i].buf.index = i;
+               queue->buffer[i].buf.m.offset = i * bufsize;
+               queue->buffer[i].buf.length = buflength;
+               queue->buffer[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               queue->buffer[i].buf.sequence = 0;
+               queue->buffer[i].buf.field = V4L2_FIELD_NONE;
+               queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
+               queue->buffer[i].buf.flags = 0;
+               init_waitqueue_head(&queue->buffer[i].wait);
+       }
+
+       queue->mem = mem;
+       queue->count = nbuffers;
+       queue->buf_size = bufsize;
+       ret = nbuffers;
+
+done:
+       mutex_unlock(&queue->mutex);
+       return ret;
+}
+
+/*
+ * Free the video buffers.
+ *
+ * This function must be called with the queue lock held.
+ */
+int uvc_free_buffers(struct uvc_video_queue *queue)
+{
+       unsigned int i;
+
+       for (i = 0; i < queue->count; ++i) {
+               if (queue->buffer[i].vma_use_count != 0)
+                       return -EBUSY;
+       }
+
+       if (queue->count) {
+               vfree(queue->mem);
+               queue->count = 0;
+       }
+
+       return 0;
+}
+
+static void __uvc_query_buffer(struct uvc_buffer *buf,
+               struct v4l2_buffer *v4l2_buf)
+{
+       memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
+
+       if (buf->vma_use_count)
+               v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
+
+       switch (buf->state) {
+       case UVC_BUF_STATE_ERROR:
+       case UVC_BUF_STATE_DONE:
+               v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
+               break;
+       case UVC_BUF_STATE_QUEUED:
+       case UVC_BUF_STATE_ACTIVE:
+               v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
+               break;
+       case UVC_BUF_STATE_IDLE:
+       default:
+               break;
+       }
+}
+
+int uvc_query_buffer(struct uvc_video_queue *queue,
+               struct v4l2_buffer *v4l2_buf)
+{
+       int ret = 0;
+
+       mutex_lock(&queue->mutex);
+       if (v4l2_buf->index >= queue->count) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
+
+done:
+       mutex_unlock(&queue->mutex);
+       return ret;
+}
+
+/*
+ * Queue a video buffer. Attempting to queue a buffer that has already been
+ * queued will return -EINVAL.
+ */
+int uvc_queue_buffer(struct uvc_video_queue *queue,
+       struct v4l2_buffer *v4l2_buf)
+{
+       struct uvc_buffer *buf;
+       unsigned long flags;
+       int ret = 0;
+
+       uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
+
+       if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           v4l2_buf->memory != V4L2_MEMORY_MMAP) {
+               uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
+                       "and/or memory (%u).\n", v4l2_buf->type,
+                       v4l2_buf->memory);
+               return -EINVAL;
+       }
+
+       mutex_lock(&queue->mutex);
+       if (v4l2_buf->index >= queue->count)  {
+               uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
+               ret = -EINVAL;
+               goto done;
+       }
+
+       buf = &queue->buffer[v4l2_buf->index];
+       if (buf->state != UVC_BUF_STATE_IDLE) {
+               uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state "
+                       "(%u).\n", buf->state);
+               ret = -EINVAL;
+               goto done;
+       }
+
+       spin_lock_irqsave(&queue->irqlock, flags);
+       if (queue->flags & UVC_QUEUE_DISCONNECTED) {
+               spin_unlock_irqrestore(&queue->irqlock, flags);
+               ret = -ENODEV;
+               goto done;
+       }
+       buf->state = UVC_BUF_STATE_QUEUED;
+       buf->buf.bytesused = 0;
+       list_add_tail(&buf->stream, &queue->mainqueue);
+       list_add_tail(&buf->queue, &queue->irqqueue);
+       spin_unlock_irqrestore(&queue->irqlock, flags);
+
+done:
+       mutex_unlock(&queue->mutex);
+       return ret;
+}
+
+static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
+{
+       if (nonblocking) {
+               return (buf->state != UVC_BUF_STATE_QUEUED &&
+                       buf->state != UVC_BUF_STATE_ACTIVE)
+                       ? 0 : -EAGAIN;
+       }
+
+       return wait_event_interruptible(buf->wait,
+               buf->state != UVC_BUF_STATE_QUEUED &&
+               buf->state != UVC_BUF_STATE_ACTIVE);
+}
+
+/*
+ * Dequeue a video buffer. If nonblocking is false, block until a buffer is
+ * available.
+ */
+int uvc_dequeue_buffer(struct uvc_video_queue *queue,
+               struct v4l2_buffer *v4l2_buf, int nonblocking)
+{
+       struct uvc_buffer *buf;
+       int ret = 0;
+
+       if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           v4l2_buf->memory != V4L2_MEMORY_MMAP) {
+               uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
+                       "and/or memory (%u).\n", v4l2_buf->type,
+                       v4l2_buf->memory);
+               return -EINVAL;
+       }
+
+       mutex_lock(&queue->mutex);
+       if (list_empty(&queue->mainqueue)) {
+               uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n");
+               ret = -EINVAL;
+               goto done;
+       }
+
+       buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
+       if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
+               goto done;
+
+       uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
+               buf->buf.index, buf->state, buf->buf.bytesused);
+
+       switch (buf->state) {
+       case UVC_BUF_STATE_ERROR:
+               uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
+                       "(transmission error).\n");
+               ret = -EIO;
+       case UVC_BUF_STATE_DONE:
+               buf->state = UVC_BUF_STATE_IDLE;
+               break;
+
+       case UVC_BUF_STATE_IDLE:
+       case UVC_BUF_STATE_QUEUED:
+       case UVC_BUF_STATE_ACTIVE:
+       default:
+               uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
+                       "(driver bug?).\n", buf->state);
+               ret = -EINVAL;
+               goto done;
+       }
+
+       list_del(&buf->stream);
+       __uvc_query_buffer(buf, v4l2_buf);
+
+done:
+       mutex_unlock(&queue->mutex);
+       return ret;
+}
+
+/*
+ * Poll the video queue.
+ *
+ * This function implements video queue polling and is intended to be used by
+ * the device poll handler.
+ */
+unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
+               poll_table *wait)
+{
+       struct uvc_buffer *buf;
+       unsigned int mask = 0;
+
+       mutex_lock(&queue->mutex);
+       if (list_empty(&queue->mainqueue)) {
+               mask |= POLLERR;
+               goto done;
+       }
+       buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
+
+       poll_wait(file, &buf->wait, wait);
+       if (buf->state == UVC_BUF_STATE_DONE ||
+           buf->state == UVC_BUF_STATE_ERROR)
+               mask |= POLLIN | POLLRDNORM;
+
+done:
+       mutex_unlock(&queue->mutex);
+       return mask;
+}
+
+/*
+ * Enable or disable the video buffers queue.
+ *
+ * The queue must be enabled before starting video acquisition and must be
+ * disabled after stopping it. This ensures that the video buffers queue
+ * state can be properly initialized before buffers are accessed from the
+ * interrupt handler.
+ *
+ * Enabling the video queue initializes parameters (such as sequence number,
+ * sync pattern, ...). If the queue is already enabled, return -EBUSY.
+ *
+ * Disabling the video queue cancels the queue and removes all buffers from
+ * the main queue.
+ *
+ * This function can't be called from interrupt context. Use
+ * uvc_queue_cancel() instead.
+ */
+int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
+{
+       unsigned int i;
+       int ret = 0;
+
+       mutex_lock(&queue->mutex);
+       if (enable) {
+               if (uvc_queue_streaming(queue)) {
+                       ret = -EBUSY;
+                       goto done;
+               }
+               queue->sequence = 0;
+               queue->flags |= UVC_QUEUE_STREAMING;
+       } else {
+               uvc_queue_cancel(queue, 0);
+               INIT_LIST_HEAD(&queue->mainqueue);
+
+               for (i = 0; i < queue->count; ++i)
+                       queue->buffer[i].state = UVC_BUF_STATE_IDLE;
+
+               queue->flags &= ~UVC_QUEUE_STREAMING;
+       }
+
+done:
+       mutex_unlock(&queue->mutex);
+       return ret;
+}
+
+/*
+ * Cancel the video buffers queue.
+ *
+ * Cancelling the queue marks all buffers on the irq queue as erroneous,
+ * wakes them up and remove them from the queue.
+ *
+ * If the disconnect parameter is set, further calls to uvc_queue_buffer will
+ * fail with -ENODEV.
+ *
+ * This function acquires the irq spinlock and can be called from interrupt
+ * context.
+ */
+void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
+{
+       struct uvc_buffer *buf;
+       unsigned long flags;
+
+       spin_lock_irqsave(&queue->irqlock, flags);
+       while (!list_empty(&queue->irqqueue)) {
+               buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
+                                      queue);
+               list_del(&buf->queue);
+               buf->state = UVC_BUF_STATE_ERROR;
+               wake_up(&buf->wait);
+       }
+       /* This must be protected by the irqlock spinlock to avoid race
+        * conditions between uvc_queue_buffer and the disconnection event that
+        * could result in an interruptible wait in uvc_dequeue_buffer. Do not
+        * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
+        * state outside the queue code.
+        */
+       if (disconnect)
+               queue->flags |= UVC_QUEUE_DISCONNECTED;
+       spin_unlock_irqrestore(&queue->irqlock, flags);
+}
+
+struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
+               struct uvc_buffer *buf)
+{
+       struct uvc_buffer *nextbuf;
+       unsigned long flags;
+
+       if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
+           buf->buf.length != buf->buf.bytesused) {
+               buf->state = UVC_BUF_STATE_QUEUED;
+               buf->buf.bytesused = 0;
+               return buf;
+       }
+
+       spin_lock_irqsave(&queue->irqlock, flags);
+       list_del(&buf->queue);
+       if (!list_empty(&queue->irqqueue))
+               nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
+                                          queue);
+       else
+               nextbuf = NULL;
+       spin_unlock_irqrestore(&queue->irqlock, flags);
+
+       buf->buf.sequence = queue->sequence++;
+       do_gettimeofday(&buf->buf.timestamp);
+
+       wake_up(&buf->wait);
+       return nextbuf;
+}
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c
new file mode 100644 (file)
index 0000000..be9084e
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ *      uvc_status.c  --  USB Video Class driver - Status endpoint
+ *
+ *      Copyright (C) 2007-2008
+ *          Laurent Pinchart (laurent.pinchart@skynet.be)
+ *
+ *      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/kernel.h>
+#include <linux/version.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+
+#include "uvcvideo.h"
+
+/* --------------------------------------------------------------------------
+ * Input device
+ */
+static int uvc_input_init(struct uvc_device *dev)
+{
+       struct usb_device *udev = dev->udev;
+       struct input_dev *input;
+       char *phys = NULL;
+       int ret;
+
+       input = input_allocate_device();
+       if (input == NULL)
+               return -ENOMEM;
+
+       phys = kmalloc(6 + strlen(udev->bus->bus_name) + strlen(udev->devpath),
+                       GFP_KERNEL);
+       if (phys == NULL) {
+               ret = -ENOMEM;
+               goto error;
+       }
+       sprintf(phys, "usb-%s-%s", udev->bus->bus_name, udev->devpath);
+
+       input->name = dev->name;
+       input->phys = phys;
+       usb_to_input_id(udev, &input->id);
+       input->dev.parent = &dev->intf->dev;
+
+       set_bit(EV_KEY, input->evbit);
+       set_bit(BTN_0, input->keybit);
+
+       if ((ret = input_register_device(input)) < 0)
+               goto error;
+
+       dev->input = input;
+       return 0;
+
+error:
+       input_free_device(input);
+       kfree(phys);
+       return ret;
+}
+
+static void uvc_input_cleanup(struct uvc_device *dev)
+{
+       if (dev->input)
+               input_unregister_device(dev->input);
+}
+
+/* --------------------------------------------------------------------------
+ * Status interrupt endpoint
+ */
+static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len)
+{
+       if (len < 3) {
+               uvc_trace(UVC_TRACE_STATUS, "Invalid streaming status event "
+                               "received.\n");
+               return;
+       }
+
+       if (data[2] == 0) {
+               if (len < 4)
+                       return;
+               uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n",
+                       data[1], data[3] ? "pressed" : "released", len);
+               if (dev->input)
+                       input_report_key(dev->input, BTN_0, data[3]);
+       } else {
+               uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x "
+                       "len %d.\n", data[1], data[2], data[3], len);
+       }
+}
+
+static void uvc_event_control(struct uvc_device *dev, __u8 *data, int len)
+{
+       char *attrs[3] = { "value", "info", "failure" };
+
+       if (len < 6 || data[2] != 0 || data[4] > 2) {
+               uvc_trace(UVC_TRACE_STATUS, "Invalid control status event "
+                               "received.\n");
+               return;
+       }
+
+       uvc_trace(UVC_TRACE_STATUS, "Control %u/%u %s change len %d.\n",
+               data[1], data[3], attrs[data[4]], len);
+}
+
+static void uvc_status_complete(struct urb *urb)
+{
+       struct uvc_device *dev = urb->context;
+       int len, ret;
+
+       switch (urb->status) {
+       case 0:
+               break;
+
+       case -ENOENT:           /* usb_kill_urb() called. */
+       case -ECONNRESET:       /* usb_unlink_urb() called. */
+       case -ESHUTDOWN:        /* The endpoint is being disabled. */
+       case -EPROTO:           /* Device is disconnected (reported by some
+                                * host controller). */
+               return;
+
+       default:
+               uvc_printk(KERN_WARNING, "Non-zero status (%d) in status "
+                       "completion handler.\n", urb->status);
+               return;
+       }
+
+       len = urb->actual_length;
+       if (len > 0) {
+               switch (dev->status[0] & 0x0f) {
+               case UVC_STATUS_TYPE_CONTROL:
+                       uvc_event_control(dev, dev->status, len);
+                       break;
+
+               case UVC_STATUS_TYPE_STREAMING:
+                       uvc_event_streaming(dev, dev->status, len);
+                       break;
+
+               default:
+                       uvc_printk(KERN_INFO, "unknown event type %u.\n",
+                               dev->status[0]);
+                       break;
+               }
+       }
+
+       /* Resubmit the URB. */
+       urb->interval = dev->int_ep->desc.bInterval;
+       if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+               uvc_printk(KERN_ERR, "Failed to resubmit status URB (%d).\n",
+                       ret);
+       }
+}
+
+int uvc_status_init(struct uvc_device *dev)
+{
+       struct usb_host_endpoint *ep = dev->int_ep;
+       unsigned int pipe;
+       int interval;
+
+       if (ep == NULL)
+               return 0;
+
+       uvc_input_init(dev);
+
+       dev->int_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (dev->int_urb == NULL)
+               return -ENOMEM;
+
+       pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress);
+
+       /* For high-speed interrupt endpoints, the bInterval value is used as
+        * an exponent of two. Some developers forgot about it.
+        */
+       interval = ep->desc.bInterval;
+       if (interval > 16 && dev->udev->speed == USB_SPEED_HIGH &&
+           (dev->quirks & UVC_QUIRK_STATUS_INTERVAL))
+               interval = fls(interval) - 1;
+
+       usb_fill_int_urb(dev->int_urb, dev->udev, pipe,
+               dev->status, sizeof dev->status, uvc_status_complete,
+               dev, interval);
+
+       return usb_submit_urb(dev->int_urb, GFP_KERNEL);
+}
+
+void uvc_status_cleanup(struct uvc_device *dev)
+{
+       usb_kill_urb(dev->int_urb);
+       usb_free_urb(dev->int_urb);
+       uvc_input_cleanup(dev);
+}
+
+int uvc_status_suspend(struct uvc_device *dev)
+{
+       usb_kill_urb(dev->int_urb);
+       return 0;
+}
+
+int uvc_status_resume(struct uvc_device *dev)
+{
+       if (dev->int_urb == NULL)
+               return 0;
+
+       return usb_submit_urb(dev->int_urb, GFP_KERNEL);
+}
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
new file mode 100644 (file)
index 0000000..2e0a665
--- /dev/null
@@ -0,0 +1,1105 @@
+/*
+ *      uvc_v4l2.c  --  USB Video Class driver - V4L2 API
+ *
+ *      Copyright (C) 2005-2008
+ *          Laurent Pinchart (laurent.pinchart@skynet.be)
+ *
+ *      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/kernel.h>
+#include <linux/version.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/wait.h>
+#include <asm/atomic.h>
+
+#include <media/v4l2-common.h>
+
+#include "uvcvideo.h"
+
+/* ------------------------------------------------------------------------
+ * V4L2 interface
+ */
+
+/*
+ * Mapping V4L2 controls to UVC controls can be straighforward if done well.
+ * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
+ * must be grouped (for instance the Red Balance, Blue Balance and Do White
+ * Balance V4L2 controls use the White Balance Component UVC control) or
+ * otherwise translated. The approach we take here is to use a translation
+ * table for the controls which can be mapped directly, and handle the others
+ * manually.
+ */
+static int uvc_v4l2_query_menu(struct uvc_video_device *video,
+       struct v4l2_querymenu *query_menu)
+{
+       struct uvc_menu_info *menu_info;
+       struct uvc_control_mapping *mapping;
+       struct uvc_control *ctrl;
+
+       ctrl = uvc_find_control(video, query_menu->id, &mapping);
+       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU)
+               return -EINVAL;
+
+       if (query_menu->index >= mapping->menu_count)
+               return -EINVAL;
+
+       menu_info = &mapping->menu_info[query_menu->index];
+       strncpy(query_menu->name, menu_info->name, 32);
+       return 0;
+}
+
+/*
+ * Find the frame interval closest to the requested frame interval for the
+ * given frame format and size. This should be done by the device as part of
+ * the Video Probe and Commit negotiation, but some hardware don't implement
+ * that feature.
+ */
+static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval)
+{
+       unsigned int i;
+
+       if (frame->bFrameIntervalType) {
+               __u32 best = -1, dist;
+
+               for (i = 0; i < frame->bFrameIntervalType; ++i) {
+                       dist = interval > frame->dwFrameInterval[i]
+                            ? interval - frame->dwFrameInterval[i]
+                            : frame->dwFrameInterval[i] - interval;
+
+                       if (dist > best)
+                               break;
+
+                       best = dist;
+               }
+
+               interval = frame->dwFrameInterval[i-1];
+       } else {
+               const __u32 min = frame->dwFrameInterval[0];
+               const __u32 max = frame->dwFrameInterval[1];
+               const __u32 step = frame->dwFrameInterval[2];
+
+               interval = min + (interval - min + step/2) / step * step;
+               if (interval > max)
+                       interval = max;
+       }
+
+       return interval;
+}
+
+static int uvc_v4l2_try_format(struct uvc_video_device *video,
+       struct v4l2_format *fmt, struct uvc_streaming_control *probe,
+       struct uvc_format **uvc_format, struct uvc_frame **uvc_frame)
+{
+       struct uvc_format *format = NULL;
+       struct uvc_frame *frame = NULL;
+       __u16 rw, rh;
+       unsigned int d, maxd;
+       unsigned int i;
+       __u32 interval;
+       int ret = 0;
+       __u8 *fcc;
+
+       if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       fcc = (__u8 *)&fmt->fmt.pix.pixelformat;
+       uvc_trace(UVC_TRACE_FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u.\n",
+                       fmt->fmt.pix.pixelformat,
+                       fcc[0], fcc[1], fcc[2], fcc[3],
+                       fmt->fmt.pix.width, fmt->fmt.pix.height);
+
+       /* Check if the hardware supports the requested format. */
+       for (i = 0; i < video->streaming->nformats; ++i) {
+               format = &video->streaming->format[i];
+               if (format->fcc == fmt->fmt.pix.pixelformat)
+                       break;
+       }
+
+       if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) {
+               uvc_trace(UVC_TRACE_FORMAT, "Unsupported format 0x%08x.\n",
+                               fmt->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       /* Find the closest image size. The distance between image sizes is
+        * the size in pixels of the non-overlapping regions between the
+        * requested size and the frame-specified size.
+        */
+       rw = fmt->fmt.pix.width;
+       rh = fmt->fmt.pix.height;
+       maxd = (unsigned int)-1;
+
+       for (i = 0; i < format->nframes; ++i) {
+               __u16 w = format->frame[i].wWidth;
+               __u16 h = format->frame[i].wHeight;
+
+               d = min(w, rw) * min(h, rh);
+               d = w*h + rw*rh - 2*d;
+               if (d < maxd) {
+                       maxd = d;
+                       frame = &format->frame[i];
+               }
+
+               if (maxd == 0)
+                       break;
+       }
+
+       if (frame == NULL) {
+               uvc_trace(UVC_TRACE_FORMAT, "Unsupported size %ux%u.\n",
+                               fmt->fmt.pix.width, fmt->fmt.pix.height);
+               return -EINVAL;
+       }
+
+       /* Use the default frame interval. */
+       interval = frame->dwDefaultFrameInterval;
+       uvc_trace(UVC_TRACE_FORMAT, "Using default frame interval %u.%u us "
+               "(%u.%u fps).\n", interval/10, interval%10, 10000000/interval,
+               (100000000/interval)%10);
+
+       /* Set the format index, frame index and frame interval. */
+       memset(probe, 0, sizeof *probe);
+       probe->bmHint = 1;      /* dwFrameInterval */
+       probe->bFormatIndex = format->index;
+       probe->bFrameIndex = frame->bFrameIndex;
+       probe->dwFrameInterval = uvc_try_frame_interval(frame, interval);
+       /* Some webcams stall the probe control set request when the
+        * dwMaxVideoFrameSize field is set to zero. The UVC specification
+        * clearly states that the field is read-only from the host, so this
+        * is a webcam bug. Set dwMaxVideoFrameSize to the value reported by
+        * the webcam to work around the problem.
+        *
+        * The workaround could probably be enabled for all webcams, so the
+        * quirk can be removed if needed. It's currently useful to detect
+        * webcam bugs and fix them before they hit the market (providing
+        * developers test their webcams with the Linux driver as well as with
+        * the Windows driver).
+        */
+       if (video->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
+               probe->dwMaxVideoFrameSize =
+                       video->streaming->ctrl.dwMaxVideoFrameSize;
+
+       /* Probe the device */
+       if ((ret = uvc_probe_video(video, probe)) < 0)
+               goto done;
+
+       fmt->fmt.pix.width = frame->wWidth;
+       fmt->fmt.pix.height = frame->wHeight;
+       fmt->fmt.pix.field = V4L2_FIELD_NONE;
+       fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8;
+       fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize;
+       fmt->fmt.pix.colorspace = format->colorspace;
+       fmt->fmt.pix.priv = 0;
+
+       if (uvc_format != NULL)
+               *uvc_format = format;
+       if (uvc_frame != NULL)
+               *uvc_frame = frame;
+
+done:
+       return ret;
+}
+
+static int uvc_v4l2_get_format(struct uvc_video_device *video,
+       struct v4l2_format *fmt)
+{
+       struct uvc_format *format = video->streaming->cur_format;
+       struct uvc_frame *frame = video->streaming->cur_frame;
+
+       if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (format == NULL || frame == NULL)
+               return -EINVAL;
+
+       fmt->fmt.pix.pixelformat = format->fcc;
+       fmt->fmt.pix.width = frame->wWidth;
+       fmt->fmt.pix.height = frame->wHeight;
+       fmt->fmt.pix.field = V4L2_FIELD_NONE;
+       fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8;
+       fmt->fmt.pix.sizeimage = video->streaming->ctrl.dwMaxVideoFrameSize;
+       fmt->fmt.pix.colorspace = format->colorspace;
+       fmt->fmt.pix.priv = 0;
+
+       return 0;
+}
+
+static int uvc_v4l2_set_format(struct uvc_video_device *video,
+       struct v4l2_format *fmt)
+{
+       struct uvc_streaming_control probe;
+       struct uvc_format *format;
+       struct uvc_frame *frame;
+       int ret;
+
+       if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (uvc_queue_streaming(&video->queue))
+               return -EBUSY;
+
+       ret = uvc_v4l2_try_format(video, fmt, &probe, &format, &frame);
+       if (ret < 0)
+               return ret;
+
+       if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0)
+               return ret;
+
+       memcpy(&video->streaming->ctrl, &probe, sizeof probe);
+       video->streaming->cur_format = format;
+       video->streaming->cur_frame = frame;
+
+       return 0;
+}
+
+static int uvc_v4l2_get_streamparm(struct uvc_video_device *video,
+               struct v4l2_streamparm *parm)
+{
+       uint32_t numerator, denominator;
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       numerator = video->streaming->ctrl.dwFrameInterval;
+       denominator = 10000000;
+       uvc_simplify_fraction(&numerator, &denominator, 8, 333);
+
+       memset(parm, 0, sizeof *parm);
+       parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+       parm->parm.capture.capturemode = 0;
+       parm->parm.capture.timeperframe.numerator = numerator;
+       parm->parm.capture.timeperframe.denominator = denominator;
+       parm->parm.capture.extendedmode = 0;
+       parm->parm.capture.readbuffers = 0;
+
+       return 0;
+}
+
+static int uvc_v4l2_set_streamparm(struct uvc_video_device *video,
+               struct v4l2_streamparm *parm)
+{
+       struct uvc_frame *frame = video->streaming->cur_frame;
+       struct uvc_streaming_control probe;
+       uint32_t interval;
+       int ret;
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (uvc_queue_streaming(&video->queue))
+               return -EBUSY;
+
+       memcpy(&probe, &video->streaming->ctrl, sizeof probe);
+       interval = uvc_fraction_to_interval(
+                       parm->parm.capture.timeperframe.numerator,
+                       parm->parm.capture.timeperframe.denominator);
+
+       uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",
+                       parm->parm.capture.timeperframe.numerator,
+                       parm->parm.capture.timeperframe.denominator,
+                       interval);
+       probe.dwFrameInterval = uvc_try_frame_interval(frame, interval);
+
+       /* Probe the device with the new settings. */
+       if ((ret = uvc_probe_video(video, &probe)) < 0)
+               return ret;
+
+       /* Commit the new settings. */
+       if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0)
+               return ret;
+
+       memcpy(&video->streaming->ctrl, &probe, sizeof probe);
+
+       /* Return the actual frame period. */
+       parm->parm.capture.timeperframe.numerator = probe.dwFrameInterval;
+       parm->parm.capture.timeperframe.denominator = 10000000;
+       uvc_simplify_fraction(&parm->parm.capture.timeperframe.numerator,
+                               &parm->parm.capture.timeperframe.denominator,
+                               8, 333);
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------------
+ * Privilege management
+ */
+
+/*
+ * Privilege management is the multiple-open implementation basis. The current
+ * implementation is completely transparent for the end-user and doesn't
+ * require explicit use of the VIDIOC_G_PRIORITY and VIDIOC_S_PRIORITY ioctls.
+ * Those ioctls enable finer control on the device (by making possible for a
+ * user to request exclusive access to a device), but are not mature yet.
+ * Switching to the V4L2 priority mechanism might be considered in the future
+ * if this situation changes.
+ *
+ * Each open instance of a UVC device can either be in a privileged or
+ * unprivileged state. Only a single instance can be in a privileged state at
+ * a given time. Trying to perform an operation which requires privileges will
+ * automatically acquire the required privileges if possible, or return -EBUSY
+ * otherwise. Privileges are dismissed when closing the instance.
+ *
+ * Operations which require privileges are:
+ *
+ * - VIDIOC_S_INPUT
+ * - VIDIOC_S_PARM
+ * - VIDIOC_S_FMT
+ * - VIDIOC_TRY_FMT
+ * - VIDIOC_REQBUFS
+ */
+static int uvc_acquire_privileges(struct uvc_fh *handle)
+{
+       int ret = 0;
+
+       /* Always succeed if the handle is already privileged. */
+       if (handle->state == UVC_HANDLE_ACTIVE)
+               return 0;
+
+       /* Check if the device already has a privileged handle. */
+       mutex_lock(&uvc_driver.open_mutex);
+       if (atomic_inc_return(&handle->device->active) != 1) {
+               atomic_dec(&handle->device->active);
+               ret = -EBUSY;
+               goto done;
+       }
+
+       handle->state = UVC_HANDLE_ACTIVE;
+
+done:
+       mutex_unlock(&uvc_driver.open_mutex);
+       return ret;
+}
+
+static void uvc_dismiss_privileges(struct uvc_fh *handle)
+{
+       if (handle->state == UVC_HANDLE_ACTIVE)
+               atomic_dec(&handle->device->active);
+
+       handle->state = UVC_HANDLE_PASSIVE;
+}
+
+static int uvc_has_privileges(struct uvc_fh *handle)
+{
+       return handle->state == UVC_HANDLE_ACTIVE;
+}
+
+/* ------------------------------------------------------------------------
+ * V4L2 file operations
+ */
+
+static int uvc_v4l2_open(struct inode *inode, struct file *file)
+{
+       struct video_device *vdev;
+       struct uvc_video_device *video;
+       struct uvc_fh *handle;
+       int ret = 0;
+
+       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n");
+       mutex_lock(&uvc_driver.open_mutex);
+       vdev = video_devdata(file);
+       video = video_get_drvdata(vdev);
+
+       if (video->dev->state & UVC_DEV_DISCONNECTED) {
+               ret = -ENODEV;
+               goto done;
+       }
+
+       ret = usb_autopm_get_interface(video->dev->intf);
+       if (ret < 0)
+               goto done;
+
+       /* Create the device handle. */
+       handle = kzalloc(sizeof *handle, GFP_KERNEL);
+       if (handle == NULL) {
+               usb_autopm_put_interface(video->dev->intf);
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       handle->device = video;
+       handle->state = UVC_HANDLE_PASSIVE;
+       file->private_data = handle;
+
+       kref_get(&video->dev->kref);
+
+done:
+       mutex_unlock(&uvc_driver.open_mutex);
+       return ret;
+}
+
+static int uvc_v4l2_release(struct inode *inode, struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct uvc_video_device *video = video_get_drvdata(vdev);
+       struct uvc_fh *handle = (struct uvc_fh *)file->private_data;
+
+       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");
+
+       /* Only free resources if this is a privileged handle. */
+       if (uvc_has_privileges(handle)) {
+               uvc_video_enable(video, 0);
+
+               mutex_lock(&video->queue.mutex);
+               if (uvc_free_buffers(&video->queue) < 0)
+                       uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to "
+                                       "free buffers.\n");
+               mutex_unlock(&video->queue.mutex);
+       }
+
+       /* Release the file handle. */
+       uvc_dismiss_privileges(handle);
+       kfree(handle);
+       file->private_data = NULL;
+
+       usb_autopm_put_interface(video->dev->intf);
+       kref_put(&video->dev->kref, uvc_delete);
+       return 0;
+}
+
+static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file,
+                    unsigned int cmd, void *arg)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct uvc_video_device *video = video_get_drvdata(vdev);
+       struct uvc_fh *handle = (struct uvc_fh *)file->private_data;
+       int ret = 0;
+
+       if (uvc_trace_param & UVC_TRACE_IOCTL)
+               v4l_printk_ioctl(cmd);
+
+       switch (cmd) {
+       /* Query capabilities */
+       case VIDIOC_QUERYCAP:
+       {
+               struct v4l2_capability *cap = arg;
+
+               memset(cap, 0, sizeof *cap);
+               strncpy(cap->driver, "uvcvideo", sizeof cap->driver);
+               strncpy(cap->card, vdev->name, 32);
+               strncpy(cap->bus_info, video->dev->udev->bus->bus_name,
+                       sizeof cap->bus_info);
+               cap->version = DRIVER_VERSION_NUMBER;
+               cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
+                                 | V4L2_CAP_STREAMING;
+               break;
+       }
+
+       /* Get, Set & Query control */
+       case VIDIOC_QUERYCTRL:
+               return uvc_query_v4l2_ctrl(video, arg);
+
+       case VIDIOC_G_CTRL:
+       {
+               struct v4l2_control *ctrl = arg;
+               struct v4l2_ext_control xctrl;
+
+               memset(&xctrl, 0, sizeof xctrl);
+               xctrl.id = ctrl->id;
+
+               uvc_ctrl_begin(video);
+               ret = uvc_ctrl_get(video, &xctrl);
+               uvc_ctrl_rollback(video);
+               if (ret >= 0)
+                       ctrl->value = xctrl.value;
+               break;
+       }
+
+       case VIDIOC_S_CTRL:
+       {
+               struct v4l2_control *ctrl = arg;
+               struct v4l2_ext_control xctrl;
+
+               memset(&xctrl, 0, sizeof xctrl);
+               xctrl.id = ctrl->id;
+               xctrl.value = ctrl->value;
+
+               uvc_ctrl_begin(video);
+               ret = uvc_ctrl_set(video, &xctrl);
+               if (ret < 0) {
+                       uvc_ctrl_rollback(video);
+                       return ret;
+               }
+               ret = uvc_ctrl_commit(video);
+               break;
+       }
+
+       case VIDIOC_QUERYMENU:
+               return uvc_v4l2_query_menu(video, arg);
+
+       case VIDIOC_G_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *ctrls = arg;
+               struct v4l2_ext_control *ctrl = ctrls->controls;
+               unsigned int i;
+
+               uvc_ctrl_begin(video);
+               for (i = 0; i < ctrls->count; ++ctrl, ++i) {
+                       ret = uvc_ctrl_get(video, ctrl);
+                       if (ret < 0) {
+                               uvc_ctrl_rollback(video);
+                               ctrls->error_idx = i;
+                               return ret;
+                       }
+               }
+               ctrls->error_idx = 0;
+               ret = uvc_ctrl_rollback(video);
+               break;
+       }
+
+       case VIDIOC_S_EXT_CTRLS:
+       case VIDIOC_TRY_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *ctrls = arg;
+               struct v4l2_ext_control *ctrl = ctrls->controls;
+               unsigned int i;
+
+               ret = uvc_ctrl_begin(video);
+               if (ret < 0)
+                       return ret;
+
+               for (i = 0; i < ctrls->count; ++ctrl, ++i) {
+                       ret = uvc_ctrl_set(video, ctrl);
+                       if (ret < 0) {
+                               uvc_ctrl_rollback(video);
+                               ctrls->error_idx = i;
+                               return ret;
+                       }
+               }
+
+               ctrls->error_idx = 0;
+
+               if (cmd == VIDIOC_S_EXT_CTRLS)
+                       ret = uvc_ctrl_commit(video);
+               else
+                       ret = uvc_ctrl_rollback(video);
+               break;
+       }
+
+       /* Get, Set & Enum input */
+       case VIDIOC_ENUMINPUT:
+       {
+               const struct uvc_entity *selector = video->selector;
+               struct v4l2_input *input = arg;
+               struct uvc_entity *iterm = NULL;
+               u32 index = input->index;
+               int pin = 0;
+
+               if (selector == NULL ||
+                   (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+                       if (index != 0)
+                               return -EINVAL;
+                       iterm = list_first_entry(&video->iterms,
+                                       struct uvc_entity, chain);
+                       pin = iterm->id;
+               } else if (pin < selector->selector.bNrInPins) {
+                       pin = selector->selector.baSourceID[index];
+                       list_for_each_entry(iterm, video->iterms.next, chain) {
+                               if (iterm->id == pin)
+                                       break;
+                       }
+               }
+
+               if (iterm == NULL || iterm->id != pin)
+                       return -EINVAL;
+
+               memset(input, 0, sizeof *input);
+               input->index = index;
+               strncpy(input->name, iterm->name, sizeof input->name);
+               if (UVC_ENTITY_TYPE(iterm) == ITT_CAMERA)
+                       input->type = V4L2_INPUT_TYPE_CAMERA;
+               break;
+       }
+
+       case VIDIOC_G_INPUT:
+       {
+               u8 input;
+
+               if (video->selector == NULL ||
+                   (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+                       *(int *)arg = 0;
+                       break;
+               }
+
+               ret = uvc_query_ctrl(video->dev, GET_CUR, video->selector->id,
+                       video->dev->intfnum, SU_INPUT_SELECT_CONTROL,
+                       &input, 1);
+               if (ret < 0)
+                       return ret;
+
+               *(int *)arg = input - 1;
+               break;
+       }
+
+       case VIDIOC_S_INPUT:
+       {
+               u8 input = *(u32 *)arg + 1;
+
+               if ((ret = uvc_acquire_privileges(handle)) < 0)
+                       return ret;
+
+               if (video->selector == NULL ||
+                   (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+                       if (input != 1)
+                               return -EINVAL;
+                       break;
+               }
+
+               if (input > video->selector->selector.bNrInPins)
+                       return -EINVAL;
+
+               return uvc_query_ctrl(video->dev, SET_CUR, video->selector->id,
+                       video->dev->intfnum, SU_INPUT_SELECT_CONTROL,
+                       &input, 1);
+       }
+
+       /* Try, Get, Set & Enum format */
+       case VIDIOC_ENUM_FMT:
+       {
+               struct v4l2_fmtdesc *fmt = arg;
+               struct uvc_format *format;
+
+               if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+                   fmt->index >= video->streaming->nformats)
+                       return -EINVAL;
+
+               format = &video->streaming->format[fmt->index];
+               fmt->flags = 0;
+               if (format->flags & UVC_FMT_FLAG_COMPRESSED)
+                       fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
+               strncpy(fmt->description, format->name,
+                       sizeof fmt->description);
+               fmt->description[sizeof fmt->description - 1] = 0;
+               fmt->pixelformat = format->fcc;
+               break;
+       }
+
+       case VIDIOC_TRY_FMT:
+       {
+               struct uvc_streaming_control probe;
+
+               if ((ret = uvc_acquire_privileges(handle)) < 0)
+                       return ret;
+
+               return uvc_v4l2_try_format(video, arg, &probe, NULL, NULL);
+       }
+
+       case VIDIOC_S_FMT:
+               if ((ret = uvc_acquire_privileges(handle)) < 0)
+                       return ret;
+
+               return uvc_v4l2_set_format(video, arg);
+
+       case VIDIOC_G_FMT:
+               return uvc_v4l2_get_format(video, arg);
+
+       /* Frame size enumeration */
+       case VIDIOC_ENUM_FRAMESIZES:
+       {
+               struct v4l2_frmsizeenum *fsize = arg;
+               struct uvc_format *format = NULL;
+               struct uvc_frame *frame;
+               int i;
+
+               /* Look for the given pixel format */
+               for (i = 0; i < video->streaming->nformats; i++) {
+                       if (video->streaming->format[i].fcc ==
+                                       fsize->pixel_format) {
+                               format = &video->streaming->format[i];
+                               break;
+                       }
+               }
+               if (format == NULL)
+                       return -EINVAL;
+
+               if (fsize->index >= format->nframes)
+                       return -EINVAL;
+
+               frame = &format->frame[fsize->index];
+               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+               fsize->discrete.width = frame->wWidth;
+               fsize->discrete.height = frame->wHeight;
+               break;
+       }
+
+       /* Frame interval enumeration */
+       case VIDIOC_ENUM_FRAMEINTERVALS:
+       {
+               struct v4l2_frmivalenum *fival = arg;
+               struct uvc_format *format = NULL;
+               struct uvc_frame *frame = NULL;
+               int i;
+
+               /* Look for the given pixel format and frame size */
+               for (i = 0; i < video->streaming->nformats; i++) {
+                       if (video->streaming->format[i].fcc ==
+                                       fival->pixel_format) {
+                               format = &video->streaming->format[i];
+                               break;
+                       }
+               }
+               if (format == NULL)
+                       return -EINVAL;
+
+               for (i = 0; i < format->nframes; i++) {
+                       if (format->frame[i].wWidth == fival->width &&
+                           format->frame[i].wHeight == fival->height) {
+                               frame = &format->frame[i];
+                               break;
+                       }
+               }
+               if (frame == NULL)
+                       return -EINVAL;
+
+               if (frame->bFrameIntervalType) {
+                       if (fival->index >= frame->bFrameIntervalType)
+                               return -EINVAL;
+
+                       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+                       fival->discrete.numerator =
+                               frame->dwFrameInterval[fival->index];
+                       fival->discrete.denominator = 10000000;
+                       uvc_simplify_fraction(&fival->discrete.numerator,
+                               &fival->discrete.denominator, 8, 333);
+               } else {
+                       fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
+                       fival->stepwise.min.numerator =
+                               frame->dwFrameInterval[0];
+                       fival->stepwise.min.denominator = 10000000;
+                       fival->stepwise.max.numerator =
+                               frame->dwFrameInterval[1];
+                       fival->stepwise.max.denominator = 10000000;
+                       fival->stepwise.step.numerator =
+                               frame->dwFrameInterval[2];
+                       fival->stepwise.step.denominator = 10000000;
+                       uvc_simplify_fraction(&fival->stepwise.min.numerator,
+                               &fival->stepwise.min.denominator, 8, 333);
+                       uvc_simplify_fraction(&fival->stepwise.max.numerator,
+                               &fival->stepwise.max.denominator, 8, 333);
+                       uvc_simplify_fraction(&fival->stepwise.step.numerator,
+                               &fival->stepwise.step.denominator, 8, 333);
+               }
+               break;
+       }
+
+       /* Get & Set streaming parameters */
+       case VIDIOC_G_PARM:
+               return uvc_v4l2_get_streamparm(video, arg);
+
+       case VIDIOC_S_PARM:
+               if ((ret = uvc_acquire_privileges(handle)) < 0)
+                       return ret;
+
+               return uvc_v4l2_set_streamparm(video, arg);
+
+       /* Cropping and scaling */
+       case VIDIOC_CROPCAP:
+       {
+               struct v4l2_cropcap *ccap = arg;
+               struct uvc_frame *frame = video->streaming->cur_frame;
+
+               if (ccap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       return -EINVAL;
+
+               ccap->bounds.left = 0;
+               ccap->bounds.top = 0;
+               ccap->bounds.width = frame->wWidth;
+               ccap->bounds.height = frame->wHeight;
+
+               ccap->defrect = ccap->bounds;
+
+               ccap->pixelaspect.numerator = 1;
+               ccap->pixelaspect.denominator = 1;
+               break;
+       }
+
+       case VIDIOC_G_CROP:
+       case VIDIOC_S_CROP:
+               return -EINVAL;
+
+       /* Buffers & streaming */
+       case VIDIOC_REQBUFS:
+       {
+               struct v4l2_requestbuffers *rb = arg;
+               unsigned int bufsize =
+                       video->streaming->ctrl.dwMaxVideoFrameSize;
+
+               if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+                   rb->memory != V4L2_MEMORY_MMAP)
+                       return -EINVAL;
+
+               if ((ret = uvc_acquire_privileges(handle)) < 0)
+                       return ret;
+
+               ret = uvc_alloc_buffers(&video->queue, rb->count, bufsize);
+               if (ret < 0)
+                       return ret;
+
+               if (!(video->streaming->cur_format->flags &
+                   UVC_FMT_FLAG_COMPRESSED))
+                       video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE;
+
+               rb->count = ret;
+               ret = 0;
+               break;
+       }
+
+       case VIDIOC_QUERYBUF:
+       {
+               struct v4l2_buffer *buf = arg;
+
+               if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       return -EINVAL;
+
+               if (!uvc_has_privileges(handle))
+                       return -EBUSY;
+
+               return uvc_query_buffer(&video->queue, buf);
+       }
+
+       case VIDIOC_QBUF:
+               if (!uvc_has_privileges(handle))
+                       return -EBUSY;
+
+               return uvc_queue_buffer(&video->queue, arg);
+
+       case VIDIOC_DQBUF:
+               if (!uvc_has_privileges(handle))
+                       return -EBUSY;
+
+               return uvc_dequeue_buffer(&video->queue, arg,
+                       file->f_flags & O_NONBLOCK);
+
+       case VIDIOC_STREAMON:
+       {
+               int *type = arg;
+
+               if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       return -EINVAL;
+
+               if (!uvc_has_privileges(handle))
+                       return -EBUSY;
+
+               if ((ret = uvc_video_enable(video, 1)) < 0)
+                       return ret;
+               break;
+       }
+
+       case VIDIOC_STREAMOFF:
+       {
+               int *type = arg;
+
+               if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       return -EINVAL;
+
+               if (!uvc_has_privileges(handle))
+                       return -EBUSY;
+
+               return uvc_video_enable(video, 0);
+       }
+
+       /* Analog video standards make no sense for digital cameras. */
+       case VIDIOC_ENUMSTD:
+       case VIDIOC_QUERYSTD:
+       case VIDIOC_G_STD:
+       case VIDIOC_S_STD:
+
+       case VIDIOC_OVERLAY:
+
+       case VIDIOC_ENUMAUDIO:
+       case VIDIOC_ENUMAUDOUT:
+
+       case VIDIOC_ENUMOUTPUT:
+               uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd);
+               return -EINVAL;
+
+       /* Dynamic controls. */
+       case UVCIOC_CTRL_ADD:
+       {
+               struct uvc_xu_control_info *xinfo = arg;
+               struct uvc_control_info *info;
+
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+
+               info = kmalloc(sizeof *info, GFP_KERNEL);
+               if (info == NULL)
+                       return -ENOMEM;
+
+               memcpy(info->entity, xinfo->entity, sizeof info->entity);
+               info->index = xinfo->index;
+               info->selector = xinfo->selector;
+               info->size = xinfo->size;
+               info->flags = xinfo->flags;
+
+               info->flags |= UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX |
+                               UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF;
+
+               ret = uvc_ctrl_add_info(info);
+               if (ret < 0)
+                       kfree(info);
+               break;
+       }
+
+       case UVCIOC_CTRL_MAP:
+       {
+               struct uvc_xu_control_mapping *xmap = arg;
+               struct uvc_control_mapping *map;
+
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+
+               map = kmalloc(sizeof *map, GFP_KERNEL);
+               if (map == NULL)
+                       return -ENOMEM;
+
+               map->id = xmap->id;
+               memcpy(map->name, xmap->name, sizeof map->name);
+               memcpy(map->entity, xmap->entity, sizeof map->entity);
+               map->selector = xmap->selector;
+               map->size = xmap->size;
+               map->offset = xmap->offset;
+               map->v4l2_type = xmap->v4l2_type;
+               map->data_type = xmap->data_type;
+
+               ret = uvc_ctrl_add_mapping(map);
+               if (ret < 0)
+                       kfree(map);
+               break;
+       }
+
+       case UVCIOC_CTRL_GET:
+               return uvc_xu_ctrl_query(video, arg, 0);
+
+       case UVCIOC_CTRL_SET:
+               return uvc_xu_ctrl_query(video, arg, 1);
+
+       default:
+               if ((ret = v4l_compat_translate_ioctl(inode, file, cmd, arg,
+                       uvc_v4l2_do_ioctl)) == -ENOIOCTLCMD)
+                       uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n",
+                                 cmd);
+               return ret;
+       }
+
+       return ret;
+}
+
+static int uvc_v4l2_ioctl(struct inode *inode, struct file *file,
+                    unsigned int cmd, unsigned long arg)
+{
+       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_ioctl\n");
+       return video_usercopy(inode, file, cmd, arg, uvc_v4l2_do_ioctl);
+}
+
+static ssize_t uvc_v4l2_read(struct file *file, char __user *data,
+                   size_t count, loff_t *ppos)
+{
+       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n");
+       return -ENODEV;
+}
+
+/*
+ * VMA operations.
+ */
+static void uvc_vm_open(struct vm_area_struct *vma)
+{
+       struct uvc_buffer *buffer = vma->vm_private_data;
+       buffer->vma_use_count++;
+}
+
+static void uvc_vm_close(struct vm_area_struct *vma)
+{
+       struct uvc_buffer *buffer = vma->vm_private_data;
+       buffer->vma_use_count--;
+}
+
+static struct vm_operations_struct uvc_vm_ops = {
+       .open           = uvc_vm_open,
+       .close          = uvc_vm_close,
+};
+
+static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct uvc_video_device *video = video_get_drvdata(vdev);
+       struct uvc_buffer *buffer;
+       struct page *page;
+       unsigned long addr, start, size;
+       unsigned int i;
+       int ret = 0;
+
+       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");
+
+       start = vma->vm_start;
+       size = vma->vm_end - vma->vm_start;
+
+       mutex_lock(&video->queue.mutex);
+
+       for (i = 0; i < video->queue.count; ++i) {
+               buffer = &video->queue.buffer[i];
+               if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
+                       break;
+       }
+
+       if (i == video->queue.count || size != video->queue.buf_size) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       /*
+        * VM_IO marks the area as being an mmaped region for I/O to a
+        * device. It also prevents the region from being core dumped.
+        */
+       vma->vm_flags |= VM_IO;
+
+       addr = (unsigned long)video->queue.mem + buffer->buf.m.offset;
+       while (size > 0) {
+               page = vmalloc_to_page((void *)addr);
+               if ((ret = vm_insert_page(vma, start, page)) < 0)
+                       goto done;
+
+               start += PAGE_SIZE;
+               addr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       vma->vm_ops = &uvc_vm_ops;
+       vma->vm_private_data = buffer;
+       uvc_vm_open(vma);
+
+done:
+       mutex_unlock(&video->queue.mutex);
+       return ret;
+}
+
+static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct uvc_video_device *video = video_get_drvdata(vdev);
+
+       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n");
+
+       return uvc_queue_poll(&video->queue, file, wait);
+}
+
+struct file_operations uvc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = uvc_v4l2_open,
+       .release        = uvc_v4l2_release,
+       .ioctl          = uvc_v4l2_ioctl,
+       .compat_ioctl   = v4l_compat_ioctl32,
+       .llseek         = no_llseek,
+       .read           = uvc_v4l2_read,
+       .mmap           = uvc_v4l2_mmap,
+       .poll           = uvc_v4l2_poll,
+};
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
new file mode 100644 (file)
index 0000000..6faf1fb
--- /dev/null
@@ -0,0 +1,934 @@
+/*
+ *      uvc_video.c  --  USB Video Class driver - Video handling
+ *
+ *      Copyright (C) 2005-2008
+ *          Laurent Pinchart (laurent.pinchart@skynet.be)
+ *
+ *      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/kernel.h>
+#include <linux/version.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+#include <asm/atomic.h>
+#include <asm/unaligned.h>
+
+#include <media/v4l2-common.h>
+
+#include "uvcvideo.h"
+
+/* ------------------------------------------------------------------------
+ * UVC Controls
+ */
+
+static int __uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
+                       __u8 intfnum, __u8 cs, void *data, __u16 size,
+                       int timeout)
+{
+       __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+       unsigned int pipe;
+       int ret;
+
+       pipe = (query & 0x80) ? usb_rcvctrlpipe(dev->udev, 0)
+                             : usb_sndctrlpipe(dev->udev, 0);
+       type |= (query & 0x80) ? USB_DIR_IN : USB_DIR_OUT;
+
+       ret = usb_control_msg(dev->udev, pipe, query, type, cs << 8,
+                       unit << 8 | intfnum, data, size, timeout);
+
+       if (ret != size) {
+               uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u "
+                       "(unit %u) : %d (exp. %u).\n", query, cs, unit, ret,
+                       size);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
+                       __u8 intfnum, __u8 cs, void *data, __u16 size)
+{
+       return __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size,
+                               UVC_CTRL_CONTROL_TIMEOUT);
+}
+
+static void uvc_fixup_buffer_size(struct uvc_video_device *video,
+       struct uvc_streaming_control *ctrl)
+{
+       struct uvc_format *format;
+       struct uvc_frame *frame;
+
+       if (ctrl->bFormatIndex <= 0 ||
+           ctrl->bFormatIndex > video->streaming->nformats)
+               return;
+
+       format = &video->streaming->format[ctrl->bFormatIndex - 1];
+
+       if (ctrl->bFrameIndex <= 0 ||
+           ctrl->bFrameIndex > format->nframes)
+               return;
+
+       frame = &format->frame[ctrl->bFrameIndex - 1];
+
+       if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) ||
+            (ctrl->dwMaxVideoFrameSize == 0 &&
+             video->dev->uvc_version < 0x0110))
+               ctrl->dwMaxVideoFrameSize =
+                       frame->dwMaxVideoFrameBufferSize;
+}
+
+static int uvc_get_video_ctrl(struct uvc_video_device *video,
+       struct uvc_streaming_control *ctrl, int probe, __u8 query)
+{
+       __u8 data[34];
+       __u8 size;
+       int ret;
+
+       size = video->dev->uvc_version >= 0x0110 ? 34 : 26;
+       ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum,
+               probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size,
+               UVC_CTRL_STREAMING_TIMEOUT);
+
+       if (ret < 0)
+               return ret;
+
+       ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]);
+       ctrl->bFormatIndex = data[2];
+       ctrl->bFrameIndex = data[3];
+       ctrl->dwFrameInterval = le32_to_cpup((__le32 *)&data[4]);
+       ctrl->wKeyFrameRate = le16_to_cpup((__le16 *)&data[8]);
+       ctrl->wPFrameRate = le16_to_cpup((__le16 *)&data[10]);
+       ctrl->wCompQuality = le16_to_cpup((__le16 *)&data[12]);
+       ctrl->wCompWindowSize = le16_to_cpup((__le16 *)&data[14]);
+       ctrl->wDelay = le16_to_cpup((__le16 *)&data[16]);
+       ctrl->dwMaxVideoFrameSize =
+               le32_to_cpu(get_unaligned((__le32 *)&data[18]));
+       ctrl->dwMaxPayloadTransferSize =
+               le32_to_cpu(get_unaligned((__le32 *)&data[22]));
+
+       if (size == 34) {
+               ctrl->dwClockFrequency =
+                       le32_to_cpu(get_unaligned((__le32 *)&data[26]));
+               ctrl->bmFramingInfo = data[30];
+               ctrl->bPreferedVersion = data[31];
+               ctrl->bMinVersion = data[32];
+               ctrl->bMaxVersion = data[33];
+       } else {
+               ctrl->dwClockFrequency = video->dev->clock_frequency;
+               ctrl->bmFramingInfo = 0;
+               ctrl->bPreferedVersion = 0;
+               ctrl->bMinVersion = 0;
+               ctrl->bMaxVersion = 0;
+       }
+
+       /* Some broken devices return a null or wrong dwMaxVideoFrameSize.
+        * Try to get the value from the format and frame descriptor.
+        */
+       uvc_fixup_buffer_size(video, ctrl);
+
+       return 0;
+}
+
+int uvc_set_video_ctrl(struct uvc_video_device *video,
+       struct uvc_streaming_control *ctrl, int probe)
+{
+       __u8 data[34];
+       __u8 size;
+
+       size = video->dev->uvc_version >= 0x0110 ? 34 : 26;
+       memset(data, 0, sizeof data);
+
+       *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint);
+       data[2] = ctrl->bFormatIndex;
+       data[3] = ctrl->bFrameIndex;
+       *(__le32 *)&data[4] = cpu_to_le32(ctrl->dwFrameInterval);
+       *(__le16 *)&data[8] = cpu_to_le16(ctrl->wKeyFrameRate);
+       *(__le16 *)&data[10] = cpu_to_le16(ctrl->wPFrameRate);
+       *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality);
+       *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize);
+       *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay);
+       /* Note: Some of the fields below are not required for IN devices (see
+        * UVC spec, 4.3.1.1), but we still copy them in case support for OUT
+        * devices is added in the future. */
+       put_unaligned(cpu_to_le32(ctrl->dwMaxVideoFrameSize),
+               (__le32 *)&data[18]);
+       put_unaligned(cpu_to_le32(ctrl->dwMaxPayloadTransferSize),
+               (__le32 *)&data[22]);
+
+       if (size == 34) {
+               put_unaligned(cpu_to_le32(ctrl->dwClockFrequency),
+                       (__le32 *)&data[26]);
+               data[30] = ctrl->bmFramingInfo;
+               data[31] = ctrl->bPreferedVersion;
+               data[32] = ctrl->bMinVersion;
+               data[33] = ctrl->bMaxVersion;
+       }
+
+       return __uvc_query_ctrl(video->dev, SET_CUR, 0,
+               video->streaming->intfnum,
+               probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size,
+               UVC_CTRL_STREAMING_TIMEOUT);
+}
+
+int uvc_probe_video(struct uvc_video_device *video,
+       struct uvc_streaming_control *probe)
+{
+       struct uvc_streaming_control probe_min, probe_max;
+       __u16 bandwidth;
+       unsigned int i;
+       int ret;
+
+       mutex_lock(&video->streaming->mutex);
+
+       /* Perform probing. The device should adjust the requested values
+        * according to its capabilities. However, some devices, namely the
+        * first generation UVC Logitech webcams, don't implement the Video
+        * Probe control properly, and just return the needed bandwidth. For
+        * that reason, if the needed bandwidth exceeds the maximum available
+        * bandwidth, try to lower the quality.
+        */
+       if ((ret = uvc_set_video_ctrl(video, probe, 1)) < 0)
+               goto done;
+
+       /* Get the minimum and maximum values for compression settings. */
+       if (!(video->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) {
+               ret = uvc_get_video_ctrl(video, &probe_min, 1, GET_MIN);
+               if (ret < 0)
+                       goto done;
+               ret = uvc_get_video_ctrl(video, &probe_max, 1, GET_MAX);
+               if (ret < 0)
+                       goto done;
+
+               probe->wCompQuality = probe_max.wCompQuality;
+       }
+
+       for (i = 0; i < 2; ++i) {
+               if ((ret = uvc_set_video_ctrl(video, probe, 1)) < 0 ||
+                   (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0)
+                       goto done;
+
+               if (video->streaming->intf->num_altsetting == 1)
+                       break;
+
+               bandwidth = probe->dwMaxPayloadTransferSize;
+               if (bandwidth <= video->streaming->maxpsize)
+                       break;
+
+               if (video->dev->quirks & UVC_QUIRK_PROBE_MINMAX) {
+                       ret = -ENOSPC;
+                       goto done;
+               }
+
+               /* TODO: negotiate compression parameters */
+               probe->wKeyFrameRate = probe_min.wKeyFrameRate;
+               probe->wPFrameRate = probe_min.wPFrameRate;
+               probe->wCompQuality = probe_max.wCompQuality;
+               probe->wCompWindowSize = probe_min.wCompWindowSize;
+       }
+
+done:
+       mutex_unlock(&video->streaming->mutex);
+       return ret;
+}
+
+/* ------------------------------------------------------------------------
+ * Video codecs
+ */
+
+/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
+#define UVC_STREAM_EOH (1 << 7)
+#define UVC_STREAM_ERR (1 << 6)
+#define UVC_STREAM_STI (1 << 5)
+#define UVC_STREAM_RES (1 << 4)
+#define UVC_STREAM_SCR (1 << 3)
+#define UVC_STREAM_PTS (1 << 2)
+#define UVC_STREAM_EOF (1 << 1)
+#define UVC_STREAM_FID (1 << 0)
+
+/* Video payload decoding is handled by uvc_video_decode_start(),
+ * uvc_video_decode_data() and uvc_video_decode_end().
+ *
+ * uvc_video_decode_start is called with URB data at the start of a bulk or
+ * isochronous payload. It processes header data and returns the header size
+ * in bytes if successful. If an error occurs, it returns a negative error
+ * code. The following error codes have special meanings.
+ *
+ * - EAGAIN informs the caller that the current video buffer should be marked
+ *   as done, and that the function should be called again with the same data
+ *   and a new video buffer. This is used when end of frame conditions can be
+ *   reliably detected at the beginning of the next frame only.
+ *
+ * If an error other than -EAGAIN is returned, the caller will drop the current
+ * payload. No call to uvc_video_decode_data and uvc_video_decode_end will be
+ * made until the next payload. -ENODATA can be used to drop the current
+ * payload if no other error code is appropriate.
+ *
+ * uvc_video_decode_data is called for every URB with URB data. It copies the
+ * data to the video buffer.
+ *
+ * uvc_video_decode_end is called with header data at the end of a bulk or
+ * isochronous payload. It performs any additional header data processing and
+ * returns 0 or a negative error code if an error occured. As header data have
+ * already been processed by uvc_video_decode_start, this functions isn't
+ * required to perform sanity checks a second time.
+ *
+ * For isochronous transfers where a payload is always transfered in a single
+ * URB, the three functions will be called in a row.
+ *
+ * To let the decoder process header data and update its internal state even
+ * when no video buffer is available, uvc_video_decode_start must be prepared
+ * to be called with a NULL buf parameter. uvc_video_decode_data and
+ * uvc_video_decode_end will never be called with a NULL buffer.
+ */
+static int uvc_video_decode_start(struct uvc_video_device *video,
+               struct uvc_buffer *buf, const __u8 *data, int len)
+{
+       __u8 fid;
+
+       /* Sanity checks:
+        * - packet must be at least 2 bytes long
+        * - bHeaderLength value must be at least 2 bytes (see above)
+        * - bHeaderLength value can't be larger than the packet size.
+        */
+       if (len < 2 || data[0] < 2 || data[0] > len)
+               return -EINVAL;
+
+       /* Skip payloads marked with the error bit ("error frames"). */
+       if (data[1] & UVC_STREAM_ERR) {
+               uvc_trace(UVC_TRACE_FRAME, "Dropping payload (error bit "
+                         "set).\n");
+               return -ENODATA;
+       }
+
+       fid = data[1] & UVC_STREAM_FID;
+
+       /* Store the payload FID bit and return immediately when the buffer is
+        * NULL.
+        */
+       if (buf == NULL) {
+               video->last_fid = fid;
+               return -ENODATA;
+       }
+
+       /* Synchronize to the input stream by waiting for the FID bit to be
+        * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE.
+        * queue->last_fid is initialized to -1, so the first isochronous
+        * frame will always be in sync.
+        *
+        * If the device doesn't toggle the FID bit, invert video->last_fid
+        * when the EOF bit is set to force synchronisation on the next packet.
+        */
+       if (buf->state != UVC_BUF_STATE_ACTIVE) {
+               if (fid == video->last_fid) {
+                       uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of "
+                               "sync).\n");
+                       if ((video->dev->quirks & UVC_QUIRK_STREAM_NO_FID) &&
+                           (data[1] & UVC_STREAM_EOF))
+                               video->last_fid ^= UVC_STREAM_FID;
+                       return -ENODATA;
+               }
+
+               /* TODO: Handle PTS and SCR. */
+               buf->state = UVC_BUF_STATE_ACTIVE;
+       }
+
+       /* Mark the buffer as done if we're at the beginning of a new frame.
+        * End of frame detection is better implemented by checking the EOF
+        * bit (FID bit toggling is delayed by one frame compared to the EOF
+        * bit), but some devices don't set the bit at end of frame (and the
+        * last payload can be lost anyway). We thus must check if the FID has
+        * been toggled.
+        *
+        * queue->last_fid is initialized to -1, so the first isochronous
+        * frame will never trigger an end of frame detection.
+        *
+        * Empty buffers (bytesused == 0) don't trigger end of frame detection
+        * as it doesn't make sense to return an empty buffer. This also
+        * avoids detecting and of frame conditions at FID toggling if the
+        * previous payload had the EOF bit set.
+        */
+       if (fid != video->last_fid && buf->buf.bytesused != 0) {
+               uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit "
+                               "toggled).\n");
+               buf->state = UVC_BUF_STATE_DONE;
+               return -EAGAIN;
+       }
+
+       video->last_fid = fid;
+
+       return data[0];
+}
+
+static void uvc_video_decode_data(struct uvc_video_device *video,
+               struct uvc_buffer *buf, const __u8 *data, int len)
+{
+       struct uvc_video_queue *queue = &video->queue;
+       unsigned int maxlen, nbytes;
+       void *mem;
+
+       if (len <= 0)
+               return;
+
+       /* Copy the video data to the buffer. */
+       maxlen = buf->buf.length - buf->buf.bytesused;
+       mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused;
+       nbytes = min((unsigned int)len, maxlen);
+       memcpy(mem, data, nbytes);
+       buf->buf.bytesused += nbytes;
+
+       /* Complete the current frame if the buffer size was exceeded. */
+       if (len > maxlen) {
+               uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n");
+               buf->state = UVC_BUF_STATE_DONE;
+       }
+}
+
+static void uvc_video_decode_end(struct uvc_video_device *video,
+               struct uvc_buffer *buf, const __u8 *data, int len)
+{
+       /* Mark the buffer as done if the EOF marker is set. */
+       if (data[1] & UVC_STREAM_EOF && buf->buf.bytesused != 0) {
+               uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n");
+               if (data[0] == len)
+                       uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n");
+               buf->state = UVC_BUF_STATE_DONE;
+               if (video->dev->quirks & UVC_QUIRK_STREAM_NO_FID)
+                       video->last_fid ^= UVC_STREAM_FID;
+       }
+}
+
+/* ------------------------------------------------------------------------
+ * URB handling
+ */
+
+/*
+ * Completion handler for video URBs.
+ */
+static void uvc_video_decode_isoc(struct urb *urb,
+       struct uvc_video_device *video, struct uvc_buffer *buf)
+{
+       u8 *mem;
+       int ret, i;
+
+       for (i = 0; i < urb->number_of_packets; ++i) {
+               if (urb->iso_frame_desc[i].status < 0) {
+                       uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame "
+                               "lost (%d).\n", urb->iso_frame_desc[i].status);
+                       continue;
+               }
+
+               /* Decode the payload header. */
+               mem = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+               do {
+                       ret = uvc_video_decode_start(video, buf, mem,
+                               urb->iso_frame_desc[i].actual_length);
+                       if (ret == -EAGAIN)
+                               buf = uvc_queue_next_buffer(&video->queue, buf);
+               } while (ret == -EAGAIN);
+
+               if (ret < 0)
+                       continue;
+
+               /* Decode the payload data. */
+               uvc_video_decode_data(video, buf, mem + ret,
+                       urb->iso_frame_desc[i].actual_length - ret);
+
+               /* Process the header again. */
+               uvc_video_decode_end(video, buf, mem, ret);
+
+               if (buf->state == UVC_BUF_STATE_DONE ||
+                   buf->state == UVC_BUF_STATE_ERROR)
+                       buf = uvc_queue_next_buffer(&video->queue, buf);
+       }
+}
+
+static void uvc_video_decode_bulk(struct urb *urb,
+       struct uvc_video_device *video, struct uvc_buffer *buf)
+{
+       u8 *mem;
+       int len, ret;
+
+       mem = urb->transfer_buffer;
+       len = urb->actual_length;
+       video->bulk.payload_size += len;
+
+       /* If the URB is the first of its payload, decode and save the
+        * header.
+        */
+       if (video->bulk.header_size == 0) {
+               do {
+                       ret = uvc_video_decode_start(video, buf, mem, len);
+                       if (ret == -EAGAIN)
+                               buf = uvc_queue_next_buffer(&video->queue, buf);
+               } while (ret == -EAGAIN);
+
+               /* If an error occured skip the rest of the payload. */
+               if (ret < 0 || buf == NULL) {
+                       video->bulk.skip_payload = 1;
+                       return;
+               }
+
+               video->bulk.header_size = ret;
+               memcpy(video->bulk.header, mem, video->bulk.header_size);
+
+               mem += ret;
+               len -= ret;
+       }
+
+       /* The buffer queue might have been cancelled while a bulk transfer
+        * was in progress, so we can reach here with buf equal to NULL. Make
+        * sure buf is never dereferenced if NULL.
+        */
+
+       /* Process video data. */
+       if (!video->bulk.skip_payload && buf != NULL)
+               uvc_video_decode_data(video, buf, mem, len);
+
+       /* Detect the payload end by a URB smaller than the maximum size (or
+        * a payload size equal to the maximum) and process the header again.
+        */
+       if (urb->actual_length < urb->transfer_buffer_length ||
+           video->bulk.payload_size >= video->bulk.max_payload_size) {
+               if (!video->bulk.skip_payload && buf != NULL) {
+                       uvc_video_decode_end(video, buf, video->bulk.header,
+                               video->bulk.header_size);
+                       if (buf->state == UVC_BUF_STATE_DONE ||
+                           buf->state == UVC_BUF_STATE_ERROR)
+                               buf = uvc_queue_next_buffer(&video->queue, buf);
+               }
+
+               video->bulk.header_size = 0;
+               video->bulk.skip_payload = 0;
+               video->bulk.payload_size = 0;
+       }
+}
+
+static void uvc_video_complete(struct urb *urb)
+{
+       struct uvc_video_device *video = urb->context;
+       struct uvc_video_queue *queue = &video->queue;
+       struct uvc_buffer *buf = NULL;
+       unsigned long flags;
+       int ret;
+
+       switch (urb->status) {
+       case 0:
+               break;
+
+       default:
+               uvc_printk(KERN_WARNING, "Non-zero status (%d) in video "
+                       "completion handler.\n", urb->status);
+
+       case -ENOENT:           /* usb_kill_urb() called. */
+               if (video->frozen)
+                       return;
+
+       case -ECONNRESET:       /* usb_unlink_urb() called. */
+       case -ESHUTDOWN:        /* The endpoint is being disabled. */
+               uvc_queue_cancel(queue, urb->status == -ESHUTDOWN);
+               return;
+       }
+
+       spin_lock_irqsave(&queue->irqlock, flags);
+       if (!list_empty(&queue->irqqueue))
+               buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
+                                      queue);
+       spin_unlock_irqrestore(&queue->irqlock, flags);
+
+       video->decode(urb, video, buf);
+
+       if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+               uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n",
+                       ret);
+       }
+}
+
+/*
+ * Uninitialize isochronous/bulk URBs and free transfer buffers.
+ */
+static void uvc_uninit_video(struct uvc_video_device *video)
+{
+       struct urb *urb;
+       unsigned int i;
+
+       for (i = 0; i < UVC_URBS; ++i) {
+               if ((urb = video->urb[i]) == NULL)
+                       continue;
+
+               usb_kill_urb(urb);
+               /* urb->transfer_buffer_length is not touched by USB core, so
+                * we can use it here as the buffer length.
+                */
+               if (video->urb_buffer[i]) {
+                       usb_buffer_free(video->dev->udev,
+                               urb->transfer_buffer_length,
+                               video->urb_buffer[i], urb->transfer_dma);
+                       video->urb_buffer[i] = NULL;
+               }
+
+               usb_free_urb(urb);
+               video->urb[i] = NULL;
+       }
+}
+
+/*
+ * Initialize isochronous URBs and allocate transfer buffers. The packet size
+ * is given by the endpoint.
+ */
+static int uvc_init_video_isoc(struct uvc_video_device *video,
+       struct usb_host_endpoint *ep)
+{
+       struct urb *urb;
+       unsigned int npackets, i, j;
+       __u16 psize;
+       __u32 size;
+
+       /* Compute the number of isochronous packets to allocate by dividing
+        * the maximum video frame size by the packet size. Limit the result
+        * to UVC_MAX_ISO_PACKETS.
+        */
+       psize = le16_to_cpu(ep->desc.wMaxPacketSize);
+       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+
+       size = video->streaming->ctrl.dwMaxVideoFrameSize;
+       if (size > UVC_MAX_FRAME_SIZE)
+               return -EINVAL;
+
+       npackets = (size + psize - 1) / psize;
+       if (npackets > UVC_MAX_ISO_PACKETS)
+               npackets = UVC_MAX_ISO_PACKETS;
+
+       size = npackets * psize;
+
+       for (i = 0; i < UVC_URBS; ++i) {
+               urb = usb_alloc_urb(npackets, GFP_KERNEL);
+               if (urb == NULL) {
+                       uvc_uninit_video(video);
+                       return -ENOMEM;
+               }
+
+               video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev,
+                       size, GFP_KERNEL, &urb->transfer_dma);
+               if (video->urb_buffer[i] == NULL) {
+                       usb_free_urb(urb);
+                       uvc_uninit_video(video);
+                       return -ENOMEM;
+               }
+
+               urb->dev = video->dev->udev;
+               urb->context = video;
+               urb->pipe = usb_rcvisocpipe(video->dev->udev,
+                               ep->desc.bEndpointAddress);
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+               urb->interval = ep->desc.bInterval;
+               urb->transfer_buffer = video->urb_buffer[i];
+               urb->complete = uvc_video_complete;
+               urb->number_of_packets = npackets;
+               urb->transfer_buffer_length = size;
+
+               for (j = 0; j < npackets; ++j) {
+                       urb->iso_frame_desc[j].offset = j * psize;
+                       urb->iso_frame_desc[j].length = psize;
+               }
+
+               video->urb[i] = urb;
+       }
+
+       return 0;
+}
+
+/*
+ * Initialize bulk URBs and allocate transfer buffers. The packet size is
+ * given by the endpoint.
+ */
+static int uvc_init_video_bulk(struct uvc_video_device *video,
+       struct usb_host_endpoint *ep)
+{
+       struct urb *urb;
+       unsigned int pipe, i;
+       __u16 psize;
+       __u32 size;
+
+       /* Compute the bulk URB size. Some devices set the maximum payload
+        * size to a value too high for memory-constrained devices. We must
+        * then transfer the payload accross multiple URBs. To be consistant
+        * with isochronous mode, allocate maximum UVC_MAX_ISO_PACKETS per bulk
+        * URB.
+        */
+       psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff;
+       size = video->streaming->ctrl.dwMaxPayloadTransferSize;
+       video->bulk.max_payload_size = size;
+       if (size > psize * UVC_MAX_ISO_PACKETS)
+               size = psize * UVC_MAX_ISO_PACKETS;
+
+       pipe = usb_rcvbulkpipe(video->dev->udev, ep->desc.bEndpointAddress);
+
+       for (i = 0; i < UVC_URBS; ++i) {
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (urb == NULL) {
+                       uvc_uninit_video(video);
+                       return -ENOMEM;
+               }
+
+               video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev,
+                       size, GFP_KERNEL, &urb->transfer_dma);
+               if (video->urb_buffer[i] == NULL) {
+                       usb_free_urb(urb);
+                       uvc_uninit_video(video);
+                       return -ENOMEM;
+               }
+
+               usb_fill_bulk_urb(urb, video->dev->udev, pipe,
+                       video->urb_buffer[i], size, uvc_video_complete,
+                       video);
+               urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+
+               video->urb[i] = urb;
+       }
+
+       return 0;
+}
+
+/*
+ * Initialize isochronous/bulk URBs and allocate transfer buffers.
+ */
+static int uvc_init_video(struct uvc_video_device *video)
+{
+       struct usb_interface *intf = video->streaming->intf;
+       struct usb_host_interface *alts;
+       struct usb_host_endpoint *ep = NULL;
+       int intfnum = video->streaming->intfnum;
+       unsigned int bandwidth, psize, i;
+       int ret;
+
+       video->last_fid = -1;
+       video->bulk.header_size = 0;
+       video->bulk.skip_payload = 0;
+       video->bulk.payload_size = 0;
+
+       if (intf->num_altsetting > 1) {
+               /* Isochronous endpoint, select the alternate setting. */
+               bandwidth = video->streaming->ctrl.dwMaxPayloadTransferSize;
+
+               if (bandwidth == 0) {
+                       uvc_printk(KERN_WARNING, "device %s requested null "
+                               "bandwidth, defaulting to lowest.\n",
+                               video->vdev->name);
+                       bandwidth = 1;
+               }
+
+               for (i = 0; i < intf->num_altsetting; ++i) {
+                       alts = &intf->altsetting[i];
+                       ep = uvc_find_endpoint(alts,
+                               video->streaming->header.bEndpointAddress);
+                       if (ep == NULL)
+                               continue;
+
+                       /* Check if the bandwidth is high enough. */
+                       psize = le16_to_cpu(ep->desc.wMaxPacketSize);
+                       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+                       if (psize >= bandwidth)
+                               break;
+               }
+
+               if (i >= intf->num_altsetting)
+                       return -EIO;
+
+               if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0)
+                       return ret;
+
+               ret = uvc_init_video_isoc(video, ep);
+       } else {
+               /* Bulk endpoint, proceed to URB initialization. */
+               ep = uvc_find_endpoint(&intf->altsetting[0],
+                               video->streaming->header.bEndpointAddress);
+               if (ep == NULL)
+                       return -EIO;
+
+               ret = uvc_init_video_bulk(video, ep);
+       }
+
+       if (ret < 0)
+               return ret;
+
+       /* Submit the URBs. */
+       for (i = 0; i < UVC_URBS; ++i) {
+               if ((ret = usb_submit_urb(video->urb[i], GFP_KERNEL)) < 0) {
+                       uvc_printk(KERN_ERR, "Failed to submit URB %u "
+                                       "(%d).\n", i, ret);
+                       uvc_uninit_video(video);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * Suspend/resume
+ */
+
+/*
+ * Stop streaming without disabling the video queue.
+ *
+ * To let userspace applications resume without trouble, we must not touch the
+ * video buffers in any way. We mark the device as frozen to make sure the URB
+ * completion handler won't try to cancel the queue when we kill the URBs.
+ */
+int uvc_video_suspend(struct uvc_video_device *video)
+{
+       if (!uvc_queue_streaming(&video->queue))
+               return 0;
+
+       video->frozen = 1;
+       uvc_uninit_video(video);
+       usb_set_interface(video->dev->udev, video->streaming->intfnum, 0);
+       return 0;
+}
+
+/*
+ * Reconfigure the video interface and restart streaming if it was enable
+ * before suspend.
+ *
+ * If an error occurs, disable the video queue. This will wake all pending
+ * buffers, making sure userspace applications are notified of the problem
+ * instead of waiting forever.
+ */
+int uvc_video_resume(struct uvc_video_device *video)
+{
+       int ret;
+
+       video->frozen = 0;
+
+       if ((ret = uvc_set_video_ctrl(video, &video->streaming->ctrl, 0)) < 0) {
+               uvc_queue_enable(&video->queue, 0);
+               return ret;
+       }
+
+       if (!uvc_queue_streaming(&video->queue))
+               return 0;
+
+       if ((ret = uvc_init_video(video)) < 0)
+               uvc_queue_enable(&video->queue, 0);
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------------
+ * Video device
+ */
+
+/*
+ * Initialize the UVC video device by retrieving the default format and
+ * committing it.
+ *
+ * Some cameras (namely the Fuji Finepix) set the format and frame
+ * indexes to zero. The UVC standard doesn't clearly make this a spec
+ * violation, so try to silently fix the values if possible.
+ *
+ * This function is called before registering the device with V4L.
+ */
+int uvc_video_init(struct uvc_video_device *video)
+{
+       struct uvc_streaming_control *probe = &video->streaming->ctrl;
+       struct uvc_format *format = NULL;
+       struct uvc_frame *frame = NULL;
+       unsigned int i;
+       int ret;
+
+       if (video->streaming->nformats == 0) {
+               uvc_printk(KERN_INFO, "No supported video formats found.\n");
+               return -EINVAL;
+       }
+
+       /* Alternate setting 0 should be the default, yet the XBox Live Vision
+        * Cam (and possibly other devices) crash or otherwise misbehave if
+        * they don't receive a SET_INTERFACE request before any other video
+        * control request.
+        */
+       usb_set_interface(video->dev->udev, video->streaming->intfnum, 0);
+
+       /* Some webcams don't suport GET_DEF request on the probe control. We
+        * fall back to GET_CUR if GET_DEF fails.
+        */
+       if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 &&
+           (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0)
+               return ret;
+
+       /* Check if the default format descriptor exists. Use the first
+        * available format otherwise.
+        */
+       for (i = video->streaming->nformats; i > 0; --i) {
+               format = &video->streaming->format[i-1];
+               if (format->index == probe->bFormatIndex)
+                       break;
+       }
+
+       if (format->nframes == 0) {
+               uvc_printk(KERN_INFO, "No frame descriptor found for the "
+                       "default format.\n");
+               return -EINVAL;
+       }
+
+       /* Zero bFrameIndex might be correct. Stream-based formats (including
+        * MPEG-2 TS and DV) do not support frames but have a dummy frame
+        * descriptor with bFrameIndex set to zero. If the default frame
+        * descriptor is not found, use the first avalable frame.
+        */
+       for (i = format->nframes; i > 0; --i) {
+               frame = &format->frame[i-1];
+               if (frame->bFrameIndex == probe->bFrameIndex)
+                       break;
+       }
+
+       /* Commit the default settings. */
+       probe->bFormatIndex = format->index;
+       probe->bFrameIndex = frame->bFrameIndex;
+       if ((ret = uvc_set_video_ctrl(video, probe, 0)) < 0)
+               return ret;
+
+       video->streaming->cur_format = format;
+       video->streaming->cur_frame = frame;
+       atomic_set(&video->active, 0);
+
+       /* Select the video decoding function */
+       if (video->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)
+               video->decode = uvc_video_decode_isight;
+       else if (video->streaming->intf->num_altsetting > 1)
+               video->decode = uvc_video_decode_isoc;
+       else
+               video->decode = uvc_video_decode_bulk;
+
+       return 0;
+}
+
+/*
+ * Enable or disable the video stream.
+ */
+int uvc_video_enable(struct uvc_video_device *video, int enable)
+{
+       int ret;
+
+       if (!enable) {
+               uvc_uninit_video(video);
+               usb_set_interface(video->dev->udev,
+                       video->streaming->intfnum, 0);
+               uvc_queue_enable(&video->queue, 0);
+               return 0;
+       }
+
+       if ((ret = uvc_queue_enable(&video->queue, 1)) < 0)
+               return ret;
+
+       return uvc_init_video(video);
+}
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
new file mode 100644 (file)
index 0000000..a995a78
--- /dev/null
@@ -0,0 +1,796 @@
+#ifndef _USB_VIDEO_H_
+#define _USB_VIDEO_H_
+
+#include <linux/kernel.h>
+#include <linux/videodev2.h>
+
+
+/*
+ * Dynamic controls
+ */
+
+/* Data types for UVC control data */
+#define UVC_CTRL_DATA_TYPE_RAW         0
+#define UVC_CTRL_DATA_TYPE_SIGNED      1
+#define UVC_CTRL_DATA_TYPE_UNSIGNED    2
+#define UVC_CTRL_DATA_TYPE_BOOLEAN     3
+#define UVC_CTRL_DATA_TYPE_ENUM                4
+#define UVC_CTRL_DATA_TYPE_BITMASK     5
+
+/* Control flags */
+#define UVC_CONTROL_SET_CUR    (1 << 0)
+#define UVC_CONTROL_GET_CUR    (1 << 1)
+#define UVC_CONTROL_GET_MIN    (1 << 2)
+#define UVC_CONTROL_GET_MAX    (1 << 3)
+#define UVC_CONTROL_GET_RES    (1 << 4)
+#define UVC_CONTROL_GET_DEF    (1 << 5)
+/* Control should be saved at suspend and restored at resume. */
+#define UVC_CONTROL_RESTORE    (1 << 6)
+/* Control can be updated by the camera. */
+#define UVC_CONTROL_AUTO_UPDATE        (1 << 7)
+
+#define UVC_CONTROL_GET_RANGE  (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \
+                                UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \
+                                UVC_CONTROL_GET_DEF)
+
+struct uvc_xu_control_info {
+       __u8 entity[16];
+       __u8 index;
+       __u8 selector;
+       __u16 size;
+       __u32 flags;
+};
+
+struct uvc_xu_control_mapping {
+       __u32 id;
+       __u8 name[32];
+       __u8 entity[16];
+       __u8 selector;
+
+       __u8 size;
+       __u8 offset;
+       enum v4l2_ctrl_type v4l2_type;
+       __u32 data_type;
+};
+
+struct uvc_xu_control {
+       __u8 unit;
+       __u8 selector;
+       __u16 size;
+       __u8 __user *data;
+};
+
+#define UVCIOC_CTRL_ADD                _IOW('U', 1, struct uvc_xu_control_info)
+#define UVCIOC_CTRL_MAP                _IOWR('U', 2, struct uvc_xu_control_mapping)
+#define UVCIOC_CTRL_GET                _IOWR('U', 3, struct uvc_xu_control)
+#define UVCIOC_CTRL_SET                _IOW('U', 4, struct uvc_xu_control)
+
+#ifdef __KERNEL__
+
+#include <linux/poll.h>
+
+/* --------------------------------------------------------------------------
+ * UVC constants
+ */
+
+#define SC_UNDEFINED                    0x00
+#define SC_VIDEOCONTROL                 0x01
+#define SC_VIDEOSTREAMING               0x02
+#define SC_VIDEO_INTERFACE_COLLECTION   0x03
+
+#define PC_PROTOCOL_UNDEFINED           0x00
+
+#define CS_UNDEFINED                    0x20
+#define CS_DEVICE                       0x21
+#define CS_CONFIGURATION                0x22
+#define CS_STRING                       0x23
+#define CS_INTERFACE                    0x24
+#define CS_ENDPOINT                     0x25
+
+/* VideoControl class specific interface descriptor */
+#define VC_DESCRIPTOR_UNDEFINED         0x00
+#define VC_HEADER                       0x01
+#define VC_INPUT_TERMINAL               0x02
+#define VC_OUTPUT_TERMINAL              0x03
+#define VC_SELECTOR_UNIT                0x04
+#define VC_PROCESSING_UNIT              0x05
+#define VC_EXTENSION_UNIT               0x06
+
+/* VideoStreaming class specific interface descriptor */
+#define VS_UNDEFINED                    0x00
+#define VS_INPUT_HEADER                 0x01
+#define VS_OUTPUT_HEADER                0x02
+#define VS_STILL_IMAGE_FRAME            0x03
+#define VS_FORMAT_UNCOMPRESSED          0x04
+#define VS_FRAME_UNCOMPRESSED           0x05
+#define VS_FORMAT_MJPEG                 0x06
+#define VS_FRAME_MJPEG                  0x07
+#define VS_FORMAT_MPEG2TS               0x0a
+#define VS_FORMAT_DV                    0x0c
+#define VS_COLORFORMAT                  0x0d
+#define VS_FORMAT_FRAME_BASED           0x10
+#define VS_FRAME_FRAME_BASED            0x11
+#define VS_FORMAT_STREAM_BASED          0x12
+
+/* Endpoint type */
+#define EP_UNDEFINED                    0x00
+#define EP_GENERAL                      0x01
+#define EP_ENDPOINT                     0x02
+#define EP_INTERRUPT                    0x03
+
+/* Request codes */
+#define RC_UNDEFINED                    0x00
+#define SET_CUR                         0x01
+#define GET_CUR                         0x81
+#define GET_MIN                         0x82
+#define GET_MAX                         0x83
+#define GET_RES                         0x84
+#define GET_LEN                         0x85
+#define GET_INFO                        0x86
+#define GET_DEF                         0x87
+
+/* VideoControl interface controls */
+#define VC_CONTROL_UNDEFINED            0x00
+#define VC_VIDEO_POWER_MODE_CONTROL     0x01
+#define VC_REQUEST_ERROR_CODE_CONTROL   0x02
+
+/* Terminal controls */
+#define TE_CONTROL_UNDEFINED            0x00
+
+/* Selector Unit controls */
+#define SU_CONTROL_UNDEFINED            0x00
+#define SU_INPUT_SELECT_CONTROL         0x01
+
+/* Camera Terminal controls */
+#define CT_CONTROL_UNDEFINED                           0x00
+#define CT_SCANNING_MODE_CONTROL                       0x01
+#define CT_AE_MODE_CONTROL                             0x02
+#define CT_AE_PRIORITY_CONTROL                         0x03
+#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL               0x04
+#define CT_EXPOSURE_TIME_RELATIVE_CONTROL               0x05
+#define CT_FOCUS_ABSOLUTE_CONTROL                      0x06
+#define CT_FOCUS_RELATIVE_CONTROL                      0x07
+#define CT_FOCUS_AUTO_CONTROL                          0x08
+#define CT_IRIS_ABSOLUTE_CONTROL                       0x09
+#define CT_IRIS_RELATIVE_CONTROL                       0x0a
+#define CT_ZOOM_ABSOLUTE_CONTROL                       0x0b
+#define CT_ZOOM_RELATIVE_CONTROL                       0x0c
+#define CT_PANTILT_ABSOLUTE_CONTROL                    0x0d
+#define CT_PANTILT_RELATIVE_CONTROL                    0x0e
+#define CT_ROLL_ABSOLUTE_CONTROL                       0x0f
+#define CT_ROLL_RELATIVE_CONTROL                       0x10
+#define CT_PRIVACY_CONTROL                             0x11
+
+/* Processing Unit controls */
+#define PU_CONTROL_UNDEFINED                           0x00
+#define PU_BACKLIGHT_COMPENSATION_CONTROL               0x01
+#define PU_BRIGHTNESS_CONTROL                          0x02
+#define PU_CONTRAST_CONTROL                            0x03
+#define PU_GAIN_CONTROL                                0x04
+#define PU_POWER_LINE_FREQUENCY_CONTROL                0x05
+#define PU_HUE_CONTROL                                 0x06
+#define PU_SATURATION_CONTROL                          0x07
+#define PU_SHARPNESS_CONTROL                           0x08
+#define PU_GAMMA_CONTROL                               0x09
+#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL            0x0a
+#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL       0x0b
+#define PU_WHITE_BALANCE_COMPONENT_CONTROL              0x0c
+#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL         0x0d
+#define PU_DIGITAL_MULTIPLIER_CONTROL                  0x0e
+#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL             0x0f
+#define PU_HUE_AUTO_CONTROL                            0x10
+#define PU_ANALOG_VIDEO_STANDARD_CONTROL                0x11
+#define PU_ANALOG_LOCK_STATUS_CONTROL                  0x12
+
+#define LXU_MOTOR_PANTILT_RELATIVE_CONTROL             0x01
+#define LXU_MOTOR_PANTILT_RESET_CONTROL                        0x02
+#define LXU_MOTOR_FOCUS_MOTOR_CONTROL                  0x03
+
+/* VideoStreaming interface controls */
+#define VS_CONTROL_UNDEFINED            0x00
+#define VS_PROBE_CONTROL                0x01
+#define VS_COMMIT_CONTROL               0x02
+#define VS_STILL_PROBE_CONTROL          0x03
+#define VS_STILL_COMMIT_CONTROL         0x04
+#define VS_STILL_IMAGE_TRIGGER_CONTROL  0x05
+#define VS_STREAM_ERROR_CODE_CONTROL    0x06
+#define VS_GENERATE_KEY_FRAME_CONTROL   0x07
+#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08
+#define VS_SYNC_DELAY_CONTROL           0x09
+
+#define TT_VENDOR_SPECIFIC              0x0100
+#define TT_STREAMING                    0x0101
+
+/* Input Terminal types */
+#define ITT_VENDOR_SPECIFIC             0x0200
+#define ITT_CAMERA                      0x0201
+#define ITT_MEDIA_TRANSPORT_INPUT       0x0202
+
+/* Output Terminal types */
+#define OTT_VENDOR_SPECIFIC             0x0300
+#define OTT_DISPLAY                     0x0301
+#define OTT_MEDIA_TRANSPORT_OUTPUT      0x0302
+
+/* External Terminal types */
+#define EXTERNAL_VENDOR_SPECIFIC        0x0400
+#define COMPOSITE_CONNECTOR             0x0401
+#define SVIDEO_CONNECTOR                0x0402
+#define COMPONENT_CONNECTOR             0x0403
+
+#define UVC_TERM_INPUT                 0x0000
+#define UVC_TERM_OUTPUT                        0x8000
+
+#define UVC_ENTITY_TYPE(entity)                ((entity)->type & 0x7fff)
+#define UVC_ENTITY_IS_UNIT(entity)     (((entity)->type & 0xff00) == 0)
+#define UVC_ENTITY_IS_TERM(entity)     (((entity)->type & 0xff00) != 0)
+#define UVC_ENTITY_IS_ITERM(entity) \
+       (((entity)->type & 0x8000) == UVC_TERM_INPUT)
+#define UVC_ENTITY_IS_OTERM(entity) \
+       (((entity)->type & 0x8000) == UVC_TERM_OUTPUT)
+
+#define UVC_STATUS_TYPE_CONTROL                1
+#define UVC_STATUS_TYPE_STREAMING      2
+
+/* ------------------------------------------------------------------------
+ * GUIDs
+ */
+#define UVC_GUID_UVC_CAMERA \
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
+#define UVC_GUID_UVC_OUTPUT \
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}
+#define UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT \
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
+#define UVC_GUID_UVC_PROCESSING \
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}
+#define UVC_GUID_UVC_SELECTOR \
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02}
+
+#define UVC_GUID_LOGITECH_DEV_INFO \
+       {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
+        0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1e}
+#define UVC_GUID_LOGITECH_USER_HW \
+       {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
+        0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1f}
+#define UVC_GUID_LOGITECH_VIDEO \
+       {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
+        0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x50}
+#define UVC_GUID_LOGITECH_MOTOR \
+       {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
+        0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x56}
+
+#define UVC_GUID_FORMAT_MJPEG \
+       { 'M',  'J',  'P',  'G', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_YUY2 \
+       { 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_NV12 \
+       { 'N',  'V',  '1',  '2', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_YV12 \
+       { 'Y',  'V',  '1',  '2', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_I420 \
+       { 'I',  '4',  '2',  '0', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_UYVY \
+       { 'U',  'Y',  'V',  'Y', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y800 \
+       { 'Y',  '8',  '0',  '0', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_BY8 \
+       { 'B',  'Y',  '8',  ' ', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+
+
+/* ------------------------------------------------------------------------
+ * Driver specific constants.
+ */
+
+#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(0, 1, 0)
+
+/* Number of isochronous URBs. */
+#define UVC_URBS               5
+/* Maximum number of packets per isochronous URB. */
+#define UVC_MAX_ISO_PACKETS    40
+/* Maximum frame size in bytes, for sanity checking. */
+#define UVC_MAX_FRAME_SIZE     (16*1024*1024)
+/* Maximum number of video buffers. */
+#define UVC_MAX_VIDEO_BUFFERS  32
+
+#define UVC_CTRL_CONTROL_TIMEOUT       300
+#define UVC_CTRL_STREAMING_TIMEOUT     1000
+
+/* Devices quirks */
+#define UVC_QUIRK_STATUS_INTERVAL      0x00000001
+#define UVC_QUIRK_PROBE_MINMAX         0x00000002
+#define UVC_QUIRK_PROBE_EXTRAFIELDS    0x00000004
+#define UVC_QUIRK_BUILTIN_ISIGHT       0x00000008
+#define UVC_QUIRK_STREAM_NO_FID                0x00000010
+#define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020
+
+/* Format flags */
+#define UVC_FMT_FLAG_COMPRESSED                0x00000001
+#define UVC_FMT_FLAG_STREAM            0x00000002
+
+/* ------------------------------------------------------------------------
+ * Structures.
+ */
+
+struct uvc_device;
+
+/* TODO: Put the most frequently accessed fields at the beginning of
+ * structures to maximize cache efficiency.
+ */
+struct uvc_streaming_control {
+       __u16 bmHint;
+       __u8  bFormatIndex;
+       __u8  bFrameIndex;
+       __u32 dwFrameInterval;
+       __u16 wKeyFrameRate;
+       __u16 wPFrameRate;
+       __u16 wCompQuality;
+       __u16 wCompWindowSize;
+       __u16 wDelay;
+       __u32 dwMaxVideoFrameSize;
+       __u32 dwMaxPayloadTransferSize;
+       __u32 dwClockFrequency;
+       __u8  bmFramingInfo;
+       __u8  bPreferedVersion;
+       __u8  bMinVersion;
+       __u8  bMaxVersion;
+};
+
+struct uvc_menu_info {
+       __u32 value;
+       __u8 name[32];
+};
+
+struct uvc_control_info {
+       struct list_head list;
+       struct list_head mappings;
+
+       __u8 entity[16];
+       __u8 index;
+       __u8 selector;
+
+       __u16 size;
+       __u32 flags;
+};
+
+struct uvc_control_mapping {
+       struct list_head list;
+
+       struct uvc_control_info *ctrl;
+
+       __u32 id;
+       __u8 name[32];
+       __u8 entity[16];
+       __u8 selector;
+
+       __u8 size;
+       __u8 offset;
+       enum v4l2_ctrl_type v4l2_type;
+       __u32 data_type;
+
+       struct uvc_menu_info *menu_info;
+       __u32 menu_count;
+};
+
+struct uvc_control {
+       struct uvc_entity *entity;
+       struct uvc_control_info *info;
+
+       __u8 index;     /* Used to match the uvc_control entry with a
+                          uvc_control_info. */
+       __u8 dirty : 1,
+            loaded : 1,
+            modified : 1;
+
+       __u8 *data;
+};
+
+struct uvc_format_desc {
+       char *name;
+       __u8 guid[16];
+       __u32 fcc;
+};
+
+/* The term 'entity' refers to both UVC units and UVC terminals.
+ *
+ * The type field is either the terminal type (wTerminalType in the terminal
+ * descriptor), or the unit type (bDescriptorSubtype in the unit descriptor).
+ * As the bDescriptorSubtype field is one byte long, the type value will
+ * always have a null MSB for units. All terminal types defined by the UVC
+ * specification have a non-null MSB, so it is safe to use the MSB to
+ * differentiate between units and terminals as long as the descriptor parsing
+ * code makes sure terminal types have a non-null MSB.
+ *
+ * For terminals, the type's most significant bit stores the terminal
+ * direction (either UVC_TERM_INPUT or UVC_TERM_OUTPUT). The type field should
+ * always be accessed with the UVC_ENTITY_* macros and never directly.
+ */
+
+struct uvc_entity {
+       struct list_head list;          /* Entity as part of a UVC device. */
+       struct list_head chain;         /* Entity as part of a video device
+                                        * chain. */
+       __u8 id;
+       __u16 type;
+       char name[64];
+
+       union {
+               struct {
+                       __u16 wObjectiveFocalLengthMin;
+                       __u16 wObjectiveFocalLengthMax;
+                       __u16 wOcularFocalLength;
+                       __u8  bControlSize;
+                       __u8  *bmControls;
+               } camera;
+
+               struct {
+                       __u8  bControlSize;
+                       __u8  *bmControls;
+                       __u8  bTransportModeSize;
+                       __u8  *bmTransportModes;
+               } media;
+
+               struct {
+                       __u8  bSourceID;
+               } output;
+
+               struct {
+                       __u8  bSourceID;
+                       __u16 wMaxMultiplier;
+                       __u8  bControlSize;
+                       __u8  *bmControls;
+                       __u8  bmVideoStandards;
+               } processing;
+
+               struct {
+                       __u8  bNrInPins;
+                       __u8  *baSourceID;
+               } selector;
+
+               struct {
+                       __u8  guidExtensionCode[16];
+                       __u8  bNumControls;
+                       __u8  bNrInPins;
+                       __u8  *baSourceID;
+                       __u8  bControlSize;
+                       __u8  *bmControls;
+                       __u8  *bmControlsType;
+               } extension;
+       };
+
+       unsigned int ncontrols;
+       struct uvc_control *controls;
+};
+
+struct uvc_frame {
+       __u8  bFrameIndex;
+       __u8  bmCapabilities;
+       __u16 wWidth;
+       __u16 wHeight;
+       __u32 dwMinBitRate;
+       __u32 dwMaxBitRate;
+       __u32 dwMaxVideoFrameBufferSize;
+       __u8  bFrameIntervalType;
+       __u32 dwDefaultFrameInterval;
+       __u32 *dwFrameInterval;
+};
+
+struct uvc_format {
+       __u8 type;
+       __u8 index;
+       __u8 bpp;
+       __u8 colorspace;
+       __u32 fcc;
+       __u32 flags;
+
+       char name[32];
+
+       unsigned int nframes;
+       struct uvc_frame *frame;
+};
+
+struct uvc_streaming_header {
+       __u8 bNumFormats;
+       __u8 bEndpointAddress;
+       __u8 bTerminalLink;
+       __u8 bControlSize;
+       __u8 *bmaControls;
+       /* The following fields are used by input headers only. */
+       __u8 bmInfo;
+       __u8 bStillCaptureMethod;
+       __u8 bTriggerSupport;
+       __u8 bTriggerUsage;
+};
+
+struct uvc_streaming {
+       struct list_head list;
+
+       struct usb_interface *intf;
+       int intfnum;
+       __u16 maxpsize;
+
+       struct uvc_streaming_header header;
+
+       unsigned int nformats;
+       struct uvc_format *format;
+
+       struct uvc_streaming_control ctrl;
+       struct uvc_format *cur_format;
+       struct uvc_frame *cur_frame;
+
+       struct mutex mutex;
+};
+
+enum uvc_buffer_state {
+       UVC_BUF_STATE_IDLE       = 0,
+       UVC_BUF_STATE_QUEUED     = 1,
+       UVC_BUF_STATE_ACTIVE     = 2,
+       UVC_BUF_STATE_DONE       = 3,
+       UVC_BUF_STATE_ERROR      = 4,
+};
+
+struct uvc_buffer {
+       unsigned long vma_use_count;
+       struct list_head stream;
+
+       /* Touched by interrupt handler. */
+       struct v4l2_buffer buf;
+       struct list_head queue;
+       wait_queue_head_t wait;
+       enum uvc_buffer_state state;
+};
+
+#define UVC_QUEUE_STREAMING            (1 << 0)
+#define UVC_QUEUE_DISCONNECTED         (1 << 1)
+#define UVC_QUEUE_DROP_INCOMPLETE      (1 << 2)
+
+struct uvc_video_queue {
+       void *mem;
+       unsigned int flags;
+       __u32 sequence;
+
+       unsigned int count;
+       unsigned int buf_size;
+       struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
+       struct mutex mutex;     /* protects buffers and mainqueue */
+       spinlock_t irqlock;     /* protects irqqueue */
+
+       struct list_head mainqueue;
+       struct list_head irqqueue;
+};
+
+struct uvc_video_device {
+       struct uvc_device *dev;
+       struct video_device *vdev;
+       atomic_t active;
+       unsigned int frozen : 1;
+
+       struct list_head iterms;
+       struct uvc_entity *oterm;
+       struct uvc_entity *processing;
+       struct uvc_entity *selector;
+       struct list_head extensions;
+       struct mutex ctrl_mutex;
+
+       struct uvc_video_queue queue;
+
+       /* Video streaming object, must always be non-NULL. */
+       struct uvc_streaming *streaming;
+
+       void (*decode) (struct urb *urb, struct uvc_video_device *video,
+                       struct uvc_buffer *buf);
+
+       /* Context data used by the bulk completion handler. */
+       struct {
+               __u8 header[256];
+               unsigned int header_size;
+               int skip_payload;
+               __u32 payload_size;
+               __u32 max_payload_size;
+       } bulk;
+
+       struct urb *urb[UVC_URBS];
+       char *urb_buffer[UVC_URBS];
+
+       __u8 last_fid;
+};
+
+enum uvc_device_state {
+       UVC_DEV_DISCONNECTED = 1,
+};
+
+struct uvc_device {
+       struct usb_device *udev;
+       struct usb_interface *intf;
+       __u32 quirks;
+       int intfnum;
+       char name[32];
+
+       enum uvc_device_state state;
+       struct kref kref;
+       struct list_head list;
+
+       /* Video control interface */
+       __u16 uvc_version;
+       __u32 clock_frequency;
+
+       struct list_head entities;
+
+       struct uvc_video_device video;
+
+       /* Status Interrupt Endpoint */
+       struct usb_host_endpoint *int_ep;
+       struct urb *int_urb;
+       __u8 status[16];
+       struct input_dev *input;
+
+       /* Video Streaming interfaces */
+       struct list_head streaming;
+};
+
+enum uvc_handle_state {
+       UVC_HANDLE_PASSIVE      = 0,
+       UVC_HANDLE_ACTIVE       = 1,
+};
+
+struct uvc_fh {
+       struct uvc_video_device *device;
+       enum uvc_handle_state state;
+};
+
+struct uvc_driver {
+       struct usb_driver driver;
+
+       struct mutex open_mutex;        /* protects from open/disconnect race */
+
+       struct list_head devices;       /* struct uvc_device list */
+       struct list_head controls;      /* struct uvc_control_info list */
+       struct mutex ctrl_mutex;        /* protects controls and devices
+                                          lists */
+};
+
+/* ------------------------------------------------------------------------
+ * Debugging, printing and logging
+ */
+
+#define UVC_TRACE_PROBE                (1 << 0)
+#define UVC_TRACE_DESCR                (1 << 1)
+#define UVC_TRACE_CONTROL      (1 << 2)
+#define UVC_TRACE_FORMAT       (1 << 3)
+#define UVC_TRACE_CAPTURE      (1 << 4)
+#define UVC_TRACE_CALLS                (1 << 5)
+#define UVC_TRACE_IOCTL                (1 << 6)
+#define UVC_TRACE_FRAME                (1 << 7)
+#define UVC_TRACE_SUSPEND      (1 << 8)
+#define UVC_TRACE_STATUS       (1 << 9)
+
+extern unsigned int uvc_trace_param;
+
+#define uvc_trace(flag, msg...) \
+       do { \
+               if (uvc_trace_param & flag) \
+                       printk(KERN_DEBUG "uvcvideo: " msg); \
+       } while (0)
+
+#define uvc_printk(level, msg...) \
+       printk(level "uvcvideo: " msg)
+
+#define UVC_GUID_FORMAT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" \
+                       "%02x%02x%02x%02x%02x%02x"
+#define UVC_GUID_ARGS(guid) \
+       (guid)[3],  (guid)[2],  (guid)[1],  (guid)[0], \
+       (guid)[5],  (guid)[4], \
+       (guid)[7],  (guid)[6], \
+       (guid)[8],  (guid)[9], \
+       (guid)[10], (guid)[11], (guid)[12], \
+       (guid)[13], (guid)[14], (guid)[15]
+
+/* --------------------------------------------------------------------------
+ * Internal functions.
+ */
+
+/* Core driver */
+extern struct uvc_driver uvc_driver;
+extern void uvc_delete(struct kref *kref);
+
+/* Video buffers queue management. */
+extern void uvc_queue_init(struct uvc_video_queue *queue);
+extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
+               unsigned int nbuffers, unsigned int buflength);
+extern int uvc_free_buffers(struct uvc_video_queue *queue);
+extern int uvc_query_buffer(struct uvc_video_queue *queue,
+               struct v4l2_buffer *v4l2_buf);
+extern int uvc_queue_buffer(struct uvc_video_queue *queue,
+               struct v4l2_buffer *v4l2_buf);
+extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,
+               struct v4l2_buffer *v4l2_buf, int nonblocking);
+extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
+extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
+extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
+               struct uvc_buffer *buf);
+extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
+               struct file *file, poll_table *wait);
+static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
+{
+       return queue->flags & UVC_QUEUE_STREAMING;
+}
+
+/* V4L2 interface */
+extern struct file_operations uvc_fops;
+
+/* Video */
+extern int uvc_video_init(struct uvc_video_device *video);
+extern int uvc_video_suspend(struct uvc_video_device *video);
+extern int uvc_video_resume(struct uvc_video_device *video);
+extern int uvc_video_enable(struct uvc_video_device *video, int enable);
+extern int uvc_probe_video(struct uvc_video_device *video,
+               struct uvc_streaming_control *probe);
+extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
+               __u8 intfnum, __u8 cs, void *data, __u16 size);
+extern int uvc_set_video_ctrl(struct uvc_video_device *video,
+               struct uvc_streaming_control *ctrl, int probe);
+
+/* Status */
+extern int uvc_status_init(struct uvc_device *dev);
+extern void uvc_status_cleanup(struct uvc_device *dev);
+extern int uvc_status_suspend(struct uvc_device *dev);
+extern int uvc_status_resume(struct uvc_device *dev);
+
+/* Controls */
+extern struct uvc_control *uvc_find_control(struct uvc_video_device *video,
+               __u32 v4l2_id, struct uvc_control_mapping **mapping);
+extern int uvc_query_v4l2_ctrl(struct uvc_video_device *video,
+               struct v4l2_queryctrl *v4l2_ctrl);
+
+extern int uvc_ctrl_add_info(struct uvc_control_info *info);
+extern int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping);
+extern int uvc_ctrl_init_device(struct uvc_device *dev);
+extern void uvc_ctrl_cleanup_device(struct uvc_device *dev);
+extern int uvc_ctrl_resume_device(struct uvc_device *dev);
+extern void uvc_ctrl_init(void);
+
+extern int uvc_ctrl_begin(struct uvc_video_device *video);
+extern int __uvc_ctrl_commit(struct uvc_video_device *video, int rollback);
+static inline int uvc_ctrl_commit(struct uvc_video_device *video)
+{
+       return __uvc_ctrl_commit(video, 0);
+}
+static inline int uvc_ctrl_rollback(struct uvc_video_device *video)
+{
+       return __uvc_ctrl_commit(video, 1);
+}
+
+extern int uvc_ctrl_get(struct uvc_video_device *video,
+               struct v4l2_ext_control *xctrl);
+extern int uvc_ctrl_set(struct uvc_video_device *video,
+               struct v4l2_ext_control *xctrl);
+
+extern int uvc_xu_ctrl_query(struct uvc_video_device *video,
+               struct uvc_xu_control *ctrl, int set);
+
+/* Utility functions */
+extern void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,
+               unsigned int n_terms, unsigned int threshold);
+extern uint32_t uvc_fraction_to_interval(uint32_t numerator,
+               uint32_t denominator);
+extern struct usb_host_endpoint *uvc_find_endpoint(
+               struct usb_host_interface *alts, __u8 epaddr);
+
+/* Quirks support */
+void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video,
+               struct uvc_buffer *buf);
+
+#endif /* __KERNEL__ */
+
+#endif
index 31e8af0ba2785e105e60587b8153602b948f55eb..67a661cf5219bc65e225f304d5872579c034313b 100644 (file)
 #define VIDEO_NUM_DEVICES      256
 #define VIDEO_NAME              "video4linux"
 
+struct std_descr {
+       v4l2_std_id std;
+       const char *descr;
+};
+
+static const struct std_descr standards[] = {
+       { V4L2_STD_NTSC,        "NTSC"      },
+       { V4L2_STD_NTSC_M,      "NTSC-M"    },
+       { V4L2_STD_NTSC_M_JP,   "NTSC-M-JP" },
+       { V4L2_STD_NTSC_M_KR,   "NTSC-M-KR" },
+       { V4L2_STD_NTSC_443,    "NTSC-443"  },
+       { V4L2_STD_PAL,         "PAL"       },
+       { V4L2_STD_PAL_BG,      "PAL-BG"    },
+       { V4L2_STD_PAL_B,       "PAL-B"     },
+       { V4L2_STD_PAL_B1,      "PAL-B1"    },
+       { V4L2_STD_PAL_G,       "PAL-G"     },
+       { V4L2_STD_PAL_H,       "PAL-H"     },
+       { V4L2_STD_PAL_I,       "PAL-I"     },
+       { V4L2_STD_PAL_DK,      "PAL-DK"    },
+       { V4L2_STD_PAL_D,       "PAL-D"     },
+       { V4L2_STD_PAL_D1,      "PAL-D1"    },
+       { V4L2_STD_PAL_K,       "PAL-K"     },
+       { V4L2_STD_PAL_M,       "PAL-M"     },
+       { V4L2_STD_PAL_N,       "PAL-N"     },
+       { V4L2_STD_PAL_Nc,      "PAL-Nc"    },
+       { V4L2_STD_PAL_60,      "PAL-60"    },
+       { V4L2_STD_SECAM,       "SECAM"     },
+       { V4L2_STD_SECAM_B,     "SECAM-B"   },
+       { V4L2_STD_SECAM_G,     "SECAM-G"   },
+       { V4L2_STD_SECAM_H,     "SECAM-H"   },
+       { V4L2_STD_SECAM_DK,    "SECAM-DK"  },
+       { V4L2_STD_SECAM_D,     "SECAM-D"   },
+       { V4L2_STD_SECAM_K,     "SECAM-K"   },
+       { V4L2_STD_SECAM_K1,    "SECAM-K1"  },
+       { V4L2_STD_SECAM_L,     "SECAM-L"   },
+       { V4L2_STD_SECAM_LC,    "SECAM-Lc"  },
+       { 0,                    "Unknown"   }
+};
+
 /* video4linux standard ID conversion to standard name
  */
-char *v4l2_norm_to_name(v4l2_std_id id)
+const char *v4l2_norm_to_name(v4l2_std_id id)
 {
-       char *name;
        u32 myid = id;
+       int i;
 
        /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
           64 bit comparations. So, on that architecture, with some gcc
@@ -64,110 +103,17 @@ char *v4l2_norm_to_name(v4l2_std_id id)
         */
        BUG_ON(myid != id);
 
-       switch (myid) {
-       case V4L2_STD_PAL:
-               name = "PAL";
-               break;
-       case V4L2_STD_PAL_BG:
-               name = "PAL-BG";
-               break;
-       case V4L2_STD_PAL_DK:
-               name = "PAL-DK";
-               break;
-       case V4L2_STD_PAL_B:
-               name = "PAL-B";
-               break;
-       case V4L2_STD_PAL_B1:
-               name = "PAL-B1";
-               break;
-       case V4L2_STD_PAL_G:
-               name = "PAL-G";
-               break;
-       case V4L2_STD_PAL_H:
-               name = "PAL-H";
-               break;
-       case V4L2_STD_PAL_I:
-               name = "PAL-I";
-               break;
-       case V4L2_STD_PAL_D:
-               name = "PAL-D";
-               break;
-       case V4L2_STD_PAL_D1:
-               name = "PAL-D1";
-               break;
-       case V4L2_STD_PAL_K:
-               name = "PAL-K";
-               break;
-       case V4L2_STD_PAL_M:
-               name = "PAL-M";
-               break;
-       case V4L2_STD_PAL_N:
-               name = "PAL-N";
-               break;
-       case V4L2_STD_PAL_Nc:
-               name = "PAL-Nc";
-               break;
-       case V4L2_STD_PAL_60:
-               name = "PAL-60";
-               break;
-       case V4L2_STD_NTSC:
-               name = "NTSC";
-               break;
-       case V4L2_STD_NTSC_M:
-               name = "NTSC-M";
-               break;
-       case V4L2_STD_NTSC_M_JP:
-               name = "NTSC-M-JP";
-               break;
-       case V4L2_STD_NTSC_443:
-               name = "NTSC-443";
-               break;
-       case V4L2_STD_NTSC_M_KR:
-               name = "NTSC-M-KR";
-               break;
-       case V4L2_STD_SECAM:
-               name = "SECAM";
-               break;
-       case V4L2_STD_SECAM_DK:
-               name = "SECAM-DK";
-               break;
-       case V4L2_STD_SECAM_B:
-               name = "SECAM-B";
-               break;
-       case V4L2_STD_SECAM_D:
-               name = "SECAM-D";
-               break;
-       case V4L2_STD_SECAM_G:
-               name = "SECAM-G";
-               break;
-       case V4L2_STD_SECAM_H:
-               name = "SECAM-H";
-               break;
-       case V4L2_STD_SECAM_K:
-               name = "SECAM-K";
-               break;
-       case V4L2_STD_SECAM_K1:
-               name = "SECAM-K1";
-               break;
-       case V4L2_STD_SECAM_L:
-               name = "SECAM-L";
-               break;
-       case V4L2_STD_SECAM_LC:
-               name = "SECAM-LC";
-               break;
-       default:
-               name = "Unknown";
-               break;
-       }
-
-       return name;
+       for (i = 0; standards[i].std; i++)
+               if (myid == standards[i].std)
+                       break;
+       return standards[i].descr;
 }
 EXPORT_SYMBOL(v4l2_norm_to_name);
 
 /* Fill in the fields of a v4l2_standard structure according to the
    'id' and 'transmission' parameters.  Returns negative on error.  */
 int v4l2_video_std_construct(struct v4l2_standard *vs,
-                            int id, char *name)
+                            int id, const char *name)
 {
        u32 index = vs->index;
 
@@ -1218,95 +1164,40 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
        case VIDIOC_ENUMSTD:
        {
                struct v4l2_standard *p = arg;
-               v4l2_std_id id = vfd->tvnorms,curr_id=0;
-               unsigned int index = p->index,i;
-
-               if (index<0) {
-                       ret=-EINVAL;
-                       break;
-               }
-
-               /* Return norm array on a canonical way */
-               for (i=0;i<= index && id; i++) {
-                       if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) {
-                               curr_id = V4L2_STD_PAL;
-                       } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) {
-                               curr_id = V4L2_STD_PAL_BG;
-                       } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) {
-                               curr_id = V4L2_STD_PAL_DK;
-                       } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) {
-                               curr_id = V4L2_STD_PAL_B;
-                       } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) {
-                               curr_id = V4L2_STD_PAL_B1;
-                       } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) {
-                               curr_id = V4L2_STD_PAL_G;
-                       } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) {
-                               curr_id = V4L2_STD_PAL_H;
-                       } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) {
-                               curr_id = V4L2_STD_PAL_I;
-                       } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) {
-                               curr_id = V4L2_STD_PAL_D;
-                       } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) {
-                               curr_id = V4L2_STD_PAL_D1;
-                       } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) {
-                               curr_id = V4L2_STD_PAL_K;
-                       } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) {
-                               curr_id = V4L2_STD_PAL_M;
-                       } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) {
-                               curr_id = V4L2_STD_PAL_N;
-                       } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) {
-                               curr_id = V4L2_STD_PAL_Nc;
-                       } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) {
-                               curr_id = V4L2_STD_PAL_60;
-                       } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
-                               curr_id = V4L2_STD_NTSC;
-                       } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) {
-                               curr_id = V4L2_STD_NTSC_M;
-                       } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) {
-                               curr_id = V4L2_STD_NTSC_M_JP;
-                       } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) {
-                               curr_id = V4L2_STD_NTSC_443;
-                       } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) {
-                               curr_id = V4L2_STD_NTSC_M_KR;
-                       } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
-                               curr_id = V4L2_STD_SECAM;
-                       } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) {
-                               curr_id = V4L2_STD_SECAM_DK;
-                       } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) {
-                               curr_id = V4L2_STD_SECAM_B;
-                       } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) {
-                               curr_id = V4L2_STD_SECAM_D;
-                       } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) {
-                               curr_id = V4L2_STD_SECAM_G;
-                       } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) {
-                               curr_id = V4L2_STD_SECAM_H;
-                       } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) {
-                               curr_id = V4L2_STD_SECAM_K;
-                       } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) {
-                               curr_id = V4L2_STD_SECAM_K1;
-                       } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) {
-                               curr_id = V4L2_STD_SECAM_L;
-                       } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) {
-                               curr_id = V4L2_STD_SECAM_LC;
-                       } else {
+               v4l2_std_id id = vfd->tvnorms, curr_id = 0;
+               unsigned int index = p->index, i, j = 0;
+               const char *descr = "";
+
+               /* Return norm array in a canonical way */
+               for (i = 0; i <= index && id; i++) {
+                       /* last std value in the standards array is 0, so this
+                          while always ends there since (id & 0) == 0. */
+                       while ((id & standards[j].std) != standards[j].std)
+                               j++;
+                       curr_id = standards[j].std;
+                       descr = standards[j].descr;
+                       j++;
+                       if (curr_id == 0)
                                break;
-                       }
-                       id &= ~curr_id;
+                       if (curr_id != V4L2_STD_PAL &&
+                           curr_id != V4L2_STD_SECAM &&
+                           curr_id != V4L2_STD_NTSC)
+                               id &= ~curr_id;
                }
-               if (i<=index)
+               if (i <= index)
                        return -EINVAL;
 
-               v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id));
+               v4l2_video_std_construct(p, curr_id, descr);
                p->index = index;
 
-               dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, "
+               dbgarg(cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, "
                                "framelines=%d\n", p->index,
                                (unsigned long long)p->id, p->name,
                                p->frameperiod.numerator,
                                p->frameperiod.denominator,
                                p->framelines);
 
-               ret=0;
+               ret = 0;
                break;
        }
        case VIDIOC_G_STD:
index 845be1864f685a01fad3a225bc9826ab09d61985..5ff9a58b6135b98b8644af14d042cc31cc824a5a 100644 (file)
@@ -327,13 +327,14 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
        int hmax  = buf->vb.height;
        int wmax  = buf->vb.width;
        struct timeval ts;
-       char *tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);
+       char *tmpbuf;
        void *vbuf = videobuf_to_vmalloc(&buf->vb);
 
-       if (!tmpbuf)
+       if (!vbuf)
                return;
 
-       if (!vbuf)
+       tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC);
+       if (!tmpbuf)
                return;
 
        for (h = 0; h < hmax; h++) {
index db3c892f87fb50aafc6f53ac5aaaaf016ee2860f..d40d6d15ae20f62d158d5456f857689e051cdf5a 100644 (file)
@@ -1686,9 +1686,14 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
                ioc->bus_type = SAS;
        }
 
-       if (ioc->bus_type == SAS && mpt_msi_enable == -1)
-               ioc->msi_enable = 1;
-       else
+       if (mpt_msi_enable == -1) {
+               /* Enable on SAS, disable on FC and SPI */
+               if (ioc->bus_type == SAS)
+                       ioc->msi_enable = 1;
+               else
+                       ioc->msi_enable = 0;
+       } else
+               /* follow flag: 0 - disable; 1 - enable */
                ioc->msi_enable = mpt_msi_enable;
 
        if (ioc->errata_flag_1064)
index 25bcfcf36f2e365bbdebf0afc06b261ab2be8a36..1effca4e40e119d28f5ae3b9ed681f60eaa026f0 100644 (file)
@@ -1266,13 +1266,18 @@ mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd)
 static int
 mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
-       struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
        int rc;
 
        rc = mptscsih_ioc_reset(ioc, reset_phase);
 
-       if (reset_phase == MPT_IOC_POST_RESET)
+       /* only try to do a renegotiation if we're properly set up
+        * if we get an ioc fault on bringup, ioc->sh will be NULL */
+       if (reset_phase == MPT_IOC_POST_RESET &&
+           ioc->sh) {
+               struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
+
                mptspi_dv_renegotiate(hd);
+       }
 
        return rc;
 }
index 65210fca37ede70f3c42199579b142e01a2a120c..d89475d36988228c09e60b54034c288bd81368e6 100644 (file)
@@ -114,6 +114,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
        unsigned int nob = data->blocks;
        unsigned long long clks;
        unsigned int timeout;
+       bool dalgn = 0;
        u32 dcmd;
        int i;
 
@@ -152,6 +153,9 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
                host->sg_cpu[i].dcmd = dcmd | length;
                if (length & 31 && !(data->flags & MMC_DATA_READ))
                        host->sg_cpu[i].dcmd |= DCMD_ENDIRQEN;
+               /* Not aligned to 8-byte boundary? */
+               if (sg_dma_address(&data->sg[i]) & 0x7)
+                       dalgn = 1;
                if (data->flags & MMC_DATA_READ) {
                        host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO;
                        host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]);
@@ -165,6 +169,15 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
        host->sg_cpu[host->dma_len - 1].ddadr = DDADR_STOP;
        wmb();
 
+       /*
+        * The PXA27x DMA controller encounters overhead when working with
+        * unaligned (to 8-byte boundaries) data, so switch on byte alignment
+        * mode only if we have unaligned data.
+        */
+       if (dalgn)
+               DALGN |= (1 << host->dma);
+       else
+               DALGN &= (1 << host->dma);
        DDADR(host->dma) = host->sg_dma;
        DCSR(host->dma) = DCSR_RUN;
 }
index 07c2048b230ba0ec37d8ca3d140921162ae96253..b413aa6c246b938649f47e63a2af5482f76fdc11 100644 (file)
@@ -55,6 +55,10 @@ static unsigned int debug_quirks = 0;
 #define SDHCI_QUIRK_32BIT_DMA_SIZE                     (1<<7)
 /* Controller needs to be reset after each request to stay stable */
 #define SDHCI_QUIRK_RESET_AFTER_REQUEST                        (1<<8)
+/* Controller needs voltage and power writes to happen separately */
+#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER            (1<<9)
+/* Controller has an off-by-one issue with timeout value */
+#define SDHCI_QUIRK_INCR_TIMEOUT_CONTROL               (1<<10)
 
 static const struct pci_device_id pci_ids[] __devinitdata = {
        {
@@ -115,7 +119,8 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
                .driver_data    = SDHCI_QUIRK_SINGLE_POWER_WRITE |
-                                 SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS,
+                                 SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS |
+                                 SDHCI_QUIRK_BROKEN_DMA,
        },
 
        {
@@ -124,7 +129,17 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
                .driver_data    = SDHCI_QUIRK_SINGLE_POWER_WRITE |
-                                 SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS,
+                                 SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS |
+                                 SDHCI_QUIRK_BROKEN_DMA,
+       },
+
+       {
+               .vendor         = PCI_VENDOR_ID_MARVELL,
+               .device         = PCI_DEVICE_ID_MARVELL_CAFE_SD,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
+                                 SDHCI_QUIRK_INCR_TIMEOUT_CONTROL,
        },
 
        {
@@ -469,6 +484,13 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
                        break;
        }
 
+       /*
+        * Compensate for an off-by-one error in the CaFe hardware; otherwise,
+        * a too-small count gives us interrupt timeouts.
+        */
+       if ((host->chip->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL))
+               count++;
+
        if (count >= 0xF) {
                printk(KERN_WARNING "%s: Too large timeout requested!\n",
                        mmc_hostname(host->mmc));
@@ -774,6 +796,14 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
                BUG();
        }
 
+       /*
+        * At least the CaFe chip gets confused if we set the voltage
+        * and set turn on power at the same time, so set the voltage first.
+        */
+       if ((host->chip->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER))
+               writeb(pwr & ~SDHCI_POWER_ON,
+                               host->ioaddr + SDHCI_POWER_CONTROL);
+
        writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
 
 out:
index 4a79b187b568870ad207eaa94e905aec5133e390..5c29872184e65b64c3f5938968aaeb29061601f6 100644 (file)
@@ -130,10 +130,6 @@ typedef struct partition_t {
     u_int16_t          DataUnits;
     u_int32_t          BlocksPerUnit;
     erase_unit_header_t        header;
-#if 0
-    region_info_t      region;
-    memory_handle_t    handle;
-#endif
 } partition_t;
 
 /* Partition state flags */
index 1912d968718b38e81752b8c5df587b9081ef92f7..0cc31675aeb909c472479c41a14abc970ec9217e 100644 (file)
@@ -498,17 +498,14 @@ static int pcmciamtd_config(struct pcmcia_device *link)
        int i;
        config_info_t t;
        static char *probes[] = { "jedec_probe", "cfi_probe" };
-       cisinfo_t cisinfo;
        int new_name = 0;
 
        DEBUG(3, "link=0x%p", link);
 
        DEBUG(2, "Validating CIS");
-       ret = pcmcia_validate_cis(link, &cisinfo);
+       ret = pcmcia_validate_cis(link, NULL);
        if(ret != CS_SUCCESS) {
                cs_error(link, GetTupleData, ret);
-       } else {
-               DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains);
        }
 
        card_settings(dev, link, &new_name);
@@ -563,9 +560,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
        DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
 
        /* Get write protect status */
-       CS_CHECK(GetStatus, pcmcia_get_status(link, &status));
-       DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx",
-             status.CardState, (unsigned long)link->win);
+       DEBUG(2, "window handle = 0x%8.8lx", (unsigned long)link->win);
        dev->win_base = ioremap(req.Base, req.Size);
        if(!dev->win_base) {
                err("ioremap(%lu, %u) failed", req.Base, req.Size);
index 2edda8cc7f9999af1e5f772df389c20719373190..aabad8ce7458c852a496422991c0683c0fe43d26 100644 (file)
@@ -1768,9 +1768,10 @@ vortex_timer(unsigned long data)
        case XCVR_MII: case XCVR_NWAY:
                {
                        ok = 1;
-                       spin_lock_bh(&vp->lock);
+                       /* Interrupts are already disabled */
+                       spin_lock(&vp->lock);
                        vortex_check_media(dev, 0);
-                       spin_unlock_bh(&vp->lock);
+                       spin_unlock(&vp->lock);
                }
                break;
          default:                                      /* Other media types handled by Tx timeouts. */
index f3cba5e24ec511a7a08ea6c0659155850a165b00..1037b1332312998aa36274b279381263419f0371 100644 (file)
@@ -1803,6 +1803,8 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
        if (rx->prev->skb) {
                struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
                put_unaligned_le32(rx->dma_addr, &prev_rfd->link);
+               pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr,
+                       sizeof(struct rfd), PCI_DMA_TODEVICE);
        }
 
        return 0;
index 701531e72e7b3b4d1ddab378e5b05795c320d052..a3f6a9c72ec8546b11ab987b27ea330ca1fba5e2 100644 (file)
@@ -347,7 +347,7 @@ e1000_set_tso(struct net_device *netdev, u32 data)
        else
                netdev->features &= ~NETIF_F_TSO;
 
-       if (data)
+       if (data && (adapter->hw.mac_type > e1000_82547_rev_2))
                netdev->features |= NETIF_F_TSO6;
        else
                netdev->features &= ~NETIF_F_TSO6;
index cab1835173cd9bb7096f82647a5f59ae13eaba18..648a87bbf4670ae8f87ffce4f123769d66de84f6 100644 (file)
@@ -2535,7 +2535,8 @@ void e1000e_down(struct e1000_adapter *adapter)
        adapter->link_speed = 0;
        adapter->link_duplex = 0;
 
-       e1000e_reset(adapter);
+       if (!pci_channel_offline(adapter->pdev))
+               e1000e_reset(adapter);
        e1000_clean_tx_ring(adapter);
        e1000_clean_rx_ring(adapter);
 
index fe872fbd671e3c740705f910be4e6af3d7549373..e01926b7b5b7609cffec07754b7781c77fe26b3f 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "ehea"
-#define DRV_VERSION    "EHEA_0091"
+#define DRV_VERSION    "EHEA_0092"
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
@@ -452,7 +452,7 @@ struct ehea_bcmc_reg_entry {
 struct ehea_bcmc_reg_array {
        struct ehea_bcmc_reg_entry *arr;
        int num_entries;
-       struct mutex lock;
+       spinlock_t lock;
 };
 
 #define EHEA_PORT_UP 1
@@ -478,6 +478,7 @@ struct ehea_port {
        int num_add_tx_qps;
        int num_mcs;
        int resets;
+       u64 flags;
        u64 mac_addr;
        u32 logical_port_id;
        u32 port_speed;
@@ -501,7 +502,8 @@ struct port_res_cfg {
 };
 
 enum ehea_flag_bits {
-       __EHEA_STOP_XFER
+       __EHEA_STOP_XFER,
+       __EHEA_DISABLE_PORT_RESET
 };
 
 void ehea_set_ethtool_ops(struct net_device *netdev);
index 075fd547421e5b2c2a57932ba240e55130bb7e75..0920b796bd78375b17c679861a30e50338c9c3c7 100644 (file)
@@ -118,6 +118,7 @@ static struct of_device_id ehea_device_table[] = {
        },
        {},
 };
+MODULE_DEVICE_TABLE(of, ehea_device_table);
 
 static struct of_platform_driver ehea_driver = {
        .name = "ehea",
@@ -137,6 +138,12 @@ void ehea_dump(void *adr, int len, char *msg)
        }
 }
 
+void ehea_schedule_port_reset(struct ehea_port *port)
+{
+       if (!test_bit(__EHEA_DISABLE_PORT_RESET, &port->flags))
+               schedule_work(&port->reset_task);
+}
+
 static void ehea_update_firmware_handles(void)
 {
        struct ehea_fw_handle_entry *arr = NULL;
@@ -241,7 +248,7 @@ static void ehea_update_bcmc_registrations(void)
                }
 
        if (num_registrations) {
-               arr = kzalloc(num_registrations * sizeof(*arr), GFP_KERNEL);
+               arr = kzalloc(num_registrations * sizeof(*arr), GFP_ATOMIC);
                if (!arr)
                        return;  /* Keep the existing array */
        } else
@@ -301,7 +308,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev)
 
        memset(stats, 0, sizeof(*stats));
 
-       cb2 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       cb2 = kzalloc(PAGE_SIZE, GFP_ATOMIC);
        if (!cb2) {
                ehea_error("no mem for cb2");
                goto out;
@@ -587,7 +594,7 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq,
                                   "Resetting port.", pr->qp->init_attr.qp_nr);
                        ehea_dump(cqe, sizeof(*cqe), "CQE");
                }
-               schedule_work(&pr->port->reset_task);
+               ehea_schedule_port_reset(pr->port);
                return 1;
        }
 
@@ -616,7 +623,7 @@ static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
        *tcph = tcp_hdr(skb);
 
        /* check if ip header and tcp header are complete */
-       if (iph->tot_len < ip_len + tcp_hdrlen(skb))
+       if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb))
                return -1;
 
        *hdr_flags = LRO_IPV4 | LRO_TCP;
@@ -765,7 +772,7 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
                        ehea_error("Send Completion Error: Resetting port");
                        if (netif_msg_tx_err(pr->port))
                                ehea_dump(cqe, sizeof(*cqe), "Send CQE");
-                       schedule_work(&pr->port->reset_task);
+                       ehea_schedule_port_reset(pr->port);
                        break;
                }
 
@@ -885,7 +892,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
                eqe = ehea_poll_eq(port->qp_eq);
        }
 
-       schedule_work(&port->reset_task);
+       ehea_schedule_port_reset(port);
 
        return IRQ_HANDLED;
 }
@@ -1763,7 +1770,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
 
        memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
 
-       mutex_lock(&ehea_bcmc_regs.lock);
+       spin_lock(&ehea_bcmc_regs.lock);
 
        /* Deregister old MAC in pHYP */
        if (port->state == EHEA_PORT_UP) {
@@ -1785,7 +1792,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
 
 out_upregs:
        ehea_update_bcmc_registrations();
-       mutex_unlock(&ehea_bcmc_regs.lock);
+       spin_unlock(&ehea_bcmc_regs.lock);
 out_free:
        kfree(cb0);
 out:
@@ -1947,7 +1954,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
        }
        ehea_promiscuous(dev, 0);
 
-       mutex_lock(&ehea_bcmc_regs.lock);
+       spin_lock(&ehea_bcmc_regs.lock);
 
        if (dev->flags & IFF_ALLMULTI) {
                ehea_allmulti(dev, 1);
@@ -1978,7 +1985,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
        }
 out:
        ehea_update_bcmc_registrations();
-       mutex_unlock(&ehea_bcmc_regs.lock);
+       spin_unlock(&ehea_bcmc_regs.lock);
        return;
 }
 
@@ -2497,7 +2504,7 @@ static int ehea_up(struct net_device *dev)
                }
        }
 
-       mutex_lock(&ehea_bcmc_regs.lock);
+       spin_lock(&ehea_bcmc_regs.lock);
 
        ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
        if (ret) {
@@ -2520,7 +2527,7 @@ out:
                ehea_info("Failed starting %s. ret=%i", dev->name, ret);
 
        ehea_update_bcmc_registrations();
-       mutex_unlock(&ehea_bcmc_regs.lock);
+       spin_unlock(&ehea_bcmc_regs.lock);
 
        ehea_update_firmware_handles();
        mutex_unlock(&ehea_fw_handles.lock);
@@ -2575,7 +2582,7 @@ static int ehea_down(struct net_device *dev)
 
        mutex_lock(&ehea_fw_handles.lock);
 
-       mutex_lock(&ehea_bcmc_regs.lock);
+       spin_lock(&ehea_bcmc_regs.lock);
        ehea_drop_multicast_list(dev);
        ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
 
@@ -2584,7 +2591,7 @@ static int ehea_down(struct net_device *dev)
        port->state = EHEA_PORT_DOWN;
 
        ehea_update_bcmc_registrations();
-       mutex_unlock(&ehea_bcmc_regs.lock);
+       spin_unlock(&ehea_bcmc_regs.lock);
 
        ret = ehea_clean_all_portres(port);
        if (ret)
@@ -2605,13 +2612,14 @@ static int ehea_stop(struct net_device *dev)
        if (netif_msg_ifdown(port))
                ehea_info("disabling port %s", dev->name);
 
+       set_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
        cancel_work_sync(&port->reset_task);
-
        mutex_lock(&port->port_lock);
        netif_stop_queue(dev);
        port_napi_disable(port);
        ret = ehea_down(dev);
        mutex_unlock(&port->port_lock);
+       clear_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
        return ret;
 }
 
@@ -2941,7 +2949,7 @@ static void ehea_tx_watchdog(struct net_device *dev)
 
        if (netif_carrier_ok(dev) &&
            !test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
-               schedule_work(&port->reset_task);
+               ehea_schedule_port_reset(port);
 }
 
 int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
@@ -3590,7 +3598,7 @@ int __init ehea_module_init(void)
        memset(&ehea_bcmc_regs, 0, sizeof(ehea_bcmc_regs));
 
        mutex_init(&ehea_fw_handles.lock);
-       mutex_init(&ehea_bcmc_regs.lock);
+       spin_lock_init(&ehea_bcmc_regs.lock);
 
        ret = check_module_parm();
        if (ret)
index 2cb2447632928a4fd4bc9972a9f375a96065c4ae..20d4fe96a81cc57b98bbedc255a395c2a065183a 100644 (file)
@@ -4194,12 +4194,23 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 
        netif_carrier_off(dev);
        if (netif_running(dev)) {
+               unsigned long flags;
+
                nv_disable_irq(dev);
                netif_tx_lock_bh(dev);
-               spin_lock(&np->lock);
+               /* with plain spinlock lockdep complains */
+               spin_lock_irqsave(&np->lock, flags);
                /* stop engines */
+               /* FIXME:
+                * this can take some time, and interrupts are disabled
+                * due to spin_lock_irqsave, but let's hope no daemon
+                * is going to change the settings very often...
+                * Worst case:
+                * NV_RXSTOP_DELAY1MAX + NV_TXSTOP_DELAY1MAX
+                * + some minor delays, which is up to a second approximately
+                */
                nv_stop_rxtx(dev);
-               spin_unlock(&np->lock);
+               spin_unlock_irqrestore(&np->lock, flags);
                netif_tx_unlock_bh(dev);
        }
 
index e36321152d504cf0f9a23b880f07e6afbba5b565..8268b3535b30caff91ed208ec6c85025a658238e 100644 (file)
@@ -463,6 +463,9 @@ static void restart(struct net_device *dev)
        else
                C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
 
+       /* Restore multicast and promiscuous settings */
+       set_multicast_list(dev);
+
        S32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT);
 }
 
index 0b94833e23f7a48b76d16e3f5419d24d7f0556a7..e8cfadefa4b6751dbb74bd663a0f101e76a98d54 100644 (file)
@@ -1077,8 +1077,6 @@ static inline void rx_off(struct scc_priv *priv)
 
 static void start_timer(struct scc_priv *priv, int t, int r15)
 {
-       unsigned long flags;
-
        outb(priv->tmr_mode, priv->tmr_ctrl);
        if (t == 0) {
                tm_isr(priv);
index 5d2108c5ac7c872d32409de44edc22f07bf5620e..babc79ad490b6ada422a3ce96f9fefd510050b65 100644 (file)
@@ -1636,6 +1636,12 @@ static int emac_poll_rx(void *param, int budget)
                        goto next;
                }
 
+               if (len < ETH_HLEN) {
+                       ++dev->estats.rx_dropped_stack;
+                       emac_recycle_rx_skb(dev, slot, len);
+                       goto next;
+               }
+
                if (len && len < EMAC_RX_COPY_THRESH) {
                        struct sk_buff *copy_skb =
                            alloc_skb(len + EMAC_RX_SKB_HEADROOM + 2, GFP_ATOMIC);
@@ -2719,6 +2725,8 @@ static int __devinit emac_probe(struct of_device *ofdev,
        /* Clean rings */
        memset(dev->tx_desc, 0, NUM_TX_BUFF * sizeof(struct mal_descriptor));
        memset(dev->rx_desc, 0, NUM_RX_BUFF * sizeof(struct mal_descriptor));
+       memset(dev->tx_skb, 0, NUM_TX_BUFF * sizeof(struct sk_buff *));
+       memset(dev->rx_skb, 0, NUM_RX_BUFF * sizeof(struct sk_buff *));
 
        /* Attach to ZMII, if needed */
        if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII) &&
index ae398f04c7b44d8ef8865ed4f902dba1d12a0172..e79a26a886c883e0fc56ba0318a1aaa87b41e366 100644 (file)
@@ -718,7 +718,8 @@ void igb_down(struct igb_adapter *adapter)
        adapter->link_speed = 0;
        adapter->link_duplex = 0;
 
-       igb_reset(adapter);
+       if (!pci_channel_offline(adapter->pdev))
+               igb_reset(adapter);
        igb_clean_all_tx_rings(adapter);
        igb_clean_all_rx_rings(adapter);
 }
index 679a0826780e3471346a902c516daf534811e80c..2c03f4e2ccc44427206e8a868412be0bb92fac49 100644 (file)
@@ -1271,7 +1271,7 @@ static void ipg_nic_rx_with_end(struct net_device *dev,
 
                        framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN;
 
-                       endframeLen = framelen - jumbo->current_size;
+                       endframelen = framelen - jumbo->current_size;
                        /*
                        if (framelen > IPG_RXFRAG_SIZE)
                                framelen=IPG_RXFRAG_SIZE;
@@ -1279,8 +1279,8 @@ static void ipg_nic_rx_with_end(struct net_device *dev,
                        if (framelen > IPG_RXSUPPORT_SIZE)
                                dev_kfree_skb_irq(jumbo->skb);
                        else {
-                               memcpy(skb_put(jumbo->skb, endframeLen),
-                                      skb->data, endframeLen);
+                               memcpy(skb_put(jumbo->skb, endframelen),
+                                      skb->data, endframelen);
 
                                jumbo->skb->protocol =
                                    eth_type_trans(jumbo->skb, dev);
@@ -1352,16 +1352,16 @@ static int ipg_nic_rx(struct net_device *dev)
 
                switch (ipg_nic_rx_check_frame_type(dev)) {
                case FRAME_WITH_START_WITH_END:
-                       ipg_nic_rx_with_start_and_end(dev, tp, rxfd, entry);
+                       ipg_nic_rx_with_start_and_end(dev, sp, rxfd, entry);
                        break;
                case FRAME_WITH_START:
-                       ipg_nic_rx_with_start(dev, tp, rxfd, entry);
+                       ipg_nic_rx_with_start(dev, sp, rxfd, entry);
                        break;
                case FRAME_WITH_END:
-                       ipg_nic_rx_with_end(dev, tp, rxfd, entry);
+                       ipg_nic_rx_with_end(dev, sp, rxfd, entry);
                        break;
                case FRAME_NO_START_NO_END:
-                       ipg_nic_rx_no_start_no_end(dev, tp, rxfd, entry);
+                       ipg_nic_rx_no_start_no_end(dev, sp, rxfd, entry);
                        break;
                }
        }
@@ -1808,7 +1808,7 @@ static int ipg_nic_open(struct net_device *dev)
        /* initialize JUMBO Frame control variable */
        sp->jumbo.found_start = 0;
        sp->jumbo.current_size = 0;
-       sp->jumbo.skb = 0;
+       sp->jumbo.skb = NULL;
        dev->mtu = IPG_TXFRAG_SIZE;
 #endif
 
index a7714da7c283c84d48082b34540fbb05f86f85d2..effc1ce8179a9feed4f1fa42da4a90f4b6a1a244 100644 (file)
@@ -152,6 +152,7 @@ static chipio_t pnp_info;
 static const struct pnp_device_id nsc_ircc_pnp_table[] = {
        { .id = "NSC6001", .driver_data = 0 },
        { .id = "IBM0071", .driver_data = 0 },
+       { .id = "HWPC224", .driver_data = 0 },
        { }
 };
 
index 58e128784585a41b9c80410eaf46500e40a337ba..04ad3573b15993e3ae8bc1f7521ad6ac3dbae5de 100644 (file)
@@ -1546,6 +1546,7 @@ static int via_ircc_net_open(struct net_device *dev)
                        IRDA_WARNING("%s, unable to allocate dma2=%d\n",
                                     driver_name, self->io.dma2);
                        free_irq(self->io.irq, self);
+                       free_dma(self->io.dma);
                        return -EAGAIN;
                }
        }
@@ -1606,6 +1607,8 @@ static int via_ircc_net_close(struct net_device *dev)
        EnAllInt(iobase, OFF);
        free_irq(self->io.irq, dev);
        free_dma(self->io.dma);
+       if (self->io.dma2 != self->io.dma)
+               free_dma(self->io.dma2);
 
        return 0;
 }
index 7b859220c255b3b81017f156548df2dcca2f32e7..8f04609011538e257b820e9b521359750073cc63 100644 (file)
@@ -1969,7 +1969,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
        netif_carrier_off(netdev);
        netif_stop_queue(netdev);
 
-       ixgbe_reset(adapter);
+       if (!pci_channel_offline(adapter->pdev))
+               ixgbe_reset(adapter);
        ixgbe_clean_all_tx_rings(adapter);
        ixgbe_clean_all_rx_rings(adapter);
 
index 6797ed069f1f43ed659147da5d925bda1036e9e8..63cd67b931e7537cde2c407c63812c9fd3ffac02 100644 (file)
@@ -71,14 +71,18 @@ static irqreturn_t netxen_intr(int irq, void *data);
 static irqreturn_t netxen_msi_intr(int irq, void *data);
 
 /*  PCI Device ID Table  */
+#define ENTRY(device) \
+       {PCI_DEVICE(0x4040, (device)), \
+       .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0}
+
 static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
-       {PCI_DEVICE(0x4040, 0x0001), PCI_DEVICE_CLASS(0x020000, ~0)},
-       {PCI_DEVICE(0x4040, 0x0002), PCI_DEVICE_CLASS(0x020000, ~0)},
-       {PCI_DEVICE(0x4040, 0x0003), PCI_DEVICE_CLASS(0x020000, ~0)},
-       {PCI_DEVICE(0x4040, 0x0004), PCI_DEVICE_CLASS(0x020000, ~0)},
-       {PCI_DEVICE(0x4040, 0x0005), PCI_DEVICE_CLASS(0x020000, ~0)},
-       {PCI_DEVICE(0x4040, 0x0024), PCI_DEVICE_CLASS(0x020000, ~0)},
-       {PCI_DEVICE(0x4040, 0x0025), PCI_DEVICE_CLASS(0x020000, ~0)},
+       ENTRY(0x0001),
+       ENTRY(0x0002),
+       ENTRY(0x0003),
+       ENTRY(0x0004),
+       ENTRY(0x0005),
+       ENTRY(0x0024),
+       ENTRY(0x0025),
        {0,}
 };
 
index 3b2a6c5980883b6d86e46542910586b29cb8d220..993d87c9296f92361763e1662eae7ce545cb7aaf 100644 (file)
@@ -277,7 +277,7 @@ static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
        *tcph = tcp_hdr(skb);
 
        /* check if ip header and tcp header are complete */
-       if (iph->tot_len < ip_len + tcp_hdrlen(skb))
+       if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb))
                return -1;
 
        *hdr_flags = LRO_IPV4 | LRO_TCP;
index ce95c5d168fe9922382726ce71e295392548f2a3..70d012e90dcf35bb1aea12b0bcc6ee7f6e3d1260 100644 (file)
@@ -525,12 +525,14 @@ static int axnet_open(struct net_device *dev)
     int ret;
     axnet_dev_t *info = PRIV(dev);
     struct pcmcia_device *link = info->p_dev;
+    unsigned int nic_base = dev->base_addr;
     
     DEBUG(2, "axnet_open('%s')\n", dev->name);
 
     if (!pcmcia_dev_present(link))
        return -ENODEV;
 
+    outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */
     ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
     if (ret)
            return ret;
index fd8158a86f6490ce7dbaf389595b8e34a3d51821..2d4c4ad89b8dbda9fdcd773b7c9825d4de1889b8 100644 (file)
@@ -969,6 +969,7 @@ static int pcnet_open(struct net_device *dev)
     int ret;
     pcnet_dev_t *info = PRIV(dev);
     struct pcmcia_device *link = info->p_dev;
+    unsigned int nic_base = dev->base_addr;
 
     DEBUG(2, "pcnet_open('%s')\n", dev->name);
 
@@ -976,6 +977,8 @@ static int pcnet_open(struct net_device *dev)
        return -ENODEV;
 
     set_misc_reg(dev);
+
+    outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */
     ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
     if (ret)
            return ret;
index b7f7b2227d5697df09413841074d143c5ef8ac88..bccee68bd48a53fb671f2634d2b7bc3dd64cb36e 100644 (file)
@@ -3701,7 +3701,9 @@ static int ql_cycle_adapter(struct ql3_adapter *qdev, int reset)
                printk(KERN_ERR PFX
                                "%s: Driver up/down cycle failed, "
                                "closing device\n",qdev->ndev->name);
+               rtnl_lock();
                dev_close(qdev->ndev);
+               rtnl_unlock();
                return -1;
        }
        return 0;
index 858b191517b3dfc17800147191d0afe4e3f22b1b..504a48ff73c83e5cbac2eaa96c25bdc754bbd40e 100644 (file)
@@ -273,7 +273,7 @@ static void r6040_init_ring_desc(struct r6040_descriptor *desc_ring,
        dma_addr_t mapping = desc_dma;
 
        while (size-- > 0) {
-               mapping += sizeof(sizeof(*desc));
+               mapping += sizeof(*desc);
                desc->ndesc = cpu_to_le32(mapping);
                desc->vndescp = desc + 1;
                desc++;
index b5c1e663417d874aaba92270b2f765fe5cab8ee0..ae7b697456b4c88245ec36e6599efb17e6dc280f 100644 (file)
@@ -2625,9 +2625,7 @@ static int fill_rx_buffers(struct ring_info *ring)
                        rxdp1->Buffer0_ptr = pci_map_single
                            (ring->pdev, skb->data, size - NET_IP_ALIGN,
                                PCI_DMA_FROMDEVICE);
-                       if( (rxdp1->Buffer0_ptr == 0) ||
-                               (rxdp1->Buffer0_ptr ==
-                               DMA_ERROR_CODE))
+                       if(pci_dma_mapping_error(rxdp1->Buffer0_ptr))
                                goto pci_map_failed;
 
                        rxdp->Control_2 =
@@ -2657,6 +2655,7 @@ static int fill_rx_buffers(struct ring_info *ring)
                        skb->data = (void *) (unsigned long)tmp;
                        skb_reset_tail_pointer(skb);
 
+                       /* AK: check is wrong. 0 can be valid dma address */
                        if (!(rxdp3->Buffer0_ptr))
                                rxdp3->Buffer0_ptr =
                                   pci_map_single(ring->pdev, ba->ba_0,
@@ -2665,8 +2664,7 @@ static int fill_rx_buffers(struct ring_info *ring)
                                pci_dma_sync_single_for_device(ring->pdev,
                                (dma_addr_t) rxdp3->Buffer0_ptr,
                                    BUF0_LEN, PCI_DMA_FROMDEVICE);
-                       if( (rxdp3->Buffer0_ptr == 0) ||
-                               (rxdp3->Buffer0_ptr == DMA_ERROR_CODE))
+                       if (pci_dma_mapping_error(rxdp3->Buffer0_ptr))
                                goto pci_map_failed;
 
                        rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
@@ -2681,18 +2679,17 @@ static int fill_rx_buffers(struct ring_info *ring)
                                (ring->pdev, skb->data, ring->mtu + 4,
                                                PCI_DMA_FROMDEVICE);
 
-                               if( (rxdp3->Buffer2_ptr == 0) ||
-                                       (rxdp3->Buffer2_ptr == DMA_ERROR_CODE))
+                               if (pci_dma_mapping_error(rxdp3->Buffer2_ptr))
                                        goto pci_map_failed;
 
+                               /* AK: check is wrong */
                                if (!rxdp3->Buffer1_ptr)
                                        rxdp3->Buffer1_ptr =
                                                pci_map_single(ring->pdev,
                                                ba->ba_1, BUF1_LEN,
                                                PCI_DMA_FROMDEVICE);
 
-                               if( (rxdp3->Buffer1_ptr == 0) ||
-                                       (rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) {
+                               if (pci_dma_mapping_error(rxdp3->Buffer1_ptr)) {
                                        pci_unmap_single
                                                (ring->pdev,
                                                (dma_addr_t)(unsigned long)
@@ -4264,16 +4261,14 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
                txdp->Buffer_Pointer = pci_map_single(sp->pdev,
                                        fifo->ufo_in_band_v,
                                        sizeof(u64), PCI_DMA_TODEVICE);
-               if((txdp->Buffer_Pointer == 0) ||
-                       (txdp->Buffer_Pointer == DMA_ERROR_CODE))
+               if (pci_dma_mapping_error(txdp->Buffer_Pointer))
                        goto pci_map_failed;
                txdp++;
        }
 
        txdp->Buffer_Pointer = pci_map_single
            (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE);
-       if((txdp->Buffer_Pointer == 0) ||
-               (txdp->Buffer_Pointer == DMA_ERROR_CODE))
+       if (pci_dma_mapping_error(txdp->Buffer_Pointer))
                goto pci_map_failed;
 
        txdp->Host_Control = (unsigned long) skb;
@@ -6884,10 +6879,8 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
                                pci_map_single( sp->pdev, (*skb)->data,
                                        size - NET_IP_ALIGN,
                                        PCI_DMA_FROMDEVICE);
-                       if( (rxdp1->Buffer0_ptr == 0) ||
-                               (rxdp1->Buffer0_ptr == DMA_ERROR_CODE)) {
+                       if (pci_dma_mapping_error(rxdp1->Buffer0_ptr))
                                goto memalloc_failed;
-                       }
                        rxdp->Host_Control = (unsigned long) (*skb);
                }
        } else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) {
@@ -6913,15 +6906,12 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
                                pci_map_single(sp->pdev, (*skb)->data,
                                               dev->mtu + 4,
                                               PCI_DMA_FROMDEVICE);
-                       if( (rxdp3->Buffer2_ptr == 0) ||
-                               (rxdp3->Buffer2_ptr == DMA_ERROR_CODE)) {
+                       if (pci_dma_mapping_error(rxdp3->Buffer2_ptr))
                                goto memalloc_failed;
-                       }
                        rxdp3->Buffer0_ptr = *temp0 =
                                pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN,
                                                PCI_DMA_FROMDEVICE);
-                       if( (rxdp3->Buffer0_ptr == 0) ||
-                               (rxdp3->Buffer0_ptr == DMA_ERROR_CODE)) {
+                       if (pci_dma_mapping_error(rxdp3->Buffer0_ptr)) {
                                pci_unmap_single (sp->pdev,
                                        (dma_addr_t)rxdp3->Buffer2_ptr,
                                        dev->mtu + 4, PCI_DMA_FROMDEVICE);
@@ -6933,8 +6923,7 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp,
                        rxdp3->Buffer1_ptr = *temp1 =
                                pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN,
                                                PCI_DMA_FROMDEVICE);
-                       if( (rxdp3->Buffer1_ptr == 0) ||
-                               (rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) {
+                       if (pci_dma_mapping_error(rxdp3->Buffer1_ptr)) {
                                pci_unmap_single (sp->pdev,
                                        (dma_addr_t)rxdp3->Buffer0_ptr,
                                        BUF0_LEN, PCI_DMA_FROMDEVICE);
index 4706f7f9acb628b423834e90a467f273f2245fd7..1827b6686c986ff4ab2c70c8521f3dc8cfe0c35d 100644 (file)
@@ -75,10 +75,6 @@ static int debug_level = ERR_DBG;
 /* DEBUG message print. */
 #define DBG_PRINT(dbg_level, args...)  if(!(debug_level<dbg_level)) printk(args)
 
-#ifndef DMA_ERROR_CODE
-#define DMA_ERROR_CODE          (~(dma_addr_t)0x0)
-#endif
-
 /* Protocol assist features of the NIC */
 #define L3_CKSUM_OK 0xFFFF
 #define L4_CKSUM_OK 0xFFFF
index 10e4e85da3fcae7af7e9435145f06dad72abd35f..b07b8cbadeaf8eb4a34dbbfe848ad5499f2a628b 100644 (file)
@@ -1394,6 +1394,7 @@ tc35815_open(struct net_device *dev)
        tc35815_chip_init(dev);
        spin_unlock_irq(&lp->lock);
 
+       netif_carrier_off(dev);
        /* schedule a link state check */
        phy_start(lp->phy_dev);
 
@@ -1735,7 +1736,6 @@ tc35815_rx(struct net_device *dev)
                        skb = lp->rx_skbs[cur_bd].skb;
                        prefetch(skb->data);
                        lp->rx_skbs[cur_bd].skb = NULL;
-                       lp->fbl_count--;
                        pci_unmap_single(lp->pci_dev,
                                         lp->rx_skbs[cur_bd].skb_dma,
                                         RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
@@ -1791,6 +1791,7 @@ tc35815_rx(struct net_device *dev)
 #ifdef TC35815_USE_PACKEDBUFFER
                        while (lp->fbl_curid != id)
 #else
+                       lp->fbl_count--;
                        while (lp->fbl_count < RX_BUF_NUM)
 #endif
                        {
@@ -2453,6 +2454,7 @@ static int tc35815_resume(struct pci_dev *pdev)
                return 0;
        pci_set_power_state(pdev, PCI_D0);
        tc35815_restart(dev);
+       netif_carrier_off(dev);
        if (lp->phy_dev)
                phy_start(lp->phy_dev);
        netif_device_attach(dev);
index 7ab94c825b577f13b606bc938b834db6003559ad..b9018bfa0a9724d2a28ee54d9f9af50429c55da0 100644 (file)
@@ -602,6 +602,12 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
        tun->attached = 1;
        get_net(dev_net(tun->dev));
 
+       /* Make sure persistent devices do not get stuck in
+        * xoff state.
+        */
+       if (netif_running(tun->dev))
+               netif_wake_queue(tun->dev);
+
        strcpy(ifr->ifr_name, tun->dev->name);
        return 0;
 
index 520bb0b1a9a2f6f1c6a74d00d9200631fda23bf5..6d35155c7145185a6ba1685097b49dcebc99b118 100644 (file)
@@ -1008,6 +1008,7 @@ static int fr_rx(struct sk_buff *skb)
                stats->rx_bytes += skb->len;
                if (pvc->state.becn)
                        stats->rx_compressed++;
+               skb->dev = dev;
                netif_rx(skb);
                return NET_RX_SUCCESS;
        } else {
index 249e18053d5fa4a2d6e29a60e33878bbe1f78c90..069f8bb0a99fa401e254a03ff94a77a4217d58b5 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/x25.h>
 #include <linux/lapb.h>
 #include <linux/init.h>
+#include <linux/rtnetlink.h>
 #include "x25_asy.h"
 
 #include <net/x25device.h>
@@ -601,8 +602,10 @@ static void x25_asy_close_tty(struct tty_struct *tty)
        if (!sl || sl->magic != X25_ASY_MAGIC)
                return;
 
+       rtnl_lock();
        if (sl->dev->flags & IFF_UP)
                dev_close(sl->dev);
+       rtnl_unlock();
 
        tty->disc_data = NULL;
        sl->tty = NULL;
index 36a9c42df835c3fa77241533cf90f1eb6c14e9e4..76f4c7bad8b83e52b30000ccc62f86a77113e45b 100644 (file)
@@ -72,6 +72,9 @@ static void b43_led_brightness_set(struct led_classdev *led_dev,
        struct b43_wldev *dev = led->dev;
        bool radio_enabled;
 
+       if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED))
+               return;
+
        /* Checking the radio-enabled status here is slightly racy,
         * but we want to avoid the locking overhead and we don't care
         * whether the LED has the wrong state for a second. */
index fa4b0d8b74a26df90df59f8f3fa57dc8925d023e..a70827793086e68aa14291ecb1f3086a29cdf384 100644 (file)
@@ -2883,12 +2883,11 @@ static int b43_op_tx(struct ieee80211_hw *hw,
 
        if (unlikely(skb->len < 2 + 2 + 6)) {
                /* Too short, this can't be a valid frame. */
-               dev_kfree_skb_any(skb);
-               return NETDEV_TX_OK;
+               goto drop_packet;
        }
        B43_WARN_ON(skb_shinfo(skb)->nr_frags);
        if (unlikely(!dev))
-               return NETDEV_TX_BUSY;
+               goto drop_packet;
 
        /* Transmissions on seperate queues can run concurrently. */
        read_lock_irqsave(&wl->tx_lock, flags);
@@ -2904,7 +2903,12 @@ static int b43_op_tx(struct ieee80211_hw *hw,
        read_unlock_irqrestore(&wl->tx_lock, flags);
 
        if (unlikely(err))
-               return NETDEV_TX_BUSY;
+               goto drop_packet;
+       return NETDEV_TX_OK;
+
+drop_packet:
+       /* We can not transmit this packet. Drop it. */
+       dev_kfree_skb_any(skb);
        return NETDEV_TX_OK;
 }
 
index c990f87b107acff6603a24a70b8f402144f64d9c..93ddc1cbcc8b2bb7453e8040288a1a2771c1d01b 100644 (file)
@@ -876,6 +876,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
        if (!ring)
                goto out;
        ring->type = type;
+       ring->dev = dev;
 
        nr_slots = B43legacy_RXRING_SLOTS;
        if (for_tx)
@@ -922,7 +923,6 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
                                 DMA_TO_DEVICE);
        }
 
-       ring->dev = dev;
        ring->nr_slots = nr_slots;
        ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index);
        ring->index = controller_index;
index 204077c13870c05b619f781154bcc942eb1cdf1d..3e612d0a13e8fc927c766c09507067a0d009a988 100644 (file)
@@ -2378,8 +2378,10 @@ static int b43legacy_op_tx(struct ieee80211_hw *hw,
        } else
                err = b43legacy_dma_tx(dev, skb, ctl);
 out:
-       if (unlikely(err))
-               return NETDEV_TX_BUSY;
+       if (unlikely(err)) {
+               /* Drop the packet. */
+               dev_kfree_skb_any(skb);
+       }
        return NETDEV_TX_OK;
 }
 
index 4fd73809602e7e8af816a30570b7da7306af71e3..020f450e9dba9cd7f903e7c5b380a5f0600d1c04 100644 (file)
@@ -64,7 +64,7 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
        int hdrlen, phdrlen, head_need, tail_need;
        u16 fc;
        int prism_header, ret;
-       struct ieee80211_hdr_4addr *hdr;
+       struct ieee80211_hdr_4addr *fhdr;
 
        iface = netdev_priv(dev);
        local = iface->local;
@@ -83,8 +83,8 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
                phdrlen = 0;
        }
 
-       hdr = (struct ieee80211_hdr_4addr *) skb->data;
-       fc = le16_to_cpu(hdr->frame_ctl);
+       fhdr = (struct ieee80211_hdr_4addr *) skb->data;
+       fc = le16_to_cpu(fhdr->frame_ctl);
 
        if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) {
                printk(KERN_DEBUG "%s: dropped management frame with header "
@@ -551,7 +551,7 @@ hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
             hdr->addr1[2] != 0xff || hdr->addr1[3] != 0xff ||
             hdr->addr1[4] != 0xff || hdr->addr1[5] != 0xff)) {
                /* RA (or BSSID) is not ours - drop */
-               PDEBUG(DEBUG_EXTRA, "%s: received WDS frame with "
+               PDEBUG(DEBUG_EXTRA2, "%s: received WDS frame with "
                       "not own or broadcast %s=%s\n",
                       local->dev->name,
                       fc & IEEE80211_FCTL_FROMDS ? "RA" : "BSSID",
index 0acd9589c48c0f36277f6b1351a559bbb1988f14..ab981afd481d6ea5a3cc199dcac224b015f6c5bd 100644 (file)
@@ -1930,7 +1930,7 @@ static void handle_pspoll(local_info_t *local,
                PDEBUG(DEBUG_PS, "   PSPOLL and AID[15:14] not set\n");
                return;
        }
-       aid &= ~BIT(15) & ~BIT(14);
+       aid &= ~(BIT(15) | BIT(14));
        if (aid == 0 || aid > MAX_AID_TABLE_SIZE) {
                PDEBUG(DEBUG_PS, "   invalid aid=%d\n", aid);
                return;
index ed4317a17cbb03beafb276e9f870dece124b24e8..3b4e55cf33cd4a071b57a35144b4a3aa3b6883af 100644 (file)
@@ -533,10 +533,10 @@ static void prism2_detach(struct pcmcia_device *link)
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
 #define CFG_CHECK2(fn, retf) \
-do { int ret = (retf); \
-if (ret != 0) { \
-       PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", ret); \
-       cs_error(link, fn, ret); \
+do { int _ret = (retf); \
+if (_ret != 0) { \
+       PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", _ret); \
+       cs_error(link, fn, _ret); \
        goto next_entry; \
 } \
 } while (0)
@@ -777,8 +777,10 @@ static int hostap_cs_suspend(struct pcmcia_device *link)
        int dev_open = 0;
        struct hostap_interface *iface = NULL;
 
-       if (dev)
-               iface = netdev_priv(dev);
+       if (!dev)
+               return -ENODEV;
+
+       iface = netdev_priv(dev);
 
        PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
        if (iface && iface->local)
@@ -798,8 +800,10 @@ static int hostap_cs_resume(struct pcmcia_device *link)
        int dev_open = 0;
        struct hostap_interface *iface = NULL;
 
-       if (dev)
-               iface = netdev_priv(dev);
+       if (!dev)
+               return -ENODEV;
+
+       iface = netdev_priv(dev);
 
        PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
 
index cdf90c40f11b872c60fc293e5caef3a1d82756b9..936f52e3d95c4040a18515e2f949027a95442638 100644 (file)
@@ -2835,7 +2835,7 @@ static void hostap_passive_scan(unsigned long data)
 {
        local_info_t *local = (local_info_t *) data;
        struct net_device *dev = local->dev;
-       u16 channel;
+       u16 chan;
 
        if (local->passive_scan_interval <= 0)
                return;
@@ -2872,11 +2872,11 @@ static void hostap_passive_scan(unsigned long data)
 
                printk(KERN_DEBUG "%s: passive scan channel %d\n",
                       dev->name, local->passive_scan_channel);
-               channel = local->passive_scan_channel;
+               chan = local->passive_scan_channel;
                local->passive_scan_state = PASSIVE_SCAN_WAIT;
                local->passive_scan_timer.expires = jiffies + HZ / 10;
        } else {
-               channel = local->channel;
+               chan = local->channel;
                local->passive_scan_state = PASSIVE_SCAN_LISTEN;
                local->passive_scan_timer.expires = jiffies +
                        local->passive_scan_interval * HZ;
@@ -2884,9 +2884,9 @@ static void hostap_passive_scan(unsigned long data)
 
        if (hfa384x_cmd_callback(dev, HFA384X_CMDCODE_TEST |
                                 (HFA384X_TEST_CHANGE_CHANNEL << 8),
-                                channel, NULL, 0))
+                                chan, NULL, 0))
                printk(KERN_ERR "%s: passive scan channel set %d "
-                      "failed\n", dev->name, channel);
+                      "failed\n", dev->name, chan);
 
        add_timer(&local->passive_scan_timer);
 }
index f7aec9309d0412c86dd0bc3fd111ff9c37ef7d5c..a38e85f334df2991e7d086085250d7fd092d2080 100644 (file)
@@ -594,7 +594,8 @@ void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx)
 }
 
 
-int hostap_80211_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+static int hostap_80211_header_parse(const struct sk_buff *skb,
+                                    unsigned char *haddr)
 {
        struct hostap_interface *iface = netdev_priv(skb->dev);
        local_info_t *local = iface->local;
@@ -857,7 +858,6 @@ const struct header_ops hostap_80211_ops = {
        .rebuild        = eth_rebuild_header,
        .cache          = eth_header_cache,
        .cache_update   = eth_header_cache_update,
-
        .parse          = hostap_80211_header_parse,
 };
 EXPORT_SYMBOL(hostap_80211_ops);
@@ -1150,7 +1150,6 @@ EXPORT_SYMBOL(hostap_set_roaming);
 EXPORT_SYMBOL(hostap_set_auth_algs);
 EXPORT_SYMBOL(hostap_dump_rx_header);
 EXPORT_SYMBOL(hostap_dump_tx_header);
-EXPORT_SYMBOL(hostap_80211_header_parse);
 EXPORT_SYMBOL(hostap_80211_get_hdrlen);
 EXPORT_SYMBOL(hostap_get_stats);
 EXPORT_SYMBOL(hostap_setup_dev);
index 62a3d8f8563ed07cbd7d6a743831dfdc66bf78cb..55ac850744b343024189ec0db16efc10e0d9aec9 100644 (file)
@@ -449,7 +449,7 @@ static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv,
 
        if (print_summary) {
                char *title;
-               u32 rate;
+               int rate;
 
                if (hundred)
                        title = "100Frames";
@@ -487,7 +487,7 @@ static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv,
                 *    but you can hack it to show more, if you'd like to. */
                if (dataframe)
                        IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
-                                    "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
+                                    "len=%u, rssi=%d, chnl=%d, rate=%d, \n",
                                     title, fc, header->addr1[5],
                                     length, rssi, channel, rate);
                else {
@@ -588,8 +588,12 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
 
        if (rate == -1)
                iwl3945_rt->rt_rate = 0;
-       else
+       else {
+               if (stats->band == IEEE80211_BAND_5GHZ)
+                       rate += IWL_FIRST_OFDM_RATE;
+
                iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee;
+       }
 
        /* antenna number */
        antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK;
index bf19eb8aafd02f4db85e4d4f856d79f5ec2825fc..de330ae0ca959974dab58d18b306a11cd9071733 100644 (file)
@@ -3528,8 +3528,12 @@ static void iwl4965_add_radiotap(struct iwl_priv *priv,
 
        if (rate == -1)
                iwl4965_rt->rt_rate = 0;
-       else
+       else {
+               if (stats->band == IEEE80211_BAND_5GHZ)
+                       rate += IWL_FIRST_OFDM_RATE;
+
                iwl4965_rt->rt_rate = iwl4965_rates[rate].ieee;
+       }
 
        /*
         * "antenna number"
index 13925b627e3b5569f5ebaf1399f121dea3d489d2..6027e1119c3fd8fde2fefae8536b35603ac343d0 100644 (file)
@@ -2227,7 +2227,10 @@ static int iwl3945_scan_initiate(struct iwl3945_priv *priv)
        }
 
        IWL_DEBUG_INFO("Starting scan...\n");
-       priv->scan_bands = 2;
+       if (priv->cfg->sku & IWL_SKU_G)
+               priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
+       if (priv->cfg->sku & IWL_SKU_A)
+               priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
        set_bit(STATUS_SCANNING, &priv->status);
        priv->scan_start = jiffies;
        priv->scan_pass_start = priv->scan_start;
@@ -3352,13 +3355,18 @@ static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv,
        cancel_delayed_work(&priv->scan_check);
 
        IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n",
-                      (priv->scan_bands == 2) ? "2.4" : "5.2",
+                      (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ?
+                                                       "2.4" : "5.2",
                       jiffies_to_msecs(elapsed_jiffies
                                        (priv->scan_pass_start, jiffies)));
 
-       /* Remove this scanned band from the list
-        * of pending bands to scan */
-       priv->scan_bands--;
+       /* Remove this scanned band from the list of pending
+        * bands to scan, band G precedes A in order of scanning
+        * as seen in iwl3945_bg_request_scan */
+       if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ))
+               priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ);
+       else if (priv->scan_bands &  BIT(IEEE80211_BAND_5GHZ))
+               priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ);
 
        /* If a request to abort was given, or the scan did not succeed
         * then we reset the scan state machine and terminate,
@@ -4972,7 +4980,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
 
                ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel);
                if (!is_channel_valid(ch_info)) {
-                       IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
+                       IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n",
                                       scan_ch->channel);
                        continue;
                }
@@ -6315,21 +6323,16 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
        /* flags + rate selection */
 
-       switch (priv->scan_bands) {
-       case 2:
+       if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
                scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
                scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
                scan->good_CRC_th = 0;
                band = IEEE80211_BAND_2GHZ;
-               break;
-
-       case 1:
+       } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
                scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
                scan->good_CRC_th = IWL_GOOD_CRC_TH;
                band = IEEE80211_BAND_5GHZ;
-               break;
-
-       default:
+       } else {
                IWL_WARNING("Invalid scan band count\n");
                goto done;
        }
@@ -6684,7 +6687,8 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 
        if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
                IWL_DEBUG_MAC80211("leave - monitor\n");
-               return -1;
+               dev_kfree_skb_any(skb);
+               return 0;
        }
 
        IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
@@ -6770,7 +6774,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
        ch_info = iwl3945_get_channel_info(priv, conf->channel->band,
                                           conf->channel->hw_value);
        if (!is_channel_valid(ch_info)) {
-               IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
+               IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this band.\n",
                               conf->channel->hw_value, conf->channel->band);
                IWL_DEBUG_MAC80211("leave - invalid channel\n");
                spin_unlock_irqrestore(&priv->lock, flags);
index 883b42f7e9989dff95e085cf6afb6577eb9f7f1a..0bd55bb19739b4f506944ef1c1489d88ae820b86 100644 (file)
@@ -1774,7 +1774,10 @@ static int iwl4965_scan_initiate(struct iwl_priv *priv)
        }
 
        IWL_DEBUG_INFO("Starting scan...\n");
-       priv->scan_bands = 2;
+       if (priv->cfg->sku & IWL_SKU_G)
+               priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
+       if (priv->cfg->sku & IWL_SKU_A)
+               priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
        set_bit(STATUS_SCANNING, &priv->status);
        priv->scan_start = jiffies;
        priv->scan_pass_start = priv->scan_start;
@@ -3023,8 +3026,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
 
        IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
        if (index != -1) {
-               int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
 #ifdef CONFIG_IWL4965_HT
+               int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
+
                if (tid != MAX_TID_COUNT)
                        priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
                if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
@@ -3276,13 +3280,18 @@ static void iwl4965_rx_scan_complete_notif(struct iwl_priv *priv,
        cancel_delayed_work(&priv->scan_check);
 
        IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n",
-                      (priv->scan_bands == 2) ? "2.4" : "5.2",
+                      (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ?
+                                               "2.4" : "5.2",
                       jiffies_to_msecs(elapsed_jiffies
                                        (priv->scan_pass_start, jiffies)));
 
-       /* Remove this scanned band from the list
-        * of pending bands to scan */
-       priv->scan_bands--;
+       /* Remove this scanned band from the list of pending
+        * bands to scan, band G precedes A in order of scanning
+        * as seen in iwl_bg_request_scan */
+       if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ))
+               priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ);
+       else if (priv->scan_bands &  BIT(IEEE80211_BAND_5GHZ))
+               priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ);
 
        /* If a request to abort was given, or the scan did not succeed
         * then we reset the scan state machine and terminate,
@@ -3292,7 +3301,7 @@ static void iwl4965_rx_scan_complete_notif(struct iwl_priv *priv,
                clear_bit(STATUS_SCAN_ABORTING, &priv->status);
        } else {
                /* If there are more bands on this scan pass reschedule */
-               if (priv->scan_bands > 0)
+               if (priv->scan_bands)
                        goto reschedule;
        }
 
@@ -4635,10 +4644,9 @@ static int iwl4965_get_channels_for_scan(struct iwl_priv *priv,
 
                scan_ch->channel = ieee80211_frequency_to_channel(channels[i].center_freq);
 
-               ch_info = iwl_get_channel_info(priv, band,
-                                        scan_ch->channel);
+               ch_info = iwl_get_channel_info(priv, band, scan_ch->channel);
                if (!is_channel_valid(ch_info)) {
-                       IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
+                       IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n",
                                       scan_ch->channel);
                        continue;
                }
@@ -5830,8 +5838,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
        scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
 
 
-       switch (priv->scan_bands) {
-       case 2:
+       if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
                scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
                scan->tx_cmd.rate_n_flags =
                                iwl4965_hw_set_rate_n_flags(IWL_RATE_1M_PLCP,
@@ -5839,17 +5846,13 @@ static void iwl4965_bg_request_scan(struct work_struct *data)
 
                scan->good_CRC_th = 0;
                band = IEEE80211_BAND_2GHZ;
-               break;
-
-       case 1:
+       } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
                scan->tx_cmd.rate_n_flags =
                                iwl4965_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
                                RATE_MCS_ANT_B_MSK);
                scan->good_CRC_th = IWL_GOOD_CRC_TH;
                band = IEEE80211_BAND_5GHZ;
-               break;
-
-       default:
+       } else {
                IWL_WARNING("Invalid scan band count\n");
                goto done;
        }
@@ -6234,7 +6237,8 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 
        if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
                IWL_DEBUG_MAC80211("leave - monitor\n");
-               return -1;
+               dev_kfree_skb_any(skb);
+               return 0;
        }
 
        IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
index 8032df72aaab59fa368783d82325befd23ee7dda..36288b29abf7da14fe7a58b4d130a517e952daf2 100644 (file)
@@ -925,6 +925,7 @@ static struct usb_driver if_usb_driver = {
        .id_table = if_usb_table,
        .suspend = if_usb_suspend,
        .resume = if_usb_resume,
+       .reset_resume = if_usb_resume,
 };
 
 static int __init if_usb_init_module(void)
index d448c9702a0f93528d66f7d5f2ee116a452a1604..387d4878af2f02488b32f95804e66ed0dea6e377 100644 (file)
@@ -567,11 +567,11 @@ static int lbs_process_bss(struct bss_descriptor *bss,
        pos += 8;
 
        /* beacon interval is 2 bytes long */
-       bss->beaconperiod = le16_to_cpup((void *) pos);
+       bss->beaconperiod = get_unaligned_le16(pos);
        pos += 2;
 
        /* capability information is 2 bytes long */
-       bss->capability = le16_to_cpup((void *) pos);
+       bss->capability = get_unaligned_le16(pos);
        lbs_deb_scan("process_bss: capabilities 0x%04x\n", bss->capability);
        pos += 2;
 
index 762e85bef55dcef657ded932a53f911b051ae4b9..e43bae97ed8f66a6bc9ccb9eeb86a66a6db0302c 100644 (file)
@@ -290,7 +290,7 @@ islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb)
 
                avs->version = cpu_to_be32(P80211CAPTURE_VERSION);
                avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header));
-               avs->mactime = cpu_to_be64(le64_to_cpu(clock));
+               avs->mactime = cpu_to_be64(clock);
                avs->hosttime = cpu_to_be64(jiffies);
                avs->phytype = cpu_to_be32(6);  /*OFDM: 6 for (g), 8 for (a) */
                avs->channel = cpu_to_be32(channel_of_freq(freq));
index 560b9c73c0b9bcd41e1c0698818be95b59445084..b36ed1c6c746a037d943e174f7cba49bb06bc4fc 100644 (file)
@@ -731,6 +731,17 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
                           (rt2x00dev->rx->data_size / 128));
        rt2x00pci_register_write(rt2x00dev, CSR9, reg);
 
+       rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+       rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+       rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+       rt2x00_set_field32(&reg, CSR14_TCFP, 0);
+       rt2x00_set_field32(&reg, CSR14_TATIMW, 0);
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
+       rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+
        rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000);
 
        rt2x00pci_register_read(rt2x00dev, ARCSR0, &reg);
index a5ed54b69262f8f6b167ebf87d6613b9c4319ec0..f7731fb82555745488391a0f4e3f9f72a81c3119 100644 (file)
@@ -824,6 +824,17 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, CSR11_CW_SELECT, 0);
        rt2x00pci_register_write(rt2x00dev, CSR11, reg);
 
+       rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+       rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+       rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+       rt2x00_set_field32(&reg, CSR14_TCFP, 0);
+       rt2x00_set_field32(&reg, CSR14_TATIMW, 0);
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
+       rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+
        rt2x00pci_register_write(rt2x00dev, CNT3, 0);
 
        rt2x00pci_register_read(rt2x00dev, TXCSR8, &reg);
index fdbd0ef2be4bceef492431262796e6466a11e0b8..d90512f97b394f1049edf2981d3fe423ac6e7ed2 100644 (file)
@@ -138,11 +138,8 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
         * Wait until the BBP becomes ready.
         */
        reg = rt2500usb_bbp_check(rt2x00dev);
-       if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
-               ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
-               mutex_unlock(&rt2x00dev->usb_cache_mutex);
-               return;
-       }
+       if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
+               goto exit_fail;
 
        /*
         * Write the data into the BBP.
@@ -155,6 +152,13 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
        rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
 
        mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+       return;
+
+exit_fail:
+       mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+       ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
 }
 
 static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -168,10 +172,8 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
         * Wait until the BBP becomes ready.
         */
        reg = rt2500usb_bbp_check(rt2x00dev);
-       if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
-               ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
-               return;
-       }
+       if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
+               goto exit_fail;
 
        /*
         * Write the request into the BBP.
@@ -186,17 +188,21 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
         * Wait until the BBP becomes ready.
         */
        reg = rt2500usb_bbp_check(rt2x00dev);
-       if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
-               ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
-               *value = 0xff;
-               mutex_unlock(&rt2x00dev->usb_cache_mutex);
-               return;
-       }
+       if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
+               goto exit_fail;
 
        rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
        *value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
 
        mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+       return;
+
+exit_fail:
+       mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+       ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
+       *value = 0xff;
 }
 
 static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -795,6 +801,13 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1_VALID, 0);
        rt2500usb_register_write(rt2x00dev, TXRX_CSR8, reg);
 
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+
        rt2500usb_register_write(rt2x00dev, TXRX_CSR21, 0xe78f);
        rt2500usb_register_write(rt2x00dev, MAC_CSR9, 0xff1d);
 
index 611d98320593869dc9c26faf2c64218c8c32e3ec..b4bf1e09cf9a906447ed8a5770e9e0cdfec52626 100644 (file)
@@ -821,6 +821,7 @@ struct rt2x00_dev {
        /*
         * Scheduled work.
         */
+       struct workqueue_struct *workqueue;
        struct work_struct intf_work;
        struct work_struct filter_work;
 
index 2673d568bcac286dc9f3cbdb8da9d3c5051ff7cc..c997d4f28ab39bd31e7e8b25adad8ea278b1c198 100644 (file)
@@ -75,7 +75,7 @@ static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev)
 
        rt2x00lib_reset_link_tuner(rt2x00dev);
 
-       queue_delayed_work(rt2x00dev->hw->workqueue,
+       queue_delayed_work(rt2x00dev->workqueue,
                           &rt2x00dev->link.work, LINK_TUNE_INTERVAL);
 }
 
@@ -136,14 +136,6 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
        if (!__test_and_clear_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
                return;
 
-       /*
-        * Stop all scheduled work.
-        */
-       if (work_pending(&rt2x00dev->intf_work))
-               cancel_work_sync(&rt2x00dev->intf_work);
-       if (work_pending(&rt2x00dev->filter_work))
-               cancel_work_sync(&rt2x00dev->filter_work);
-
        /*
         * Stop the TX queues.
         */
@@ -398,8 +390,8 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
         * Increase tuner counter, and reschedule the next link tuner run.
         */
        rt2x00dev->link.count++;
-       queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work,
-                          LINK_TUNE_INTERVAL);
+       queue_delayed_work(rt2x00dev->workqueue,
+                          &rt2x00dev->link.work, LINK_TUNE_INTERVAL);
 }
 
 static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
@@ -433,6 +425,15 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
 
        spin_unlock(&intf->lock);
 
+       /*
+        * It is possible the radio was disabled while the work had been
+        * scheduled. If that happens we should return here immediately,
+        * note that in the spinlock protected area above the delayed_flags
+        * have been cleared correctly.
+        */
+       if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+               return;
+
        if (delayed_flags & DELAYED_UPDATE_BEACON) {
                skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control);
                if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw,
@@ -441,7 +442,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
        }
 
        if (delayed_flags & DELAYED_CONFIG_ERP)
-               rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf);
+               rt2x00lib_config_erp(rt2x00dev, intf, &conf);
 
        if (delayed_flags & DELAYED_LED_ASSOC)
                rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
@@ -487,7 +488,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
                                                   rt2x00lib_beacondone_iter,
                                                   rt2x00dev);
 
-       queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
+       queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
 
@@ -1130,6 +1131,10 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize configuration work.
         */
+       rt2x00dev->workqueue = create_singlethread_workqueue("rt2x00lib");
+       if (!rt2x00dev->workqueue)
+               goto exit;
+
        INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
        INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);
        INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner);
@@ -1189,6 +1194,13 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
        rt2x00rfkill_free(rt2x00dev);
        rt2x00leds_unregister(rt2x00dev);
 
+       /*
+        * Stop all queued work. Note that most tasks will already be halted
+        * during rt2x00lib_disable_radio() and rt2x00lib_uninitialize().
+        */
+       flush_workqueue(rt2x00dev->workqueue);
+       destroy_workqueue(rt2x00dev->workqueue);
+
        /*
         * Free ieee80211_hw memory.
         */
index 87e280a21971faf5dbb8e5f15186ec8d41c21ec2..9cb023edd2e9bf7eaad394c5a205c2af3a6e9076 100644 (file)
@@ -428,7 +428,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
        if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
                rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
        else
-               queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
+               queue_work(rt2x00dev->workqueue, &rt2x00dev->filter_work);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
 
@@ -509,7 +509,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
        memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));
        if (delayed) {
                intf->delayed_flags |= delayed;
-               queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
+               queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work);
        }
        spin_unlock(&intf->lock);
 }
index 14bc7b281659c621bdd380c190c6e8bb181cc326..c3afb5cbe807f9a5387df50255b598a4f2d0027e 100644 (file)
@@ -1201,6 +1201,15 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR8, reg);
 
+       rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
+       rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
 
        rt2x00pci_register_write(rt2x00dev, MAC_CSR6, 0x00000fff);
index fff8386e816ba289045ff8955575b7377a98b60b..46e9e081fbf1fcae1d491872ab5298bdce30520b 100644 (file)
@@ -134,11 +134,8 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
         * Wait until the BBP becomes ready.
         */
        reg = rt73usb_bbp_check(rt2x00dev);
-       if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
-               ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
-               mutex_unlock(&rt2x00dev->usb_cache_mutex);
-               return;
-       }
+       if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
+               goto exit_fail;
 
        /*
         * Write the data into the BBP.
@@ -151,6 +148,13 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
 
        rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
        mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+       return;
+
+exit_fail:
+       mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+       ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
 }
 
 static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -164,11 +168,8 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
         * Wait until the BBP becomes ready.
         */
        reg = rt73usb_bbp_check(rt2x00dev);
-       if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
-               ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
-               mutex_unlock(&rt2x00dev->usb_cache_mutex);
-               return;
-       }
+       if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
+               goto exit_fail;
 
        /*
         * Write the request into the BBP.
@@ -184,14 +185,19 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
         * Wait until the BBP becomes ready.
         */
        reg = rt73usb_bbp_check(rt2x00dev);
-       if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
-               ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
-               *value = 0xff;
-               return;
-       }
+       if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
+               goto exit_fail;
 
        *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
        mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+       return;
+
+exit_fail:
+       mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+       ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
+       *value = 0xff;
 }
 
 static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -1000,6 +1006,15 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
        rt73usb_register_write(rt2x00dev, TXRX_CSR8, reg);
 
+       rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
+       rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+
        rt73usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
 
        rt73usb_register_read(rt2x00dev, MAC_CSR6, &reg);
index 418606ac1c3be8263b8f62bd9f15b00763254705..694e95d35fd437afc0dcf269ad20ec98232ef648 100644 (file)
@@ -765,6 +765,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
 {
        struct zd_mac *mac = zd_hw_mac(hw);
        mac->type = IEEE80211_IF_TYPE_INVALID;
+       zd_set_beacon_interval(&mac->chip, 0);
        zd_write_mac_addr(&mac->chip, NULL);
 }
 
index 8941f5eb96c2774cb6a6e2004d237c66eaab7bc7..6cdad97646049bd89d49ce5128751b8c8d59e746 100644 (file)
@@ -64,6 +64,7 @@ static struct usb_device_id usb_ids[] = {
        { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x083a, 0xe506), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x13b1, 0x0024), .driver_info = DEVICE_ZD1211B },
index d26f69b0184f05bac7ec906d5d4f50c11b99b458..ef671d1a3bf08441719b5f0bda8338648b1d1ee6 100644 (file)
@@ -1324,7 +1324,7 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info)
                goto fail;
        }
 
-       txs = (struct xen_netif_tx_sring *)get_zeroed_page(GFP_KERNEL);
+       txs = (struct xen_netif_tx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
        if (!txs) {
                err = -ENOMEM;
                xenbus_dev_fatal(dev, err, "allocating tx ring page");
@@ -1340,7 +1340,7 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info)
        }
 
        info->tx_ring_ref = err;
-       rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_KERNEL);
+       rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
        if (!rxs) {
                err = -ENOMEM;
                xenbus_dev_fatal(dev, err, "allocating rx ring page");
index ec8f7002b09d3423a8f5c80d94ed48f001e9d4b4..39bb96b413ef1b696eae53d6239c2d3a29bbd20e 100644 (file)
@@ -178,8 +178,7 @@ static int pci_vpd_pci22_read(struct pci_dev *dev, int pos, int size,
        int ret;
        int begin, end, i;
 
-       if (pos < 0 || pos > PCI_VPD_PCI22_SIZE ||
-           size > PCI_VPD_PCI22_SIZE  - pos)
+       if (pos < 0 || pos > vpd->base.len || size > vpd->base.len  - pos)
                return -EINVAL;
        if (size == 0)
                return 0;
@@ -223,8 +222,8 @@ static int pci_vpd_pci22_write(struct pci_dev *dev, int pos, int size,
        u32 val;
        int ret;
 
-       if (pos < 0 || pos > PCI_VPD_PCI22_SIZE || pos & 3 ||
-           size > PCI_VPD_PCI22_SIZE - pos || size < 4)
+       if (pos < 0 || pos > vpd->base.len || pos & 3 ||
+           size > vpd->base.len - pos || size < 4)
                return -EINVAL;
 
        val = (u8) *buf++;
@@ -255,11 +254,6 @@ out:
        return 4;
 }
 
-static int pci_vpd_pci22_get_size(struct pci_dev *dev)
-{
-       return PCI_VPD_PCI22_SIZE;
-}
-
 static void pci_vpd_pci22_release(struct pci_dev *dev)
 {
        kfree(container_of(dev->vpd, struct pci_vpd_pci22, base));
@@ -268,7 +262,6 @@ static void pci_vpd_pci22_release(struct pci_dev *dev)
 static struct pci_vpd_ops pci_vpd_pci22_ops = {
        .read = pci_vpd_pci22_read,
        .write = pci_vpd_pci22_write,
-       .get_size = pci_vpd_pci22_get_size,
        .release = pci_vpd_pci22_release,
 };
 
@@ -284,6 +277,7 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
        if (!vpd)
                return -ENOMEM;
 
+       vpd->base.len = PCI_VPD_PCI22_SIZE;
        vpd->base.ops = &pci_vpd_pci22_ops;
        spin_lock_init(&vpd->lock);
        vpd->cap = cap;
index 648596d469f66bf3005c57b355fd3911d733ae8b..91156f85a9267371c1c9354646bdcc6975e206af 100644 (file)
@@ -700,9 +700,10 @@ cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
        acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
                                cleanup_p2p_bridge, NULL, NULL);
 
-       if (!(bridge = acpiphp_handle_to_bridge(handle)))
-               return AE_OK;
-       cleanup_bridge(bridge);
+       bridge = acpiphp_handle_to_bridge(handle);
+       if (bridge)
+               cleanup_bridge(bridge);
+
        return AE_OK;
 }
 
@@ -715,9 +716,19 @@ static void remove_bridge(acpi_handle handle)
        acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
                                (u32)1, cleanup_p2p_bridge, NULL, NULL);
 
+       /*
+        * On root bridges with hotplug slots directly underneath (ie,
+        * no p2p bridge inbetween), we call cleanup_bridge(). 
+        *
+        * The else clause cleans up root bridges that either had no
+        * hotplug slots at all, or had a p2p bridge underneath.
+        */
        bridge = acpiphp_handle_to_bridge(handle);
        if (bridge)
                cleanup_bridge(bridge);
+       else
+               acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+                                          handle_hotplug_event_bridge);
 }
 
 static struct pci_dev * get_apic_pci_info(acpi_handle handle)
index 6f3c7446c329f3dfedc9dd60ee50497184062a63..9c718583a237f4f6082e7dcc5e84e23e85ee651c 100644 (file)
@@ -736,9 +736,9 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
                attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
                if (attr) {
                        pdev->vpd->attr = attr;
-                       attr->size = pdev->vpd->ops->get_size(pdev);
+                       attr->size = pdev->vpd->len;
                        attr->attr.name = "vpd";
-                       attr->attr.mode = S_IRUGO | S_IWUSR;
+                       attr->attr.mode = S_IRUSR | S_IWUSR;
                        attr->read = pci_read_vpd;
                        attr->write = pci_write_vpd;
                        retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
index 0a497c1b4227c0b80df7be89f56dcc8c5aba55f6..00408c97e5fc8cc2e38f52b408c70fdab9d133a8 100644 (file)
@@ -21,11 +21,11 @@ extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
 struct pci_vpd_ops {
        int (*read)(struct pci_dev *dev, int pos, int size, char *buf);
        int (*write)(struct pci_dev *dev, int pos, int size, const char *buf);
-       int (*get_size)(struct pci_dev *dev);
        void (*release)(struct pci_dev *dev);
 };
 
 struct pci_vpd {
+       unsigned int len;
        struct pci_vpd_ops *ops;
        struct bin_attribute *attr; /* descriptor for sysfs VPD entry */
 };
index dabb563f51d9466e4379f9095c85d2ce04545925..338a3f94b4d43bdf3d44dd0548e018199a49774a 100644 (file)
@@ -1670,6 +1670,48 @@ static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching);
 
+/*
+ * For Broadcom 5706, 5708, 5709 rev. A nics, any read beyond the
+ * VPD end tag will hang the device.  This problem was initially
+ * observed when a vpd entry was created in sysfs
+ * ('/sys/bus/pci/devices/<id>/vpd').   A read to this sysfs entry
+ * will dump 32k of data.  Reading a full 32k will cause an access
+ * beyond the VPD end tag causing the device to hang.  Once the device
+ * is hung, the bnx2 driver will not be able to reset the device.
+ * We believe that it is legal to read beyond the end tag and
+ * therefore the solution is to limit the read/write length.
+ */
+static void __devinit quirk_brcm_570x_limit_vpd(struct pci_dev *dev)
+{
+       /*  Only disable the VPD capability for 5706, 5708, and 5709 rev. A */
+       if ((dev->device == PCI_DEVICE_ID_NX2_5706) ||
+           (dev->device == PCI_DEVICE_ID_NX2_5708) ||
+           ((dev->device == PCI_DEVICE_ID_NX2_5709) &&
+            (dev->revision & 0xf0) == 0x0)) {
+               if (dev->vpd)
+                       dev->vpd->len = 0x80;
+       }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM,
+                        PCI_DEVICE_ID_NX2_5706,
+                        quirk_brcm_570x_limit_vpd);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM,
+                        PCI_DEVICE_ID_NX2_5706S,
+                        quirk_brcm_570x_limit_vpd);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM,
+                        PCI_DEVICE_ID_NX2_5708,
+                        quirk_brcm_570x_limit_vpd);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM,
+                        PCI_DEVICE_ID_NX2_5708S,
+                        quirk_brcm_570x_limit_vpd);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM,
+                        PCI_DEVICE_ID_NX2_5709,
+                        quirk_brcm_570x_limit_vpd);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM,
+                        PCI_DEVICE_ID_NX2_5709S,
+                        quirk_brcm_570x_limit_vpd);
+
 #ifdef CONFIG_PCI_MSI
 /* Some chipsets do not support MSI. We cannot easily rely on setting
  * PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually
@@ -1685,6 +1727,7 @@ static void __init quirk_disable_all_msi(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_disable_all_msi);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_all_msi);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disable_all_msi);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi);
 
 /* Disable MSI on chipsets that are known to not support it */
index 1b0eb5aaf650738a57300890941136d33ec06c62..e45402adac3f89e233ae1a4ebbcf6e0619e4d2dd 100644 (file)
@@ -263,6 +263,13 @@ config OMAP_CF
          Say Y here to support the CompactFlash controller on OMAP.
          Note that this doesn't support "True IDE" mode.
 
+config BFIN_CFPCMCIA
+       tristate "Blackfin CompactFlash PCMCIA Driver"
+       depends on PCMCIA && BLACKFIN
+       help
+         Say Y here to support the CompactFlash PCMCIA driver for Blackfin.
+
+
 config AT91_CF
        tristate "AT91 CompactFlash Controller"
        depends on PCMCIA && ARCH_AT91RM9200
index 6f6478ba7174fa8291eee50bb8a671ff913672bc..85c6cc931f979760dd3c545762b1dbd6b4a198a1 100644 (file)
@@ -36,6 +36,7 @@ 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
+obj-$(CONFIG_BFIN_CFPCMCIA)                    += bfin_cf_pcmcia.o
 obj-$(CONFIG_AT91_CF)                          += at91_cf.o
 obj-$(CONFIG_ELECTRA_CF)                       += electra_cf.o
 
index 1e467bb54077fed1f5f92175ba240d251e6a256d..a53ef5902518d88e7434b456a4d5b54eb0f90663 100644 (file)
@@ -26,7 +26,6 @@
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
@@ -34,9 +33,9 @@
 #define AU1000_PCMCIA_IO_SPEED       (255)
 #define AU1000_PCMCIA_MEM_SPEED      (300)
 
-#define AU1X_SOCK0_IO        0xF00000000
-#define AU1X_SOCK0_PHYS_ATTR 0xF40000000
-#define AU1X_SOCK0_PHYS_MEM  0xF80000000
+#define AU1X_SOCK0_IO        0xF00000000ULL
+#define AU1X_SOCK0_PHYS_ATTR 0xF40000000ULL
+#define AU1X_SOCK0_PHYS_MEM  0xF80000000ULL
 /* pseudo 32 bit phys addresses, which get fixed up to the
  * real 36 bit address in fixup_bigphys_addr() */
 #define AU1X_SOCK0_PSEUDO_PHYS_ATTR 0xF4000000
 /* pcmcia socket 1 needs external glue logic so the memory map
  * differs from board to board.
  */
-#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_PB1200)
-#define AU1X_SOCK1_IO        0xF08000000
-#define AU1X_SOCK1_PHYS_ATTR 0xF48000000
-#define AU1X_SOCK1_PHYS_MEM  0xF88000000
+#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || \
+    defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1550) || \
+    defined(CONFIG_MIPS_PB1200)
+#define AU1X_SOCK1_IO        0xF08000000ULL
+#define AU1X_SOCK1_PHYS_ATTR 0xF48000000ULL
+#define AU1X_SOCK1_PHYS_MEM  0xF88000000ULL
 #define AU1X_SOCK1_PSEUDO_PHYS_ATTR 0xF4800000
 #define AU1X_SOCK1_PSEUDO_PHYS_MEM  0xF8800000
-#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550) || defined(CONFIG_MIPS_DB1200)
-#define AU1X_SOCK1_IO        0xF04000000
-#define AU1X_SOCK1_PHYS_ATTR 0xF44000000
-#define AU1X_SOCK1_PHYS_MEM  0xF84000000
+#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || \
+      defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_DB1550) || \
+      defined(CONFIG_MIPS_DB1200)
+#define AU1X_SOCK1_IO        0xF04000000ULL
+#define AU1X_SOCK1_PHYS_ATTR 0xF44000000ULL
+#define AU1X_SOCK1_PHYS_MEM  0xF84000000ULL
 #define AU1X_SOCK1_PSEUDO_PHYS_ATTR 0xF4400000
 #define AU1X_SOCK1_PSEUDO_PHYS_MEM  0xF8400000
 #endif
index 157e41423a0a5390e42bb5106eccc5be489fb16f..aa1cd4d3aa292c4e840a4b09471b6068a81f9385 100644 (file)
@@ -35,7 +35,6 @@
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/bus_ops.h>
 #include "cs_internal.h"
index c78ed53475107c7371b503aa68c6d6ff96c6c4e6..8a9b18cee847e980881c1f0536925fca0bbcc52f 100644 (file)
@@ -39,7 +39,6 @@
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/bus_ops.h>
 #include "cs_internal.h"
diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c
new file mode 100644 (file)
index 0000000..bb73388
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * file: drivers/pcmcia/bfin_cf.c
+ *
+ * based on: drivers/pcmcia/omap_cf.c
+ * omap_cf.c -- OMAP 16xx CompactFlash controller driver
+ *
+ * Copyright (c) 2005 David Brownell
+ * Copyright (c) 2006-2008 Michael Hennerich Analog Devices Inc.
+ *
+ * bugs:         enter bugs at http://blackfin.uclinux.org/
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <pcmcia/ss.h>
+#include <pcmcia/cisreg.h>
+#include <asm/gpio.h>
+
+#define        SZ_1K   0x00000400
+#define        SZ_8K   0x00002000
+#define        SZ_2K   (2 * SZ_1K)
+
+#define        POLL_INTERVAL   (2 * HZ)
+
+#define        CF_ATASEL_ENA   0x20311802      /* Inverts RESET */
+#define        CF_ATASEL_DIS   0x20311800
+
+#define bfin_cf_present(pfx) (gpio_get_value(pfx))
+
+/*--------------------------------------------------------------------------*/
+
+static const char driver_name[] = "bfin_cf_pcmcia";
+
+struct bfin_cf_socket {
+       struct pcmcia_socket socket;
+
+       struct timer_list timer;
+       unsigned present:1;
+       unsigned active:1;
+
+       struct platform_device *pdev;
+       unsigned long phys_cf_io;
+       unsigned long phys_cf_attr;
+       u_int irq;
+       u_short cd_pfx;
+};
+
+/*--------------------------------------------------------------------------*/
+static int bfin_cf_reset(void)
+{
+       outw(0, CF_ATASEL_ENA);
+       mdelay(200);
+       outw(0, CF_ATASEL_DIS);
+
+       return 0;
+}
+
+static int bfin_cf_ss_init(struct pcmcia_socket *s)
+{
+       return 0;
+}
+
+/* the timer is primarily to kick this socket's pccardd */
+static void bfin_cf_timer(unsigned long _cf)
+{
+       struct bfin_cf_socket *cf = (void *)_cf;
+       unsigned short present = bfin_cf_present(cf->cd_pfx);
+
+       if (present != cf->present) {
+               cf->present = present;
+               dev_dbg(&cf->pdev->dev, ": card %s\n",
+                        present ? "present" : "gone");
+               pcmcia_parse_events(&cf->socket, SS_DETECT);
+       }
+
+       if (cf->active)
+               mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
+}
+
+static int bfin_cf_get_status(struct pcmcia_socket *s, u_int *sp)
+{
+       struct bfin_cf_socket *cf;
+
+       if (!sp)
+               return -EINVAL;
+
+       cf = container_of(s, struct bfin_cf_socket, socket);
+
+       if (bfin_cf_present(cf->cd_pfx)) {
+               *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD;
+               s->irq.AssignedIRQ = 0;
+               s->pci_irq = cf->irq;
+
+       } else
+               *sp = 0;
+       return 0;
+}
+
+static int
+bfin_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
+{
+
+       struct bfin_cf_socket *cf;
+       cf = container_of(sock, struct bfin_cf_socket, socket);
+
+       switch (s->Vcc) {
+       case 0:
+       case 33:
+               break;
+       case 50:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (s->flags & SS_RESET) {
+               disable_irq(cf->irq);
+               bfin_cf_reset();
+               enable_irq(cf->irq);
+       }
+
+       dev_dbg(&cf->pdev->dev, ": Vcc %d, io_irq %d, flags %04x csc %04x\n",
+                s->Vcc, s->io_irq, s->flags, s->csc_mask);
+
+       return 0;
+}
+
+static int bfin_cf_ss_suspend(struct pcmcia_socket *s)
+{
+       return bfin_cf_set_socket(s, &dead_socket);
+}
+
+/* regions are 2K each:  mem, attrib, io (and reserved-for-ide) */
+
+static int bfin_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
+{
+       struct bfin_cf_socket *cf;
+
+       cf = container_of(s, struct bfin_cf_socket, socket);
+       io->flags &= MAP_ACTIVE | MAP_ATTRIB | MAP_16BIT;
+       io->start = cf->phys_cf_io;
+       io->stop = io->start + SZ_2K - 1;
+       return 0;
+}
+
+static int
+bfin_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
+{
+       struct bfin_cf_socket *cf;
+
+       if (map->card_start)
+               return -EINVAL;
+       cf = container_of(s, struct bfin_cf_socket, socket);
+       map->static_start = cf->phys_cf_io;
+       map->flags &= MAP_ACTIVE | MAP_ATTRIB | MAP_16BIT;
+       if (map->flags & MAP_ATTRIB)
+               map->static_start = cf->phys_cf_attr;
+
+       return 0;
+}
+
+static struct pccard_operations bfin_cf_ops = {
+       .init = bfin_cf_ss_init,
+       .suspend = bfin_cf_ss_suspend,
+       .get_status = bfin_cf_get_status,
+       .set_socket = bfin_cf_set_socket,
+       .set_io_map = bfin_cf_set_io_map,
+       .set_mem_map = bfin_cf_set_mem_map,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __devinit bfin_cf_probe(struct platform_device *pdev)
+{
+       struct bfin_cf_socket *cf;
+       struct resource *io_mem, *attr_mem;
+       int irq;
+       unsigned short cd_pfx;
+       int status = 0;
+
+       dev_info(&pdev->dev, "Blackfin CompactFlash/PCMCIA Socket Driver\n");
+
+       irq = platform_get_irq(pdev, 0);
+       if (!irq)
+               return -EINVAL;
+
+       cd_pfx = platform_get_irq(pdev, 1);     /*Card Detect GPIO PIN */
+
+       if (gpio_request(cd_pfx, "pcmcia: CD")) {
+               dev_err(&pdev->dev,
+                      "Failed ro request Card Detect GPIO_%d\n",
+                      cd_pfx);
+               return -EBUSY;
+       }
+       gpio_direction_input(cd_pfx);
+
+       cf = kzalloc(sizeof *cf, GFP_KERNEL);
+       if (!cf) {
+               gpio_free(cd_pfx);
+               return -ENOMEM;
+       }
+
+       cf->cd_pfx = cd_pfx;
+
+       setup_timer(&cf->timer, bfin_cf_timer, (unsigned long)cf);
+
+       cf->pdev = pdev;
+       platform_set_drvdata(pdev, cf);
+
+       cf->irq = irq;
+       cf->socket.pci_irq = irq;
+
+       set_irq_type(irq, IRQF_TRIGGER_LOW);
+
+       io_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       attr_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+       if (!io_mem || !attr_mem)
+               goto fail0;
+
+       cf->phys_cf_io = io_mem->start;
+       cf->phys_cf_attr = attr_mem->start;
+
+       /* pcmcia layer only remaps "real" memory */
+       cf->socket.io_offset = (unsigned long)
+           ioremap(cf->phys_cf_io, SZ_2K);
+
+       if (!cf->socket.io_offset)
+               goto fail0;
+
+       dev_err(&pdev->dev, ": on irq %d\n", irq);
+
+       dev_dbg(&pdev->dev, ": %s\n",
+                bfin_cf_present(cf->cd_pfx) ? "present" : "(not present)");
+
+       cf->socket.owner = THIS_MODULE;
+       cf->socket.dev.parent = &pdev->dev;
+       cf->socket.ops = &bfin_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_io, SZ_8K);
+
+fail0:
+       gpio_free(cf->cd_pfx);
+       kfree(cf);
+       platform_set_drvdata(pdev, NULL);
+
+       return status;
+}
+
+static int __devexit bfin_cf_remove(struct platform_device *pdev)
+{
+       struct bfin_cf_socket *cf = platform_get_drvdata(pdev);
+
+       gpio_free(cf->cd_pfx);
+       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_io, SZ_8K);
+       platform_set_drvdata(pdev, NULL);
+       kfree(cf);
+       return 0;
+}
+
+static int bfin_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+       return pcmcia_socket_dev_suspend(&pdev->dev, mesg);
+}
+
+static int bfin_cf_resume(struct platform_device *pdev)
+{
+       return pcmcia_socket_dev_resume(&pdev->dev);
+}
+
+static struct platform_driver bfin_cf_driver = {
+       .driver = {
+                  .name = (char *)driver_name,
+                  .owner = THIS_MODULE,
+                  },
+       .probe = bfin_cf_probe,
+       .remove = __devexit_p(bfin_cf_remove),
+       .suspend = bfin_cf_suspend,
+       .resume = bfin_cf_resume,
+};
+
+static int __init bfin_cf_init(void)
+{
+       return platform_driver_register(&bfin_cf_driver);
+}
+
+static void __exit bfin_cf_exit(void)
+{
+       platform_driver_unregister(&bfin_cf_driver);
+}
+
+module_init(bfin_cf_init);
+module_exit(bfin_cf_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>")
+MODULE_DESCRIPTION("BFIN CF/PCMCIA Driver");
+MODULE_LICENSE("GPL");
index fb2f38dc92c560de378ddab5b688657e82d8661a..911ca0e8dfc29b94498fec85b10c73cb33be7aef 100644 (file)
 #include <asm/irq.h>
 #include <asm/io.h>
 
-#define IN_CARD_SERVICES
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
index 36379535f9daf17f8cb86a779cab491203afa9c1..9fcff0c336193e3fa4d5ccfc465e5766514cd4cc 100644 (file)
@@ -30,7 +30,6 @@
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
@@ -1439,10 +1438,11 @@ EXPORT_SYMBOL(pccard_read_tuple);
     
 ======================================================================*/
 
-int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_t *info)
+int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned int *info)
 {
     tuple_t *tuple;
     cisparse_t *p;
+    unsigned int count = 0;
     int ret, reserved, dev_ok = 0, ident_ok = 0;
 
     if (!s)
@@ -1457,7 +1457,7 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_
        return CS_OUT_OF_RESOURCE;
     }
 
-    info->Chains = reserved = 0;
+    count = reserved = 0;
     tuple->DesiredTuple = RETURN_FIRST_TUPLE;
     tuple->Attributes = TUPLE_RETURN_COMMON;
     ret = pccard_get_first_tuple(s, function, tuple);
@@ -1482,7 +1482,7 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_
     if (!dev_ok && !ident_ok)
        goto done;
 
-    for (info->Chains = 1; info->Chains < MAX_TUPLES; info->Chains++) {
+    for (count = 1; count < MAX_TUPLES; count++) {
        ret = pccard_get_next_tuple(s, function, tuple);
        if (ret != CS_SUCCESS) break;
        if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) ||
@@ -1490,11 +1490,13 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_
            ((tuple->TupleCode > 0x90) && (tuple->TupleCode < 0xff)))
            reserved++;
     }
-    if ((info->Chains == MAX_TUPLES) || (reserved > 5) ||
-       ((!dev_ok || !ident_ok) && (info->Chains > 10)))
-       info->Chains = 0;
+    if ((count) || (reserved > 5) ||
+       ((!dev_ok || !ident_ok) && (count > 10)))
+       count = 0;
 
 done:
+    if (info)
+           *info = count;
     kfree(tuple);
     kfree(p);
     return CS_SUCCESS;
index 29276bd28295007212a73e89c4bc44cb6f0a0a2a..d1207393fc3e4029a8b5f6402f82c185d517ff39 100644 (file)
 #include <asm/system.h>
 #include <asm/irq.h>
 
-#define IN_CARD_SERVICES
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -238,7 +236,6 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
 
        init_completion(&socket->socket_released);
        init_completion(&socket->thread_done);
-       init_waitqueue_head(&socket->thread_wait);
        mutex_init(&socket->skt_mutex);
        spin_lock_init(&socket->thread_lock);
 
@@ -278,10 +275,9 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
 
        cs_dbg(socket, 0, "pcmcia_unregister_socket(0x%p)\n", socket->ops);
 
-       if (socket->thread) {
-               wake_up(&socket->thread_wait);
+       if (socket->thread)
                kthread_stop(socket->thread);
-       }
+
        release_cis_mem(socket);
 
        /* remove from our own list */
@@ -635,7 +631,6 @@ static void socket_detect_change(struct pcmcia_socket *skt)
 static int pccardd(void *__skt)
 {
        struct pcmcia_socket *skt = __skt;
-       DECLARE_WAITQUEUE(wait, current);
        int ret;
 
        skt->thread = current;
@@ -656,7 +651,6 @@ static int pccardd(void *__skt)
        if (ret)
                dev_warn(&skt->dev, "err %d adding socket attributes\n", ret);
 
-       add_wait_queue(&skt->thread_wait, &wait);
        complete(&skt->thread_done);
 
        set_freezable();
@@ -694,8 +688,6 @@ static int pccardd(void *__skt)
        /* make sure we are running before we exit */
        set_current_state(TASK_RUNNING);
 
-       remove_wait_queue(&skt->thread_wait, &wait);
-
        /* remove from the device core */
        pccard_sysfs_remove_socket(&skt->dev);
        device_unregister(&skt->dev);
@@ -716,7 +708,7 @@ void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
                s->thread_events |= events;
                spin_unlock_irqrestore(&s->thread_lock, flags);
 
-               wake_up(&s->thread_wait);
+               wake_up_process(s->thread);
        }
 } /* pcmcia_parse_events */
 EXPORT_SYMBOL(pcmcia_parse_events);
index e7d5d141f24dc9b661f9ed4412752c53a04b7764..63dc1a28bda2772d6f2f213656ce07223cd8dd6c 100644 (file)
 #define CLIENT_WIN_REQ(i)      (0x1<<(i))
 #define CLIENT_CARDBUS         0x8000
 
-#define REGION_MAGIC   0xE3C9
-typedef struct region_t {
-    u_short            region_magic;
-    u_short            state;
-    dev_info_t         dev_info;
-    struct pcmcia_device       *mtd;
-    u_int              MediaID;
-    region_info_t      info;
-} region_t;
-
-#define REGION_STALE   0x01
-
 /* Each card function gets one of these guys */
 typedef struct config_t {
        struct kref     ref;
@@ -130,7 +118,6 @@ extern struct list_head pcmcia_socket_list;
 int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req);
 int pccard_get_configuration_info(struct pcmcia_socket *s, struct pcmcia_device *p_dev, config_info_t *config);
 int pccard_reset_card(struct pcmcia_socket *skt);
-int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_status_t *status);
 
 
 struct pcmcia_callback{
index e40775443d04c73233735c61b0802eaa4936a751..4174d9656e357f8ec5f16520ad03c86544a5e969 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/kref.h>
 #include <linux/dma-mapping.h>
 
-#define IN_CARD_SERVICES
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
@@ -741,9 +740,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
 
 static int pcmcia_card_add(struct pcmcia_socket *s)
 {
-       cisinfo_t cisinfo;
        cistpl_longlink_mfc_t mfc;
-       unsigned int no_funcs, i;
+       unsigned int no_funcs, i, no_chains;
        int ret = 0;
 
        if (!(s->resource_setup_done)) {
@@ -757,8 +755,8 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
                return -EAGAIN; /* try again, but later... */
        }
 
-       ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo);
-       if (ret || !cisinfo.Chains) {
+       ret = pccard_validate_cis(s, BIND_FN_ALL, &no_chains);
+       if (ret || !no_chains) {
                ds_dbg(0, "invalid CIS or invalid resources\n");
                return -ENODEV;
        }
@@ -852,7 +850,7 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
 {
        struct pcmcia_socket *s = dev->socket;
        const struct firmware *fw;
-       char path[20];
+       char path[FIRMWARE_NAME_MAX];
        int ret = -ENOMEM;
        int no_funcs;
        int old_funcs;
@@ -864,7 +862,7 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
 
        ds_dbg(1, "trying to load CIS file %s\n", filename);
 
-       if (strlen(filename) > 14) {
+       if (strlen(filename) > (FIRMWARE_NAME_MAX - 1)) {
                printk(KERN_WARNING "pcmcia: CIS filename is too long [%s]\n",
                        filename);
                return -EINVAL;
index f2e810f53c81ca67b172e7b4789b60d9b2d3b473..fb2bc1fb015d417c19d879378a4538bee57ee372 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: hd64465_ss.c,v 1.7 2003/07/06 14:42:50 lethal Exp $
- *
  * Device driver for the PCMCIA controller module of the
  * Hitachi HD64465 handheld companion chip.
  *
@@ -48,7 +46,6 @@
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/ss.h>
-#include <pcmcia/bulkmem.h>
 #include "cs_internal.h"
 
 #define MODNAME "hd64465_ss"
index e13618656ff7ee7807618c9a52e0398334e04505..46561face128842e4a3bd8c7c3138e36a59d7fc9 100644 (file)
@@ -5,8 +5,6 @@
  *
  * Author: Arjan Van De Ven <arjanv@redhat.com>
  * Loosly based on i82365.c from the pcmcia-cs package
- *
- * $Id: i82092aa.c,v 1.2 2001/10/23 14:43:34 arjanv Exp $
  */
 
 #include <linux/kernel.h>
index b0d453303c5deb852e917af9e2757ba1b10edfbb..8836d393ad020ce58894745b490b2d6b1199e68c 100644 (file)
@@ -3,8 +3,6 @@
 
 #include <linux/interrupt.h>
 
-/* $Id: i82092aa.h,v 1.1.1.1 2001/09/19 14:53:15 dwmw2 Exp $ */
-
 /* Debuging defines */
 #ifdef NOTRACE
 #define enter(x)   printk("Enter: %s, %s line %i\n",x,__FILE__,__LINE__)
index 32a2ab119798ccfc2f18c1df52377b7da2009ad3..68f6b2702bc42c66f27758c3fbbd25dcb80f83bc 100644 (file)
@@ -1263,7 +1263,7 @@ static int __init init_i82365(void)
 
     ret = driver_register(&i82365_driver);
     if (ret)
-       return ret;
+       goto err_out;
 
     i82365_device = platform_device_alloc("i82365", 0);
     if (i82365_device) {
@@ -1273,10 +1273,8 @@ static int __init init_i82365(void)
     } else
            ret = -ENOMEM;
 
-    if (ret) {
-       driver_unregister(&i82365_driver);
-       return ret;
-    }
+    if (ret)
+       goto err_driver_unregister;
 
     printk(KERN_INFO "Intel ISA PCIC probe: ");
     sockets = 0;
@@ -1285,16 +1283,17 @@ static int __init init_i82365(void)
 
     if (sockets == 0) {
        printk("not found.\n");
-       platform_device_unregister(i82365_device);
-       release_region(i365_base, 2);
-       driver_unregister(&i82365_driver);
-       return -ENODEV;
+       ret = -ENODEV;
+       goto err_dev_unregister;
     }
 
     /* Set up interrupt handler(s) */
     if (grab_irq != 0)
-       request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
-    
+       ret = request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
+
+    if (ret)
+       goto err_socket_release;
+
     /* register sockets with the pcmcia core */
     for (i = 0; i < sockets; i++) {
            socket[i].socket.dev.parent = &i82365_device->dev;
@@ -1324,7 +1323,23 @@ static int __init init_i82365(void)
     }
     
     return 0;
-    
+err_socket_release:
+    for (i = 0; i < sockets; i++) {
+       /* Turn off all interrupt sources! */
+       i365_set(i, I365_CSCINT, 0);
+       release_region(socket[i].ioaddr, 2);
+    }
+err_dev_unregister:
+    platform_device_unregister(i82365_device);
+    release_region(i365_base, 2);
+#ifdef CONFIG_PNP
+    if (i82365_pnpdev)
+       pnp_disable_dev(i82365_pnpdev);
+#endif
+err_driver_unregister:
+    driver_unregister(&i82365_driver);
+err_out:
+    return ret;
 } /* init_i82365 */
 
 static void __exit exit_i82365(void)
index ac70d2cb7dd409764deb755e13e821d366702d5f..13a5fbd50a078fe3d45c2c1028066e679fe7c581 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series.
  *
- * (C) 1999-2000 Magnus Damm <damm@bitsmart.com>
+ * (C) 1999-2000 Magnus Damm <damm@opensource.se>
  * (C) 2001-2002 Montavista Software, Inc.
  *     <mlocke@mvista.com>
  *
@@ -60,7 +60,6 @@
 #include <asm/of_device.h>
 #include <asm/of_platform.h>
 
-#include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
index 5f186abca1082843a7b12e30865b3bb7c8b83f34..afd00e7bbbefe92f53cbfd82cc52ea8f323357e8 100644 (file)
 #include <linux/pci.h>
 #include <linux/workqueue.h>
 
-#define IN_CARD_SERVICES
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/ss.h>
 
@@ -138,6 +138,154 @@ static int proc_read_drivers(char *buf, char **start, off_t pos,
 }
 #endif
 
+
+#ifdef CONFIG_PCMCIA_PROBE
+
+static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
+{
+       int irq;
+       u32 mask;
+
+       irq = adj->resource.irq.IRQ;
+       if ((irq < 0) || (irq > 15))
+               return CS_BAD_IRQ;
+
+       if (adj->Action != REMOVE_MANAGED_RESOURCE)
+               return 0;
+
+       mask = 1 << irq;
+
+       if (!(s->irq_mask & mask))
+               return 0;
+
+       s->irq_mask &= ~mask;
+
+       return 0;
+}
+
+#else
+
+static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) {
+       return CS_SUCCESS;
+}
+
+#endif
+
+static int pcmcia_adjust_resource_info(adjust_t *adj)
+{
+       struct pcmcia_socket *s;
+       int ret = CS_UNSUPPORTED_FUNCTION;
+       unsigned long flags;
+
+       down_read(&pcmcia_socket_list_rwsem);
+       list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
+
+               if (adj->Resource == RES_IRQ)
+                       ret = adjust_irq(s, adj);
+
+               else if (s->resource_ops->add_io) {
+                       unsigned long begin, end;
+
+                       /* you can't use the old interface if the new
+                        * one was used before */
+                       spin_lock_irqsave(&s->lock, flags);
+                       if ((s->resource_setup_new) &&
+                           !(s->resource_setup_old)) {
+                               spin_unlock_irqrestore(&s->lock, flags);
+                               continue;
+                       } else if (!(s->resource_setup_old))
+                               s->resource_setup_old = 1;
+                       spin_unlock_irqrestore(&s->lock, flags);
+
+                       switch (adj->Resource) {
+                       case RES_MEMORY_RANGE:
+                               begin = adj->resource.memory.Base;
+                               end = adj->resource.memory.Base + adj->resource.memory.Size - 1;
+                               if (s->resource_ops->add_mem)
+                                       ret =s->resource_ops->add_mem(s, adj->Action, begin, end);
+                       case RES_IO_RANGE:
+                               begin = adj->resource.io.BasePort;
+                               end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1;
+                               if (s->resource_ops->add_io)
+                                       ret = s->resource_ops->add_io(s, adj->Action, begin, end);
+                       }
+                       if (!ret) {
+                               /* as there's no way we know this is the
+                                * last call to adjust_resource_info, we
+                                * always need to assume this is the latest
+                                * one... */
+                               spin_lock_irqsave(&s->lock, flags);
+                               s->resource_setup_done = 1;
+                               spin_unlock_irqrestore(&s->lock, flags);
+                       }
+               }
+       }
+       up_read(&pcmcia_socket_list_rwsem);
+
+       return (ret);
+}
+
+/** pccard_get_status
+ *
+ * Get the current socket state bits.  We don't support the latched
+ * SocketState yet: I haven't seen any point for it.
+ */
+
+static int pccard_get_status(struct pcmcia_socket *s,
+                            struct pcmcia_device *p_dev,
+                            cs_status_t *status)
+{
+       config_t *c;
+       int val;
+
+       s->ops->get_status(s, &val);
+       status->CardState = status->SocketState = 0;
+       status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
+       status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
+       status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0;
+       status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0;
+       if (s->state & SOCKET_SUSPEND)
+               status->CardState |= CS_EVENT_PM_SUSPEND;
+       if (!(s->state & SOCKET_PRESENT))
+               return CS_NO_CARD;
+
+       c = (p_dev) ? p_dev->function_config : NULL;
+
+       if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
+           (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
+               u_char reg;
+               if (c->CardValues & PRESENT_PIN_REPLACE) {
+                       pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
+                       status->CardState |=
+                               (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
+                       status->CardState |=
+                               (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0;
+                       status->CardState |=
+                               (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0;
+                       status->CardState |=
+                               (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0;
+               } else {
+                       /* No PRR?  Then assume we're always ready */
+                       status->CardState |= CS_EVENT_READY_CHANGE;
+               }
+               if (c->CardValues & PRESENT_EXT_STATUS) {
+                       pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
+                       status->CardState |=
+                               (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
+               }
+               return CS_SUCCESS;
+       }
+       status->CardState |=
+               (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0;
+       status->CardState |=
+               (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0;
+       status->CardState |=
+               (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0;
+       status->CardState |=
+               (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0;
+       return CS_SUCCESS;
+} /* pccard_get_status */
+
 /*======================================================================
 
     These manage a ring buffer of events pending for one user process
@@ -546,8 +694,6 @@ static u_int ds_poll(struct file *file, poll_table *wait)
 
 /*====================================================================*/
 
-extern int pcmcia_adjust_resource_info(adjust_t *adj);
-
 static int ds_ioctl(struct inode * inode, struct file * file,
                    u_int cmd, u_long arg)
 {
@@ -649,7 +795,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
        mutex_lock(&s->skt_mutex);
        pcmcia_validate_mem(s);
        mutex_unlock(&s->skt_mutex);
-       ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo);
+       ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo.Chains);
        break;
     case DS_SUSPEND_CARD:
        ret = pcmcia_suspend_card(s);
index 1d128fbd1a92d9f4dcdaed4a3065c3365b5fce68..4884a18cf9e69918c0e3371cebb5a89b944921bb 100644 (file)
 #include <linux/pci.h>
 #include <linux/device.h>
 
-#define IN_CARD_SERVICES
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -311,74 +309,6 @@ int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle,
 EXPORT_SYMBOL(pcmcia_get_window);
 
 
-/** pccard_get_status
- *
- * Get the current socket state bits.  We don't support the latched
- * SocketState yet: I haven't seen any point for it.
- */
-
-int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev,
-                     cs_status_t *status)
-{
-       config_t *c;
-       int val;
-
-       s->ops->get_status(s, &val);
-       status->CardState = status->SocketState = 0;
-       status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
-       status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
-       status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0;
-       status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0;
-       if (s->state & SOCKET_SUSPEND)
-               status->CardState |= CS_EVENT_PM_SUSPEND;
-       if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
-
-       c = (p_dev) ? p_dev->function_config : NULL;
-
-       if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
-           (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
-               u_char reg;
-               if (c->CardValues & PRESENT_PIN_REPLACE) {
-                       pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
-                       status->CardState |=
-                               (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
-                       status->CardState |=
-                               (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0;
-                       status->CardState |=
-                               (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0;
-                       status->CardState |=
-                               (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0;
-               } else {
-                       /* No PRR?  Then assume we're always ready */
-                       status->CardState |= CS_EVENT_READY_CHANGE;
-               }
-               if (c->CardValues & PRESENT_EXT_STATUS) {
-                       pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
-                       status->CardState |=
-                               (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
-               }
-               return CS_SUCCESS;
-       }
-       status->CardState |=
-               (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0;
-       status->CardState |=
-               (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0;
-       status->CardState |=
-               (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0;
-       status->CardState |=
-               (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0;
-       return CS_SUCCESS;
-} /* pccard_get_status */
-
-int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status)
-{
-       return pccard_get_status(p_dev->socket, p_dev, status);
-}
-EXPORT_SYMBOL(pcmcia_get_status);
-
-
-
 /** pcmcia_get_mem_page
  *
  * Change the card address of an already open memory window.
@@ -812,6 +742,15 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
                type = IRQF_SHARED;
 
 #ifdef CONFIG_PCMCIA_PROBE
+
+#ifdef IRQ_NOAUTOEN
+       /* if the underlying IRQ infrastructure allows for it, only allocate
+        * the IRQ, but do not enable it
+        */
+       if (!(req->Attributes & IRQ_HANDLE_PRESENT))
+               type |= IRQ_NOAUTOEN;
+#endif /* IRQ_NOAUTOEN */
+
        if (s->irq.AssignedIRQ != 0) {
                /* If the interrupt is already assigned, it must be the same */
                irq = s->irq.AssignedIRQ;
@@ -966,7 +905,7 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) {
        pcmcia_release_configuration(p_dev);
        pcmcia_release_io(p_dev, &p_dev->io);
        pcmcia_release_irq(p_dev, &p_dev->irq);
-       if (&p_dev->win)
+       if (p_dev->win)
                pcmcia_release_window(p_dev->win);
 }
 EXPORT_SYMBOL(pcmcia_disable_device);
index 9414163c78e7ec2582a7c58848a02387e893c0a2..ccfdf1969a7f643bf41686c40399afdfffcaca99 100644 (file)
@@ -33,7 +33,6 @@
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cistpl.h>
 
 #include "cs_internal.h"
index ce2226273aaa72fa4f55b8d5d718c9014a231602..c0e2afc79e3e4555877562498d30035aa65815ae 100644 (file)
 #include "cs_internal.h"
 
 
-#ifdef CONFIG_PCMCIA_IOCTL
-
-#ifdef CONFIG_PCMCIA_PROBE
-
-static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
-{
-       int irq;
-       u32 mask;
-
-       irq = adj->resource.irq.IRQ;
-       if ((irq < 0) || (irq > 15))
-               return CS_BAD_IRQ;
-
-       if (adj->Action != REMOVE_MANAGED_RESOURCE)
-               return 0;
-
-       mask = 1 << irq;
-
-       if (!(s->irq_mask & mask))
-               return 0;
-
-       s->irq_mask &= ~mask;
-
-       return 0;
-}
-
-#else
-
-static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) {
-       return CS_SUCCESS;
-}
-
-#endif
-
-
-int pcmcia_adjust_resource_info(adjust_t *adj)
-{
-       struct pcmcia_socket *s;
-       int ret = CS_UNSUPPORTED_FUNCTION;
-       unsigned long flags;
-
-       down_read(&pcmcia_socket_list_rwsem);
-       list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
-
-               if (adj->Resource == RES_IRQ)
-                       ret = adjust_irq(s, adj);
-
-               else if (s->resource_ops->adjust_resource) {
-
-                       /* you can't use the old interface if the new
-                        * one was used before */
-                       spin_lock_irqsave(&s->lock, flags);
-                       if ((s->resource_setup_new) &&
-                           !(s->resource_setup_old)) {
-                               spin_unlock_irqrestore(&s->lock, flags);
-                               continue;
-                       } else if (!(s->resource_setup_old))
-                               s->resource_setup_old = 1;
-                       spin_unlock_irqrestore(&s->lock, flags);
-
-                       ret = s->resource_ops->adjust_resource(s, adj);
-                       if (!ret) {
-                               /* as there's no way we know this is the
-                                * last call to adjust_resource_info, we
-                                * always need to assume this is the latest
-                                * one... */
-                               spin_lock_irqsave(&s->lock, flags);
-                               s->resource_setup_done = 1;
-                               spin_unlock_irqrestore(&s->lock, flags);
-                       }
-               }
-       }
-       up_read(&pcmcia_socket_list_rwsem);
-
-       return (ret);
-}
-EXPORT_SYMBOL(pcmcia_adjust_resource_info);
-
-#endif
-
 int pcmcia_validate_mem(struct pcmcia_socket *s)
 {
        if (s->resource_ops->validate_mem)
@@ -164,7 +84,8 @@ struct pccard_resource_ops pccard_static_ops = {
        .adjust_io_region = NULL,
        .find_io = NULL,
        .find_mem = NULL,
-       .adjust_resource = NULL,
+       .add_io = NULL,
+       .add_mem = NULL,
        .init = static_init,
        .exit = NULL,
 };
@@ -264,7 +185,8 @@ struct pccard_resource_ops pccard_iodyn_ops = {
        .adjust_io_region = iodyn_adjust_io_region,
        .find_io = iodyn_find_io_region,
        .find_mem = NULL,
-       .adjust_resource = NULL,
+       .add_io = NULL,
+       .add_mem = NULL,
        .init = static_init,
        .exit = NULL,
 };
index 0fcf763b9175a077768d6e85b9a933e24ef52967..d0c1d63d1891bbe7a87587d79e120cfce4aef813 100644 (file)
@@ -31,7 +31,6 @@
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
@@ -261,21 +260,22 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
 ======================================================================*/
 
 /* Validation function for cards with a valid CIS */
-static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *info)
+static int readable(struct pcmcia_socket *s, struct resource *res,
+                   unsigned int *count)
 {
        int ret = -1;
 
        s->cis_mem.res = res;
        s->cis_virt = ioremap(res->start, s->map_size);
        if (s->cis_virt) {
-               ret = pccard_validate_cis(s, BIND_FN_ALL, info);
+               ret = pccard_validate_cis(s, BIND_FN_ALL, count);
                /* invalidate mapping and CIS cache */
                iounmap(s->cis_virt);
                s->cis_virt = NULL;
                destroy_cis_cache(s);
        }
        s->cis_mem.res = NULL;
-       if ((ret != 0) || (info->Chains == 0))
+       if ((ret != 0) || (count == 0))
                return 0;
        return 1;
 }
@@ -316,7 +316,7 @@ static int
 cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
 {
        struct resource *res1, *res2;
-       cisinfo_t info1, info2;
+       unsigned int info1, info2;
        int ret = 0;
 
        res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
@@ -330,7 +330,7 @@ cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
        free_region(res2);
        free_region(res1);
 
-       return (ret == 2) && (info1.Chains == info2.Chains);
+       return (ret == 2) && (info1 == info2);
 }
 
 static int
@@ -766,21 +766,6 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long
 }
 
 
-static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj)
-{
-       unsigned long end;
-
-       switch (adj->Resource) {
-       case RES_MEMORY_RANGE:
-               end = adj->resource.memory.Base + adj->resource.memory.Size - 1;
-               return adjust_memory(s, adj->Action, adj->resource.memory.Base, end);
-       case RES_IO_RANGE:
-               end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1;
-               return adjust_io(s, adj->Action, adj->resource.io.BasePort, end);
-       }
-       return CS_UNSUPPORTED_FUNCTION;
-}
-
 #ifdef CONFIG_PCI
 static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
 {
@@ -889,7 +874,8 @@ struct pccard_resource_ops pccard_nonstatic_ops = {
        .adjust_io_region = nonstatic_adjust_io_region,
        .find_io = nonstatic_find_io_region,
        .find_mem = nonstatic_find_mem_region,
-       .adjust_resource = nonstatic_adjust_resource_info,
+       .add_io = adjust_io,
+       .add_mem = adjust_memory,
        .init = nonstatic_init,
        .exit = nonstatic_release_resource_db,
 };
@@ -1008,41 +994,34 @@ static ssize_t store_mem_db(struct device *dev,
 }
 static DEVICE_ATTR(available_resources_mem, 0600, show_mem_db, store_mem_db);
 
-static struct device_attribute *pccard_rsrc_attributes[] = {
-       &dev_attr_available_resources_io,
-       &dev_attr_available_resources_mem,
+static struct attribute *pccard_rsrc_attributes[] = {
+       &dev_attr_available_resources_io.attr,
+       &dev_attr_available_resources_mem.attr,
        NULL,
 };
 
+static const struct attribute_group rsrc_attributes = {
+       .attrs = pccard_rsrc_attributes,
+};
+
 static int __devinit pccard_sysfs_add_rsrc(struct device *dev,
                                           struct class_interface *class_intf)
 {
        struct pcmcia_socket *s = dev_get_drvdata(dev);
-       struct device_attribute **attr;
-       int ret = 0;
+
        if (s->resource_ops != &pccard_nonstatic_ops)
                return 0;
-
-       for (attr = pccard_rsrc_attributes; *attr; attr++) {
-               ret = device_create_file(dev, *attr);
-               if (ret)
-                       break;
-       }
-
-       return ret;
+       return sysfs_create_group(&dev->kobj, &rsrc_attributes);
 }
 
 static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
                                               struct class_interface *class_intf)
 {
        struct pcmcia_socket *s = dev_get_drvdata(dev);
-       struct device_attribute **attr;
 
        if (s->resource_ops != &pccard_nonstatic_ops)
                return;
-
-       for (attr = pccard_rsrc_attributes; *attr; attr++)
-               device_remove_file(dev, *attr);
+       sysfs_remove_group(&dev->kobj, &rsrc_attributes);
 }
 
 static struct class_interface pccard_rsrc_interface __refdata = {
index 1edc1da9d3537b208c3af78e8de487e752477f91..91ef6a0da3ab14d84893ee47129de75876d7cf4d 100644 (file)
@@ -14,7 +14,6 @@
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
index 562384d6f3213b71e0f9f83999b4579b3d3b16e5..006a29e91d83d58118ee8ff5a40234a45efcc85e 100644 (file)
 #include <asm/system.h>
 #include <asm/irq.h>
 
-#define IN_CARD_SERVICES
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -293,7 +291,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj,
                count = 0;
        else {
                struct pcmcia_socket *s;
-               cisinfo_t cisinfo;
+               unsigned int chains;
 
                if (off + count > size)
                        count = size - off;
@@ -302,9 +300,9 @@ static ssize_t pccard_show_cis(struct kobject *kobj,
 
                if (!(s->state & SOCKET_PRESENT))
                        return -ENODEV;
-               if (pccard_validate_cis(s, BIND_FN_ALL, &cisinfo))
+               if (pccard_validate_cis(s, BIND_FN_ALL, &chains))
                        return -EIO;
-               if (!cisinfo.Chains)
+               if (!chains)
                        return -ENODATA;
 
                count = pccard_extract_cis(s, buf, off, count);
index d29657bf1b40faecefd0598ad73cc60c42d292c1..129db7bd06c3661e291204f893bb4c6dedbcccd6 100644 (file)
 #define ENE_TEST_C9_TLTENABLE          0x02
 #define ENE_TEST_C9_PFENABLE_F0                0x04
 #define ENE_TEST_C9_PFENABLE_F1                0x08
-#define ENE_TEST_C9_PFENABLE           (ENE_TEST_C9_PFENABLE_F0 | ENE_TEST_C9_PFENABLE_F0)
+#define ENE_TEST_C9_PFENABLE           (ENE_TEST_C9_PFENABLE_F0 | ENE_TEST_C9_PFENABLE_F1)
 #define ENE_TEST_C9_WPDISALBLE_F0      0x40
 #define ENE_TEST_C9_WPDISALBLE_F1      0x80
 #define ENE_TEST_C9_WPDISALBLE         (ENE_TEST_C9_WPDISALBLE_F0 | ENE_TEST_C9_WPDISALBLE_F1)
@@ -692,7 +692,7 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
                goto out;
 
        /* check state */
-       yenta_get_status(&socket->socket, &state);
+       yenta_get_status(&slot2->socket, &state);
        if (state & SS_DETECT) {
                ret = 0;
                goto out;
index 3ce9f3defc1287f688f6484f2f265b7cdb620125..956d3e79f6aaab9c701be85526dbade07cd69a3b 100644 (file)
@@ -101,8 +101,8 @@ static int rio_device_probe(struct device *dev)
                if (error >= 0) {
                        rdev->driver = rdrv;
                        error = 0;
+               } else
                        rio_dev_put(rdev);
-               }
        }
        return error;
 }
index 7e3ad4f3b3432aa89c8a7d9a4d9902453f9adbbf..58b7336640ff7a1559263798f46e9d7912f09088 100644 (file)
@@ -126,12 +126,25 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
        int err;
        struct rtc_time before, now;
        int first_time = 1;
+       unsigned long t_now, t_alm;
+       enum { none, day, month, year } missing = none;
+       unsigned days;
 
-       /* The lower level RTC driver may not be capable of filling
-        * in all fields of the rtc_time struct (eg. rtc-cmos),
-        * and so might instead return -1 in some fields.
-        * We deal with that here by grabbing a current RTC timestamp
-        * and using values from that for any missing (-1) values.
+       /* The lower level RTC driver may return -1 in some fields,
+        * creating invalid alarm->time values, for reasons like:
+        *
+        *   - The hardware may not be capable of filling them in;
+        *     many alarms match only on time-of-day fields, not
+        *     day/month/year calendar data.
+        *
+        *   - Some hardware uses illegal values as "wildcard" match
+        *     values, which non-Linux firmware (like a BIOS) may try
+        *     to set up as e.g. "alarm 15 minutes after each hour".
+        *     Linux uses only oneshot alarms.
+        *
+        * When we see that here, we deal with it by using values from
+        * a current RTC timestamp for any missing (-1) values.  The
+        * RTC driver prevents "periodic alarm" modes.
         *
         * But this can be racey, because some fields of the RTC timestamp
         * may have wrapped in the interval since we read the RTC alarm,
@@ -174,6 +187,10 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
                if (!alarm->enabled)
                        return 0;
 
+               /* full-function RTCs won't have such missing fields */
+               if (rtc_valid_tm(&alarm->time) == 0)
+                       return 0;
+
                /* get the "after" timestamp, to detect wrapped fields */
                err = rtc_read_time(rtc, &now);
                if (err < 0)
@@ -183,22 +200,85 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
        } while (   before.tm_min   != now.tm_min
                 || before.tm_hour  != now.tm_hour
                 || before.tm_mon   != now.tm_mon
-                || before.tm_year  != now.tm_year
-                || before.tm_isdst != now.tm_isdst);
+                || before.tm_year  != now.tm_year);
 
-       /* Fill in any missing alarm fields using the timestamp */
+       /* Fill in the missing alarm fields using the timestamp; we
+        * know there's at least one since alarm->time is invalid.
+        */
        if (alarm->time.tm_sec == -1)
                alarm->time.tm_sec = now.tm_sec;
        if (alarm->time.tm_min == -1)
                alarm->time.tm_min = now.tm_min;
        if (alarm->time.tm_hour == -1)
                alarm->time.tm_hour = now.tm_hour;
-       if (alarm->time.tm_mday == -1)
+
+       /* For simplicity, only support date rollover for now */
+       if (alarm->time.tm_mday == -1) {
                alarm->time.tm_mday = now.tm_mday;
-       if (alarm->time.tm_mon == -1)
+               missing = day;
+       }
+       if (alarm->time.tm_mon == -1) {
                alarm->time.tm_mon = now.tm_mon;
-       if (alarm->time.tm_year == -1)
+               if (missing == none)
+                       missing = month;
+       }
+       if (alarm->time.tm_year == -1) {
                alarm->time.tm_year = now.tm_year;
+               if (missing == none)
+                       missing = year;
+       }
+
+       /* with luck, no rollover is needed */
+       rtc_tm_to_time(&now, &t_now);
+       rtc_tm_to_time(&alarm->time, &t_alm);
+       if (t_now < t_alm)
+               goto done;
+
+       switch (missing) {
+
+       /* 24 hour rollover ... if it's now 10am Monday, an alarm that
+        * that will trigger at 5am will do so at 5am Tuesday, which
+        * could also be in the next month or year.  This is a common
+        * case, especially for PCs.
+        */
+       case day:
+               dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day");
+               t_alm += 24 * 60 * 60;
+               rtc_time_to_tm(t_alm, &alarm->time);
+               break;
+
+       /* Month rollover ... if it's the 31th, an alarm on the 3rd will
+        * be next month.  An alarm matching on the 30th, 29th, or 28th
+        * may end up in the month after that!  Many newer PCs support
+        * this type of alarm.
+        */
+       case month:
+               dev_dbg(&rtc->dev, "alarm rollover: %s\n", "month");
+               do {
+                       if (alarm->time.tm_mon < 11)
+                               alarm->time.tm_mon++;
+                       else {
+                               alarm->time.tm_mon = 0;
+                               alarm->time.tm_year++;
+                       }
+                       days = rtc_month_days(alarm->time.tm_mon,
+                                       alarm->time.tm_year);
+               } while (days < alarm->time.tm_mday);
+               break;
+
+       /* Year rollover ... easy except for leap years! */
+       case year:
+               dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");
+               do {
+                       alarm->time.tm_year++;
+               } while (!rtc_valid_tm(&alarm->time));
+               break;
+
+       default:
+               dev_warn(&rtc->dev, "alarm rollover not handled\n");
+       }
+
+done:
        return 0;
 }
 EXPORT_SYMBOL_GPL(rtc_read_alarm);
index 11644c8fca829882dc1b0f8225cc1dda148b62c2..abfdfcbaa059f2334dea356dd5b094924783315e 100644 (file)
@@ -55,7 +55,7 @@ struct fm3130 {
        int                     alarm;
 };
 static const struct i2c_device_id fm3130_id[] = {
-       { "fm3130-rtc", 0 },
+       { "fm3130", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, fm3130_id);
index 0fc4c363078003e6d189f39a8b3f6f5a4ddd790a..748a502a63558fd499e26d56338132aabcae85f2 100644 (file)
@@ -302,6 +302,7 @@ static int pcf8563_remove(struct i2c_client *client)
 
 static const struct i2c_device_id pcf8563_id[] = {
        { "pcf8563", 0 },
+       { "rtc8564", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, pcf8563_id);
index 82f62d25f92180e01caecd6c4467a7fdbf92aa7e..67421b0d3a7b33ff7e2b87d641a5e3e499e5fa98 100644 (file)
@@ -331,14 +331,14 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
                RCNR = 0;
        }
 
+       device_init_wakeup(&pdev->dev, 1);
+
        rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
                                THIS_MODULE);
 
        if (IS_ERR(rtc))
                return PTR_ERR(rtc);
 
-       device_init_wakeup(&pdev->dev, 1);
-
        platform_set_drvdata(pdev, rtc);
 
        return 0;
index eaf55945f21bbf860318a082b24463caa8648ebc..7dcfba1bbfe131539af2aba38d361e53d036280e 100644 (file)
@@ -71,6 +71,7 @@
 #define X1205_SR_RTCF          0x01    /* Clock failure */
 #define X1205_SR_WEL           0x02    /* Write Enable Latch */
 #define X1205_SR_RWEL          0x04    /* Register Write Enable */
+#define X1205_SR_AL0           0x20    /* Alarm 0 match */
 
 #define X1205_DTR_DTR0         0x01
 #define X1205_DTR_DTR1         0x02
@@ -78,6 +79,8 @@
 
 #define X1205_HR_MIL           0x80    /* Set in ccr.hour for 24 hr mode */
 
+#define X1205_INT_AL0E         0x20    /* Alarm 0 enable */
+
 static struct i2c_driver x1205_driver;
 
 /*
@@ -89,8 +92,8 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
                                unsigned char reg_base)
 {
        unsigned char dt_addr[2] = { 0, reg_base };
-
        unsigned char buf[8];
+       int i;
 
        struct i2c_msg msgs[] = {
                { client->addr, 0, 2, dt_addr },        /* setup read ptr */
@@ -98,7 +101,7 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
        };
 
        /* read date registers */
-       if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+       if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
                dev_err(&client->dev, "%s: read error\n", __func__);
                return -EIO;
        }
@@ -110,6 +113,11 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
                buf[0], buf[1], buf[2], buf[3],
                buf[4], buf[5], buf[6], buf[7]);
 
+       /* Mask out the enable bits if these are alarm registers */
+       if (reg_base < X1205_CCR_BASE)
+               for (i = 0; i <= 4; i++)
+                       buf[i] &= 0x7F;
+
        tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
        tm->tm_min = BCD2BIN(buf[CCR_MIN]);
        tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
@@ -138,7 +146,7 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
        };
 
        /* read status register */
-       if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+       if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
                dev_err(&client->dev, "%s: read error\n", __func__);
                return -EIO;
        }
@@ -147,10 +155,11 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
 }
 
 static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
-                               int datetoo, u8 reg_base)
+                       int datetoo, u8 reg_base, unsigned char alm_enable)
 {
-       int i, xfer;
+       int i, xfer, nbytes;
        unsigned char buf[8];
+       unsigned char rdata[10] = { 0, reg_base };
 
        static const unsigned char wel[3] = { 0, X1205_REG_SR,
                                                X1205_SR_WEL };
@@ -189,6 +198,11 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
                buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100);
        }
 
+       /* If writing alarm registers, set compare bits on registers 0-4 */
+       if (reg_base < X1205_CCR_BASE)
+               for (i = 0; i <= 4; i++)
+                       buf[i] |= 0x80;
+
        /* this sequence is required to unlock the chip */
        if ((xfer = i2c_master_send(client, wel, 3)) != 3) {
                dev_err(&client->dev, "%s: wel - %d\n", __func__, xfer);
@@ -200,19 +214,57 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
                return -EIO;
        }
 
+
        /* write register's data */
-       for (i = 0; i < (datetoo ? 8 : 3); i++) {
-               unsigned char rdata[3] = { 0, reg_base + i, buf[i] };
+       if (datetoo)
+               nbytes = 8;
+       else
+               nbytes = 3;
+       for (i = 0; i < nbytes; i++)
+               rdata[2+i] = buf[i];
+
+       xfer = i2c_master_send(client, rdata, nbytes+2);
+       if (xfer != nbytes+2) {
+               dev_err(&client->dev,
+                       "%s: result=%d addr=%02x, data=%02x\n",
+                       __func__,
+                        xfer, rdata[1], rdata[2]);
+               return -EIO;
+       }
+
+       /* If we wrote to the nonvolatile region, wait 10msec for write cycle*/
+       if (reg_base < X1205_CCR_BASE) {
+               unsigned char al0e[3] = { 0, X1205_REG_INT, 0 };
+
+               msleep(10);
 
-               xfer = i2c_master_send(client, rdata, 3);
+               /* ...and set or clear the AL0E bit in the INT register */
+
+               /* Need to set RWEL again as the write has cleared it */
+               xfer = i2c_master_send(client, rwel, 3);
                if (xfer != 3) {
                        dev_err(&client->dev,
-                               "%s: xfer=%d addr=%02x, data=%02x\n",
+                               "%s: aloe rwel - %d\n",
                                __func__,
-                                xfer, rdata[1], rdata[2]);
+                               xfer);
+                       return -EIO;
+               }
+
+               if (alm_enable)
+                       al0e[2] = X1205_INT_AL0E;
+
+               xfer = i2c_master_send(client, al0e, 3);
+               if (xfer != 3) {
+                       dev_err(&client->dev,
+                               "%s: al0e - %d\n",
+                               __func__,
+                               xfer);
                        return -EIO;
                }
-       };
+
+               /* and wait 10msec again for this write to complete */
+               msleep(10);
+       }
 
        /* disable further writes */
        if ((xfer = i2c_master_send(client, diswe, 3)) != 3) {
@@ -230,9 +282,9 @@ static int x1205_fix_osc(struct i2c_client *client)
 
        tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
 
-       if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0)
-               dev_err(&client->dev,
-                       "unable to restart the oscillator\n");
+       err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE, 0);
+       if (err < 0)
+               dev_err(&client->dev, "unable to restart the oscillator\n");
 
        return err;
 }
@@ -248,7 +300,7 @@ static int x1205_get_dtrim(struct i2c_client *client, int *trim)
        };
 
        /* read dtr register */
-       if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+       if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
                dev_err(&client->dev, "%s: read error\n", __func__);
                return -EIO;
        }
@@ -280,7 +332,7 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim)
        };
 
        /* read atr register */
-       if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+       if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
                dev_err(&client->dev, "%s: read error\n", __func__);
                return -EIO;
        }
@@ -403,14 +455,33 @@ static int x1205_validate_client(struct i2c_client *client)
 
 static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
-       return x1205_get_datetime(to_i2c_client(dev),
-               &alrm->time, X1205_ALM0_BASE);
+       int err;
+       unsigned char intreg, status;
+       static unsigned char int_addr[2] = { 0, X1205_REG_INT };
+       struct i2c_client *client = to_i2c_client(dev);
+       struct i2c_msg msgs[] = {
+               { client->addr, 0, 2, int_addr },        /* setup read ptr */
+               { client->addr, I2C_M_RD, 1, &intreg },  /* read INT register */
+       };
+
+       /* read interrupt register and status register */
+       if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
+               dev_err(&client->dev, "%s: read error\n", __func__);
+               return -EIO;
+       }
+       err = x1205_get_status(client, &status);
+       if (err == 0) {
+               alrm->pending = (status & X1205_SR_AL0) ? 1 : 0;
+               alrm->enabled = (intreg & X1205_INT_AL0E) ? 1 : 0;
+               err = x1205_get_datetime(client, &alrm->time, X1205_ALM0_BASE);
+       }
+       return err;
 }
 
 static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
        return x1205_set_datetime(to_i2c_client(dev),
-               &alrm->time, 1, X1205_ALM0_BASE);
+               &alrm->time, 1, X1205_ALM0_BASE, alrm->enabled);
 }
 
 static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm)
@@ -422,7 +493,7 @@ static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm)
 static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        return x1205_set_datetime(to_i2c_client(dev),
-               tm, 1, X1205_CCR_BASE);
+               tm, 1, X1205_CCR_BASE, 0);
 }
 
 static int x1205_rtc_proc(struct device *dev, struct seq_file *seq)
index 1a40256833625e4ea9da26f92e679e9f878b9971..1b6c52ef73391da1aff66cc1aa6bcda8c193ddd8 100644 (file)
@@ -995,14 +995,14 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
        now = get_clock();
 
        DBF_EVENT(DBF_ERR, "Interrupt: bus_id %s CS/DS %04x ip %08x",
-                 cdev->dev.bus_id, ((irb->scsw.cstat<<8)|irb->scsw.dstat),
-                 (unsigned int) intparm);
+                 cdev->dev.bus_id, ((irb->scsw.cmd.cstat << 8) |
+                 irb->scsw.cmd.dstat), (unsigned int) intparm);
 
        /* check for unsolicited interrupts */
        cqr = (struct dasd_ccw_req *) intparm;
-       if (!cqr || ((irb->scsw.cc == 1) &&
-                    (irb->scsw.fctl & SCSW_FCTL_START_FUNC) &&
-                    (irb->scsw.stctl & SCSW_STCTL_STATUS_PEND)) ) {
+       if (!cqr || ((irb->scsw.cmd.cc == 1) &&
+                    (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) &&
+                    (irb->scsw.cmd.stctl & SCSW_STCTL_STATUS_PEND))) {
                if (cqr && cqr->status == DASD_CQR_IN_IO)
                        cqr->status = DASD_CQR_QUEUED;
                device = dasd_device_from_cdev_locked(cdev);
@@ -1025,7 +1025,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
 
        /* Check for clear pending */
        if (cqr->status == DASD_CQR_CLEAR_PENDING &&
-           irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) {
+           irb->scsw.cmd.fctl & SCSW_FCTL_CLEAR_FUNC) {
                cqr->status = DASD_CQR_CLEARED;
                dasd_device_clear_timer(device);
                wake_up(&dasd_flush_wq);
@@ -1041,11 +1041,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
                return;
        }
        DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x for cqr %p",
-                     ((irb->scsw.cstat << 8) | irb->scsw.dstat), cqr);
+                     ((irb->scsw.cmd.cstat << 8) | irb->scsw.cmd.dstat), cqr);
        next = NULL;
        expires = 0;
-       if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) &&
-           irb->scsw.cstat == 0 && !irb->esw.esw0.erw.cons) {
+       if (irb->scsw.cmd.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) &&
+           irb->scsw.cmd.cstat == 0 && !irb->esw.esw0.erw.cons) {
                /* request was completed successfully */
                cqr->status = DASD_CQR_SUCCESS;
                cqr->stopclk = now;
index e6700df52df48750ea00d544d61972bb0212e518..5c6e6f331cb0691e097f55321eb5fe37007adbb3 100644 (file)
@@ -1572,7 +1572,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
 
        /* determine the address of the CCW to be restarted */
        /* Imprecise ending is not set -> addr from IRB-SCSW */
-       cpa = default_erp->refers->irb.scsw.cpa;
+       cpa = default_erp->refers->irb.scsw.cmd.cpa;
 
        if (cpa == 0) {
 
@@ -1725,7 +1725,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
 
        /* determine the address of the CCW to be restarted */
        /* Imprecise ending is not set -> addr from IRB-SCSW */
-       cpa = previous_erp->irb.scsw.cpa;
+       cpa = previous_erp->irb.scsw.cmd.cpa;
 
        if (cpa == 0) {
 
@@ -2171,7 +2171,7 @@ dasd_3990_erp_control_check(struct dasd_ccw_req *erp)
 {
        struct dasd_device *device = erp->startdev;
 
-       if (erp->refers->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK
+       if (erp->refers->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK
                                           | SCHN_STAT_CHN_CTRL_CHK)) {
                DEV_MESSAGE(KERN_DEBUG, device, "%s",
                            "channel or interface control check");
@@ -2352,9 +2352,9 @@ dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2)
 
        if ((cqr1->irb.esw.esw0.erw.cons == 0) &&
            (cqr2->irb.esw.esw0.erw.cons == 0)) {
-               if ((cqr1->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK |
+               if ((cqr1->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK |
                                             SCHN_STAT_CHN_CTRL_CHK)) ==
-                   (cqr2->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK |
+                   (cqr2->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK |
                                             SCHN_STAT_CHN_CTRL_CHK)))
                        return 1; /* match with ifcc*/
        }
@@ -2622,8 +2622,9 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
        }
 
        /* double-check if current erp/cqr was successfull */
-       if ((cqr->irb.scsw.cstat == 0x00) &&
-           (cqr->irb.scsw.dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END))) {
+       if ((cqr->irb.scsw.cmd.cstat == 0x00) &&
+           (cqr->irb.scsw.cmd.dstat ==
+            (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) {
 
                DEV_MESSAGE(KERN_DEBUG, device,
                            "ERP called for successful request %p"
index a0edae091b5e54f1c022115ab60b8912ff3324f3..e0b77210d37a5b95f15b707c39baf42397396ba2 100644 (file)
@@ -1404,13 +1404,14 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
 
        /* first of all check for state change pending interrupt */
        mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;
-       if ((irb->scsw.dstat & mask) == mask) {
+       if ((irb->scsw.cmd.dstat & mask) == mask) {
                dasd_generic_handle_state_change(device);
                return;
        }
 
        /* summary unit check */
-       if ((irb->scsw.dstat & DEV_STAT_UNIT_CHECK) && irb->ecw[7] == 0x0D) {
+       if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) &&
+           (irb->ecw[7] == 0x0D)) {
                dasd_alias_handle_summary_unit_check(device, irb);
                return;
        }
@@ -2068,11 +2069,11 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,
                      device->cdev->dev.bus_id);
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                       " in req: %p CS: 0x%02X DS: 0x%02X\n", req,
-                      irb->scsw.cstat, irb->scsw.dstat);
+                      irb->scsw.cmd.cstat, irb->scsw.cmd.dstat);
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                       " device %s: Failing CCW: %p\n",
                       device->cdev->dev.bus_id,
-                      (void *) (addr_t) irb->scsw.cpa);
+                      (void *) (addr_t) irb->scsw.cmd.cpa);
        if (irb->esw.esw0.erw.cons) {
                for (sl = 0; sl < 4; sl++) {
                        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
@@ -2122,7 +2123,8 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,
                /* scsw->cda is either valid or zero  */
                len = 0;
                from = ++to;
-               fail = (struct ccw1 *)(addr_t) irb->scsw.cpa; /* failing CCW */
+               fail = (struct ccw1 *)(addr_t)
+                               irb->scsw.cmd.cpa; /* failing CCW */
                if (from <  fail - 2) {
                        from = fail - 2;     /* there is a gap - print header */
                        len += sprintf(page, KERN_ERR PRINTK_HEADER "......\n");
index 116611583df8215ea1ec7ecc6f9d25987812b00d..aee4656127f76e9ddeb8dc2439b2bbf38ea30efb 100644 (file)
@@ -222,7 +222,7 @@ static void dasd_fba_handle_unsolicited_interrupt(struct dasd_device *device,
 
        /* first of all check for state change pending interrupt */
        mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;
-       if ((irb->scsw.dstat & mask) == mask) {
+       if ((irb->scsw.cmd.dstat & mask) == mask) {
                dasd_generic_handle_state_change(device);
                return;
        }
@@ -449,11 +449,11 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
                      device->cdev->dev.bus_id);
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                       " in req: %p CS: 0x%02X DS: 0x%02X\n", req,
-                      irb->scsw.cstat, irb->scsw.dstat);
+                      irb->scsw.cmd.cstat, irb->scsw.cmd.dstat);
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                       " device %s: Failing CCW: %p\n",
                       device->cdev->dev.bus_id,
-                      (void *) (addr_t) irb->scsw.cpa);
+                      (void *) (addr_t) irb->scsw.cmd.cpa);
        if (irb->esw.esw0.erw.cons) {
                for (sl = 0; sl < 4; sl++) {
                        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
@@ -498,11 +498,11 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
 
        /* print failing CCW area */
        len = 0;
-       if (act <  ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2) {
-               act = ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2;
+       if (act <  ((struct ccw1 *)(addr_t) irb->scsw.cmd.cpa) - 2) {
+               act = ((struct ccw1 *)(addr_t) irb->scsw.cmd.cpa) - 2;
                len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n");
        }
-       end = min((struct ccw1 *)(addr_t) irb->scsw.cpa + 2, last);
+       end = min((struct ccw1 *)(addr_t) irb->scsw.cmd.cpa + 2, last);
        while (act <= end) {
                len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                               " CCW %p: %08X %08X DAT:",
index bb52d2fbac183b7a98e4e7872ace113a92a8cecc..01fcdd91b846533a920cc3076c67bf85ca3816c2 100644 (file)
@@ -167,10 +167,8 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
        struct dcssblk_dev_info *dev_info;
        int rc;
 
-       if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0')) {
-               PRINT_WARN("Invalid value, must be 0 or 1\n");
+       if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0'))
                return -EINVAL;
-       }
        down_write(&dcssblk_devices_sem);
        dev_info = container_of(dev, struct dcssblk_dev_info, dev);
        if (atomic_read(&dev_info->use_count)) {
@@ -215,7 +213,6 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
                        set_disk_ro(dev_info->gd, 0);
                }
        } else {
-               PRINT_WARN("Invalid value, must be 0 or 1\n");
                rc = -EINVAL;
                goto out;
        }
@@ -258,10 +255,8 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
 {
        struct dcssblk_dev_info *dev_info;
 
-       if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0')) {
-               PRINT_WARN("Invalid value, must be 0 or 1\n");
+       if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0'))
                return -EINVAL;
-       }
        dev_info = container_of(dev, struct dcssblk_dev_info, dev);
 
        down_write(&dcssblk_devices_sem);
@@ -289,7 +284,6 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
                }
        } else {
                up_write(&dcssblk_devices_sem);
-               PRINT_WARN("Invalid value, must be 0 or 1\n");
                return -EINVAL;
        }
        up_write(&dcssblk_devices_sem);
@@ -441,7 +435,6 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
        goto out;
 
 unregister_dev:
-       PRINT_ERR("device_create_file() failed!\n");
        list_del(&dev_info->lh);
        blk_cleanup_queue(dev_info->dcssblk_queue);
        dev_info->gd->queue = NULL;
@@ -702,10 +695,8 @@ dcssblk_check_params(void)
 static void __exit
 dcssblk_exit(void)
 {
-       PRINT_DEBUG("DCSSBLOCK EXIT...\n");
        s390_root_dev_unregister(dcssblk_root_dev);
        unregister_blkdev(dcssblk_major, DCSSBLK_NAME);
-       PRINT_DEBUG("...finished!\n");
 }
 
 static int __init
@@ -713,27 +704,21 @@ dcssblk_init(void)
 {
        int rc;
 
-       PRINT_DEBUG("DCSSBLOCK INIT...\n");
        dcssblk_root_dev = s390_root_dev_register("dcssblk");
-       if (IS_ERR(dcssblk_root_dev)) {
-               PRINT_ERR("device_register() failed!\n");
+       if (IS_ERR(dcssblk_root_dev))
                return PTR_ERR(dcssblk_root_dev);
-       }
        rc = device_create_file(dcssblk_root_dev, &dev_attr_add);
        if (rc) {
-               PRINT_ERR("device_create_file(add) failed!\n");
                s390_root_dev_unregister(dcssblk_root_dev);
                return rc;
        }
        rc = device_create_file(dcssblk_root_dev, &dev_attr_remove);
        if (rc) {
-               PRINT_ERR("device_create_file(remove) failed!\n");
                s390_root_dev_unregister(dcssblk_root_dev);
                return rc;
        }
        rc = register_blkdev(0, DCSSBLK_NAME);
        if (rc < 0) {
-               PRINT_ERR("Can't get dynamic major!\n");
                s390_root_dev_unregister(dcssblk_root_dev);
                return rc;
        }
@@ -742,7 +727,6 @@ dcssblk_init(void)
 
        dcssblk_check_params();
 
-       PRINT_DEBUG("...finished!\n");
        return 0;
 }
 
index f231bc21b1cafd3465dcf97cc3c4f6618b5b804c..dd9b986389a2bf4a2d38a71a64c01dfe25718ef3 100644 (file)
@@ -100,15 +100,10 @@ static int xpram_page_in (unsigned long page_addr, unsigned int xpage_index)
                : "+d" (cc) : "a" (__pa(page_addr)), "d" (xpage_index) : "cc");
        if (cc == 3)
                return -ENXIO;
-       if (cc == 2) {
-               PRINT_ERR("expanded storage lost!\n");
+       if (cc == 2)
                return -ENXIO;
-       }
-       if (cc == 1) {
-               PRINT_ERR("page in failed for page index %u.\n",
-                         xpage_index);
+       if (cc == 1)
                return -EIO;
-       }
        return 0;
 }
 
@@ -135,15 +130,10 @@ static long xpram_page_out (unsigned long page_addr, unsigned int xpage_index)
                : "+d" (cc) : "a" (__pa(page_addr)), "d" (xpage_index) : "cc");
        if (cc == 3)
                return -ENXIO;
-       if (cc == 2) {
-               PRINT_ERR("expanded storage lost!\n");
+       if (cc == 2)
                return -ENXIO;
-       }
-       if (cc == 1) {
-               PRINT_ERR("page out failed for page index %u.\n",
-                         xpage_index);
+       if (cc == 1)
                return -EIO;
-       }
        return 0;
 }
 
index 3e5653c92f4b5e5b6d1c5b1edd14b5f6eaa23af6..d3ec9b55ab351c665016c0c1fd139a6cf841fa9f 100644 (file)
@@ -93,9 +93,6 @@ struct raw3215_info {
        struct raw3215_req *queued_write;/* pointer to queued write requests */
        wait_queue_head_t empty_wait; /* wait queue for flushing */
        struct timer_list timer;      /* timer for delayed output */
-       char *message;                /* pending message from raw3215_irq */
-       int msg_dstat;                /* dstat for pending message */
-       int msg_cstat;                /* cstat for pending message */
        int line_pos;                 /* position on the line (for tabs) */
        char ubuffer[80];             /* copy_from_user buffer */
 };
@@ -359,11 +356,6 @@ raw3215_tasklet(void *data)
        raw3215_mk_write_req(raw);
        raw3215_try_io(raw);
        spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
-       /* Check for pending message from raw3215_irq */
-       if (raw->message != NULL) {
-               printk(raw->message, raw->msg_dstat, raw->msg_cstat);
-               raw->message = NULL;
-       }
        tty = raw->tty;
        if (tty != NULL &&
            RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
@@ -381,20 +373,14 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
        struct raw3215_req *req;
        struct tty_struct *tty;
        int cstat, dstat;
-       int count, slen;
+       int count;
 
        raw = cdev->dev.driver_data;
        req = (struct raw3215_req *) intparm;
-       cstat = irb->scsw.cstat;
-       dstat = irb->scsw.dstat;
-       if (cstat != 0) {
-               raw->message = KERN_WARNING
-                       "Got nonzero channel status in raw3215_irq "
-                       "(dev sts 0x%2x, sch sts 0x%2x)";
-               raw->msg_dstat = dstat;
-               raw->msg_cstat = cstat;
+       cstat = irb->scsw.cmd.cstat;
+       dstat = irb->scsw.cmd.dstat;
+       if (cstat != 0)
                tasklet_schedule(&raw->tasklet);
-       }
        if (dstat & 0x01) { /* we got a unit exception */
                dstat &= ~0x01;  /* we can ignore it */
        }
@@ -404,8 +390,6 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                        break;
                /* Attention interrupt, someone hit the enter key */
                raw3215_mk_read_req(raw);
-               if (MACHINE_IS_P390)
-                       memset(raw->inbuf, 0, RAW3215_INBUF_SIZE);
                tasklet_schedule(&raw->tasklet);
                break;
        case 0x08:
@@ -415,7 +399,7 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                        return;              /* That shouldn't happen ... */
                if (req->type == RAW3215_READ) {
                        /* store residual count, then wait for device end */
-                       req->residual = irb->scsw.count;
+                       req->residual = irb->scsw.cmd.count;
                }
                if (dstat == 0x08)
                        break;
@@ -428,11 +412,6 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
 
                        tty = raw->tty;
                        count = 160 - req->residual;
-                       if (MACHINE_IS_P390) {
-                               slen = strnlen(raw->inbuf, RAW3215_INBUF_SIZE);
-                               if (count > slen)
-                                       count = slen;
-                       } else
                        EBCASC(raw->inbuf, count);
                        cchar = ctrlchar_handle(raw->inbuf, count, tty);
                        switch (cchar & CTRLCHAR_MASK) {
@@ -481,11 +460,6 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                        raw->flags &= ~RAW3215_WORKING;
                        raw3215_free_req(req);
                }
-               raw->message = KERN_WARNING
-                       "Spurious interrupt in in raw3215_irq "
-                       "(dev sts 0x%2x, sch sts 0x%2x)";
-               raw->msg_dstat = dstat;
-               raw->msg_cstat = cstat;
                tasklet_schedule(&raw->tasklet);
        }
        return;
@@ -883,7 +857,6 @@ con3215_init(void)
                free_bootmem((unsigned long) raw->buffer, RAW3215_BUFFER_SIZE);
                free_bootmem((unsigned long) raw, sizeof(struct raw3215_info));
                raw3215[0] = NULL;
-               printk("Couldn't find a 3215 console device\n");
                return -ENODEV;
        }
        register_console(&con3215);
@@ -1157,7 +1130,6 @@ tty3215_init(void)
        tty_set_operations(driver, &tty3215_ops);
        ret = tty_register_driver(driver);
        if (ret) {
-               printk("Couldn't register tty3215 driver\n");
                put_tty_driver(driver);
                return ret;
        }
index 0b040557db02d5ee67ad91c4179f4179d14d6a54..3c07974886ed2aa1f8fa23dea19fd7e3b77860c0 100644 (file)
@@ -411,15 +411,15 @@ static int
 con3270_irq(struct con3270 *cp, struct raw3270_request *rq, struct irb *irb)
 {
        /* Handle ATTN. Schedule tasklet to read aid. */
-       if (irb->scsw.dstat & DEV_STAT_ATTENTION)
+       if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION)
                con3270_issue_read(cp);
 
        if (rq) {
-               if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK)
+               if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
                        rq->rc = -EIO;
                else
                        /* Normal end. Copy residual count. */
-                       rq->rescnt = irb->scsw.count;
+                       rq->rescnt = irb->scsw.cmd.count;
        }
        return RAW3270_IO_DONE;
 }
index ef36f2132aa43fb994ee878a46022f5776c64ed0..e136d10a0de6da541f788937d32fd0a513091e0f 100644 (file)
@@ -216,17 +216,17 @@ static int
 fs3270_irq(struct fs3270 *fp, struct raw3270_request *rq, struct irb *irb)
 {
        /* Handle ATTN. Set indication and wake waiters for attention. */
-       if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
+       if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
                fp->attention = 1;
                wake_up(&fp->wait);
        }
 
        if (rq) {
-               if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK)
+               if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
                        rq->rc = -EIO;
                else
                        /* Normal end. Copy residual count. */
-                       rq->rescnt = irb->scsw.count;
+                       rq->rescnt = irb->scsw.cmd.count;
        }
        return RAW3270_IO_DONE;
 }
@@ -512,11 +512,8 @@ fs3270_init(void)
        int rc;
 
        rc = register_chrdev(IBM_FS3270_MAJOR, "fs3270", &fs3270_fops);
-       if (rc) {
-               printk(KERN_ERR "fs3270 can't get major number %d: errno %d\n",
-                      IBM_FS3270_MAJOR, rc);
+       if (rc)
                return rc;
-       }
        return 0;
 }
 
index 1e1f50655bbfb8f01a4896dd830a09ff23f98f99..f0e4c96afbf803f12c17f296d0fd645a57cb93b4 100644 (file)
@@ -3,9 +3,8 @@
  *
  * Character device driver for reading z/VM *MONITOR service records.
  *
- * Copyright 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH.
- *
- * Author: Gerald Schaefer <geraldsc@de.ibm.com>
+ *   Copyright IBM Corp. 2004, 2008
+ *   Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
  */
 
 #include <linux/module.h>
 #include <linux/ctype.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
+#include <linux/poll.h>
+#include <net/iucv/iucv.h>
 #include <asm/uaccess.h>
 #include <asm/ebcdic.h>
 #include <asm/extmem.h>
-#include <linux/poll.h>
-#include <net/iucv/iucv.h>
-
 
 //#define MON_DEBUG                    /* Debug messages on/off */
 
@@ -152,10 +150,7 @@ static int mon_check_mca(struct mon_msg *monmsg)
            (mon_mca_end(monmsg) > mon_dcss_end) ||
            (mon_mca_start(monmsg) < mon_dcss_start) ||
            ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0)))
-       {
-               P_DEBUG("READ, IGNORED INVALID MCA\n\n");
                return -EINVAL;
-       }
        return 0;
 }
 
@@ -164,10 +159,6 @@ static int mon_send_reply(struct mon_msg *monmsg,
 {
        int rc;
 
-       P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = "
-               "0x%08X\n\n",
-               monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
-
        rc = iucv_message_reply(monpriv->path, &monmsg->msg,
                                IUCV_IPRMDATA, NULL, 0);
        atomic_dec(&monpriv->msglim_count);
@@ -202,15 +193,12 @@ static struct mon_private *mon_alloc_mem(void)
        struct mon_private *monpriv;
 
        monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
-       if (!monpriv) {
-               P_ERROR("no memory for monpriv\n");
+       if (!monpriv)
                return NULL;
-       }
        for (i = 0; i < MON_MSGLIM; i++) {
                monpriv->msg_array[i] = kzalloc(sizeof(struct mon_msg),
                                                    GFP_KERNEL);
                if (!monpriv->msg_array[i]) {
-                       P_ERROR("open, no memory for msg_array\n");
                        mon_free_mem(monpriv);
                        return NULL;
                }
@@ -218,41 +206,10 @@ static struct mon_private *mon_alloc_mem(void)
        return monpriv;
 }
 
-static inline void mon_read_debug(struct mon_msg *monmsg,
-                                 struct mon_private *monpriv)
-{
-#ifdef MON_DEBUG
-       u8 msg_type[2], mca_type;
-       unsigned long records_len;
-
-       records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1;
-
-       memcpy(msg_type, &monmsg->msg.class, 2);
-       EBCASC(msg_type, 2);
-       mca_type = mon_mca_type(monmsg, 0);
-       EBCASC(&mca_type, 1);
-
-       P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n",
-               monpriv->read_index, monpriv->write_index);
-       P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n",
-               monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
-       P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n",
-               msg_type[0], msg_type[1], mca_type ? mca_type : 'X',
-               mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2));
-       P_DEBUG("read, MCA: start = 0x%lX, end = 0x%lX\n",
-               mon_mca_start(monmsg), mon_mca_end(monmsg));
-       P_DEBUG("read, REC: start = 0x%X, end = 0x%X, len = %lu\n\n",
-               mon_rec_start(monmsg), mon_rec_end(monmsg), records_len);
-       if (mon_mca_size(monmsg) > 12)
-               P_DEBUG("READ, MORE THAN ONE MCA\n\n");
-#endif
-}
-
 static inline void mon_next_mca(struct mon_msg *monmsg)
 {
        if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12))
                return;
-       P_DEBUG("READ, NEXT MCA\n\n");
        monmsg->mca_offset += 12;
        monmsg->pos = 0;
 }
@@ -269,7 +226,6 @@ static struct mon_msg *mon_next_message(struct mon_private *monpriv)
                monmsg->msglim_reached = 0;
                monmsg->pos = 0;
                monmsg->mca_offset = 0;
-               P_WARNING("read, message limit reached\n");
                monpriv->read_index = (monpriv->read_index + 1) %
                                      MON_MSGLIM;
                atomic_dec(&monpriv->read_ready);
@@ -286,10 +242,6 @@ static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
 {
        struct mon_private *monpriv = path->private;
 
-       P_DEBUG("IUCV connection completed\n");
-       P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = "
-               "0x%02X, Sample = 0x%02X\n",
-               ipuser[0], ipuser[1], ipuser[2]);
        atomic_set(&monpriv->iucv_connected, 1);
        wake_up(&mon_conn_wait_queue);
 }
@@ -310,7 +262,6 @@ static void mon_iucv_message_pending(struct iucv_path *path,
 {
        struct mon_private *monpriv = path->private;
 
-       P_DEBUG("IUCV message pending\n");
        memcpy(&monpriv->msg_array[monpriv->write_index]->msg,
               msg, sizeof(*msg));
        if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) {
@@ -375,7 +326,6 @@ static int mon_open(struct inode *inode, struct file *filp)
                rc = -EIO;
                goto out_path;
        }
-       P_INFO("open, established connection to *MONITOR service\n\n");
        filp->private_data = monpriv;
        return nonseekable_open(inode, filp);
 
@@ -400,8 +350,6 @@ static int mon_close(struct inode *inode, struct file *filp)
        rc = iucv_path_sever(monpriv->path, user_data_sever);
        if (rc)
                P_ERROR("close, iucv_sever failed with rc = %i\n", rc);
-       else
-               P_INFO("close, terminated connection to *MONITOR service\n");
 
        atomic_set(&monpriv->iucv_severed, 0);
        atomic_set(&monpriv->iucv_connected, 0);
@@ -442,10 +390,8 @@ static ssize_t mon_read(struct file *filp, char __user *data,
                monmsg = monpriv->msg_array[monpriv->read_index];
        }
 
-       if (!monmsg->pos) {
+       if (!monmsg->pos)
                monmsg->pos = mon_mca_start(monmsg) + monmsg->mca_offset;
-               mon_read_debug(monmsg, monpriv);
-       }
        if (mon_check_mca(monmsg))
                goto reply;
 
@@ -531,7 +477,6 @@ static int __init mon_init(void)
                P_ERROR("failed to register with iucv driver\n");
                return rc;
        }
-       P_INFO("open, registered with IUCV\n");
 
        rc = segment_type(mon_dcss_name);
        if (rc < 0) {
@@ -555,13 +500,8 @@ static int __init mon_init(void)
        dcss_mkname(mon_dcss_name, &user_data_connect[8]);
 
        rc = misc_register(&mon_dev);
-       if (rc < 0 ) {
-               P_ERROR("misc_register failed, rc = %i\n", rc);
+       if (rc < 0 )
                goto out;
-       }
-       P_INFO("Loaded segment %s from %p to %p, size = %lu Byte\n",
-               mon_dcss_name, (void *) mon_dcss_start, (void *) mon_dcss_end,
-               mon_dcss_end - mon_dcss_start + 1);
        return 0;
 
 out:
index 848ef7e8523fe97ba2e0ade9f61f1cbac86a8f90..81a96e019080bf591ab68e3dee40b593ab2ff9f8 100644 (file)
@@ -153,19 +153,10 @@ struct raw3270_request __init *raw3270_request_alloc_bootmem(size_t size)
        struct raw3270_request *rq;
 
        rq = alloc_bootmem_low(sizeof(struct raw3270));
-       if (!rq)
-               return ERR_PTR(-ENOMEM);
-       memset(rq, 0, sizeof(struct raw3270_request));
 
        /* alloc output buffer. */
-       if (size > 0) {
+       if (size > 0)
                rq->buffer = alloc_bootmem_low(size);
-               if (!rq->buffer) {
-                       free_bootmem((unsigned long) rq,
-                                    sizeof(struct raw3270));
-                       return ERR_PTR(-ENOMEM);
-               }
-       }
        rq->size = size;
        INIT_LIST_HEAD(&rq->list);
 
@@ -372,17 +363,17 @@ raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
 
        if (IS_ERR(irb))
                rc = RAW3270_IO_RETRY;
-       else if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) {
+       else if (irb->scsw.cmd.fctl & SCSW_FCTL_HALT_FUNC) {
                rq->rc = -EIO;
                rc = RAW3270_IO_DONE;
-       } else if (irb->scsw.dstat ==  (DEV_STAT_CHN_END | DEV_STAT_DEV_END |
-                                       DEV_STAT_UNIT_EXCEP)) {
+       } else if (irb->scsw.cmd.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END |
+                                          DEV_STAT_UNIT_EXCEP)) {
                /* Handle CE-DE-UE and subsequent UDE */
                set_bit(RAW3270_FLAGS_BUSY, &rp->flags);
                rc = RAW3270_IO_BUSY;
        } else if (test_bit(RAW3270_FLAGS_BUSY, &rp->flags)) {
                /* Wait for UDE if busy flag is set. */
-               if (irb->scsw.dstat & DEV_STAT_DEV_END) {
+               if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
                        clear_bit(RAW3270_FLAGS_BUSY, &rp->flags);
                        /* Got it, now retry. */
                        rc = RAW3270_IO_RETRY;
@@ -497,7 +488,7 @@ raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq,
         * Unit-Check Processing:
         * Expect Command Reject or Intervention Required.
         */
-       if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
+       if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
                /* Request finished abnormally. */
                if (irb->ecw[0] & SNS0_INTERVENTION_REQ) {
                        set_bit(RAW3270_FLAGS_BUSY, &view->dev->flags);
@@ -505,16 +496,16 @@ raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq,
                }
        }
        if (rq) {
-               if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
+               if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
                        if (irb->ecw[0] & SNS0_CMD_REJECT)
                                rq->rc = -EOPNOTSUPP;
                        else
                                rq->rc = -EIO;
                } else
                        /* Request finished normally. Copy residual count. */
-                       rq->rescnt = irb->scsw.count;
+                       rq->rescnt = irb->scsw.cmd.count;
        }
-       if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
+       if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
                set_bit(RAW3270_FLAGS_ATTN, &view->dev->flags);
                wake_up(&raw3270_wait_queue);
        }
@@ -619,7 +610,6 @@ __raw3270_size_device_vm(struct raw3270 *rp)
                rp->cols = 132;
                break;
        default:
-               printk(KERN_WARNING "vrdccrmd is 0x%.8x\n", model);
                rc = -EOPNOTSUPP;
                break;
        }
index 2c7a1ee6b0410fb1f5fc1eeda314ab837a4d6e29..3c8b25e6c3457b528bb8a90c8e2074ff66faf1b8 100644 (file)
@@ -506,6 +506,8 @@ sclp_state_change_cb(struct evbuf_header *evbuf)
        if (scbuf->validity_sclp_send_mask)
                sclp_send_mask = scbuf->sclp_send_mask;
        spin_unlock_irqrestore(&sclp_lock, flags);
+       if (scbuf->validity_sclp_active_facility_mask)
+               sclp_facilities = scbuf->sclp_active_facility_mask;
        sclp_dispatch_state_change();
 }
 
@@ -782,11 +784,9 @@ sclp_check_handler(__u16 code)
        /* Is this the interrupt we are waiting for? */
        if (finished_sccb == 0)
                return;
-       if (finished_sccb != (u32) (addr_t) sclp_init_sccb) {
-               printk(KERN_WARNING SCLP_HEADER "unsolicited interrupt "
-                      "for buffer at 0x%x\n", finished_sccb);
-               return;
-       }
+       if (finished_sccb != (u32) (addr_t) sclp_init_sccb)
+               panic("sclp: unsolicited interrupt for buffer at 0x%x\n",
+                     finished_sccb);
        spin_lock(&sclp_lock);
        if (sclp_running_state == sclp_running_state_running) {
                sclp_init_req.status = SCLP_REQ_DONE;
@@ -883,8 +883,6 @@ sclp_init(void)
        unsigned long flags;
        int rc;
 
-       if (!MACHINE_HAS_SCLP)
-               return -ENODEV;
        spin_lock_irqsave(&sclp_lock, flags);
        /* Check for previous or running initialization */
        if (sclp_init_state != sclp_init_state_uninitialized) {
index b5c23396f8fe4a8a32bf11bee25002c12d54399d..0c2b77493db44ae564033ea20e247330c0951ae2 100644 (file)
@@ -11,6 +11,9 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/memory.h>
 #include <asm/chpid.h>
 #include <asm/sclp.h>
 #include "sclp.h"
@@ -43,6 +46,8 @@ static int __initdata early_read_info_sccb_valid;
 
 u64 sclp_facilities;
 static u8 sclp_fac84;
+static unsigned long long rzm;
+static unsigned long long rnmax;
 
 static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
 {
@@ -62,7 +67,7 @@ out:
        return rc;
 }
 
-void __init sclp_read_info_early(void)
+static void __init sclp_read_info_early(void)
 {
        int rc;
        int i;
@@ -92,34 +97,33 @@ void __init sclp_read_info_early(void)
 
 void __init sclp_facilities_detect(void)
 {
+       struct read_info_sccb *sccb;
+
+       sclp_read_info_early();
        if (!early_read_info_sccb_valid)
                return;
-       sclp_facilities = early_read_info_sccb.facilities;
-       sclp_fac84 = early_read_info_sccb.fac84;
+
+       sccb = &early_read_info_sccb;
+       sclp_facilities = sccb->facilities;
+       sclp_fac84 = sccb->fac84;
+       rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
+       rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
+       rzm <<= 20;
 }
 
-unsigned long long __init sclp_memory_detect(void)
+unsigned long long sclp_get_rnmax(void)
 {
-       unsigned long long memsize;
-       struct read_info_sccb *sccb;
+       return rnmax;
+}
 
-       if (!early_read_info_sccb_valid)
-               return 0;
-       sccb = &early_read_info_sccb;
-       if (sccb->rnsize)
-               memsize = sccb->rnsize << 20;
-       else
-               memsize = sccb->rnsize2 << 20;
-       if (sccb->rnmax)
-               memsize *= sccb->rnmax;
-       else
-               memsize *= sccb->rnmax2;
-       return memsize;
+unsigned long long sclp_get_rzm(void)
+{
+       return rzm;
 }
 
 /*
- * This function will be called after sclp_memory_detect(), which gets called
- * early from early.c code. Therefore the sccb should have valid contents.
+ * This function will be called after sclp_facilities_detect(), which gets
+ * called from early.c code. Therefore the sccb should have valid contents.
  */
 void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
 {
@@ -278,6 +282,305 @@ int sclp_cpu_deconfigure(u8 cpu)
        return do_cpu_configure(SCLP_CMDW_DECONFIGURE_CPU | cpu << 8);
 }
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+
+static DEFINE_MUTEX(sclp_mem_mutex);
+static LIST_HEAD(sclp_mem_list);
+static u8 sclp_max_storage_id;
+static unsigned long sclp_storage_ids[256 / BITS_PER_LONG];
+
+struct memory_increment {
+       struct list_head list;
+       u16 rn;
+       int standby;
+       int usecount;
+};
+
+struct assign_storage_sccb {
+       struct sccb_header header;
+       u16 rn;
+} __packed;
+
+static unsigned long long rn2addr(u16 rn)
+{
+       return (unsigned long long) (rn - 1) * rzm;
+}
+
+static int do_assign_storage(sclp_cmdw_t cmd, u16 rn)
+{
+       struct assign_storage_sccb *sccb;
+       int rc;
+
+       sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!sccb)
+               return -ENOMEM;
+       sccb->header.length = PAGE_SIZE;
+       sccb->rn = rn;
+       rc = do_sync_request(cmd, sccb);
+       if (rc)
+               goto out;
+       switch (sccb->header.response_code) {
+       case 0x0020:
+       case 0x0120:
+               break;
+       default:
+               rc = -EIO;
+               break;
+       }
+out:
+       free_page((unsigned long) sccb);
+       return rc;
+}
+
+static int sclp_assign_storage(u16 rn)
+{
+       return do_assign_storage(0x000d0001, rn);
+}
+
+static int sclp_unassign_storage(u16 rn)
+{
+       return do_assign_storage(0x000c0001, rn);
+}
+
+struct attach_storage_sccb {
+       struct sccb_header header;
+       u16 :16;
+       u16 assigned;
+       u32 :32;
+       u32 entries[0];
+} __packed;
+
+static int sclp_attach_storage(u8 id)
+{
+       struct attach_storage_sccb *sccb;
+       int rc;
+       int i;
+
+       sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!sccb)
+               return -ENOMEM;
+       sccb->header.length = PAGE_SIZE;
+       rc = do_sync_request(0x00080001 | id << 8, sccb);
+       if (rc)
+               goto out;
+       switch (sccb->header.response_code) {
+       case 0x0020:
+               set_bit(id, sclp_storage_ids);
+               for (i = 0; i < sccb->assigned; i++)
+                       sclp_unassign_storage(sccb->entries[i] >> 16);
+               break;
+       default:
+               rc = -EIO;
+               break;
+       }
+out:
+       free_page((unsigned long) sccb);
+       return rc;
+}
+
+static int sclp_mem_change_state(unsigned long start, unsigned long size,
+                                int online)
+{
+       struct memory_increment *incr;
+       unsigned long long istart;
+       int rc = 0;
+
+       list_for_each_entry(incr, &sclp_mem_list, list) {
+               istart = rn2addr(incr->rn);
+               if (start + size - 1 < istart)
+                       break;
+               if (start > istart + rzm - 1)
+                       continue;
+               if (online) {
+                       if (incr->usecount++)
+                               continue;
+                       /*
+                        * Don't break the loop if one assign fails. Loop may
+                        * be walked again on CANCEL and we can't save
+                        * information if state changed before or not.
+                        * So continue and increase usecount for all increments.
+                        */
+                       rc |= sclp_assign_storage(incr->rn);
+               } else {
+                       if (--incr->usecount)
+                               continue;
+                       sclp_unassign_storage(incr->rn);
+               }
+       }
+       return rc ? -EIO : 0;
+}
+
+static int sclp_mem_notifier(struct notifier_block *nb,
+                            unsigned long action, void *data)
+{
+       unsigned long start, size;
+       struct memory_notify *arg;
+       unsigned char id;
+       int rc = 0;
+
+       arg = data;
+       start = arg->start_pfn << PAGE_SHIFT;
+       size = arg->nr_pages << PAGE_SHIFT;
+       mutex_lock(&sclp_mem_mutex);
+       for (id = 0; id <= sclp_max_storage_id; id++)
+               if (!test_bit(id, sclp_storage_ids))
+                       sclp_attach_storage(id);
+       switch (action) {
+       case MEM_ONLINE:
+               break;
+       case MEM_GOING_ONLINE:
+               rc = sclp_mem_change_state(start, size, 1);
+               break;
+       case MEM_CANCEL_ONLINE:
+               sclp_mem_change_state(start, size, 0);
+               break;
+       default:
+               rc = -EINVAL;
+               break;
+       }
+       mutex_unlock(&sclp_mem_mutex);
+       return rc ? NOTIFY_BAD : NOTIFY_OK;
+}
+
+static struct notifier_block sclp_mem_nb = {
+       .notifier_call = sclp_mem_notifier,
+};
+
+static void __init add_memory_merged(u16 rn)
+{
+       static u16 first_rn, num;
+       unsigned long long start, size;
+
+       if (rn && first_rn && (first_rn + num == rn)) {
+               num++;
+               return;
+       }
+       if (!first_rn)
+               goto skip_add;
+       start = rn2addr(first_rn);
+       size = (unsigned long long ) num * rzm;
+       if (start >= VMEM_MAX_PHYS)
+               goto skip_add;
+       if (start + size > VMEM_MAX_PHYS)
+               size = VMEM_MAX_PHYS - start;
+       add_memory(0, start, size);
+skip_add:
+       first_rn = rn;
+       num = 1;
+}
+
+static void __init sclp_add_standby_memory(void)
+{
+       struct memory_increment *incr;
+
+       list_for_each_entry(incr, &sclp_mem_list, list)
+               if (incr->standby)
+                       add_memory_merged(incr->rn);
+       add_memory_merged(0);
+}
+
+static void __init insert_increment(u16 rn, int standby, int assigned)
+{
+       struct memory_increment *incr, *new_incr;
+       struct list_head *prev;
+       u16 last_rn;
+
+       new_incr = kzalloc(sizeof(*new_incr), GFP_KERNEL);
+       if (!new_incr)
+               return;
+       new_incr->rn = rn;
+       new_incr->standby = standby;
+       last_rn = 0;
+       prev = &sclp_mem_list;
+       list_for_each_entry(incr, &sclp_mem_list, list) {
+               if (assigned && incr->rn > rn)
+                       break;
+               if (!assigned && incr->rn - last_rn > 1)
+                       break;
+               last_rn = incr->rn;
+               prev = &incr->list;
+       }
+       if (!assigned)
+               new_incr->rn = last_rn + 1;
+       if (new_incr->rn > rnmax) {
+               kfree(new_incr);
+               return;
+       }
+       list_add(&new_incr->list, prev);
+}
+
+struct read_storage_sccb {
+       struct sccb_header header;
+       u16 max_id;
+       u16 assigned;
+       u16 standby;
+       u16 :16;
+       u32 entries[0];
+} __packed;
+
+static int __init sclp_detect_standby_memory(void)
+{
+       struct read_storage_sccb *sccb;
+       int i, id, assigned, rc;
+
+       if (!early_read_info_sccb_valid)
+               return 0;
+       if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL)
+               return 0;
+       rc = -ENOMEM;
+       sccb = (void *) __get_free_page(GFP_KERNEL | GFP_DMA);
+       if (!sccb)
+               goto out;
+       assigned = 0;
+       for (id = 0; id <= sclp_max_storage_id; id++) {
+               memset(sccb, 0, PAGE_SIZE);
+               sccb->header.length = PAGE_SIZE;
+               rc = do_sync_request(0x00040001 | id << 8, sccb);
+               if (rc)
+                       goto out;
+               switch (sccb->header.response_code) {
+               case 0x0010:
+                       set_bit(id, sclp_storage_ids);
+                       for (i = 0; i < sccb->assigned; i++) {
+                               if (!sccb->entries[i])
+                                       continue;
+                               assigned++;
+                               insert_increment(sccb->entries[i] >> 16, 0, 1);
+                       }
+                       break;
+               case 0x0310:
+                       break;
+               case 0x0410:
+                       for (i = 0; i < sccb->assigned; i++) {
+                               if (!sccb->entries[i])
+                                       continue;
+                               assigned++;
+                               insert_increment(sccb->entries[i] >> 16, 1, 1);
+                       }
+                       break;
+               default:
+                       rc = -EIO;
+                       break;
+               }
+               if (!rc)
+                       sclp_max_storage_id = sccb->max_id;
+       }
+       if (rc || list_empty(&sclp_mem_list))
+               goto out;
+       for (i = 1; i <= rnmax - assigned; i++)
+               insert_increment(0, 1, 0);
+       rc = register_memory_notifier(&sclp_mem_nb);
+       if (rc)
+               goto out;
+       sclp_add_standby_memory();
+out:
+       free_page((unsigned long) sccb);
+       return rc;
+}
+__initcall(sclp_detect_standby_memory);
+
+#endif /* CONFIG_MEMORY_HOTPLUG */
+
 /*
  * Channel path configuration related functions.
  */
index ead1043d788ec3338525f83ed9655a8fec5c9072..7e619c534bf46ed7e3078dfcd3a0c44738e427bd 100644 (file)
 #include <linux/timer.h>
 #include <linux/jiffies.h>
 #include <linux/bootmem.h>
+#include <linux/termios.h>
 #include <linux/err.h>
 
 #include "sclp.h"
 #include "sclp_rw.h"
 #include "sclp_tty.h"
 
-#define SCLP_CON_PRINT_HEADER "sclp console driver: "
-
 #define sclp_console_major 4           /* TTYAUX_MAJOR */
 #define sclp_console_minor 64
 #define sclp_console_name  "ttyS"
@@ -222,8 +221,6 @@ sclp_console_init(void)
        INIT_LIST_HEAD(&sclp_con_pages);
        for (i = 0; i < MAX_CONSOLE_PAGES; i++) {
                page = alloc_bootmem_low_pages(PAGE_SIZE);
-               if (page == NULL)
-                       return -ENOMEM;
                list_add_tail((struct list_head *) page, &sclp_con_pages);
        }
        INIT_LIST_HEAD(&sclp_con_outqueue);
index ad05a87bc480b14531fdd5570f78c2dc3f93c9c5..fff4ff485d9bcbb8e3bc25c05d465b8214f8774b 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/cpu.h>
+#include <linux/kthread.h>
 #include <linux/sysdev.h>
 #include <linux/workqueue.h>
 #include <asm/smp.h>
@@ -40,9 +41,19 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
        put_online_cpus();
 }
 
-static void __ref sclp_cpu_change_notify(struct work_struct *work)
+static int sclp_cpu_kthread(void *data)
 {
        smp_rescan_cpus();
+       return 0;
+}
+
+static void __ref sclp_cpu_change_notify(struct work_struct *work)
+{
+       /* Can't call smp_rescan_cpus() from  workqueue context since it may
+        * deadlock in case of cpu hotplug. So we have to create a kernel
+        * thread in order to call it.
+        */
+       kthread_run(sclp_cpu_kthread, NULL, "cpu_rescan");
 }
 
 static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
@@ -74,10 +85,8 @@ static int __init sclp_conf_init(void)
        INIT_WORK(&sclp_cpu_change_work, sclp_cpu_change_notify);
 
        rc = sclp_register(&sclp_conf_register);
-       if (rc) {
-               printk(KERN_ERR TAG "failed to register (%d).\n", rc);
+       if (rc)
                return rc;
-       }
 
        if (!(sclp_conf_register.sclp_send_mask & EVTYP_CONFMGMDATA_MASK)) {
                printk(KERN_WARNING TAG "no configuration management.\n");
index 9f37456222e9bde478386ea921e7cba393c7fa2d..d887bd261d28e2029847213d1f6e017ed41dd06f 100644 (file)
@@ -27,6 +27,8 @@
 #define CPI_LENGTH_NAME 8
 #define CPI_LENGTH_LEVEL 16
 
+static DEFINE_MUTEX(sclp_cpi_mutex);
+
 struct cpi_evbuf {
        struct evbuf_header header;
        u8      id_format;
@@ -124,21 +126,15 @@ static int cpi_req(void)
        int response;
 
        rc = sclp_register(&sclp_cpi_event);
-       if (rc) {
-               printk(KERN_WARNING "cpi: could not register "
-                       "to hardware console.\n");
+       if (rc)
                goto out;
-       }
        if (!(sclp_cpi_event.sclp_receive_mask & EVTYP_CTLPROGIDENT_MASK)) {
-               printk(KERN_WARNING "cpi: no control program "
-                       "identification support\n");
                rc = -EOPNOTSUPP;
                goto out_unregister;
        }
 
        req = cpi_prepare_req();
        if (IS_ERR(req)) {
-               printk(KERN_WARNING "cpi: could not allocate request\n");
                rc = PTR_ERR(req);
                goto out_unregister;
        }
@@ -148,10 +144,8 @@ static int cpi_req(void)
 
        /* Add request to sclp queue */
        rc = sclp_add_request(req);
-       if (rc) {
-               printk(KERN_WARNING "cpi: could not start request\n");
+       if (rc)
                goto out_free_req;
-       }
 
        wait_for_completion(&completion);
 
@@ -223,7 +217,12 @@ static void set_string(char *attr, const char *value)
 static ssize_t system_name_show(struct kobject *kobj,
                                struct kobj_attribute *attr, char *page)
 {
-       return snprintf(page, PAGE_SIZE, "%s\n", system_name);
+       int rc;
+
+       mutex_lock(&sclp_cpi_mutex);
+       rc = snprintf(page, PAGE_SIZE, "%s\n", system_name);
+       mutex_unlock(&sclp_cpi_mutex);
+       return rc;
 }
 
 static ssize_t system_name_store(struct kobject *kobj,
@@ -237,7 +236,9 @@ static ssize_t system_name_store(struct kobject *kobj,
        if (rc)
                return rc;
 
+       mutex_lock(&sclp_cpi_mutex);
        set_string(system_name, buf);
+       mutex_unlock(&sclp_cpi_mutex);
 
        return len;
 }
@@ -248,7 +249,12 @@ static struct kobj_attribute system_name_attr =
 static ssize_t sysplex_name_show(struct kobject *kobj,
                                 struct kobj_attribute *attr, char *page)
 {
-       return snprintf(page, PAGE_SIZE, "%s\n", sysplex_name);
+       int rc;
+
+       mutex_lock(&sclp_cpi_mutex);
+       rc = snprintf(page, PAGE_SIZE, "%s\n", sysplex_name);
+       mutex_unlock(&sclp_cpi_mutex);
+       return rc;
 }
 
 static ssize_t sysplex_name_store(struct kobject *kobj,
@@ -262,7 +268,9 @@ static ssize_t sysplex_name_store(struct kobject *kobj,
        if (rc)
                return rc;
 
+       mutex_lock(&sclp_cpi_mutex);
        set_string(sysplex_name, buf);
+       mutex_unlock(&sclp_cpi_mutex);
 
        return len;
 }
@@ -273,7 +281,12 @@ static struct kobj_attribute sysplex_name_attr =
 static ssize_t system_type_show(struct kobject *kobj,
                                struct kobj_attribute *attr, char *page)
 {
-       return snprintf(page, PAGE_SIZE, "%s\n", system_type);
+       int rc;
+
+       mutex_lock(&sclp_cpi_mutex);
+       rc = snprintf(page, PAGE_SIZE, "%s\n", system_type);
+       mutex_unlock(&sclp_cpi_mutex);
+       return rc;
 }
 
 static ssize_t system_type_store(struct kobject *kobj,
@@ -287,7 +300,9 @@ static ssize_t system_type_store(struct kobject *kobj,
        if (rc)
                return rc;
 
+       mutex_lock(&sclp_cpi_mutex);
        set_string(system_type, buf);
+       mutex_unlock(&sclp_cpi_mutex);
 
        return len;
 }
@@ -298,8 +313,11 @@ static struct kobj_attribute system_type_attr =
 static ssize_t system_level_show(struct kobject *kobj,
                                 struct kobj_attribute *attr, char *page)
 {
-       unsigned long long level = system_level;
+       unsigned long long level;
 
+       mutex_lock(&sclp_cpi_mutex);
+       level = system_level;
+       mutex_unlock(&sclp_cpi_mutex);
        return snprintf(page, PAGE_SIZE, "%#018llx\n", level);
 }
 
@@ -320,8 +338,9 @@ static ssize_t system_level_store(struct kobject *kobj,
        if (*endp)
                return -EINVAL;
 
+       mutex_lock(&sclp_cpi_mutex);
        system_level = level;
-
+       mutex_unlock(&sclp_cpi_mutex);
        return len;
 }
 
@@ -334,7 +353,9 @@ static ssize_t set_store(struct kobject *kobj,
 {
        int rc;
 
+       mutex_lock(&sclp_cpi_mutex);
        rc = cpi_req();
+       mutex_unlock(&sclp_cpi_mutex);
        if (rc)
                return rc;
 
@@ -373,12 +394,16 @@ int sclp_cpi_set_data(const char *system, const char *sysplex, const char *type,
        if (rc)
                return rc;
 
+       mutex_lock(&sclp_cpi_mutex);
        set_string(system_name, system);
        set_string(sysplex_name, sysplex);
        set_string(system_type, type);
        system_level = level;
 
-       return cpi_req();
+       rc = cpi_req();
+       mutex_unlock(&sclp_cpi_mutex);
+
+       return rc;
 }
 EXPORT_SYMBOL(sclp_cpi_set_data);
 
index 45ff25e787cbdad96659617eee981d6854e02700..84c191c1cd620fa1e5a723dcb060f9a8d4ae9175 100644 (file)
@@ -51,13 +51,7 @@ static struct sclp_register sclp_quiesce_event = {
 static int __init
 sclp_quiesce_init(void)
 {
-       int rc;
-
-       rc = sclp_register(&sclp_quiesce_event);
-       if (rc)
-               printk(KERN_WARNING "sclp: could not register quiesce handler "
-                      "(rc=%d)\n", rc);
-       return rc;
+       return sclp_register(&sclp_quiesce_event);
 }
 
 module_init(sclp_quiesce_init);
index da09781b32f7b0959441c2d6a4a544319d284edf..710af42603f80f7866b2d3be13e7ebaff14ce166 100644 (file)
@@ -19,8 +19,6 @@
 #include "sclp.h"
 #include "sclp_rw.h"
 
-#define SCLP_RW_PRINT_HEADER "sclp low level driver: "
-
 /*
  * The room for the SCCB (only for writing) is not equal to a pages size
  * (as it is specified as the maximum size in the SCLP documentation)
index 1c064976b32bd322a4e4554e9d335bf1cef71328..8b854857ba0733eb5a8a56a9451318a8d383603c 100644 (file)
@@ -239,10 +239,8 @@ int __init sclp_sdias_init(void)
        debug_register_view(sdias_dbf, &debug_sprintf_view);
        debug_set_level(sdias_dbf, 6);
        rc = sclp_register(&sclp_sdias_register);
-       if (rc) {
-               ERROR_MSG("sclp register failed\n");
+       if (rc)
                return rc;
-       }
        init_waitqueue_head(&sdias_wq);
        TRACE("init done\n");
        return 0;
index 40b11521cd20246ee308a34c92909f7c849058e9..434ba04b1309529e0e0959eea440a074085a5535 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/wait.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/init.h>
@@ -25,8 +24,6 @@
 #include "sclp_rw.h"
 #include "sclp_tty.h"
 
-#define SCLP_TTY_PRINT_HEADER "sclp tty driver: "
-
 /*
  * size of a buffer that collects single characters coming in
  * via sclp_tty_put_char()
@@ -50,8 +47,6 @@ static int sclp_tty_buffer_count;
 static struct sclp_buffer *sclp_ttybuf;
 /* Timer for delayed output of console messages. */
 static struct timer_list sclp_tty_timer;
-/* Waitqueue to wait for buffers to get empty. */
-static wait_queue_head_t sclp_tty_waitq;
 
 static struct tty_struct *sclp_tty;
 static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE];
@@ -59,19 +54,11 @@ static unsigned short int sclp_tty_chars_count;
 
 struct tty_driver *sclp_tty_driver;
 
-static struct sclp_ioctls sclp_ioctls;
-static struct sclp_ioctls sclp_ioctls_init =
-{
-       8,                      /* 1 hor. tab. = 8 spaces */
-       0,                      /* no echo of input by this driver */
-       80,                     /* 80 characters/line */
-       1,                      /* write after 1/10 s without final new line */
-       MAX_KMEM_PAGES,         /* quick fix: avoid __alloc_pages */
-       MAX_KMEM_PAGES,         /* take 32/64 pages from kernel memory, */
-       0,                      /* do not convert to lower case */
-       0x6c                    /* to seprate upper and lower case */
-                               /* ('%' in EBCDIC) */
-};
+static int sclp_tty_tolower;
+static int sclp_tty_columns = 80;
+
+#define SPACES_PER_TAB 8
+#define CASE_DELIMITER 0x6c /* to separate upper and lower case (% in EBCDIC) */
 
 /* This routine is called whenever we try to open a SCLP terminal. */
 static int
@@ -92,136 +79,6 @@ sclp_tty_close(struct tty_struct *tty, struct file *filp)
        sclp_tty = NULL;
 }
 
-/* execute commands to control the i/o behaviour of the SCLP tty at runtime */
-static int
-sclp_tty_ioctl(struct tty_struct *tty, struct file * file,
-              unsigned int cmd, unsigned long arg)
-{
-       unsigned long flags;
-       unsigned int obuf;
-       int check;
-       int rc;
-
-       if (tty->flags & (1 << TTY_IO_ERROR))
-               return -EIO;
-       rc = 0;
-       check = 0;
-       switch (cmd) {
-       case TIOCSCLPSHTAB:
-               /* set width of horizontal tab  */
-               if (get_user(sclp_ioctls.htab, (unsigned short __user *) arg))
-                       rc = -EFAULT;
-               else
-                       check = 1;
-               break;
-       case TIOCSCLPGHTAB:
-               /* get width of horizontal tab  */
-               if (put_user(sclp_ioctls.htab, (unsigned short __user *) arg))
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPSECHO:
-               /* enable/disable echo of input */
-               if (get_user(sclp_ioctls.echo, (unsigned char __user *) arg))
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPGECHO:
-               /* Is echo of input enabled ?  */
-               if (put_user(sclp_ioctls.echo, (unsigned char __user *) arg))
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPSCOLS:
-               /* set number of columns for output  */
-               if (get_user(sclp_ioctls.columns, (unsigned short __user *) arg))
-                       rc = -EFAULT;
-               else
-                       check = 1;
-               break;
-       case TIOCSCLPGCOLS:
-               /* get number of columns for output  */
-               if (put_user(sclp_ioctls.columns, (unsigned short __user *) arg))
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPSNL:
-               /* enable/disable writing without final new line character  */
-               if (get_user(sclp_ioctls.final_nl, (signed char __user *) arg))
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPGNL:
-               /* Is writing without final new line character enabled ?  */
-               if (put_user(sclp_ioctls.final_nl, (signed char __user *) arg))
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPSOBUF:
-               /*
-                * set the maximum buffers size for output, will be rounded
-                * up to next 4kB boundary and stored as number of SCCBs
-                * (4kB Buffers) limitation: 256 x 4kB
-                */
-               if (get_user(obuf, (unsigned int __user *) arg) == 0) {
-                       if (obuf & 0xFFF)
-                               sclp_ioctls.max_sccb = (obuf >> 12) + 1;
-                       else
-                               sclp_ioctls.max_sccb = (obuf >> 12);
-               } else
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPGOBUF:
-               /* get the maximum buffers size for output  */
-               obuf = sclp_ioctls.max_sccb << 12;
-               if (put_user(obuf, (unsigned int __user *) arg))
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPGKBUF:
-               /* get the number of buffers got from kernel at startup */
-               if (put_user(sclp_ioctls.kmem_sccb, (unsigned short __user *) arg))
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPSCASE:
-               /* enable/disable conversion from upper to lower case */
-               if (get_user(sclp_ioctls.tolower, (unsigned char __user *) arg))
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPGCASE:
-               /* Is conversion from upper to lower case of input enabled? */
-               if (put_user(sclp_ioctls.tolower, (unsigned char __user *) arg))
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPSDELIM:
-               /*
-                * set special character used for separating upper and
-                * lower case, 0x00 disables this feature
-                */
-               if (get_user(sclp_ioctls.delim, (unsigned char __user *) arg))
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPGDELIM:
-               /*
-                * get special character used for separating upper and
-                * lower case, 0x00 disables this feature
-                */
-               if (put_user(sclp_ioctls.delim, (unsigned char __user *) arg))
-                       rc = -EFAULT;
-               break;
-       case TIOCSCLPSINIT:
-               /* set initial (default) sclp ioctls  */
-               sclp_ioctls = sclp_ioctls_init;
-               check = 1;
-               break;
-       default:
-               rc = -ENOIOCTLCMD;
-               break;
-       }
-       if (check) {
-               spin_lock_irqsave(&sclp_tty_lock, flags);
-               if (sclp_ttybuf != NULL) {
-                       sclp_set_htab(sclp_ttybuf, sclp_ioctls.htab);
-                       sclp_set_columns(sclp_ttybuf, sclp_ioctls.columns);
-               }
-               spin_unlock_irqrestore(&sclp_tty_lock, flags);
-       }
-       return rc;
-}
-
 /*
  * This routine returns the numbers of characters the tty driver
  * will accept for queuing to be written.  This number is subject
@@ -268,7 +125,6 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
                                            struct sclp_buffer, list);
                spin_unlock_irqrestore(&sclp_tty_lock, flags);
        } while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback));
-       wake_up(&sclp_tty_waitq);
        /* check if the tty needs a wake up call */
        if (sclp_tty != NULL) {
                tty_wakeup(sclp_tty);
@@ -316,37 +172,37 @@ sclp_tty_timeout(unsigned long data)
 /*
  * Write a string to the sclp tty.
  */
-static void
-sclp_tty_write_string(const unsigned char *str, int count)
+static int sclp_tty_write_string(const unsigned char *str, int count, int may_fail)
 {
        unsigned long flags;
        void *page;
        int written;
+       int overall_written;
        struct sclp_buffer *buf;
 
        if (count <= 0)
-               return;
+               return 0;
+       overall_written = 0;
        spin_lock_irqsave(&sclp_tty_lock, flags);
        do {
                /* Create a sclp output buffer if none exists yet */
                if (sclp_ttybuf == NULL) {
                        while (list_empty(&sclp_tty_pages)) {
                                spin_unlock_irqrestore(&sclp_tty_lock, flags);
-                               if (in_interrupt())
-                                       sclp_sync_wait();
+                               if (may_fail)
+                                       goto out;
                                else
-                                       wait_event(sclp_tty_waitq,
-                                               !list_empty(&sclp_tty_pages));
+                                       sclp_sync_wait();
                                spin_lock_irqsave(&sclp_tty_lock, flags);
                        }
                        page = sclp_tty_pages.next;
                        list_del((struct list_head *) page);
-                       sclp_ttybuf = sclp_make_buffer(page,
-                                                      sclp_ioctls.columns,
-                                                      sclp_ioctls.htab);
+                       sclp_ttybuf = sclp_make_buffer(page, sclp_tty_columns,
+                                                      SPACES_PER_TAB);
                }
                /* try to write the string to the current output buffer */
                written = sclp_write(sclp_ttybuf, str, count);
+               overall_written += written;
                if (written == count)
                        break;
                /*
@@ -363,27 +219,17 @@ sclp_tty_write_string(const unsigned char *str, int count)
                count -= written;
        } while (count > 0);
        /* Setup timer to output current console buffer after 1/10 second */
-       if (sclp_ioctls.final_nl) {
-               if (sclp_ttybuf != NULL &&
-                   sclp_chars_in_buffer(sclp_ttybuf) != 0 &&
-                   !timer_pending(&sclp_tty_timer)) {
-                       init_timer(&sclp_tty_timer);
-                       sclp_tty_timer.function = sclp_tty_timeout;
-                       sclp_tty_timer.data = 0UL;
-                       sclp_tty_timer.expires = jiffies + HZ/10;
-                       add_timer(&sclp_tty_timer);
-               }
-       } else {
-               if (sclp_ttybuf != NULL &&
-                   sclp_chars_in_buffer(sclp_ttybuf) != 0) {
-                       buf = sclp_ttybuf;
-                       sclp_ttybuf = NULL;
-                       spin_unlock_irqrestore(&sclp_tty_lock, flags);
-                       __sclp_ttybuf_emit(buf);
-                       spin_lock_irqsave(&sclp_tty_lock, flags);
-               }
+       if (sclp_ttybuf && sclp_chars_in_buffer(sclp_ttybuf) &&
+           !timer_pending(&sclp_tty_timer)) {
+               init_timer(&sclp_tty_timer);
+               sclp_tty_timer.function = sclp_tty_timeout;
+               sclp_tty_timer.data = 0UL;
+               sclp_tty_timer.expires = jiffies + HZ/10;
+               add_timer(&sclp_tty_timer);
        }
        spin_unlock_irqrestore(&sclp_tty_lock, flags);
+out:
+       return overall_written;
 }
 
 /*
@@ -395,11 +241,10 @@ static int
 sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
        if (sclp_tty_chars_count > 0) {
-               sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
+               sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
                sclp_tty_chars_count = 0;
        }
-       sclp_tty_write_string(buf, count);
-       return count;
+       return sclp_tty_write_string(buf, count, 1);
 }
 
 /*
@@ -417,9 +262,10 @@ sclp_tty_put_char(struct tty_struct *tty, unsigned char ch)
 {
        sclp_tty_chars[sclp_tty_chars_count++] = ch;
        if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) {
-               sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
+               sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
                sclp_tty_chars_count = 0;
-       } return 1;
+       }
+       return 1;
 }
 
 /*
@@ -430,7 +276,7 @@ static void
 sclp_tty_flush_chars(struct tty_struct *tty)
 {
        if (sclp_tty_chars_count > 0) {
-               sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
+               sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
                sclp_tty_chars_count = 0;
        }
 }
@@ -469,7 +315,7 @@ static void
 sclp_tty_flush_buffer(struct tty_struct *tty)
 {
        if (sclp_tty_chars_count > 0) {
-               sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
+               sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
                sclp_tty_chars_count = 0;
        }
 }
@@ -517,9 +363,7 @@ sclp_tty_input(unsigned char* buf, unsigned int count)
  * modifiy original string,
  * returns length of resulting string
  */
-static int
-sclp_switch_cases(unsigned char *buf, int count,
-                 unsigned char delim, int tolower)
+static int sclp_switch_cases(unsigned char *buf, int count)
 {
        unsigned char *ip, *op;
        int toggle;
@@ -529,9 +373,9 @@ sclp_switch_cases(unsigned char *buf, int count,
        ip = op = buf;
        while (count-- > 0) {
                /* compare with special character */
-               if (*ip == delim) {
+               if (*ip == CASE_DELIMITER) {
                        /* followed by another special character? */
-                       if (count && ip[1] == delim) {
+                       if (count && ip[1] == CASE_DELIMITER) {
                                /*
                                 * ... then put a single copy of the special
                                 * character to the output string
@@ -550,7 +394,7 @@ sclp_switch_cases(unsigned char *buf, int count,
                        /* not the special character */
                        if (toggle)
                                /* but case switching is on */
-                               if (tolower)
+                               if (sclp_tty_tolower)
                                        /* switch to uppercase */
                                        *op++ = _ebc_toupper[(int) *ip++];
                                else
@@ -570,30 +414,12 @@ sclp_get_input(unsigned char *start, unsigned char *end)
        int count;
 
        count = end - start;
-       /*
-        * if set in ioctl convert EBCDIC to lower case
-        * (modify original input in SCCB)
-        */
-       if (sclp_ioctls.tolower)
+       if (sclp_tty_tolower)
                EBC_TOLOWER(start, count);
-
-       /*
-        * if set in ioctl find out characters in lower or upper case
-        * (depends on current case) separated by a special character,
-        * works on EBCDIC
-        */
-       if (sclp_ioctls.delim)
-               count = sclp_switch_cases(start, count,
-                                         sclp_ioctls.delim,
-                                         sclp_ioctls.tolower);
-
+       count = sclp_switch_cases(start, count);
        /* convert EBCDIC to ASCII (modify original input in SCCB) */
        sclp_ebcasc_str(start, count);
 
-       /* if set in ioctl write operators input to console  */
-       if (sclp_ioctls.echo)
-               sclp_tty_write(sclp_tty, start, count);
-
        /* transfer input to high level driver */
        sclp_tty_input(start, count);
 }
@@ -717,7 +543,6 @@ static const struct tty_operations sclp_ops = {
        .write_room = sclp_tty_write_room,
        .chars_in_buffer = sclp_tty_chars_in_buffer,
        .flush_buffer = sclp_tty_flush_buffer,
-       .ioctl = sclp_tty_ioctl,
 };
 
 static int __init
@@ -736,9 +561,6 @@ sclp_tty_init(void)
 
        rc = sclp_rw_init();
        if (rc) {
-               printk(KERN_ERR SCLP_TTY_PRINT_HEADER
-                      "could not register tty - "
-                      "sclp_rw_init returned %d\n", rc);
                put_tty_driver(driver);
                return rc;
        }
@@ -754,7 +576,6 @@ sclp_tty_init(void)
        }
        INIT_LIST_HEAD(&sclp_tty_outqueue);
        spin_lock_init(&sclp_tty_lock);
-       init_waitqueue_head(&sclp_tty_waitq);
        init_timer(&sclp_tty_timer);
        sclp_ttybuf = NULL;
        sclp_tty_buffer_count = 0;
@@ -763,11 +584,10 @@ sclp_tty_init(void)
                 * save 4 characters for the CPU number
                 * written at start of each line by VM/CP
                 */
-               sclp_ioctls_init.columns = 76;
+               sclp_tty_columns = 76;
                /* case input lines to lowercase */
-               sclp_ioctls_init.tolower = 1;
+               sclp_tty_tolower = 1;
        }
-       sclp_ioctls = sclp_ioctls_init;
        sclp_tty_chars_count = 0;
        sclp_tty = NULL;
 
@@ -792,9 +612,6 @@ sclp_tty_init(void)
        tty_set_operations(driver, &sclp_ops);
        rc = tty_register_driver(driver);
        if (rc) {
-               printk(KERN_ERR SCLP_TTY_PRINT_HEADER
-                      "could not register tty - "
-                      "tty_register_driver returned %d\n", rc);
                put_tty_driver(driver);
                return rc;
        }
index 0ce2c1fc5340674bb1826a44028b8c1b9ec00bb6..4b965b22fecd7a24e375059d8cb0aa5b7f5c5d1b 100644 (file)
 #ifndef __SCLP_TTY_H__
 #define __SCLP_TTY_H__
 
-#include <linux/ioctl.h>
-#include <linux/termios.h>
 #include <linux/tty_driver.h>
 
-/* This is the type of data structures storing sclp ioctl setting. */
-struct sclp_ioctls {
-       unsigned short htab;
-       unsigned char echo;
-       unsigned short columns;
-       unsigned char final_nl;
-       unsigned short max_sccb;
-       unsigned short kmem_sccb;       /* can't be modified at run time */
-       unsigned char tolower;
-       unsigned char delim;
-};
-
-/* must be unique, FIXME: must be added in Documentation/ioctl_number.txt */
-#define SCLP_IOCTL_LETTER 'B'
-
-/* set width of horizontal tabulator */
-#define TIOCSCLPSHTAB  _IOW(SCLP_IOCTL_LETTER, 0, unsigned short)
-/* enable/disable echo of input (independent from line discipline) */
-#define TIOCSCLPSECHO  _IOW(SCLP_IOCTL_LETTER, 1, unsigned char)
-/* set number of colums for output */
-#define TIOCSCLPSCOLS  _IOW(SCLP_IOCTL_LETTER, 2, unsigned short)
-/* enable/disable writing without final new line character */
-#define TIOCSCLPSNL    _IOW(SCLP_IOCTL_LETTER, 4, signed char)
-/* set the maximum buffers size for output, rounded up to next 4kB boundary */
-#define TIOCSCLPSOBUF  _IOW(SCLP_IOCTL_LETTER, 5, unsigned short)
-/* set initial (default) sclp ioctls */
-#define TIOCSCLPSINIT  _IO(SCLP_IOCTL_LETTER, 6)
-/* enable/disable conversion from upper to lower case of input */
-#define TIOCSCLPSCASE  _IOW(SCLP_IOCTL_LETTER, 7, unsigned char)
-/* set special character used for separating upper and lower case, */
-/* 0x00 disables this feature */
-#define TIOCSCLPSDELIM _IOW(SCLP_IOCTL_LETTER, 9, unsigned char)
-
-/* get width of horizontal tabulator */
-#define TIOCSCLPGHTAB  _IOR(SCLP_IOCTL_LETTER, 10, unsigned short)
-/* Is echo of input enabled ? (independent from line discipline) */
-#define TIOCSCLPGECHO  _IOR(SCLP_IOCTL_LETTER, 11, unsigned char)
-/* get number of colums for output */
-#define TIOCSCLPGCOLS  _IOR(SCLP_IOCTL_LETTER, 12, unsigned short)
-/* Is writing without final new line character enabled ? */
-#define TIOCSCLPGNL    _IOR(SCLP_IOCTL_LETTER, 14, signed char)
-/* get the maximum buffers size for output */
-#define TIOCSCLPGOBUF  _IOR(SCLP_IOCTL_LETTER, 15, unsigned short)
-/* Is conversion from upper to lower case of input enabled ? */
-#define TIOCSCLPGCASE  _IOR(SCLP_IOCTL_LETTER, 17, unsigned char)
-/* get special character used for separating upper and lower case, */
-/* 0x00 disables this feature */
-#define TIOCSCLPGDELIM _IOR(SCLP_IOCTL_LETTER, 19, unsigned char)
-/* get the number of buffers/pages got from kernel at startup */
-#define TIOCSCLPGKBUF  _IOR(SCLP_IOCTL_LETTER, 20, unsigned short)
-
 extern struct tty_driver *sclp_tty_driver;
 
 #endif /* __SCLP_TTY_H__ */
index 3e577f655b18dec1cd7cf24cdf3b88c155bc6783..ad51738c4261973a7f4fb8b74296dc5dcc17bb85 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/uaccess.h>
 #include "sclp.h"
 
-#define SCLP_VT220_PRINT_HEADER        "sclp vt220 tty driver: "
 #define SCLP_VT220_MAJOR               TTY_MAJOR
 #define SCLP_VT220_MINOR               65
 #define SCLP_VT220_DRIVER_NAME         "sclp_vt220"
@@ -82,8 +81,8 @@ static struct sclp_vt220_request *sclp_vt220_current_request;
 /* Number of characters in current request buffer */
 static int sclp_vt220_buffered_chars;
 
-/* Flag indicating whether this driver has already been initialized */
-static int sclp_vt220_initialized = 0;
+/* Counter controlling core driver initialization. */
+static int __initdata sclp_vt220_init_count;
 
 /* Flag indicating that sclp_vt220_current_request should really
  * have been already queued but wasn't because the SCLP was processing
@@ -609,10 +608,8 @@ sclp_vt220_flush_buffer(struct tty_struct *tty)
        sclp_vt220_emit_current();
 }
 
-/*
- * Initialize all relevant components and register driver with system.
- */
-static void __init __sclp_vt220_cleanup(void)
+/* Release allocated pages. */
+static void __init __sclp_vt220_free_pages(void)
 {
        struct list_head *page, *p;
 
@@ -623,21 +620,30 @@ static void __init __sclp_vt220_cleanup(void)
                else
                        free_bootmem((unsigned long) page, PAGE_SIZE);
        }
-       if (!list_empty(&sclp_vt220_register.list))
-               sclp_unregister(&sclp_vt220_register);
-       sclp_vt220_initialized = 0;
 }
 
-static int __init __sclp_vt220_init(void)
+/* Release memory and unregister from sclp core. Controlled by init counting -
+ * only the last invoker will actually perform these actions. */
+static void __init __sclp_vt220_cleanup(void)
+{
+       sclp_vt220_init_count--;
+       if (sclp_vt220_init_count != 0)
+               return;
+       sclp_unregister(&sclp_vt220_register);
+       __sclp_vt220_free_pages();
+}
+
+/* Allocate buffer pages and register with sclp core. Controlled by init
+ * counting - only the first invoker will actually perform these actions. */
+static int __init __sclp_vt220_init(int num_pages)
 {
        void *page;
        int i;
-       int num_pages;
        int rc;
 
-       if (sclp_vt220_initialized)
+       sclp_vt220_init_count++;
+       if (sclp_vt220_init_count != 1)
                return 0;
-       sclp_vt220_initialized = 1;
        spin_lock_init(&sclp_vt220_lock);
        INIT_LIST_HEAD(&sclp_vt220_empty);
        INIT_LIST_HEAD(&sclp_vt220_outqueue);
@@ -649,24 +655,22 @@ static int __init __sclp_vt220_init(void)
        sclp_vt220_flush_later = 0;
 
        /* Allocate pages for output buffering */
-       num_pages = slab_is_available() ? MAX_KMEM_PAGES : MAX_CONSOLE_PAGES;
        for (i = 0; i < num_pages; i++) {
                if (slab_is_available())
                        page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
                else
                        page = alloc_bootmem_low_pages(PAGE_SIZE);
                if (!page) {
-                       __sclp_vt220_cleanup();
-                       return -ENOMEM;
+                       rc = -ENOMEM;
+                       goto out;
                }
                list_add_tail((struct list_head *) page, &sclp_vt220_empty);
        }
        rc = sclp_register(&sclp_vt220_register);
+out:
        if (rc) {
-               printk(KERN_ERR SCLP_VT220_PRINT_HEADER
-                      "could not register vt220 - "
-                      "sclp_register returned %d\n", rc);
-               __sclp_vt220_cleanup();
+               __sclp_vt220_free_pages();
+               sclp_vt220_init_count--;
        }
        return rc;
 }
@@ -689,15 +693,13 @@ static int __init sclp_vt220_tty_init(void)
 {
        struct tty_driver *driver;
        int rc;
-       int cleanup;
 
        /* Note: we're not testing for CONSOLE_IS_SCLP here to preserve
         * symmetry between VM and LPAR systems regarding ttyS1. */
        driver = alloc_tty_driver(1);
        if (!driver)
                return -ENOMEM;
-       cleanup = !sclp_vt220_initialized;
-       rc = __sclp_vt220_init();
+       rc = __sclp_vt220_init(MAX_KMEM_PAGES);
        if (rc)
                goto out_driver;
 
@@ -713,18 +715,13 @@ static int __init sclp_vt220_tty_init(void)
        tty_set_operations(driver, &sclp_vt220_ops);
 
        rc = tty_register_driver(driver);
-       if (rc) {
-               printk(KERN_ERR SCLP_VT220_PRINT_HEADER
-                      "could not register tty - "
-                      "tty_register_driver returned %d\n", rc);
+       if (rc)
                goto out_init;
-       }
        sclp_vt220_driver = driver;
        return 0;
 
 out_init:
-       if (cleanup)
-               __sclp_vt220_cleanup();
+       __sclp_vt220_cleanup();
 out_driver:
        put_tty_driver(driver);
        return rc;
@@ -773,10 +770,9 @@ sclp_vt220_con_init(void)
 {
        int rc;
 
-       INIT_LIST_HEAD(&sclp_vt220_register.list);
        if (!CONSOLE_IS_SCLP)
                return 0;
-       rc = __sclp_vt220_init();
+       rc = __sclp_vt220_init(MAX_CONSOLE_PAGES);
        if (rc)
                return rc;
        /* Attach linux console */
index 874adf365e467a4f9d1bce3c89bd27b718a54461..22ca34361ed7711e15eb9a7c5688970aab46b81d 100644 (file)
@@ -196,7 +196,7 @@ tape_34xx_erp_retry(struct tape_request *request)
 static int
 tape_34xx_unsolicited_irq(struct tape_device *device, struct irb *irb)
 {
-       if (irb->scsw.dstat == 0x85 /* READY */) {
+       if (irb->scsw.cmd.dstat == 0x85) { /* READY */
                /* A medium was inserted in the drive. */
                DBF_EVENT(6, "xuud med\n");
                tape_34xx_delete_sbid_from(device, 0);
@@ -844,22 +844,22 @@ tape_34xx_irq(struct tape_device *device, struct tape_request *request,
        if (request == NULL)
                return tape_34xx_unsolicited_irq(device, irb);
 
-       if ((irb->scsw.dstat & DEV_STAT_UNIT_EXCEP) &&
-           (irb->scsw.dstat & DEV_STAT_DEV_END) &&
+       if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) &&
+           (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) &&
            (request->op == TO_WRI)) {
                /* Write at end of volume */
                PRINT_INFO("End of volume\n"); /* XXX */
                return tape_34xx_erp_failed(request, -ENOSPC);
        }
 
-       if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK)
+       if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
                return tape_34xx_unit_check(device, request, irb);
 
-       if (irb->scsw.dstat & DEV_STAT_DEV_END) {
+       if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
                /*
                 * A unit exception occurs on skipping over a tapemark block.
                 */
-               if (irb->scsw.dstat & DEV_STAT_UNIT_EXCEP) {
+               if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) {
                        if (request->op == TO_BSB || request->op == TO_FSB)
                                request->rescnt++;
                        else
index 42ce7915fc5d7cc1bce71aaa60c867f12cb16894..839987618ffd8d545538626733b4c0ca1205c8ce 100644 (file)
@@ -837,13 +837,13 @@ tape_3590_erp_retry(struct tape_device *device, struct tape_request *request,
 static int
 tape_3590_unsolicited_irq(struct tape_device *device, struct irb *irb)
 {
-       if (irb->scsw.dstat == DEV_STAT_CHN_END)
+       if (irb->scsw.cmd.dstat == DEV_STAT_CHN_END)
                /* Probably result of halt ssch */
                return TAPE_IO_PENDING;
-       else if (irb->scsw.dstat == 0x85)
+       else if (irb->scsw.cmd.dstat == 0x85)
                /* Device Ready */
                DBF_EVENT(3, "unsol.irq! tape ready: %08x\n", device->cdev_id);
-       else if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
+       else if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
                tape_3590_schedule_work(device, TO_READ_ATTMSG);
        } else {
                DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id);
@@ -1515,18 +1515,19 @@ tape_3590_irq(struct tape_device *device, struct tape_request *request,
        if (request == NULL)
                return tape_3590_unsolicited_irq(device, irb);
 
-       if ((irb->scsw.dstat & DEV_STAT_UNIT_EXCEP) &&
-           (irb->scsw.dstat & DEV_STAT_DEV_END) && (request->op == TO_WRI)) {
+       if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) &&
+           (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) &&
+           (request->op == TO_WRI)) {
                /* Write at end of volume */
                DBF_EVENT(2, "End of volume\n");
                return tape_3590_erp_failed(device, request, irb, -ENOSPC);
        }
 
-       if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK)
+       if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
                return tape_3590_unit_check(device, request, irb);
 
-       if (irb->scsw.dstat & DEV_STAT_DEV_END) {
-               if (irb->scsw.dstat == DEV_STAT_UNIT_EXCEP) {
+       if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
+               if (irb->scsw.cmd.dstat == DEV_STAT_UNIT_EXCEP) {
                        if (request->op == TO_FSB || request->op == TO_BSB)
                                request->rescnt++;
                        else
@@ -1536,12 +1537,12 @@ tape_3590_irq(struct tape_device *device, struct tape_request *request,
                return tape_3590_done(device, request);
        }
 
-       if (irb->scsw.dstat & DEV_STAT_CHN_END) {
+       if (irb->scsw.cmd.dstat & DEV_STAT_CHN_END) {
                DBF_EVENT(2, "cannel end\n");
                return TAPE_IO_PENDING;
        }
 
-       if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
+       if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
                DBF_EVENT(2, "Unit Attention when busy..\n");
                return TAPE_IO_PENDING;
        }
index c20e3c548343aa7f3b43c56d57d94f1ab6c5e441..181a5441af16f92dad8b1c0bba954ca5bbefca51 100644 (file)
@@ -839,7 +839,7 @@ tape_dump_sense(struct tape_device* device, struct tape_request *request,
 
        PRINT_INFO("-------------------------------------------------\n");
        PRINT_INFO("DSTAT : %02x  CSTAT: %02x   CPA: %04x\n",
-                  irb->scsw.dstat, irb->scsw.cstat, irb->scsw.cpa);
+                  irb->scsw.cmd.dstat, irb->scsw.cmd.cstat, irb->scsw.cmd.cpa);
        PRINT_INFO("DEVICE: %s\n", device->cdev->dev.bus_id);
        if (request != NULL)
                PRINT_INFO("OP    : %s\n", tape_op_verbose[request->op]);
@@ -867,7 +867,7 @@ tape_dump_sense_dbf(struct tape_device *device, struct tape_request *request,
        else
                op = "---";
        DBF_EVENT(3, "DSTAT : %02x   CSTAT: %02x\n",
-                 irb->scsw.dstat,irb->scsw.cstat);
+                 irb->scsw.cmd.dstat, irb->scsw.cmd.cstat);
        DBF_EVENT(3, "DEVICE: %08x OP\t: %s\n", device->cdev_id, op);
        sptr = (unsigned int *) irb->ecw;
        DBF_EVENT(3, "%08x %08x\n", sptr[0], sptr[1]);
@@ -1083,10 +1083,11 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
         * error might still apply. So we just schedule the request to be
         * started later.
         */
-       if (irb->scsw.cc != 0 && (irb->scsw.fctl & SCSW_FCTL_START_FUNC) &&
+       if (irb->scsw.cmd.cc != 0 &&
+           (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) &&
            (request->status == TAPE_REQUEST_IN_IO)) {
                DBF_EVENT(3,"(%08x): deferred cc=%i, fctl=%i. restarting\n",
-                       device->cdev_id, irb->scsw.cc, irb->scsw.fctl);
+                       device->cdev_id, irb->scsw.cmd.cc, irb->scsw.cmd.fctl);
                request->status = TAPE_REQUEST_QUEUED;
                schedule_delayed_work(&device->tape_dnr, HZ);
                return;
@@ -1094,8 +1095,8 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
 
        /* May be an unsolicited irq */
        if(request != NULL)
-               request->rescnt = irb->scsw.count;
-       else if ((irb->scsw.dstat == 0x85 || irb->scsw.dstat == 0x80) &&
+               request->rescnt = irb->scsw.cmd.count;
+       else if ((irb->scsw.cmd.dstat == 0x85 || irb->scsw.cmd.dstat == 0x80) &&
                 !list_empty(&device->req_queue)) {
                /* Not Ready to Ready after long busy ? */
                struct tape_request *req;
@@ -1111,7 +1112,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                        return;
                }
        }
-       if (irb->scsw.dstat != 0x0c) {
+       if (irb->scsw.cmd.dstat != 0x0c) {
                /* Set the 'ONLINE' flag depending on sense byte 1 */
                if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE)
                        device->tape_generic_status |= GMT_ONLINE(~0);
index 5043150019ac0788e91d4a42ee1d49955c99d527..a7fe6302c9820c3790f3c14bffb4f0aee4b35679 100644 (file)
@@ -663,7 +663,7 @@ static int
 tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb)
 {
        /* Handle ATTN. Schedule tasklet to read aid. */
-       if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
+       if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
                if (!tp->throttle)
                        tty3270_issue_read(tp, 0);
                else
@@ -671,11 +671,11 @@ tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb)
        }
 
        if (rq) {
-               if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK)
+               if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
                        rq->rc = -EIO;
                else
                        /* Normal end. Copy residual count. */
-                       rq->rescnt = irb->scsw.count;
+                       rq->rescnt = irb->scsw.cmd.count;
        }
        return RAW3270_IO_DONE;
 }
@@ -1792,15 +1792,12 @@ static int __init tty3270_init(void)
        tty_set_operations(driver, &tty3270_ops);
        ret = tty_register_driver(driver);
        if (ret) {
-               printk(KERN_ERR "tty3270 registration failed with %d\n", ret);
                put_tty_driver(driver);
                return ret;
        }
        tty3270_driver = driver;
        ret = raw3270_register_notifier(tty3270_notifier);
        if (ret) {
-               printk(KERN_ERR "tty3270 notifier registration failed "
-                      "with %d\n", ret);
                put_tty_driver(driver);
                return ret;
 
index 2f419b0ea628bf1dd47ca0385f54f95bbf808235..401ea84b3059f3e3e3f1a025233c23f3e9e78b8c 100644 (file)
@@ -61,30 +61,24 @@ static int vmcp_release(struct inode *inode, struct file *file)
 static ssize_t
 vmcp_read(struct file *file, char __user *buff, size_t count, loff_t *ppos)
 {
-       size_t tocopy;
+       ssize_t ret;
+       size_t size;
        struct vmcp_session *session;
 
-       session = (struct vmcp_session *)file->private_data;
+       session = file->private_data;
        if (mutex_lock_interruptible(&session->mutex))
                return -ERESTARTSYS;
        if (!session->response) {
                mutex_unlock(&session->mutex);
                return 0;
        }
-       if (*ppos > session->resp_size) {
-               mutex_unlock(&session->mutex);
-               return 0;
-       }
-       tocopy = min(session->resp_size - (size_t) (*ppos), count);
-       tocopy = min(tocopy, session->bufsize - (size_t) (*ppos));
+       size = min_t(size_t, session->resp_size, session->bufsize);
+       ret = simple_read_from_buffer(buff, count, ppos,
+                                       session->response, size);
 
-       if (copy_to_user(buff, session->response + (*ppos), tocopy)) {
-               mutex_unlock(&session->mutex);
-               return -EFAULT;
-       }
        mutex_unlock(&session->mutex);
-       *ppos += tocopy;
-       return tocopy;
+
+       return ret;
 }
 
 static ssize_t
@@ -198,27 +192,23 @@ static int __init vmcp_init(void)
                PRINT_WARN("z/VM CP interface is only available under z/VM\n");
                return -ENODEV;
        }
+
        vmcp_debug = debug_register("vmcp", 1, 1, 240);
-       if (!vmcp_debug) {
-               PRINT_ERR("z/VM CP interface not loaded. Could not register "
-                          "debug feature\n");
+       if (!vmcp_debug)
                return -ENOMEM;
-       }
+
        ret = debug_register_view(vmcp_debug, &debug_hex_ascii_view);
        if (ret) {
-               PRINT_ERR("z/VM CP interface not loaded. Could not register "
-                         "debug feature view. Error code: %d\n", ret);
                debug_unregister(vmcp_debug);
                return ret;
        }
+
        ret = misc_register(&vmcp_dev);
        if (ret) {
-               PRINT_ERR("z/VM CP interface not loaded. Could not register "
-                          "misc device. Error code: %d\n", ret);
                debug_unregister(vmcp_debug);
                return ret;
        }
-       PRINT_INFO("z/VM CP interface loaded\n");
+
        return 0;
 }
 
@@ -226,7 +216,6 @@ static void __exit vmcp_exit(void)
 {
        misc_deregister(&vmcp_dev);
        debug_unregister(vmcp_debug);
-       PRINT_INFO("z/VM CP interface unloaded.\n");
 }
 
 module_init(vmcp_init);
index 2c2428cc05d866efe26b9c288331ab6459afdeb0..a246bc73ae6430b5761a47ccc90305c7564da9e4 100644 (file)
@@ -216,9 +216,7 @@ static int vmlogrdr_get_recording_class_AB(void)
        char *tail;
        int len,i;
 
-       printk (KERN_DEBUG "vmlogrdr: query command: %s\n", cp_command);
        cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
-       printk (KERN_DEBUG "vmlogrdr: response: %s", cp_response);
        len = strnlen(cp_response,sizeof(cp_response));
        // now the parsing
        tail=strnchr(cp_response,len,'=');
@@ -268,11 +266,7 @@ static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr,
                         logptr->recording_name,
                         qid_string);
 
-               printk (KERN_DEBUG "vmlogrdr: recording command: %s\n",
-                       cp_command);
                cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
-               printk (KERN_DEBUG "vmlogrdr: recording response: %s",
-                       cp_response);
        }
 
        memset(cp_command, 0x00, sizeof(cp_command));
@@ -282,10 +276,7 @@ static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr,
                onoff,
                qid_string);
 
-       printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
        cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
-       printk (KERN_DEBUG "vmlogrdr: recording response: %s",
-               cp_response);
        /* The recording command will usually answer with 'Command complete'
         * on success, but when the specific service was never connected
         * before then there might be an additional informational message
@@ -567,10 +558,7 @@ static ssize_t vmlogrdr_purge_store(struct device * dev,
                         "RECORDING %s PURGE ",
                         priv->recording_name);
 
-       printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
        cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
-       printk (KERN_DEBUG "vmlogrdr: recording response: %s",
-               cp_response);
 
        return count;
 }
@@ -682,28 +670,20 @@ static int vmlogrdr_register_driver(void)
 
        /* Register with iucv driver */
        ret = iucv_register(&vmlogrdr_iucv_handler, 1);
-       if (ret) {
-               printk (KERN_ERR "vmlogrdr: failed to register with "
-                       "iucv driver\n");
+       if (ret)
                goto out;
-       }
 
        ret = driver_register(&vmlogrdr_driver);
-       if (ret) {
-               printk(KERN_ERR "vmlogrdr: failed to register driver.\n");
+       if (ret)
                goto out_iucv;
-       }
 
        ret = driver_create_file(&vmlogrdr_driver,
                                 &driver_attr_recording_status);
-       if (ret) {
-               printk(KERN_ERR "vmlogrdr: failed to add driver attribute.\n");
+       if (ret)
                goto out_driver;
-       }
 
        vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
        if (IS_ERR(vmlogrdr_class)) {
-               printk(KERN_ERR "vmlogrdr: failed to create class.\n");
                ret = PTR_ERR(vmlogrdr_class);
                vmlogrdr_class = NULL;
                goto out_attr;
@@ -871,12 +851,10 @@ static int __init vmlogrdr_init(void)
        rc = vmlogrdr_register_cdev(dev);
        if (rc)
                goto cleanup;
-       printk (KERN_INFO "vmlogrdr: driver loaded\n");
        return 0;
 
 cleanup:
        vmlogrdr_cleanup();
-       printk (KERN_ERR "vmlogrdr: driver not loaded.\n");
        return rc;
 }
 
@@ -884,7 +862,6 @@ cleanup:
 static void __exit vmlogrdr_exit(void)
 {
        vmlogrdr_cleanup();
-       printk (KERN_INFO "vmlogrdr: driver unloaded\n");
        return;
 }
 
index 83ae9a852f00c2dc5c4e2fc9be7eb81e974770de..49cba9effe892d2a1638a67a2ade3b4dddfc5550 100644 (file)
@@ -277,7 +277,8 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
        struct urdev *urd;
 
        TRACE("ur_int_handler: intparm=0x%lx cstat=%02x dstat=%02x res=%u\n",
-             intparm, irb->scsw.cstat, irb->scsw.dstat, irb->scsw.count);
+             intparm, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
+             irb->scsw.cmd.count);
 
        if (!intparm) {
                TRACE("ur_int_handler: unsolicited interrupt\n");
@@ -288,7 +289,7 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
        /* On special conditions irb is an error pointer */
        if (IS_ERR(irb))
                urd->io_request_rc = PTR_ERR(irb);
-       else if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+       else if (irb->scsw.cmd.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
                urd->io_request_rc = 0;
        else
                urd->io_request_rc = -EIO;
index 19f8389291b62c3f13b76eafde98ae03f1677666..56b3eab019cbddde76219ec3fb0bfa50406089aa 100644 (file)
@@ -92,23 +92,15 @@ static int vmwdt_keepalive(void)
 
        func = vmwdt_conceal ? (wdt_init | wdt_conceal) : wdt_init;
        ret = __diag288(func, vmwdt_interval, ebc_cmd, len);
+       WARN_ON(ret != 0);
        kfree(ebc_cmd);
-
-       if (ret) {
-               printk(KERN_WARNING "%s: problem setting interval %d, "
-                       "cmd %s\n", __func__, vmwdt_interval,
-                       vmwdt_cmd);
-       }
        return ret;
 }
 
 static int vmwdt_disable(void)
 {
        int ret = __diag288(wdt_cancel, 0, "", 0);
-       if (ret) {
-               printk(KERN_WARNING "%s: problem disabling watchdog\n",
-                       __func__);
-       }
+       WARN_ON(ret != 0);
        return ret;
 }
 
@@ -121,10 +113,8 @@ static int __init vmwdt_probe(void)
        static char __initdata ebc_begin[] = {
                194, 197, 199, 201, 213
        };
-       if (__diag288(wdt_init, 15, ebc_begin, sizeof(ebc_begin)) != 0) {
-               printk(KERN_INFO "z/VM watchdog not available\n");
+       if (__diag288(wdt_init, 15, ebc_begin, sizeof(ebc_begin)) != 0)
                return -EINVAL;
-       }
        return vmwdt_disable();
 }
 
index bbbd14e9d48f8a17a6bb9f3efd566d7781ff71c0..047dd92ae804505ed9e363e526060b1822a6f102 100644 (file)
@@ -223,12 +223,10 @@ static int __init init_cpu_info(enum arch_id arch)
        /* get info for boot cpu from lowcore, stored in the HSA */
 
        sa = kmalloc(sizeof(*sa), GFP_KERNEL);
-       if (!sa) {
-               ERROR_MSG("kmalloc failed: %s: %i\n",__func__, __LINE__);
+       if (!sa)
                return -ENOMEM;
-       }
        if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) {
-               ERROR_MSG("could not copy from HSA\n");
+               TRACE("could not copy from HSA\n");
                kfree(sa);
                return -EIO;
        }
@@ -511,6 +509,8 @@ static void __init set_s390x_lc_mask(union save_area *map)
  */
 static int __init sys_info_init(enum arch_id arch)
 {
+       int rc;
+
        switch (arch) {
        case ARCH_S390X:
                MSG("DETECTED 'S390X (64 bit) OS'\n");
@@ -529,10 +529,9 @@ static int __init sys_info_init(enum arch_id arch)
                return -EINVAL;
        }
        sys_info.arch = arch;
-       if (init_cpu_info(arch)) {
-               ERROR_MSG("get cpu info failed\n");
-               return -ENOMEM;
-       }
+       rc = init_cpu_info(arch);
+       if (rc)
+               return rc;
        sys_info.mem_size = real_memory_size;
 
        return 0;
@@ -544,12 +543,12 @@ static int __init check_sdias(void)
 
        rc = sclp_sdias_blk_count();
        if (rc < 0) {
-               ERROR_MSG("Could not determine HSA size\n");
+               TRACE("Could not determine HSA size\n");
                return rc;
        }
        act_hsa_size = (rc - 1) * PAGE_SIZE;
        if (act_hsa_size < ZFCPDUMP_HSA_SIZE) {
-               ERROR_MSG("HSA size too small: %i\n", act_hsa_size);
+               TRACE("HSA size too small: %i\n", act_hsa_size);
                return -EINVAL;
        }
        return 0;
@@ -590,16 +589,12 @@ static int __init zcore_init(void)
                goto fail;
 
        rc = check_sdias();
-       if (rc) {
-               ERROR_MSG("Dump initialization failed\n");
+       if (rc)
                goto fail;
-       }
 
        rc = memcpy_hsa_kernel(&arch, __LC_AR_MODE_ID, 1);
-       if (rc) {
-               ERROR_MSG("sdial memcpy for arch id failed\n");
+       if (rc)
                goto fail;
-       }
 
 #ifndef __s390x__
        if (arch == ARCH_S390X) {
@@ -610,10 +605,8 @@ static int __init zcore_init(void)
 #endif
 
        rc = sys_info_init(arch);
-       if (rc) {
-               ERROR_MSG("arch init failed\n");
+       if (rc)
                goto fail;
-       }
 
        zcore_header_init(arch, &zcore_header);
 
index cfaf77b320f5598d08d02067fe1ca79191eef0ab..91e9e3f3073af51b7ca4447a0143815dcc6fe9d8 100644 (file)
@@ -2,9 +2,11 @@
 # Makefile for the S/390 common i/o drivers
 #
 
-obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o
+obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o scsw.o \
+       fcx.o itcw.o
 ccw_device-objs += device.o device_fsm.o device_ops.o
 ccw_device-objs += device_id.o device_pgid.o device_status.o
 obj-y += ccw_device.o cmf.o
+obj-$(CONFIG_CHSC_SCH) += chsc_sch.o
 obj-$(CONFIG_CCWGROUP) += ccwgroup.o
 obj-$(CONFIG_QDIO) += qdio.o
index b7a07a866291624a30a3ba13fab6bce3eb6034f7..fe6cea15bbaff371fd9daa9926438bf01480f881 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/rcupdate.h>
 
 #include <asm/airq.h>
+#include <asm/isc.h>
 
 #include "cio.h"
 #include "cio_debug.h"
@@ -33,15 +34,15 @@ struct airq_t {
        void *drv_data;
 };
 
-static union indicator_t indicators;
-static struct airq_t *airqs[NR_AIRQS];
+static union indicator_t indicators[MAX_ISC];
+static struct airq_t *airqs[MAX_ISC][NR_AIRQS];
 
-static int register_airq(struct airq_t *airq)
+static int register_airq(struct airq_t *airq, u8 isc)
 {
        int i;
 
        for (i = 0; i < NR_AIRQS; i++)
-               if (!cmpxchg(&airqs[i], NULL, airq))
+               if (!cmpxchg(&airqs[isc][i], NULL, airq))
                        return i;
        return -ENOMEM;
 }
@@ -50,18 +51,21 @@ static int register_airq(struct airq_t *airq)
  * s390_register_adapter_interrupt() - register adapter interrupt handler
  * @handler: adapter handler to be registered
  * @drv_data: driver data passed with each call to the handler
+ * @isc: isc for which the handler should be called
  *
  * Returns:
  *  Pointer to the indicator to be used on success
  *  ERR_PTR() if registration failed
  */
 void *s390_register_adapter_interrupt(adapter_int_handler_t handler,
-                                     void *drv_data)
+                                     void *drv_data, u8 isc)
 {
        struct airq_t *airq;
        char dbf_txt[16];
        int ret;
 
+       if (isc > MAX_ISC)
+               return ERR_PTR(-EINVAL);
        airq = kmalloc(sizeof(struct airq_t), GFP_KERNEL);
        if (!airq) {
                ret = -ENOMEM;
@@ -69,34 +73,35 @@ void *s390_register_adapter_interrupt(adapter_int_handler_t handler,
        }
        airq->handler = handler;
        airq->drv_data = drv_data;
-       ret = register_airq(airq);
-       if (ret < 0)
-               kfree(airq);
+
+       ret = register_airq(airq, isc);
 out:
        snprintf(dbf_txt, sizeof(dbf_txt), "rairq:%d", ret);
        CIO_TRACE_EVENT(4, dbf_txt);
-       if (ret < 0)
+       if (ret < 0) {
+               kfree(airq);
                return ERR_PTR(ret);
-       else
-               return &indicators.byte[ret];
+       else
+               return &indicators[isc].byte[ret];
 }
 EXPORT_SYMBOL(s390_register_adapter_interrupt);
 
 /**
  * s390_unregister_adapter_interrupt - unregister adapter interrupt handler
  * @ind: indicator for which the handler is to be unregistered
+ * @isc: interruption subclass
  */
-void s390_unregister_adapter_interrupt(void *ind)
+void s390_unregister_adapter_interrupt(void *ind, u8 isc)
 {
        struct airq_t *airq;
        char dbf_txt[16];
        int i;
 
-       i = (int) ((addr_t) ind) - ((addr_t) &indicators.byte[0]);
+       i = (int) ((addr_t) ind) - ((addr_t) &indicators[isc].byte[0]);
        snprintf(dbf_txt, sizeof(dbf_txt), "urairq:%d", i);
        CIO_TRACE_EVENT(4, dbf_txt);
-       indicators.byte[i] = 0;
-       airq = xchg(&airqs[i], NULL);
+       indicators[isc].byte[i] = 0;
+       airq = xchg(&airqs[isc][i], NULL);
        /*
         * Allow interrupts to complete. This will ensure that the airq handle
         * is no longer referenced by any interrupt handler.
@@ -108,7 +113,7 @@ EXPORT_SYMBOL(s390_unregister_adapter_interrupt);
 
 #define INDICATOR_MASK (0xffUL << ((NR_AIRQS_PER_WORD - 1) * 8))
 
-void do_adapter_IO(void)
+void do_adapter_IO(u8 isc)
 {
        int w;
        int i;
@@ -120,22 +125,22 @@ void do_adapter_IO(void)
         * fetch operations.
         */
        for (w = 0; w < NR_AIRQ_WORDS; w++) {
-               word = indicators.word[w];
+               word = indicators[isc].word[w];
                i = w * NR_AIRQS_PER_WORD;
                /*
                 * Check bytes within word for active indicators.
                 */
                while (word) {
                        if (word & INDICATOR_MASK) {
-                               airq = airqs[i];
+                               airq = airqs[isc][i];
                                if (likely(airq))
-                                       airq->handler(&indicators.byte[i],
+                                       airq->handler(&indicators[isc].byte[i],
                                                      airq->drv_data);
                                else
                                        /*
                                         * Reset ill-behaved indicator.
                                         */
-                                       indicators.byte[i] = 0;
+                                       indicators[isc].byte[i] = 0;
                        }
                        word <<= 8;
                        i++;
index 297cdceb0ca4ba7276c57fbb8634bf6cb15f1eb9..db00b05917331b5901091f7697fa1fa2f2de8d96 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/chpid.h>
 #include <asm/sclp.h>
 
+#include "../s390mach.h"
 #include "cio.h"
 #include "css.h"
 #include "ioasm.h"
@@ -94,6 +95,7 @@ u8 chp_get_sch_opm(struct subchannel *sch)
        }
        return opm;
 }
+EXPORT_SYMBOL_GPL(chp_get_sch_opm);
 
 /**
  * chp_is_registered - check if a channel-path is registered
@@ -121,11 +123,8 @@ static int s390_vary_chpid(struct chp_id chpid, int on)
        CIO_TRACE_EVENT(2, dbf_text);
 
        status = chp_get_status(chpid);
-       if (!on && !status) {
-               printk(KERN_ERR "cio: chpid %x.%02x is already offline\n",
-                      chpid.cssid, chpid.id);
-               return -EINVAL;
-       }
+       if (!on && !status)
+               return 0;
 
        set_chp_logically_online(chpid, on);
        chsc_chp_vary(chpid, on);
@@ -141,21 +140,14 @@ static ssize_t chp_measurement_chars_read(struct kobject *kobj,
 {
        struct channel_path *chp;
        struct device *device;
-       unsigned int size;
 
        device = container_of(kobj, struct device, kobj);
        chp = to_channelpath(device);
        if (!chp->cmg_chars)
                return 0;
 
-       size = sizeof(struct cmg_chars);
-
-       if (off > size)
-               return 0;
-       if (off + count > size)
-               count = size - off;
-       memcpy(buf, chp->cmg_chars + off, count);
-       return count;
+       return memory_read_from_buffer(buf, count, &off,
+                               chp->cmg_chars, sizeof(struct cmg_chars));
 }
 
 static struct bin_attribute chp_measurement_chars_attr = {
@@ -405,7 +397,7 @@ int chp_new(struct chp_id chpid)
                 chpid.id);
 
        /* Obtain channel path description and fill it in. */
-       ret = chsc_determine_channel_path_description(chpid, &chp->desc);
+       ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc);
        if (ret)
                goto out_free;
        if ((chp->desc.flags & 0x80) == 0) {
@@ -413,8 +405,7 @@ int chp_new(struct chp_id chpid)
                goto out_free;
        }
        /* Get channel-measurement characteristics. */
-       if (css_characteristics_avail && css_chsc_characteristics.scmc
-           && css_chsc_characteristics.secm) {
+       if (css_chsc_characteristics.scmc && css_chsc_characteristics.secm) {
                ret = chsc_get_channel_measurement_chars(chp);
                if (ret)
                        goto out_free;
@@ -476,26 +467,74 @@ void *chp_get_chp_desc(struct chp_id chpid)
 
 /**
  * chp_process_crw - process channel-path status change
- * @id: channel-path ID number
- * @status: non-zero if channel-path has become available, zero otherwise
+ * @crw0: channel report-word to handler
+ * @crw1: second channel-report word (always NULL)
+ * @overflow: crw overflow indication
  *
  * Handle channel-report-words indicating that the status of a channel-path
  * has changed.
  */
-void chp_process_crw(int id, int status)
+static void chp_process_crw(struct crw *crw0, struct crw *crw1,
+                           int overflow)
 {
        struct chp_id chpid;
 
+       if (overflow) {
+               css_schedule_eval_all();
+               return;
+       }
+       CIO_CRW_EVENT(2, "CRW reports slct=%d, oflw=%d, "
+                     "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
+                     crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc,
+                     crw0->erc, crw0->rsid);
+       /*
+        * Check for solicited machine checks. These are
+        * created by reset channel path and need not be
+        * handled here.
+        */
+       if (crw0->slct) {
+               CIO_CRW_EVENT(2, "solicited machine check for "
+                             "channel path %02X\n", crw0->rsid);
+               return;
+       }
        chp_id_init(&chpid);
-       chpid.id = id;
-       if (status) {
+       chpid.id = crw0->rsid;
+       switch (crw0->erc) {
+       case CRW_ERC_IPARM: /* Path has come. */
                if (!chp_is_registered(chpid))
                        chp_new(chpid);
                chsc_chp_online(chpid);
-       } else
+               break;
+       case CRW_ERC_PERRI: /* Path has gone. */
+       case CRW_ERC_PERRN:
                chsc_chp_offline(chpid);
+               break;
+       default:
+               CIO_CRW_EVENT(2, "Don't know how to handle erc=%x\n",
+                             crw0->erc);
+       }
 }
 
+int chp_ssd_get_mask(struct chsc_ssd_info *ssd, struct chp_link *link)
+{
+       int i;
+       int mask;
+
+       for (i = 0; i < 8; i++) {
+               mask = 0x80 >> i;
+               if (!(ssd->path_mask & mask))
+                       continue;
+               if (!chp_id_is_equal(&ssd->chpid[i], &link->chpid))
+                       continue;
+               if ((ssd->fla_valid_mask & mask) &&
+                   ((ssd->fla[i] & link->fla_mask) != link->fla))
+                       continue;
+               return mask;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(chp_ssd_get_mask);
+
 static inline int info_bit_num(struct chp_id id)
 {
        return id.id + id.cssid * (__MAX_CHPID + 1);
@@ -575,6 +614,7 @@ static void cfg_func(struct work_struct *work)
 {
        struct chp_id chpid;
        enum cfg_task_t t;
+       int rc;
 
        mutex_lock(&cfg_lock);
        t = cfg_none;
@@ -589,14 +629,24 @@ static void cfg_func(struct work_struct *work)
 
        switch (t) {
        case cfg_configure:
-               sclp_chp_configure(chpid);
-               info_expire();
-               chsc_chp_online(chpid);
+               rc = sclp_chp_configure(chpid);
+               if (rc)
+                       CIO_MSG_EVENT(2, "chp: sclp_chp_configure(%x.%02x)="
+                                     "%d\n", chpid.cssid, chpid.id, rc);
+               else {
+                       info_expire();
+                       chsc_chp_online(chpid);
+               }
                break;
        case cfg_deconfigure:
-               sclp_chp_deconfigure(chpid);
-               info_expire();
-               chsc_chp_offline(chpid);
+               rc = sclp_chp_deconfigure(chpid);
+               if (rc)
+                       CIO_MSG_EVENT(2, "chp: sclp_chp_deconfigure(%x.%02x)="
+                                     "%d\n", chpid.cssid, chpid.id, rc);
+               else {
+                       info_expire();
+                       chsc_chp_offline(chpid);
+               }
                break;
        case cfg_none:
                /* Get updated information after last change. */
@@ -654,10 +704,16 @@ static int cfg_wait_idle(void)
 static int __init chp_init(void)
 {
        struct chp_id chpid;
+       int ret;
 
+       ret = s390_register_crw_handler(CRW_RSC_CPATH, chp_process_crw);
+       if (ret)
+               return ret;
        chp_wq = create_singlethread_workqueue("cio_chp");
-       if (!chp_wq)
+       if (!chp_wq) {
+               s390_unregister_crw_handler(CRW_RSC_CPATH);
                return -ENOMEM;
+       }
        INIT_WORK(&cfg_work, cfg_func);
        init_waitqueue_head(&cfg_wait_queue);
        if (info_update())
index 65286563c592c70e47b1979c177910fc2c3f768c..26c3d22461764b56630958bbbfa6cb9714b166b0 100644 (file)
 #include <linux/device.h>
 #include <asm/chpid.h>
 #include "chsc.h"
+#include "css.h"
 
 #define CHP_STATUS_STANDBY             0
 #define CHP_STATUS_CONFIGURED          1
 #define CHP_STATUS_RESERVED            2
 #define CHP_STATUS_NOT_RECOGNIZED      3
 
+#define CHP_ONLINE 0
+#define CHP_OFFLINE 1
+#define CHP_VARY_ON 2
+#define CHP_VARY_OFF 3
+
+struct chp_link {
+       struct chp_id chpid;
+       u32 fla_mask;
+       u16 fla;
+};
+
 static inline int chp_test_bit(u8 *bitmap, int num)
 {
        int byte = num >> 3;
@@ -42,12 +54,11 @@ int chp_get_status(struct chp_id chpid);
 u8 chp_get_sch_opm(struct subchannel *sch);
 int chp_is_registered(struct chp_id chpid);
 void *chp_get_chp_desc(struct chp_id chpid);
-void chp_process_crw(int id, int available);
 void chp_remove_cmg_attr(struct channel_path *chp);
 int chp_add_cmg_attr(struct channel_path *chp);
 int chp_new(struct chp_id chpid);
 void chp_cfg_schedule(struct chp_id chpid, int configure);
 void chp_cfg_cancel_deconfigure(struct chp_id chpid);
 int chp_info_get_status(struct chp_id chpid);
-
+int chp_ssd_get_mask(struct chsc_ssd_info *, struct chp_link *);
 #endif /* S390_CHP_H */
index 5de86908b0d0c2f4f2a95425f09c07cfa6f160f1..65264a38057d5cba26ba13b80787800b030ee84e 100644 (file)
@@ -2,8 +2,7 @@
  *  drivers/s390/cio/chsc.c
  *   S/390 common I/O routines -- channel subsystem call
  *
- *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
- *                           IBM Corporation
+ *    Copyright IBM Corp. 1999,2008
  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
  *              Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Arnd Bergmann (arndb@de.ibm.com)
@@ -16,7 +15,9 @@
 
 #include <asm/cio.h>
 #include <asm/chpid.h>
+#include <asm/chsc.h>
 
+#include "../s390mach.h"
 #include "css.h"
 #include "cio.h"
 #include "cio_debug.h"
@@ -127,77 +128,12 @@ out_free:
        return ret;
 }
 
-static int check_for_io_on_path(struct subchannel *sch, int mask)
-{
-       int cc;
-
-       cc = stsch(sch->schid, &sch->schib);
-       if (cc)
-               return 0;
-       if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == mask)
-               return 1;
-       return 0;
-}
-
-static void terminate_internal_io(struct subchannel *sch)
-{
-       if (cio_clear(sch)) {
-               /* Recheck device in case clear failed. */
-               sch->lpm = 0;
-               if (device_trigger_verify(sch) != 0)
-                       css_schedule_eval(sch->schid);
-               return;
-       }
-       /* Request retry of internal operation. */
-       device_set_intretry(sch);
-       /* Call handler. */
-       if (sch->driver && sch->driver->termination)
-               sch->driver->termination(sch);
-}
-
 static int s390_subchannel_remove_chpid(struct subchannel *sch, void *data)
 {
-       int j;
-       int mask;
-       struct chp_id *chpid = data;
-       struct schib schib;
-
-       for (j = 0; j < 8; j++) {
-               mask = 0x80 >> j;
-               if ((sch->schib.pmcw.pim & mask) &&
-                   (sch->schib.pmcw.chpid[j] == chpid->id))
-                       break;
-       }
-       if (j >= 8)
-               return 0;
-
        spin_lock_irq(sch->lock);
-
-       stsch(sch->schid, &schib);
-       if (!css_sch_is_valid(&schib))
-               goto out_unreg;
-       memcpy(&sch->schib, &schib, sizeof(struct schib));
-       /* Check for single path devices. */
-       if (sch->schib.pmcw.pim == 0x80)
-               goto out_unreg;
-
-       if (check_for_io_on_path(sch, mask)) {
-               if (device_is_online(sch))
-                       device_kill_io(sch);
-               else {
-                       terminate_internal_io(sch);
-                       /* Re-start path verification. */
-                       if (sch->driver && sch->driver->verify)
-                               sch->driver->verify(sch);
-               }
-       } else {
-               /* trigger path verification. */
-               if (sch->driver && sch->driver->verify)
-                       sch->driver->verify(sch);
-               else if (sch->lpm == mask)
+       if (sch->driver && sch->driver->chp_event)
+               if (sch->driver->chp_event(sch, data, CHP_OFFLINE) != 0)
                        goto out_unreg;
-       }
-
        spin_unlock_irq(sch->lock);
        return 0;
 
@@ -211,15 +147,18 @@ out_unreg:
 void chsc_chp_offline(struct chp_id chpid)
 {
        char dbf_txt[15];
+       struct chp_link link;
 
        sprintf(dbf_txt, "chpr%x.%02x", chpid.cssid, chpid.id);
        CIO_TRACE_EVENT(2, dbf_txt);
 
        if (chp_get_status(chpid) <= 0)
                return;
+       memset(&link, 0, sizeof(struct chp_link));
+       link.chpid = chpid;
        /* Wait until previous actions have settled. */
        css_wait_for_slow_path();
-       for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &chpid);
+       for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link);
 }
 
 static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data)
@@ -242,67 +181,25 @@ static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data)
        return 0;
 }
 
-struct res_acc_data {
-       struct chp_id chpid;
-       u32 fla_mask;
-       u16 fla;
-};
-
-static int get_res_chpid_mask(struct chsc_ssd_info *ssd,
-                             struct res_acc_data *data)
-{
-       int i;
-       int mask;
-
-       for (i = 0; i < 8; i++) {
-               mask = 0x80 >> i;
-               if (!(ssd->path_mask & mask))
-                       continue;
-               if (!chp_id_is_equal(&ssd->chpid[i], &data->chpid))
-                       continue;
-               if ((ssd->fla_valid_mask & mask) &&
-                   ((ssd->fla[i] & data->fla_mask) != data->fla))
-                       continue;
-               return mask;
-       }
-       return 0;
-}
-
 static int __s390_process_res_acc(struct subchannel *sch, void *data)
 {
-       int chp_mask, old_lpm;
-       struct res_acc_data *res_data = data;
-
        spin_lock_irq(sch->lock);
-       chp_mask = get_res_chpid_mask(&sch->ssd_info, res_data);
-       if (chp_mask == 0)
-               goto out;
-       if (stsch(sch->schid, &sch->schib))
-               goto out;
-       old_lpm = sch->lpm;
-       sch->lpm = ((sch->schib.pmcw.pim &
-                    sch->schib.pmcw.pam &
-                    sch->schib.pmcw.pom)
-                   | chp_mask) & sch->opm;
-       if (!old_lpm && sch->lpm)
-               device_trigger_reprobe(sch);
-       else if (sch->driver && sch->driver->verify)
-               sch->driver->verify(sch);
-out:
+       if (sch->driver && sch->driver->chp_event)
+               sch->driver->chp_event(sch, data, CHP_ONLINE);
        spin_unlock_irq(sch->lock);
 
        return 0;
 }
 
-static void s390_process_res_acc (struct res_acc_data *res_data)
+static void s390_process_res_acc(struct chp_link *link)
 {
        char dbf_txt[15];
 
-       sprintf(dbf_txt, "accpr%x.%02x", res_data->chpid.cssid,
-               res_data->chpid.id);
+       sprintf(dbf_txt, "accpr%x.%02x", link->chpid.cssid,
+               link->chpid.id);
        CIO_TRACE_EVENT( 2, dbf_txt);
-       if (res_data->fla != 0) {
-               sprintf(dbf_txt, "fla%x", res_data->fla);
+       if (link->fla != 0) {
+               sprintf(dbf_txt, "fla%x", link->fla);
                CIO_TRACE_EVENT( 2, dbf_txt);
        }
        /* Wait until previous actions have settled. */
@@ -315,7 +212,7 @@ static void s390_process_res_acc (struct res_acc_data *res_data)
         * will we have to do.
         */
        for_each_subchannel_staged(__s390_process_res_acc,
-                                  s390_process_res_acc_new_sch, res_data);
+                                  s390_process_res_acc_new_sch, link);
 }
 
 static int
@@ -388,7 +285,7 @@ static void chsc_process_sei_link_incident(struct chsc_sei_area *sei_area)
 
 static void chsc_process_sei_res_acc(struct chsc_sei_area *sei_area)
 {
-       struct res_acc_data res_data;
+       struct chp_link link;
        struct chp_id chpid;
        int status;
 
@@ -404,18 +301,18 @@ static void chsc_process_sei_res_acc(struct chsc_sei_area *sei_area)
                chp_new(chpid);
        else if (!status)
                return;
-       memset(&res_data, 0, sizeof(struct res_acc_data));
-       res_data.chpid = chpid;
+       memset(&link, 0, sizeof(struct chp_link));
+       link.chpid = chpid;
        if ((sei_area->vf & 0xc0) != 0) {
-               res_data.fla = sei_area->fla;
+               link.fla = sei_area->fla;
                if ((sei_area->vf & 0xc0) == 0xc0)
                        /* full link address */
-                       res_data.fla_mask = 0xffff;
+                       link.fla_mask = 0xffff;
                else
                        /* link address */
-                       res_data.fla_mask = 0xff00;
+                       link.fla_mask = 0xff00;
        }
-       s390_process_res_acc(&res_data);
+       s390_process_res_acc(&link);
 }
 
 struct chp_config_data {
@@ -480,17 +377,25 @@ static void chsc_process_sei(struct chsc_sei_area *sei_area)
        }
 }
 
-void chsc_process_crw(void)
+static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
 {
        struct chsc_sei_area *sei_area;
 
+       if (overflow) {
+               css_schedule_eval_all();
+               return;
+       }
+       CIO_CRW_EVENT(2, "CRW reports slct=%d, oflw=%d, "
+                     "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
+                     crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc,
+                     crw0->erc, crw0->rsid);
        if (!sei_page)
                return;
        /* Access to sei_page is serialized through machine check handler
         * thread, so no need for locking. */
        sei_area = sei_page;
 
-       CIO_TRACE_EVENT( 2, "prcss");
+       CIO_TRACE_EVENT(2, "prcss");
        do {
                memset(sei_area, 0, sizeof(*sei_area));
                sei_area->request.length = 0x0010;
@@ -509,114 +414,36 @@ void chsc_process_crw(void)
        } while (sei_area->flags & 0x80);
 }
 
-static int __chp_add_new_sch(struct subchannel_id schid, void *data)
-{
-       struct schib schib;
-
-       if (stsch_err(schid, &schib))
-               /* We're through */
-               return -ENXIO;
-
-       /* Put it on the slow path. */
-       css_schedule_eval(schid);
-       return 0;
-}
-
-
-static int __chp_add(struct subchannel *sch, void *data)
-{
-       int i, mask;
-       struct chp_id *chpid = data;
-
-       spin_lock_irq(sch->lock);
-       for (i=0; i<8; i++) {
-               mask = 0x80 >> i;
-               if ((sch->schib.pmcw.pim & mask) &&
-                   (sch->schib.pmcw.chpid[i] == chpid->id))
-                       break;
-       }
-       if (i==8) {
-               spin_unlock_irq(sch->lock);
-               return 0;
-       }
-       if (stsch(sch->schid, &sch->schib)) {
-               spin_unlock_irq(sch->lock);
-               css_schedule_eval(sch->schid);
-               return 0;
-       }
-       sch->lpm = ((sch->schib.pmcw.pim &
-                    sch->schib.pmcw.pam &
-                    sch->schib.pmcw.pom)
-                   | mask) & sch->opm;
-
-       if (sch->driver && sch->driver->verify)
-               sch->driver->verify(sch);
-
-       spin_unlock_irq(sch->lock);
-
-       return 0;
-}
-
 void chsc_chp_online(struct chp_id chpid)
 {
        char dbf_txt[15];
+       struct chp_link link;
 
        sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id);
        CIO_TRACE_EVENT(2, dbf_txt);
 
        if (chp_get_status(chpid) != 0) {
+               memset(&link, 0, sizeof(struct chp_link));
+               link.chpid = chpid;
                /* Wait until previous actions have settled. */
                css_wait_for_slow_path();
-               for_each_subchannel_staged(__chp_add, __chp_add_new_sch,
-                                          &chpid);
+               for_each_subchannel_staged(__s390_process_res_acc, NULL,
+                                          &link);
        }
 }
 
 static void __s390_subchannel_vary_chpid(struct subchannel *sch,
                                         struct chp_id chpid, int on)
 {
-       int chp, old_lpm;
-       int mask;
        unsigned long flags;
+       struct chp_link link;
 
+       memset(&link, 0, sizeof(struct chp_link));
+       link.chpid = chpid;
        spin_lock_irqsave(sch->lock, flags);
-       old_lpm = sch->lpm;
-       for (chp = 0; chp < 8; chp++) {
-               mask = 0x80 >> chp;
-               if (!(sch->ssd_info.path_mask & mask))
-                       continue;
-               if (!chp_id_is_equal(&sch->ssd_info.chpid[chp], &chpid))
-                       continue;
-
-               if (on) {
-                       sch->opm |= mask;
-                       sch->lpm |= mask;
-                       if (!old_lpm)
-                               device_trigger_reprobe(sch);
-                       else if (sch->driver && sch->driver->verify)
-                               sch->driver->verify(sch);
-                       break;
-               }
-               sch->opm &= ~mask;
-               sch->lpm &= ~mask;
-               if (check_for_io_on_path(sch, mask)) {
-                       if (device_is_online(sch))
-                               /* Path verification is done after killing. */
-                               device_kill_io(sch);
-                       else {
-                               /* Kill and retry internal I/O. */
-                               terminate_internal_io(sch);
-                               /* Re-start path verification. */
-                               if (sch->driver && sch->driver->verify)
-                                       sch->driver->verify(sch);
-                       }
-               } else if (!sch->lpm) {
-                       if (device_trigger_verify(sch) != 0)
-                               css_schedule_eval(sch->schid);
-               } else if (sch->driver && sch->driver->verify)
-                       sch->driver->verify(sch);
-               break;
-       }
+       if (sch->driver && sch->driver->chp_event)
+               sch->driver->chp_event(sch, &link,
+                                      on ? CHP_VARY_ON : CHP_VARY_OFF);
        spin_unlock_irqrestore(sch->lock, flags);
 }
 
@@ -656,6 +483,10 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data)
  */
 int chsc_chp_vary(struct chp_id chpid, int on)
 {
+       struct chp_link link;
+
+       memset(&link, 0, sizeof(struct chp_link));
+       link.chpid = chpid;
        /* Wait until previous actions have settled. */
        css_wait_for_slow_path();
        /*
@@ -664,10 +495,10 @@ int chsc_chp_vary(struct chp_id chpid, int on)
 
        if (on)
                for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
-                                          __s390_vary_chpid_on, &chpid);
+                                          __s390_vary_chpid_on, &link);
        else
                for_each_subchannel_staged(s390_subchannel_vary_chpid_off,
-                                          NULL, &chpid);
+                                          NULL, &link);
 
        return 0;
 }
@@ -797,23 +628,33 @@ chsc_secm(struct channel_subsystem *css, int enable)
        return ret;
 }
 
-int chsc_determine_channel_path_description(struct chp_id chpid,
-                                           struct channel_path_desc *desc)
+int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt,
+                                    int c, int m,
+                                    struct chsc_response_struct *resp)
 {
        int ccode, ret;
 
        struct {
                struct chsc_header request;
-               u32 : 24;
+               u32 : 2;
+               u32 m : 1;
+               u32 c : 1;
+               u32 fmt : 4;
+               u32 cssid : 8;
+               u32 : 4;
+               u32 rfmt : 4;
                u32 first_chpid : 8;
                u32 : 24;
                u32 last_chpid : 8;
                u32 zeroes1;
                struct chsc_header response;
-               u32 zeroes2;
-               struct channel_path_desc desc;
+               u8 data[PAGE_SIZE - 20];
        } __attribute__ ((packed)) *scpd_area;
 
+       if ((rfmt == 1) && !css_general_characteristics.fcs)
+               return -EINVAL;
+       if ((rfmt == 2) && !css_general_characteristics.cib)
+               return -EINVAL;
        scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
        if (!scpd_area)
                return -ENOMEM;
@@ -821,8 +662,13 @@ int chsc_determine_channel_path_description(struct chp_id chpid,
        scpd_area->request.length = 0x0010;
        scpd_area->request.code = 0x0002;
 
+       scpd_area->cssid = chpid.cssid;
        scpd_area->first_chpid = chpid.id;
        scpd_area->last_chpid = chpid.id;
+       scpd_area->m = m;
+       scpd_area->c = c;
+       scpd_area->fmt = fmt;
+       scpd_area->rfmt = rfmt;
 
        ccode = chsc(scpd_area);
        if (ccode > 0) {
@@ -833,8 +679,7 @@ int chsc_determine_channel_path_description(struct chp_id chpid,
        ret = chsc_error_from_response(scpd_area->response.code);
        if (ret == 0)
                /* Success. */
-               memcpy(desc, &scpd_area->desc,
-                      sizeof(struct channel_path_desc));
+               memcpy(resp, &scpd_area->response, scpd_area->response.length);
        else
                CIO_CRW_EVENT(2, "chsc: scpd failed (rc=%04x)\n",
                              scpd_area->response.code);
@@ -842,6 +687,25 @@ out:
        free_page((unsigned long)scpd_area);
        return ret;
 }
+EXPORT_SYMBOL_GPL(chsc_determine_channel_path_desc);
+
+int chsc_determine_base_channel_path_desc(struct chp_id chpid,
+                                         struct channel_path_desc *desc)
+{
+       struct chsc_response_struct *chsc_resp;
+       int ret;
+
+       chsc_resp = kzalloc(sizeof(*chsc_resp), GFP_KERNEL);
+       if (!chsc_resp)
+               return -ENOMEM;
+       ret = chsc_determine_channel_path_desc(chpid, 0, 0, 0, 0, chsc_resp);
+       if (ret)
+               goto out_free;
+       memcpy(desc, &chsc_resp->data, chsc_resp->length);
+out_free:
+       kfree(chsc_resp);
+       return ret;
+}
 
 static void
 chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,
@@ -937,15 +801,23 @@ out:
 
 int __init chsc_alloc_sei_area(void)
 {
+       int ret;
+
        sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-       if (!sei_page)
+       if (!sei_page) {
                CIO_MSG_EVENT(0, "Can't allocate page for processing of "
                              "chsc machine checks!\n");
-       return (sei_page ? 0 : -ENOMEM);
+               return -ENOMEM;
+       }
+       ret = s390_register_crw_handler(CRW_RSC_CSS, chsc_process_crw);
+       if (ret)
+               kfree(sei_page);
+       return ret;
 }
 
 void __init chsc_free_sei_area(void)
 {
+       s390_unregister_crw_handler(CRW_RSC_CSS);
        kfree(sei_page);
 }
 
@@ -1043,3 +915,52 @@ exit:
 
 EXPORT_SYMBOL_GPL(css_general_characteristics);
 EXPORT_SYMBOL_GPL(css_chsc_characteristics);
+
+int chsc_sstpc(void *page, unsigned int op, u16 ctrl)
+{
+       struct {
+               struct chsc_header request;
+               unsigned int rsvd0;
+               unsigned int op : 8;
+               unsigned int rsvd1 : 8;
+               unsigned int ctrl : 16;
+               unsigned int rsvd2[5];
+               struct chsc_header response;
+               unsigned int rsvd3[7];
+       } __attribute__ ((packed)) *rr;
+       int rc;
+
+       memset(page, 0, PAGE_SIZE);
+       rr = page;
+       rr->request.length = 0x0020;
+       rr->request.code = 0x0033;
+       rr->op = op;
+       rr->ctrl = ctrl;
+       rc = chsc(rr);
+       if (rc)
+               return -EIO;
+       rc = (rr->response.code == 0x0001) ? 0 : -EIO;
+       return rc;
+}
+
+int chsc_sstpi(void *page, void *result, size_t size)
+{
+       struct {
+               struct chsc_header request;
+               unsigned int rsvd0[3];
+               struct chsc_header response;
+               char data[size];
+       } __attribute__ ((packed)) *rr;
+       int rc;
+
+       memset(page, 0, PAGE_SIZE);
+       rr = page;
+       rr->request.length = 0x0010;
+       rr->request.code = 0x0038;
+       rc = chsc(rr);
+       if (rc)
+               return -EIO;
+       memcpy(result, &rr->data, size);
+       return (rr->response.code == 0x0001) ? 0 : -EIO;
+}
+
index d1f5db1e69b94d6eee24aef06351fdb515abc1e4..fb6c4d6c45b44cc68f29b7bd7a8cd7372ef70d6e 100644 (file)
@@ -4,7 +4,8 @@
 #include <linux/types.h>
 #include <linux/device.h>
 #include <asm/chpid.h>
-#include "schid.h"
+#include <asm/chsc.h>
+#include <asm/schid.h>
 
 #define CHSC_SDA_OC_MSS   0x2
 
@@ -36,14 +37,15 @@ struct channel_path_desc {
 
 struct channel_path;
 
-extern void chsc_process_crw(void);
-
 struct css_general_char {
-       u64 : 41;
+       u64 : 12;
+       u32 dynio : 1;   /* bit 12 */
+       u32 : 28;
        u32 aif : 1;     /* bit 41 */
        u32 : 3;
        u32 mcss : 1;    /* bit 45 */
-       u32 : 2;
+       u32 fcs : 1;     /* bit 46 */
+       u32 : 1;
        u32 ext_mb : 1;  /* bit 48 */
        u32 : 7;
        u32 aif_tdd : 1; /* bit 56 */
@@ -51,7 +53,11 @@ struct css_general_char {
        u32 qebsm : 1;   /* bit 58 */
        u32 : 8;
        u32 aif_osa : 1; /* bit 67 */
-       u32 : 28;
+       u32 : 14;
+       u32 cib : 1;     /* bit 82 */
+       u32 : 5;
+       u32 fcx : 1;     /* bit 88 */
+       u32 : 7;
 }__attribute__((packed));
 
 struct css_chsc_char {
@@ -78,7 +84,6 @@ struct chsc_ssd_info {
 extern int chsc_get_ssd_info(struct subchannel_id schid,
                             struct chsc_ssd_info *ssd);
 extern int chsc_determine_css_characteristics(void);
-extern int css_characteristics_avail;
 extern int chsc_alloc_sei_area(void);
 extern void chsc_free_sei_area(void);
 
@@ -87,8 +92,11 @@ struct channel_subsystem;
 extern int chsc_secm(struct channel_subsystem *, int);
 
 int chsc_chp_vary(struct chp_id chpid, int on);
-int chsc_determine_channel_path_description(struct chp_id chpid,
-                                           struct channel_path_desc *desc);
+int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt,
+                                    int c, int m,
+                                    struct chsc_response_struct *resp);
+int chsc_determine_base_channel_path_desc(struct chp_id chpid,
+                                         struct channel_path_desc *desc);
 void chsc_chp_online(struct chp_id chpid);
 void chsc_chp_offline(struct chp_id chpid);
 int chsc_get_channel_measurement_chars(struct channel_path *chp);
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
new file mode 100644 (file)
index 0000000..91ca87a
--- /dev/null
@@ -0,0 +1,820 @@
+/*
+ * Driver for s390 chsc subchannels
+ *
+ * Copyright IBM Corp. 2008
+ * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+
+#include <asm/cio.h>
+#include <asm/chsc.h>
+#include <asm/isc.h>
+
+#include "cio.h"
+#include "cio_debug.h"
+#include "css.h"
+#include "chsc_sch.h"
+#include "ioasm.h"
+
+static debug_info_t *chsc_debug_msg_id;
+static debug_info_t *chsc_debug_log_id;
+
+#define CHSC_MSG(imp, args...) do {                                    \
+               debug_sprintf_event(chsc_debug_msg_id, imp , ##args);   \
+       } while (0)
+
+#define CHSC_LOG(imp, txt) do {                                        \
+               debug_text_event(chsc_debug_log_id, imp , txt); \
+       } while (0)
+
+static void CHSC_LOG_HEX(int level, void *data, int length)
+{
+       while (length > 0) {
+               debug_event(chsc_debug_log_id, level, data, length);
+               length -= chsc_debug_log_id->buf_size;
+               data += chsc_debug_log_id->buf_size;
+       }
+}
+
+MODULE_AUTHOR("IBM Corporation");
+MODULE_DESCRIPTION("driver for s390 chsc subchannels");
+MODULE_LICENSE("GPL");
+
+static void chsc_subchannel_irq(struct subchannel *sch)
+{
+       struct chsc_private *private = sch->private;
+       struct chsc_request *request = private->request;
+       struct irb *irb = (struct irb *)__LC_IRB;
+
+       CHSC_LOG(4, "irb");
+       CHSC_LOG_HEX(4, irb, sizeof(*irb));
+       /* Copy irb to provided request and set done. */
+       if (!request) {
+               CHSC_MSG(0, "Interrupt on sch 0.%x.%04x with no request\n",
+                        sch->schid.ssid, sch->schid.sch_no);
+               return;
+       }
+       private->request = NULL;
+       memcpy(&request->irb, irb, sizeof(*irb));
+       stsch(sch->schid, &sch->schib);
+       complete(&request->completion);
+       put_device(&sch->dev);
+}
+
+static int chsc_subchannel_probe(struct subchannel *sch)
+{
+       struct chsc_private *private;
+       int ret;
+
+       CHSC_MSG(6, "Detected chsc subchannel 0.%x.%04x\n",
+                sch->schid.ssid, sch->schid.sch_no);
+       sch->isc = CHSC_SCH_ISC;
+       private = kzalloc(sizeof(*private), GFP_KERNEL);
+       if (!private)
+               return -ENOMEM;
+       ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
+       if (ret) {
+               CHSC_MSG(0, "Failed to enable 0.%x.%04x: %d\n",
+                        sch->schid.ssid, sch->schid.sch_no, ret);
+               kfree(private);
+       } else {
+               sch->private = private;
+               if (sch->dev.uevent_suppress) {
+                       sch->dev.uevent_suppress = 0;
+                       kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
+               }
+       }
+       return ret;
+}
+
+static int chsc_subchannel_remove(struct subchannel *sch)
+{
+       struct chsc_private *private;
+
+       cio_disable_subchannel(sch);
+       private = sch->private;
+       sch->private = NULL;
+       if (private->request) {
+               complete(&private->request->completion);
+               put_device(&sch->dev);
+       }
+       kfree(private);
+       return 0;
+}
+
+static void chsc_subchannel_shutdown(struct subchannel *sch)
+{
+       cio_disable_subchannel(sch);
+}
+
+static struct css_device_id chsc_subchannel_ids[] = {
+       { .match_flags = 0x1, .type =SUBCHANNEL_TYPE_CHSC, },
+       { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(css, chsc_subchannel_ids);
+
+static struct css_driver chsc_subchannel_driver = {
+       .owner = THIS_MODULE,
+       .subchannel_type = chsc_subchannel_ids,
+       .irq = chsc_subchannel_irq,
+       .probe = chsc_subchannel_probe,
+       .remove = chsc_subchannel_remove,
+       .shutdown = chsc_subchannel_shutdown,
+       .name = "chsc_subchannel",
+};
+
+static int __init chsc_init_dbfs(void)
+{
+       chsc_debug_msg_id = debug_register("chsc_msg", 16, 1,
+                                          16 * sizeof(long));
+       if (!chsc_debug_msg_id)
+               goto out;
+       debug_register_view(chsc_debug_msg_id, &debug_sprintf_view);
+       debug_set_level(chsc_debug_msg_id, 2);
+       chsc_debug_log_id = debug_register("chsc_log", 16, 1, 16);
+       if (!chsc_debug_log_id)
+               goto out;
+       debug_register_view(chsc_debug_log_id, &debug_hex_ascii_view);
+       debug_set_level(chsc_debug_log_id, 2);
+       return 0;
+out:
+       if (chsc_debug_msg_id)
+               debug_unregister(chsc_debug_msg_id);
+       return -ENOMEM;
+}
+
+static void chsc_remove_dbfs(void)
+{
+       debug_unregister(chsc_debug_log_id);
+       debug_unregister(chsc_debug_msg_id);
+}
+
+static int __init chsc_init_sch_driver(void)
+{
+       return css_driver_register(&chsc_subchannel_driver);
+}
+
+static void chsc_cleanup_sch_driver(void)
+{
+       css_driver_unregister(&chsc_subchannel_driver);
+}
+
+static DEFINE_SPINLOCK(chsc_lock);
+
+static int chsc_subchannel_match_next_free(struct device *dev, void *data)
+{
+       struct subchannel *sch = to_subchannel(dev);
+
+       return sch->schib.pmcw.ena && !scsw_fctl(&sch->schib.scsw);
+}
+
+static struct subchannel *chsc_get_next_subchannel(struct subchannel *sch)
+{
+       struct device *dev;
+
+       dev = driver_find_device(&chsc_subchannel_driver.drv,
+                                sch ? &sch->dev : NULL, NULL,
+                                chsc_subchannel_match_next_free);
+       return dev ? to_subchannel(dev) : NULL;
+}
+
+/**
+ * chsc_async() - try to start a chsc request asynchronously
+ * @chsc_area: request to be started
+ * @request: request structure to associate
+ *
+ * Tries to start a chsc request on one of the existing chsc subchannels.
+ * Returns:
+ *  %0 if the request was performed synchronously
+ *  %-EINPROGRESS if the request was successfully started
+ *  %-EBUSY if all chsc subchannels are busy
+ *  %-ENODEV if no chsc subchannels are available
+ * Context:
+ *  interrupts disabled, chsc_lock held
+ */
+static int chsc_async(struct chsc_async_area *chsc_area,
+                     struct chsc_request *request)
+{
+       int cc;
+       struct chsc_private *private;
+       struct subchannel *sch = NULL;
+       int ret = -ENODEV;
+       char dbf[10];
+
+       chsc_area->header.key = PAGE_DEFAULT_KEY;
+       while ((sch = chsc_get_next_subchannel(sch))) {
+               spin_lock(sch->lock);
+               private = sch->private;
+               if (private->request) {
+                       spin_unlock(sch->lock);
+                       ret = -EBUSY;
+                       continue;
+               }
+               chsc_area->header.sid = sch->schid;
+               CHSC_LOG(2, "schid");
+               CHSC_LOG_HEX(2, &sch->schid, sizeof(sch->schid));
+               cc = chsc(chsc_area);
+               sprintf(dbf, "cc:%d", cc);
+               CHSC_LOG(2, dbf);
+               switch (cc) {
+               case 0:
+                       ret = 0;
+                       break;
+               case 1:
+                       sch->schib.scsw.cmd.fctl |= SCSW_FCTL_START_FUNC;
+                       ret = -EINPROGRESS;
+                       private->request = request;
+                       break;
+               case 2:
+                       ret = -EBUSY;
+                       break;
+               default:
+                       ret = -ENODEV;
+               }
+               spin_unlock(sch->lock);
+               CHSC_MSG(2, "chsc on 0.%x.%04x returned cc=%d\n",
+                        sch->schid.ssid, sch->schid.sch_no, cc);
+               if (ret == -EINPROGRESS)
+                       return -EINPROGRESS;
+               put_device(&sch->dev);
+               if (ret == 0)
+                       return 0;
+       }
+       return ret;
+}
+
+static void chsc_log_command(struct chsc_async_area *chsc_area)
+{
+       char dbf[10];
+
+       sprintf(dbf, "CHSC:%x", chsc_area->header.code);
+       CHSC_LOG(0, dbf);
+       CHSC_LOG_HEX(0, chsc_area, 32);
+}
+
+static int chsc_examine_irb(struct chsc_request *request)
+{
+       int backed_up;
+
+       if (!scsw_stctl(&request->irb.scsw) & SCSW_STCTL_STATUS_PEND)
+               return -EIO;
+       backed_up = scsw_cstat(&request->irb.scsw) & SCHN_STAT_CHAIN_CHECK;
+       request->irb.scsw.cmd.cstat &= ~SCHN_STAT_CHAIN_CHECK;
+       if (scsw_cstat(&request->irb.scsw) == 0)
+               return 0;
+       if (!backed_up)
+               return 0;
+       if (scsw_cstat(&request->irb.scsw) & SCHN_STAT_PROG_CHECK)
+               return -EIO;
+       if (scsw_cstat(&request->irb.scsw) & SCHN_STAT_PROT_CHECK)
+               return -EPERM;
+       if (scsw_cstat(&request->irb.scsw) & SCHN_STAT_CHN_DATA_CHK)
+               return -EAGAIN;
+       if (scsw_cstat(&request->irb.scsw) & SCHN_STAT_CHN_CTRL_CHK)
+               return -EAGAIN;
+       return -EIO;
+}
+
+static int chsc_ioctl_start(void __user *user_area)
+{
+       struct chsc_request *request;
+       struct chsc_async_area *chsc_area;
+       int ret;
+       char dbf[10];
+
+       if (!css_general_characteristics.dynio)
+               /* It makes no sense to try. */
+               return -EOPNOTSUPP;
+       chsc_area = (void *)get_zeroed_page(GFP_DMA | GFP_KERNEL);
+       if (!chsc_area)
+               return -ENOMEM;
+       request = kzalloc(sizeof(*request), GFP_KERNEL);
+       if (!request) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
+       init_completion(&request->completion);
+       if (copy_from_user(chsc_area, user_area, PAGE_SIZE)) {
+               ret = -EFAULT;
+               goto out_free;
+       }
+       chsc_log_command(chsc_area);
+       spin_lock_irq(&chsc_lock);
+       ret = chsc_async(chsc_area, request);
+       spin_unlock_irq(&chsc_lock);
+       if (ret == -EINPROGRESS) {
+               wait_for_completion(&request->completion);
+               ret = chsc_examine_irb(request);
+       }
+       /* copy area back to user */
+       if (!ret)
+               if (copy_to_user(user_area, chsc_area, PAGE_SIZE))
+                       ret = -EFAULT;
+out_free:
+       sprintf(dbf, "ret:%d", ret);
+       CHSC_LOG(0, dbf);
+       kfree(request);
+       free_page((unsigned long)chsc_area);
+       return ret;
+}
+
+static int chsc_ioctl_info_channel_path(void __user *user_cd)
+{
+       struct chsc_chp_cd *cd;
+       int ret, ccode;
+       struct {
+               struct chsc_header request;
+               u32 : 2;
+               u32 m : 1;
+               u32 : 1;
+               u32 fmt1 : 4;
+               u32 cssid : 8;
+               u32 : 8;
+               u32 first_chpid : 8;
+               u32 : 24;
+               u32 last_chpid : 8;
+               u32 : 32;
+               struct chsc_header response;
+               u8 data[PAGE_SIZE - 20];
+       } __attribute__ ((packed)) *scpcd_area;
+
+       scpcd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!scpcd_area)
+               return -ENOMEM;
+       cd = kzalloc(sizeof(*cd), GFP_KERNEL);
+       if (!cd) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
+       if (copy_from_user(cd, user_cd, sizeof(*cd))) {
+               ret = -EFAULT;
+               goto out_free;
+       }
+       scpcd_area->request.length = 0x0010;
+       scpcd_area->request.code = 0x0028;
+       scpcd_area->m = cd->m;
+       scpcd_area->fmt1 = cd->fmt;
+       scpcd_area->cssid = cd->chpid.cssid;
+       scpcd_area->first_chpid = cd->chpid.id;
+       scpcd_area->last_chpid = cd->chpid.id;
+
+       ccode = chsc(scpcd_area);
+       if (ccode != 0) {
+               ret = -EIO;
+               goto out_free;
+       }
+       if (scpcd_area->response.code != 0x0001) {
+               ret = -EIO;
+               CHSC_MSG(0, "scpcd: response code=%x\n",
+                        scpcd_area->response.code);
+               goto out_free;
+       }
+       memcpy(&cd->cpcb, &scpcd_area->response, scpcd_area->response.length);
+       if (copy_to_user(user_cd, cd, sizeof(*cd)))
+               ret = -EFAULT;
+       else
+               ret = 0;
+out_free:
+       kfree(cd);
+       free_page((unsigned long)scpcd_area);
+       return ret;
+}
+
+static int chsc_ioctl_info_cu(void __user *user_cd)
+{
+       struct chsc_cu_cd *cd;
+       int ret, ccode;
+       struct {
+               struct chsc_header request;
+               u32 : 2;
+               u32 m : 1;
+               u32 : 1;
+               u32 fmt1 : 4;
+               u32 cssid : 8;
+               u32 : 8;
+               u32 first_cun : 8;
+               u32 : 24;
+               u32 last_cun : 8;
+               u32 : 32;
+               struct chsc_header response;
+               u8 data[PAGE_SIZE - 20];
+       } __attribute__ ((packed)) *scucd_area;
+
+       scucd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!scucd_area)
+               return -ENOMEM;
+       cd = kzalloc(sizeof(*cd), GFP_KERNEL);
+       if (!cd) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
+       if (copy_from_user(cd, user_cd, sizeof(*cd))) {
+               ret = -EFAULT;
+               goto out_free;
+       }
+       scucd_area->request.length = 0x0010;
+       scucd_area->request.code = 0x0028;
+       scucd_area->m = cd->m;
+       scucd_area->fmt1 = cd->fmt;
+       scucd_area->cssid = cd->cssid;
+       scucd_area->first_cun = cd->cun;
+       scucd_area->last_cun = cd->cun;
+
+       ccode = chsc(scucd_area);
+       if (ccode != 0) {
+               ret = -EIO;
+               goto out_free;
+       }
+       if (scucd_area->response.code != 0x0001) {
+               ret = -EIO;
+               CHSC_MSG(0, "scucd: response code=%x\n",
+                        scucd_area->response.code);
+               goto out_free;
+       }
+       memcpy(&cd->cucb, &scucd_area->response, scucd_area->response.length);
+       if (copy_to_user(user_cd, cd, sizeof(*cd)))
+               ret = -EFAULT;
+       else
+               ret = 0;
+out_free:
+       kfree(cd);
+       free_page((unsigned long)scucd_area);
+       return ret;
+}
+
+static int chsc_ioctl_info_sch_cu(void __user *user_cud)
+{
+       struct chsc_sch_cud *cud;
+       int ret, ccode;
+       struct {
+               struct chsc_header request;
+               u32 : 2;
+               u32 m : 1;
+               u32 : 5;
+               u32 fmt1 : 4;
+               u32 : 2;
+               u32 ssid : 2;
+               u32 first_sch : 16;
+               u32 : 8;
+               u32 cssid : 8;
+               u32 last_sch : 16;
+               u32 : 32;
+               struct chsc_header response;
+               u8 data[PAGE_SIZE - 20];
+       } __attribute__ ((packed)) *sscud_area;
+
+       sscud_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!sscud_area)
+               return -ENOMEM;
+       cud = kzalloc(sizeof(*cud), GFP_KERNEL);
+       if (!cud) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
+       if (copy_from_user(cud, user_cud, sizeof(*cud))) {
+               ret = -EFAULT;
+               goto out_free;
+       }
+       sscud_area->request.length = 0x0010;
+       sscud_area->request.code = 0x0006;
+       sscud_area->m = cud->schid.m;
+       sscud_area->fmt1 = cud->fmt;
+       sscud_area->ssid = cud->schid.ssid;
+       sscud_area->first_sch = cud->schid.sch_no;
+       sscud_area->cssid = cud->schid.cssid;
+       sscud_area->last_sch = cud->schid.sch_no;
+
+       ccode = chsc(sscud_area);
+       if (ccode != 0) {
+               ret = -EIO;
+               goto out_free;
+       }
+       if (sscud_area->response.code != 0x0001) {
+               ret = -EIO;
+               CHSC_MSG(0, "sscud: response code=%x\n",
+                        sscud_area->response.code);
+               goto out_free;
+       }
+       memcpy(&cud->scub, &sscud_area->response, sscud_area->response.length);
+       if (copy_to_user(user_cud, cud, sizeof(*cud)))
+               ret = -EFAULT;
+       else
+               ret = 0;
+out_free:
+       kfree(cud);
+       free_page((unsigned long)sscud_area);
+       return ret;
+}
+
+static int chsc_ioctl_conf_info(void __user *user_ci)
+{
+       struct chsc_conf_info *ci;
+       int ret, ccode;
+       struct {
+               struct chsc_header request;
+               u32 : 2;
+               u32 m : 1;
+               u32 : 1;
+               u32 fmt1 : 4;
+               u32 cssid : 8;
+               u32 : 6;
+               u32 ssid : 2;
+               u32 : 8;
+               u64 : 64;
+               struct chsc_header response;
+               u8 data[PAGE_SIZE - 20];
+       } __attribute__ ((packed)) *sci_area;
+
+       sci_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!sci_area)
+               return -ENOMEM;
+       ci = kzalloc(sizeof(*ci), GFP_KERNEL);
+       if (!ci) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
+       if (copy_from_user(ci, user_ci, sizeof(*ci))) {
+               ret = -EFAULT;
+               goto out_free;
+       }
+       sci_area->request.length = 0x0010;
+       sci_area->request.code = 0x0012;
+       sci_area->m = ci->id.m;
+       sci_area->fmt1 = ci->fmt;
+       sci_area->cssid = ci->id.cssid;
+       sci_area->ssid = ci->id.ssid;
+
+       ccode = chsc(sci_area);
+       if (ccode != 0) {
+               ret = -EIO;
+               goto out_free;
+       }
+       if (sci_area->response.code != 0x0001) {
+               ret = -EIO;
+               CHSC_MSG(0, "sci: response code=%x\n",
+                        sci_area->response.code);
+               goto out_free;
+       }
+       memcpy(&ci->scid, &sci_area->response, sci_area->response.length);
+       if (copy_to_user(user_ci, ci, sizeof(*ci)))
+               ret = -EFAULT;
+       else
+               ret = 0;
+out_free:
+       kfree(ci);
+       free_page((unsigned long)sci_area);
+       return ret;
+}
+
+static int chsc_ioctl_conf_comp_list(void __user *user_ccl)
+{
+       struct chsc_comp_list *ccl;
+       int ret, ccode;
+       struct {
+               struct chsc_header request;
+               u32 ctype : 8;
+               u32 : 4;
+               u32 fmt : 4;
+               u32 : 16;
+               u64 : 64;
+               u32 list_parm[2];
+               u64 : 64;
+               struct chsc_header response;
+               u8 data[PAGE_SIZE - 36];
+       } __attribute__ ((packed)) *sccl_area;
+       struct {
+               u32 m : 1;
+               u32 : 31;
+               u32 cssid : 8;
+               u32 : 16;
+               u32 chpid : 8;
+       } __attribute__ ((packed)) *chpid_parm;
+       struct {
+               u32 f_cssid : 8;
+               u32 l_cssid : 8;
+               u32 : 16;
+               u32 res;
+       } __attribute__ ((packed)) *cssids_parm;
+
+       sccl_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!sccl_area)
+               return -ENOMEM;
+       ccl = kzalloc(sizeof(*ccl), GFP_KERNEL);
+       if (!ccl) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
+       if (copy_from_user(ccl, user_ccl, sizeof(*ccl))) {
+               ret = -EFAULT;
+               goto out_free;
+       }
+       sccl_area->request.length = 0x0020;
+       sccl_area->request.code = 0x0030;
+       sccl_area->fmt = ccl->req.fmt;
+       sccl_area->ctype = ccl->req.ctype;
+       switch (sccl_area->ctype) {
+       case CCL_CU_ON_CHP:
+       case CCL_IOP_CHP:
+               chpid_parm = (void *)&sccl_area->list_parm;
+               chpid_parm->m = ccl->req.chpid.m;
+               chpid_parm->cssid = ccl->req.chpid.chp.cssid;
+               chpid_parm->chpid = ccl->req.chpid.chp.id;
+               break;
+       case CCL_CSS_IMG:
+       case CCL_CSS_IMG_CONF_CHAR:
+               cssids_parm = (void *)&sccl_area->list_parm;
+               cssids_parm->f_cssid = ccl->req.cssids.f_cssid;
+               cssids_parm->l_cssid = ccl->req.cssids.l_cssid;
+               break;
+       }
+       ccode = chsc(sccl_area);
+       if (ccode != 0) {
+               ret = -EIO;
+               goto out_free;
+       }
+       if (sccl_area->response.code != 0x0001) {
+               ret = -EIO;
+               CHSC_MSG(0, "sccl: response code=%x\n",
+                        sccl_area->response.code);
+               goto out_free;
+       }
+       memcpy(&ccl->sccl, &sccl_area->response, sccl_area->response.length);
+       if (copy_to_user(user_ccl, ccl, sizeof(*ccl)))
+               ret = -EFAULT;
+       else
+               ret = 0;
+out_free:
+       kfree(ccl);
+       free_page((unsigned long)sccl_area);
+       return ret;
+}
+
+static int chsc_ioctl_chpd(void __user *user_chpd)
+{
+       struct chsc_cpd_info *chpd;
+       int ret;
+
+       chpd = kzalloc(sizeof(*chpd), GFP_KERNEL);
+       if (!chpd)
+               return -ENOMEM;
+       if (copy_from_user(chpd, user_chpd, sizeof(*chpd))) {
+               ret = -EFAULT;
+               goto out_free;
+       }
+       ret = chsc_determine_channel_path_desc(chpd->chpid, chpd->fmt,
+                                              chpd->rfmt, chpd->c, chpd->m,
+                                              &chpd->chpdb);
+       if (ret)
+               goto out_free;
+       if (copy_to_user(user_chpd, chpd, sizeof(*chpd)))
+               ret = -EFAULT;
+out_free:
+       kfree(chpd);
+       return ret;
+}
+
+static int chsc_ioctl_dcal(void __user *user_dcal)
+{
+       struct chsc_dcal *dcal;
+       int ret, ccode;
+       struct {
+               struct chsc_header request;
+               u32 atype : 8;
+               u32 : 4;
+               u32 fmt : 4;
+               u32 : 16;
+               u32 res0[2];
+               u32 list_parm[2];
+               u32 res1[2];
+               struct chsc_header response;
+               u8 data[PAGE_SIZE - 36];
+       } __attribute__ ((packed)) *sdcal_area;
+
+       sdcal_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!sdcal_area)
+               return -ENOMEM;
+       dcal = kzalloc(sizeof(*dcal), GFP_KERNEL);
+       if (!dcal) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
+       if (copy_from_user(dcal, user_dcal, sizeof(*dcal))) {
+               ret = -EFAULT;
+               goto out_free;
+       }
+       sdcal_area->request.length = 0x0020;
+       sdcal_area->request.code = 0x0034;
+       sdcal_area->atype = dcal->req.atype;
+       sdcal_area->fmt = dcal->req.fmt;
+       memcpy(&sdcal_area->list_parm, &dcal->req.list_parm,
+              sizeof(sdcal_area->list_parm));
+
+       ccode = chsc(sdcal_area);
+       if (ccode != 0) {
+               ret = -EIO;
+               goto out_free;
+       }
+       if (sdcal_area->response.code != 0x0001) {
+               ret = -EIO;
+               CHSC_MSG(0, "sdcal: response code=%x\n",
+                        sdcal_area->response.code);
+               goto out_free;
+       }
+       memcpy(&dcal->sdcal, &sdcal_area->response,
+              sdcal_area->response.length);
+       if (copy_to_user(user_dcal, dcal, sizeof(*dcal)))
+               ret = -EFAULT;
+       else
+               ret = 0;
+out_free:
+       kfree(dcal);
+       free_page((unsigned long)sdcal_area);
+       return ret;
+}
+
+static long chsc_ioctl(struct file *filp, unsigned int cmd,
+                      unsigned long arg)
+{
+       CHSC_MSG(2, "chsc_ioctl called, cmd=%x\n", cmd);
+       switch (cmd) {
+       case CHSC_START:
+               return chsc_ioctl_start((void __user *)arg);
+       case CHSC_INFO_CHANNEL_PATH:
+               return chsc_ioctl_info_channel_path((void __user *)arg);
+       case CHSC_INFO_CU:
+               return chsc_ioctl_info_cu((void __user *)arg);
+       case CHSC_INFO_SCH_CU:
+               return chsc_ioctl_info_sch_cu((void __user *)arg);
+       case CHSC_INFO_CI:
+               return chsc_ioctl_conf_info((void __user *)arg);
+       case CHSC_INFO_CCL:
+               return chsc_ioctl_conf_comp_list((void __user *)arg);
+       case CHSC_INFO_CPD:
+               return chsc_ioctl_chpd((void __user *)arg);
+       case CHSC_INFO_DCAL:
+               return chsc_ioctl_dcal((void __user *)arg);
+       default: /* unknown ioctl number */
+               return -ENOIOCTLCMD;
+       }
+}
+
+static const struct file_operations chsc_fops = {
+       .owner = THIS_MODULE,
+       .unlocked_ioctl = chsc_ioctl,
+       .compat_ioctl = chsc_ioctl,
+};
+
+static struct miscdevice chsc_misc_device = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "chsc",
+       .fops = &chsc_fops,
+};
+
+static int __init chsc_misc_init(void)
+{
+       return misc_register(&chsc_misc_device);
+}
+
+static void chsc_misc_cleanup(void)
+{
+       misc_deregister(&chsc_misc_device);
+}
+
+static int __init chsc_sch_init(void)
+{
+       int ret;
+
+       ret = chsc_init_dbfs();
+       if (ret)
+               return ret;
+       isc_register(CHSC_SCH_ISC);
+       ret = chsc_init_sch_driver();
+       if (ret)
+               goto out_dbf;
+       ret = chsc_misc_init();
+       if (ret)
+               goto out_driver;
+       return ret;
+out_driver:
+       chsc_cleanup_sch_driver();
+out_dbf:
+       isc_unregister(CHSC_SCH_ISC);
+       chsc_remove_dbfs();
+       return ret;
+}
+
+static void __exit chsc_sch_exit(void)
+{
+       chsc_misc_cleanup();
+       chsc_cleanup_sch_driver();
+       isc_unregister(CHSC_SCH_ISC);
+       chsc_remove_dbfs();
+}
+
+module_init(chsc_sch_init);
+module_exit(chsc_sch_exit);
diff --git a/drivers/s390/cio/chsc_sch.h b/drivers/s390/cio/chsc_sch.h
new file mode 100644 (file)
index 0000000..589ebfa
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _CHSC_SCH_H
+#define _CHSC_SCH_H
+
+struct chsc_request {
+       struct completion completion;
+       struct irb irb;
+};
+
+struct chsc_private {
+       struct chsc_request *request;
+};
+
+#endif
index b32d7eb3d81a4d8ee3dc29fb587bc78f91b5b7e8..33bff8fec7d10b0a5b02cb0ed0824cdd210b2256 100644 (file)
@@ -2,7 +2,7 @@
  *  drivers/s390/cio/cio.c
  *   S/390 common I/O routines -- low level i/o calls
  *
- *    Copyright (C) IBM Corp. 1999,2006
+ *    Copyright IBM Corp. 1999,2008
  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
  *              Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Arnd Bergmann (arndb@de.ibm.com)
@@ -24,7 +24,9 @@
 #include <asm/ipl.h>
 #include <asm/chpid.h>
 #include <asm/airq.h>
+#include <asm/isc.h>
 #include <asm/cpu.h>
+#include <asm/fcx.h>
 #include "cio.h"
 #include "css.h"
 #include "chsc.h"
@@ -72,7 +74,6 @@ out_unregister:
                debug_unregister(cio_debug_trace_id);
        if (cio_debug_crw_id)
                debug_unregister(cio_debug_crw_id);
-       printk(KERN_WARNING"cio: could not initialize debugging\n");
        return -1;
 }
 
@@ -128,7 +129,7 @@ cio_tpi(void)
        local_bh_disable();
        irq_enter ();
        spin_lock(sch->lock);
-       memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw));
+       memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw));
        if (sch->driver && sch->driver->irq)
                sch->driver->irq(sch);
        spin_unlock(sch->lock);
@@ -167,30 +168,30 @@ cio_start_key (struct subchannel *sch,    /* subchannel structure */
 {
        char dbf_txt[15];
        int ccode;
-       struct orb *orb;
+       union orb *orb;
 
        CIO_TRACE_EVENT(4, "stIO");
        CIO_TRACE_EVENT(4, sch->dev.bus_id);
 
        orb = &to_io_private(sch)->orb;
        /* sch is always under 2G. */
-       orb->intparm = (u32)(addr_t)sch;
-       orb->fmt = 1;
+       orb->cmd.intparm = (u32)(addr_t)sch;
+       orb->cmd.fmt = 1;
 
-       orb->pfch = sch->options.prefetch == 0;
-       orb->spnd = sch->options.suspend;
-       orb->ssic = sch->options.suspend && sch->options.inter;
-       orb->lpm = (lpm != 0) ? lpm : sch->lpm;
+       orb->cmd.pfch = sch->options.prefetch == 0;
+       orb->cmd.spnd = sch->options.suspend;
+       orb->cmd.ssic = sch->options.suspend && sch->options.inter;
+       orb->cmd.lpm = (lpm != 0) ? lpm : sch->lpm;
 #ifdef CONFIG_64BIT
        /*
         * for 64 bit we always support 64 bit IDAWs with 4k page size only
         */
-       orb->c64 = 1;
-       orb->i2k = 0;
+       orb->cmd.c64 = 1;
+       orb->cmd.i2k = 0;
 #endif
-       orb->key = key >> 4;
+       orb->cmd.key = key >> 4;
        /* issue "Start Subchannel" */
-       orb->cpa = (__u32) __pa(cpa);
+       orb->cmd.cpa = (__u32) __pa(cpa);
        ccode = ssch(sch->schid, orb);
 
        /* process condition code */
@@ -202,7 +203,7 @@ cio_start_key (struct subchannel *sch,      /* subchannel structure */
                /*
                 * initialize device status information
                 */
-               sch->schib.scsw.actl |= SCSW_ACTL_START_PEND;
+               sch->schib.scsw.cmd.actl |= SCSW_ACTL_START_PEND;
                return 0;
        case 1:         /* status pending */
        case 2:         /* busy */
@@ -237,7 +238,7 @@ cio_resume (struct subchannel *sch)
 
        switch (ccode) {
        case 0:
-               sch->schib.scsw.actl |= SCSW_ACTL_RESUME_PEND;
+               sch->schib.scsw.cmd.actl |= SCSW_ACTL_RESUME_PEND;
                return 0;
        case 1:
                return -EBUSY;
@@ -277,7 +278,7 @@ cio_halt(struct subchannel *sch)
 
        switch (ccode) {
        case 0:
-               sch->schib.scsw.actl |= SCSW_ACTL_HALT_PEND;
+               sch->schib.scsw.cmd.actl |= SCSW_ACTL_HALT_PEND;
                return 0;
        case 1:         /* status pending */
        case 2:         /* busy */
@@ -312,7 +313,7 @@ cio_clear(struct subchannel *sch)
 
        switch (ccode) {
        case 0:
-               sch->schib.scsw.actl |= SCSW_ACTL_CLEAR_PEND;
+               sch->schib.scsw.cmd.actl |= SCSW_ACTL_CLEAR_PEND;
                return 0;
        default:                /* device not operational */
                return -ENODEV;
@@ -387,8 +388,10 @@ cio_modify (struct subchannel *sch)
        return ret;
 }
 
-/*
- * Enable subchannel.
+/**
+ * cio_enable_subchannel - enable a subchannel.
+ * @sch: subchannel to be enabled
+ * @intparm: interruption parameter to set
  */
 int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
 {
@@ -434,12 +437,13 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm)
        CIO_TRACE_EVENT (2, dbf_txt);
        return ret;
 }
+EXPORT_SYMBOL_GPL(cio_enable_subchannel);
 
-/*
- * Disable subchannel.
+/**
+ * cio_disable_subchannel - disable a subchannel.
+ * @sch: subchannel to disable
  */
-int
-cio_disable_subchannel (struct subchannel *sch)
+int cio_disable_subchannel(struct subchannel *sch)
 {
        char dbf_txt[15];
        int ccode;
@@ -455,7 +459,7 @@ cio_disable_subchannel (struct subchannel *sch)
        if (ccode == 3)         /* Not operational. */
                return -ENODEV;
 
-       if (sch->schib.scsw.actl != 0)
+       if (scsw_actl(&sch->schib.scsw) != 0)
                /*
                 * the disable function must not be called while there are
                 *  requests pending for completion !
@@ -484,6 +488,7 @@ cio_disable_subchannel (struct subchannel *sch)
        CIO_TRACE_EVENT (2, dbf_txt);
        return ret;
 }
+EXPORT_SYMBOL_GPL(cio_disable_subchannel);
 
 int cio_create_sch_lock(struct subchannel *sch)
 {
@@ -494,27 +499,61 @@ int cio_create_sch_lock(struct subchannel *sch)
        return 0;
 }
 
-/*
- * cio_validate_subchannel()
+static int cio_check_devno_blacklisted(struct subchannel *sch)
+{
+       if (is_blacklisted(sch->schid.ssid, sch->schib.pmcw.dev)) {
+               /*
+                * This device must not be known to Linux. So we simply
+                * say that there is no device and return ENODEV.
+                */
+               CIO_MSG_EVENT(6, "Blacklisted device detected "
+                             "at devno %04X, subchannel set %x\n",
+                             sch->schib.pmcw.dev, sch->schid.ssid);
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static int cio_validate_io_subchannel(struct subchannel *sch)
+{
+       /* Initialization for io subchannels. */
+       if (!css_sch_is_valid(&sch->schib))
+               return -ENODEV;
+
+       /* Devno is valid. */
+       return cio_check_devno_blacklisted(sch);
+}
+
+static int cio_validate_msg_subchannel(struct subchannel *sch)
+{
+       /* Initialization for message subchannels. */
+       if (!css_sch_is_valid(&sch->schib))
+               return -ENODEV;
+
+       /* Devno is valid. */
+       return cio_check_devno_blacklisted(sch);
+}
+
+/**
+ * cio_validate_subchannel - basic validation of subchannel
+ * @sch: subchannel structure to be filled out
+ * @schid: subchannel id
  *
  * Find out subchannel type and initialize struct subchannel.
  * Return codes:
- *   SUBCHANNEL_TYPE_IO for a normal io subchannel
- *   SUBCHANNEL_TYPE_CHSC for a chsc subchannel
- *   SUBCHANNEL_TYPE_MESSAGE for a messaging subchannel
- *   SUBCHANNEL_TYPE_ADM for a adm(?) subchannel
+ *   0 on success
  *   -ENXIO for non-defined subchannels
- *   -ENODEV for subchannels with invalid device number or blacklisted devices
+ *   -ENODEV for invalid subchannels or blacklisted devices
+ *   -EIO for subchannels in an invalid subchannel set
  */
-int
-cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
+int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid)
 {
        char dbf_txt[15];
        int ccode;
        int err;
 
-       sprintf (dbf_txt, "valsch%x", schid.sch_no);
-       CIO_TRACE_EVENT (4, dbf_txt);
+       sprintf(dbf_txt, "valsch%x", schid.sch_no);
+       CIO_TRACE_EVENT(4, dbf_txt);
 
        /* Nuke all fields. */
        memset(sch, 0, sizeof(struct subchannel));
@@ -546,67 +585,21 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
        /* Copy subchannel type from path management control word. */
        sch->st = sch->schib.pmcw.st;
 
-       /*
-        * ... just being curious we check for non I/O subchannels
-        */
-       if (sch->st != 0) {
-               CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports "
-                             "non-I/O subchannel type %04X\n",
-                             sch->schid.ssid, sch->schid.sch_no, sch->st);
-               /* We stop here for non-io subchannels. */
-               err = sch->st;
-               goto out;
-       }
-
-       /* Initialization for io subchannels. */
-       if (!css_sch_is_valid(&sch->schib)) {
-               err = -ENODEV;
-               goto out;
+       switch (sch->st) {
+       case SUBCHANNEL_TYPE_IO:
+               err = cio_validate_io_subchannel(sch);
+               break;
+       case SUBCHANNEL_TYPE_MSG:
+               err = cio_validate_msg_subchannel(sch);
+               break;
+       default:
+               err = 0;
        }
-
-       /* Devno is valid. */
-       if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) {
-               /*
-                * This device must not be known to Linux. So we simply
-                * say that there is no device and return ENODEV.
-                */
-               CIO_MSG_EVENT(6, "Blacklisted device detected "
-                             "at devno %04X, subchannel set %x\n",
-                             sch->schib.pmcw.dev, sch->schid.ssid);
-               err = -ENODEV;
+       if (err)
                goto out;
-       }
-       if (cio_is_console(sch->schid)) {
-               sch->opm = 0xff;
-               sch->isc = 1;
-       } else {
-               sch->opm = chp_get_sch_opm(sch);
-               sch->isc = 3;
-       }
-       sch->lpm = sch->schib.pmcw.pam & sch->opm;
-
-       CIO_MSG_EVENT(6, "Detected device %04x on subchannel 0.%x.%04X "
-                     "- PIM = %02X, PAM = %02X, POM = %02X\n",
-                     sch->schib.pmcw.dev, sch->schid.ssid,
-                     sch->schid.sch_no, sch->schib.pmcw.pim,
-                     sch->schib.pmcw.pam, sch->schib.pmcw.pom);
 
-       /*
-        * We now have to initially ...
-        *  ... enable "concurrent sense"
-        *  ... enable "multipath mode" if more than one
-        *        CHPID is available. This is done regardless
-        *        whether multiple paths are available for us.
-        */
-       sch->schib.pmcw.csense = 1;     /* concurrent sense */
-       sch->schib.pmcw.ena = 0;
-       if ((sch->lpm & (sch->lpm - 1)) != 0)
-               sch->schib.pmcw.mp = 1; /* multipath mode */
-       /* clean up possible residual cmf stuff */
-       sch->schib.pmcw.mme = 0;
-       sch->schib.pmcw.mbfc = 0;
-       sch->schib.pmcw.mbi = 0;
-       sch->schib.mba = 0;
+       CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n",
+                     sch->schid.ssid, sch->schid.sch_no, sch->st);
        return 0;
 out:
        if (!cio_is_console(schid))
@@ -647,7 +640,7 @@ do_IRQ (struct pt_regs *regs)
                 */
                if (tpi_info->adapter_IO == 1 &&
                    tpi_info->int_type == IO_INTERRUPT_TYPE) {
-                       do_adapter_IO();
+                       do_adapter_IO(tpi_info->isc);
                        continue;
                }
                sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
@@ -706,9 +699,9 @@ void wait_cons_dev(void)
        if (!console_subchannel_in_use)
                return;
 
-       /* disable all but isc 1 (console device) */
+       /* disable all but the console isc */
        __ctl_store (save_cr6, 6, 6);
-       cr6 = 0x40000000;
+       cr6 = 1UL << (31 - CONSOLE_ISC);
        __ctl_load (cr6, 6, 6);
 
        do {
@@ -716,7 +709,7 @@ void wait_cons_dev(void)
                if (!cio_tpi())
                        cpu_relax();
                spin_lock(console_subchannel.lock);
-       } while (console_subchannel.schib.scsw.actl != 0);
+       } while (console_subchannel.schib.scsw.cmd.actl != 0);
        /*
         * restore previous isc value
         */
@@ -761,7 +754,6 @@ cio_get_console_sch_no(void)
                /* unlike in 2.4, we cannot autoprobe here, since
                 * the channel subsystem is not fully initialized.
                 * With some luck, the HWC console can take over */
-               printk(KERN_WARNING "cio: No ccw console found!\n");
                return -1;
        }
        return console_irq;
@@ -778,6 +770,7 @@ cio_probe_console(void)
        sch_no = cio_get_console_sch_no();
        if (sch_no == -1) {
                console_subchannel_in_use = 0;
+               printk(KERN_WARNING "cio: No ccw console found!\n");
                return ERR_PTR(-ENODEV);
        }
        memset(&console_subchannel, 0, sizeof(struct subchannel));
@@ -790,15 +783,15 @@ cio_probe_console(void)
        }
 
        /*
-        * enable console I/O-interrupt subclass 1
+        * enable console I/O-interrupt subclass
         */
-       ctl_set_bit(6, 30);
-       console_subchannel.isc = 1;
-       console_subchannel.schib.pmcw.isc = 1;
+       isc_register(CONSOLE_ISC);
+       console_subchannel.schib.pmcw.isc = CONSOLE_ISC;
        console_subchannel.schib.pmcw.intparm =
                (u32)(addr_t)&console_subchannel;
        ret = cio_modify(&console_subchannel);
        if (ret) {
+               isc_unregister(CONSOLE_ISC);
                console_subchannel_in_use = 0;
                return ERR_PTR(ret);
        }
@@ -810,7 +803,7 @@ cio_release_console(void)
 {
        console_subchannel.schib.pmcw.intparm = 0;
        cio_modify(&console_subchannel);
-       ctl_clear_bit(6, 24);
+       isc_unregister(CONSOLE_ISC);
        console_subchannel_in_use = 0;
 }
 
@@ -864,7 +857,7 @@ static void udelay_reset(unsigned long usecs)
 }
 
 static int
-__clear_subchannel_easy(struct subchannel_id schid)
+__clear_io_subchannel_easy(struct subchannel_id schid)
 {
        int retry;
 
@@ -883,6 +876,12 @@ __clear_subchannel_easy(struct subchannel_id schid)
        return -EBUSY;
 }
 
+static void __clear_chsc_subchannel_easy(void)
+{
+       /* It seems we can only wait for a bit here :/ */
+       udelay_reset(100);
+}
+
 static int pgm_check_occured;
 
 static void cio_reset_pgm_check_handler(void)
@@ -921,11 +920,22 @@ static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data)
        case -ENODEV:
                break;
        default: /* -EBUSY */
-               if (__clear_subchannel_easy(schid))
-                       break; /* give up... */
+               switch (schib.pmcw.st) {
+               case SUBCHANNEL_TYPE_IO:
+                       if (__clear_io_subchannel_easy(schid))
+                               goto out; /* give up... */
+                       break;
+               case SUBCHANNEL_TYPE_CHSC:
+                       __clear_chsc_subchannel_easy();
+                       break;
+               default:
+                       /* No default clear strategy */
+                       break;
+               }
                stsch(schid, &schib);
                __disable_subchannel_easy(schid, &schib);
        }
+out:
        return 0;
 }
 
@@ -1068,3 +1078,61 @@ int __init cio_get_iplinfo(struct cio_iplinfo *iplinfo)
        iplinfo->is_qdio = schib.pmcw.qf;
        return 0;
 }
+
+/**
+ * cio_tm_start_key - perform start function
+ * @sch: subchannel on which to perform the start function
+ * @tcw: transport-command word to be started
+ * @lpm: mask of paths to use
+ * @key: storage key to use for storage access
+ *
+ * Start the tcw on the given subchannel. Return zero on success, non-zero
+ * otherwise.
+ */
+int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key)
+{
+       int cc;
+       union orb *orb = &to_io_private(sch)->orb;
+
+       memset(orb, 0, sizeof(union orb));
+       orb->tm.intparm = (u32) (addr_t) sch;
+       orb->tm.key = key >> 4;
+       orb->tm.b = 1;
+       orb->tm.lpm = lpm ? lpm : sch->lpm;
+       orb->tm.tcw = (u32) (addr_t) tcw;
+       cc = ssch(sch->schid, orb);
+       switch (cc) {
+       case 0:
+               return 0;
+       case 1:
+       case 2:
+               return -EBUSY;
+       default:
+               return cio_start_handle_notoper(sch, lpm);
+       }
+}
+
+/**
+ * cio_tm_intrg - perform interrogate function
+ * @sch - subchannel on which to perform the interrogate function
+ *
+ * If the specified subchannel is running in transport-mode, perform the
+ * interrogate function. Return zero on success, non-zero otherwie.
+ */
+int cio_tm_intrg(struct subchannel *sch)
+{
+       int cc;
+
+       if (!to_io_private(sch)->orb.tm.b)
+               return -EINVAL;
+       cc = xsch(sch->schid);
+       switch (cc) {
+       case 0:
+       case 2:
+               return 0;
+       case 1:
+               return -EBUSY;
+       default:
+               return -ENODEV;
+       }
+}
index 6e933aebe01308e2882f45f0320c72a9612e133d..3b236d20e83543ec127a279d132ec7f51df63958 100644 (file)
@@ -3,9 +3,12 @@
 
 #include <linux/mutex.h>
 #include <linux/device.h>
+#include <linux/mod_devicetable.h>
 #include <asm/chpid.h>
+#include <asm/cio.h>
+#include <asm/fcx.h>
+#include <asm/schid.h>
 #include "chsc.h"
-#include "schid.h"
 
 /*
  * path management control word
@@ -13,7 +16,7 @@
 struct pmcw {
        u32 intparm;            /* interruption parameter */
        u32 qf   : 1;           /* qdio facility */
-       u32 res0 : 1;           /* reserved zeros */
+       u32 w    : 1;
        u32 isc  : 3;           /* interruption sublass */
        u32 res5 : 3;           /* reserved zeros */
        u32 ena  : 1;           /* enabled */
@@ -47,7 +50,7 @@ struct pmcw {
  */
 struct schib {
        struct pmcw pmcw;        /* path management control word */
-       struct scsw scsw;        /* subchannel status word */
+       union scsw scsw;         /* subchannel status word */
        __u64 mba;               /* measurement block address */
        __u8 mda[4];             /* model dependent area */
 } __attribute__ ((packed,aligned(4)));
@@ -99,8 +102,11 @@ extern int cio_set_options (struct subchannel *, int);
 extern int cio_get_options (struct subchannel *);
 extern int cio_modify (struct subchannel *);
 
+int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key);
+int cio_tm_intrg(struct subchannel *sch);
+
 int cio_create_sch_lock(struct subchannel *);
-void do_adapter_IO(void);
+void do_adapter_IO(u8 isc);
 void do_IRQ(struct pt_regs *);
 
 /* Use with care. */
index 2808b6833b9edea7fceb7263017316e61dedbbd3..a90b28c0be5707f64bdd6a058ac416272756265c 100644 (file)
@@ -341,12 +341,12 @@ static int cmf_copy_block(struct ccw_device *cdev)
        if (stsch(sch->schid, &sch->schib))
                return -ENODEV;
 
-       if (sch->schib.scsw.fctl & SCSW_FCTL_START_FUNC) {
+       if (scsw_fctl(&sch->schib.scsw) & SCSW_FCTL_START_FUNC) {
                /* Don't copy if a start function is in progress. */
-               if ((!(sch->schib.scsw.actl & SCSW_ACTL_SUSPENDED)) &&
-                   (sch->schib.scsw.actl &
+               if ((!(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_SUSPENDED)) &&
+                   (scsw_actl(&sch->schib.scsw) &
                     (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)) &&
-                   (!(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)))
+                   (!(scsw_stctl(&sch->schib.scsw) & SCSW_STCTL_SEC_STATUS)))
                        return -EBUSY;
        }
        cmb_data = cdev->private->cmb;
@@ -612,9 +612,6 @@ static int alloc_cmb(struct ccw_device *cdev)
                        free_pages((unsigned long)mem, get_order(size));
                } else if (!mem) {
                        /* no luck */
-                       printk(KERN_WARNING "cio: failed to allocate area "
-                              "for measuring %d subchannels\n",
-                              cmb_area.num_channels);
                        ret = -ENOMEM;
                        goto out;
                } else {
@@ -1230,13 +1227,9 @@ static ssize_t cmb_enable_store(struct device *dev,
        switch (val) {
        case 0:
                ret = disable_cmf(cdev);
-               if (ret)
-                       dev_info(&cdev->dev, "disable_cmf failed (%d)\n", ret);
                break;
        case 1:
                ret = enable_cmf(cdev);
-               if (ret && ret != -EBUSY)
-                       dev_info(&cdev->dev, "enable_cmf failed (%d)\n", ret);
                break;
        }
 
@@ -1344,8 +1337,7 @@ static int __init init_cmf(void)
         * to basic mode.
         */
        if (format == CMF_AUTODETECT) {
-               if (!css_characteristics_avail ||
-                   !css_general_characteristics.ext_mb) {
+               if (!css_general_characteristics.ext_mb) {
                        format = CMF_BASIC;
                } else {
                        format = CMF_EXTENDED;
@@ -1365,8 +1357,6 @@ static int __init init_cmf(void)
                cmbops = &cmbops_extended;
                break;
        default:
-               printk(KERN_ERR "cio: Invalid format %d for channel "
-                       "measurement facility\n", format);
                return 1;
        }
 
index a76956512b2d41963a0bd89ddba91a69f7b2553a..46c021d880dc5ee7441cd11f8e885bf54d79b7dd 100644 (file)
@@ -2,8 +2,7 @@
  *  drivers/s390/cio/css.c
  *  driver for channel subsystem
  *
- *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
- *                      IBM Corporation
+ *    Copyright IBM Corp. 2002,2008
  *    Author(s): Arnd Bergmann (arndb@de.ibm.com)
  *              Cornelia Huck (cornelia.huck@de.ibm.com)
  */
@@ -14,7 +13,9 @@
 #include <linux/errno.h>
 #include <linux/list.h>
 #include <linux/reboot.h>
+#include <asm/isc.h>
 
+#include "../s390mach.h"
 #include "css.h"
 #include "cio.h"
 #include "cio_debug.h"
@@ -30,8 +31,6 @@ static int max_ssid = 0;
 
 struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1];
 
-int css_characteristics_avail = 0;
-
 int
 for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
 {
@@ -121,25 +120,6 @@ css_alloc_subchannel(struct subchannel_id schid)
                kfree(sch);
                return ERR_PTR(ret);
        }
-
-       if (sch->st != SUBCHANNEL_TYPE_IO) {
-               /* For now we ignore all non-io subchannels. */
-               kfree(sch);
-               return ERR_PTR(-EINVAL);
-       }
-
-       /* 
-        * Set intparm to subchannel address.
-        * This is fine even on 64bit since the subchannel is always located
-        * under 2G.
-        */
-       sch->schib.pmcw.intparm = (u32)(addr_t)sch;
-       ret = cio_modify(sch);
-       if (ret) {
-               kfree(sch->lock);
-               kfree(sch);
-               return ERR_PTR(ret);
-       }
        return sch;
 }
 
@@ -177,12 +157,18 @@ static int css_sch_device_register(struct subchannel *sch)
        return ret;
 }
 
+/**
+ * css_sch_device_unregister - unregister a subchannel
+ * @sch: subchannel to be unregistered
+ */
 void css_sch_device_unregister(struct subchannel *sch)
 {
        mutex_lock(&sch->reg_mutex);
-       device_unregister(&sch->dev);
+       if (device_is_registered(&sch->dev))
+               device_unregister(&sch->dev);
        mutex_unlock(&sch->reg_mutex);
 }
+EXPORT_SYMBOL_GPL(css_sch_device_unregister);
 
 static void ssd_from_pmcw(struct chsc_ssd_info *ssd, struct pmcw *pmcw)
 {
@@ -229,6 +215,41 @@ void css_update_ssd_info(struct subchannel *sch)
        }
 }
 
+static ssize_t type_show(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct subchannel *sch = to_subchannel(dev);
+
+       return sprintf(buf, "%01x\n", sch->st);
+}
+
+static DEVICE_ATTR(type, 0444, type_show, NULL);
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct subchannel *sch = to_subchannel(dev);
+
+       return sprintf(buf, "css:t%01X\n", sch->st);
+}
+
+static DEVICE_ATTR(modalias, 0444, modalias_show, NULL);
+
+static struct attribute *subch_attrs[] = {
+       &dev_attr_type.attr,
+       &dev_attr_modalias.attr,
+       NULL,
+};
+
+static struct attribute_group subch_attr_group = {
+       .attrs = subch_attrs,
+};
+
+static struct attribute_group *default_subch_attr_groups[] = {
+       &subch_attr_group,
+       NULL,
+};
+
 static int css_register_subchannel(struct subchannel *sch)
 {
        int ret;
@@ -237,16 +258,17 @@ static int css_register_subchannel(struct subchannel *sch)
        sch->dev.parent = &channel_subsystems[0]->device;
        sch->dev.bus = &css_bus_type;
        sch->dev.release = &css_subchannel_release;
-       sch->dev.groups = subch_attr_groups;
+       sch->dev.groups = default_subch_attr_groups;
        /*
         * We don't want to generate uevents for I/O subchannels that don't
         * have a working ccw device behind them since they will be
         * unregistered before they can be used anyway, so we delay the add
         * uevent until after device recognition was successful.
+        * Note that we suppress the uevent for all subchannel types;
+        * the subchannel driver can decide itself when it wants to inform
+        * userspace of its existence.
         */
-       if (!cio_is_console(sch->schid))
-               /* Console is special, no need to suppress. */
-               sch->dev.uevent_suppress = 1;
+       sch->dev.uevent_suppress = 1;
        css_update_ssd_info(sch);
        /* make it known to the system */
        ret = css_sch_device_register(sch);
@@ -255,10 +277,19 @@ static int css_register_subchannel(struct subchannel *sch)
                              sch->schid.ssid, sch->schid.sch_no, ret);
                return ret;
        }
+       if (!sch->driver) {
+               /*
+                * No driver matched. Generate the uevent now so that
+                * a fitting driver module may be loaded based on the
+                * modalias.
+                */
+               sch->dev.uevent_suppress = 0;
+               kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
+       }
        return ret;
 }
 
-static int css_probe_device(struct subchannel_id schid)
+int css_probe_device(struct subchannel_id schid)
 {
        int ret;
        struct subchannel *sch;
@@ -301,116 +332,12 @@ int css_sch_is_valid(struct schib *schib)
 {
        if ((schib->pmcw.st == SUBCHANNEL_TYPE_IO) && !schib->pmcw.dnv)
                return 0;
+       if ((schib->pmcw.st == SUBCHANNEL_TYPE_MSG) && !schib->pmcw.w)
+               return 0;
        return 1;
 }
 EXPORT_SYMBOL_GPL(css_sch_is_valid);
 
-static int css_get_subchannel_status(struct subchannel *sch)
-{
-       struct schib schib;
-
-       if (stsch(sch->schid, &schib))
-               return CIO_GONE;
-       if (!css_sch_is_valid(&schib))
-               return CIO_GONE;
-       if (sch->schib.pmcw.dnv && (schib.pmcw.dev != sch->schib.pmcw.dev))
-               return CIO_REVALIDATE;
-       if (!sch->lpm)
-               return CIO_NO_PATH;
-       return CIO_OPER;
-}
-
-static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
-{
-       int event, ret, disc;
-       unsigned long flags;
-       enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE } action;
-
-       spin_lock_irqsave(sch->lock, flags);
-       disc = device_is_disconnected(sch);
-       if (disc && slow) {
-               /* Disconnected devices are evaluated directly only.*/
-               spin_unlock_irqrestore(sch->lock, flags);
-               return 0;
-       }
-       /* No interrupt after machine check - kill pending timers. */
-       device_kill_pending_timer(sch);
-       if (!disc && !slow) {
-               /* Non-disconnected devices are evaluated on the slow path. */
-               spin_unlock_irqrestore(sch->lock, flags);
-               return -EAGAIN;
-       }
-       event = css_get_subchannel_status(sch);
-       CIO_MSG_EVENT(4, "Evaluating schid 0.%x.%04x, event %d, %s, %s path.\n",
-                     sch->schid.ssid, sch->schid.sch_no, event,
-                     disc ? "disconnected" : "normal",
-                     slow ? "slow" : "fast");
-       /* Analyze subchannel status. */
-       action = NONE;
-       switch (event) {
-       case CIO_NO_PATH:
-               if (disc) {
-                       /* Check if paths have become available. */
-                       action = REPROBE;
-                       break;
-               }
-               /* fall through */
-       case CIO_GONE:
-               /* Prevent unwanted effects when opening lock. */
-               cio_disable_subchannel(sch);
-               device_set_disconnected(sch);
-               /* Ask driver what to do with device. */
-               action = UNREGISTER;
-               if (sch->driver && sch->driver->notify) {
-                       spin_unlock_irqrestore(sch->lock, flags);
-                       ret = sch->driver->notify(sch, event);
-                       spin_lock_irqsave(sch->lock, flags);
-                       if (ret)
-                               action = NONE;
-               }
-               break;
-       case CIO_REVALIDATE:
-               /* Device will be removed, so no notify necessary. */
-               if (disc)
-                       /* Reprobe because immediate unregister might block. */
-                       action = REPROBE;
-               else
-                       action = UNREGISTER_PROBE;
-               break;
-       case CIO_OPER:
-               if (disc)
-                       /* Get device operational again. */
-                       action = REPROBE;
-               break;
-       }
-       /* Perform action. */
-       ret = 0;
-       switch (action) {
-       case UNREGISTER:
-       case UNREGISTER_PROBE:
-               /* Unregister device (will use subchannel lock). */
-               spin_unlock_irqrestore(sch->lock, flags);
-               css_sch_device_unregister(sch);
-               spin_lock_irqsave(sch->lock, flags);
-
-               /* Reset intparm to zeroes. */
-               sch->schib.pmcw.intparm = 0;
-               cio_modify(sch);
-               break;
-       case REPROBE:
-               device_trigger_reprobe(sch);
-               break;
-       default:
-               break;
-       }
-       spin_unlock_irqrestore(sch->lock, flags);
-       /* Probe if necessary. */
-       if (action == UNREGISTER_PROBE)
-               ret = css_probe_device(sch->schid);
-
-       return ret;
-}
-
 static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow)
 {
        struct schib schib;
@@ -429,6 +356,21 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow)
        return css_probe_device(schid);
 }
 
+static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
+{
+       int ret = 0;
+
+       if (sch->driver) {
+               if (sch->driver->sch_event)
+                       ret = sch->driver->sch_event(sch, slow);
+               else
+                       dev_dbg(&sch->dev,
+                               "Got subchannel machine check but "
+                               "no sch_event handler provided.\n");
+       }
+       return ret;
+}
+
 static void css_evaluate_subchannel(struct subchannel_id schid, int slow)
 {
        struct subchannel *sch;
@@ -596,18 +538,29 @@ EXPORT_SYMBOL_GPL(css_schedule_reprobe);
 /*
  * Called from the machine check handler for subchannel report words.
  */
-void css_process_crw(int rsid1, int rsid2)
+static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
 {
        struct subchannel_id mchk_schid;
 
-       CIO_CRW_EVENT(2, "source is subchannel %04X, subsystem id %x\n",
-                     rsid1, rsid2);
+       if (overflow) {
+               css_schedule_eval_all();
+               return;
+       }
+       CIO_CRW_EVENT(2, "CRW0 reports slct=%d, oflw=%d, "
+                     "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
+                     crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc,
+                     crw0->erc, crw0->rsid);
+       if (crw1)
+               CIO_CRW_EVENT(2, "CRW1 reports slct=%d, oflw=%d, "
+                             "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
+                             crw1->slct, crw1->oflw, crw1->chn, crw1->rsc,
+                             crw1->anc, crw1->erc, crw1->rsid);
        init_subchannel_id(&mchk_schid);
-       mchk_schid.sch_no = rsid1;
-       if (rsid2 != 0)
-               mchk_schid.ssid = (rsid2 >> 8) & 3;
+       mchk_schid.sch_no = crw0->rsid;
+       if (crw1)
+               mchk_schid.ssid = (crw1->rsid >> 8) & 3;
 
-       /* 
+       /*
         * Since we are always presented with IPI in the CRW, we have to
         * use stsch() to find out if the subchannel in question has come
         * or gone.
@@ -658,7 +611,7 @@ __init_channel_subsystem(struct subchannel_id schid, void *data)
 static void __init
 css_generate_pgid(struct channel_subsystem *css, u32 tod_high)
 {
-       if (css_characteristics_avail && css_general_characteristics.mcss) {
+       if (css_general_characteristics.mcss) {
                css->global_pgid.pgid_high.ext_cssid.version = 0x80;
                css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid;
        } else {
@@ -795,8 +748,6 @@ init_channel_subsystem (void)
        ret = chsc_determine_css_characteristics();
        if (ret == -ENOMEM)
                goto out; /* No need to continue. */
-       if (ret == 0)
-               css_characteristics_avail = 1;
 
        ret = chsc_alloc_sei_area();
        if (ret)
@@ -806,6 +757,10 @@ init_channel_subsystem (void)
        if (ret)
                goto out;
 
+       ret = s390_register_crw_handler(CRW_RSC_SCH, css_process_crw);
+       if (ret)
+               goto out;
+
        if ((ret = bus_register(&css_bus_type)))
                goto out;
 
@@ -836,8 +791,7 @@ init_channel_subsystem (void)
                ret = device_register(&css->device);
                if (ret)
                        goto out_free_all;
-               if (css_characteristics_avail &&
-                   css_chsc_characteristics.secm) {
+               if (css_chsc_characteristics.secm) {
                        ret = device_create_file(&css->device,
                                                 &dev_attr_cm_enable);
                        if (ret)
@@ -852,7 +806,8 @@ init_channel_subsystem (void)
                goto out_pseudo;
        css_init_done = 1;
 
-       ctl_set_bit(6, 28);
+       /* Enable default isc for I/O subchannels. */
+       isc_register(IO_SCH_ISC);
 
        for_each_subchannel(__init_channel_subsystem, NULL);
        return 0;
@@ -875,7 +830,7 @@ out_unregister:
                i--;
                css = channel_subsystems[i];
                device_unregister(&css->pseudo_subchannel->dev);
-               if (css_characteristics_avail && css_chsc_characteristics.secm)
+               if (css_chsc_characteristics.secm)
                        device_remove_file(&css->device,
                                           &dev_attr_cm_enable);
                device_unregister(&css->device);
@@ -883,6 +838,7 @@ out_unregister:
 out_bus:
        bus_unregister(&css_bus_type);
 out:
+       s390_unregister_crw_handler(CRW_RSC_CSS);
        chsc_free_sei_area();
        kfree(slow_subchannel_set);
        printk(KERN_WARNING"cio: failed to initialize css driver (%d)!\n",
@@ -895,19 +851,16 @@ int sch_is_pseudo_sch(struct subchannel *sch)
        return sch == to_css(sch->dev.parent)->pseudo_subchannel;
 }
 
-/*
- * find a driver for a subchannel. They identify by the subchannel
- * type with the exception that the console subchannel driver has its own
- * subchannel type although the device is an i/o subchannel
- */
-static int
-css_bus_match (struct device *dev, struct device_driver *drv)
+static int css_bus_match(struct device *dev, struct device_driver *drv)
 {
        struct subchannel *sch = to_subchannel(dev);
        struct css_driver *driver = to_cssdriver(drv);
+       struct css_device_id *id;
 
-       if (sch->st == driver->subchannel_type)
-               return 1;
+       for (id = driver->subchannel_type; id->match_flags; id++) {
+               if (sch->st == id->type)
+                       return 1;
+       }
 
        return 0;
 }
@@ -945,12 +898,25 @@ static void css_shutdown(struct device *dev)
                sch->driver->shutdown(sch);
 }
 
+static int css_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       struct subchannel *sch = to_subchannel(dev);
+       int ret;
+
+       ret = add_uevent_var(env, "ST=%01X", sch->st);
+       if (ret)
+               return ret;
+       ret = add_uevent_var(env, "MODALIAS=css:t%01X", sch->st);
+       return ret;
+}
+
 struct bus_type css_bus_type = {
        .name     = "css",
        .match    = css_bus_match,
        .probe    = css_probe,
        .remove   = css_remove,
        .shutdown = css_shutdown,
+       .uevent   = css_uevent,
 };
 
 /**
@@ -985,4 +951,3 @@ subsys_initcall(init_channel_subsystem);
 
 MODULE_LICENSE("GPL");
 EXPORT_SYMBOL(css_bus_type);
-EXPORT_SYMBOL_GPL(css_characteristics_avail);
index e1913518f354fff88d3508be92edb22d1ed330e8..57ebf120f825b00f68ee934e9e9a26324beedd09 100644 (file)
@@ -9,8 +9,7 @@
 
 #include <asm/cio.h>
 #include <asm/chpid.h>
-
-#include "schid.h"
+#include <asm/schid.h>
 
 /*
  * path grouping stuff
@@ -58,20 +57,28 @@ struct pgid {
        __u32 tod_high;         /* high word TOD clock */
 } __attribute__ ((packed));
 
-/*
- * A css driver handles all subchannels of one type.
- * Currently, we only care about I/O subchannels (type 0), these
- * have a ccw_device connected to them.
- */
 struct subchannel;
+struct chp_link;
+/**
+ * struct css_driver - device driver for subchannels
+ * @owner: owning module
+ * @subchannel_type: subchannel type supported by this driver
+ * @drv: embedded device driver structure
+ * @irq: called on interrupts
+ * @chp_event: called for events affecting a channel path
+ * @sch_event: called for events affecting the subchannel
+ * @probe: function called on probe
+ * @remove: function called on remove
+ * @shutdown: called at device shutdown
+ * @name: name of the device driver
+ */
 struct css_driver {
        struct module *owner;
-       unsigned int subchannel_type;
+       struct css_device_id *subchannel_type;
        struct device_driver drv;
        void (*irq)(struct subchannel *);
-       int (*notify)(struct subchannel *, int);
-       void (*verify)(struct subchannel *);
-       void (*termination)(struct subchannel *);
+       int (*chp_event)(struct subchannel *, struct chp_link *, int);
+       int (*sch_event)(struct subchannel *, int);
        int (*probe)(struct subchannel *);
        int (*remove)(struct subchannel *);
        void (*shutdown)(struct subchannel *);
@@ -89,13 +96,13 @@ extern int css_driver_register(struct css_driver *);
 extern void css_driver_unregister(struct css_driver *);
 
 extern void css_sch_device_unregister(struct subchannel *);
-extern struct subchannel * get_subchannel_by_schid(struct subchannel_id);
+extern int css_probe_device(struct subchannel_id);
+extern struct subchannel *get_subchannel_by_schid(struct subchannel_id);
 extern int css_init_done;
 int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *),
                               int (*fn_unknown)(struct subchannel_id,
                               void *), void *data);
 extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
-extern void css_process_crw(int, int);
 extern void css_reiterate_subchannels(void);
 void css_update_ssd_info(struct subchannel *sch);
 
@@ -121,20 +128,6 @@ struct channel_subsystem {
 extern struct bus_type css_bus_type;
 extern struct channel_subsystem *channel_subsystems[];
 
-/* Some helper functions for disconnected state. */
-int device_is_disconnected(struct subchannel *);
-void device_set_disconnected(struct subchannel *);
-void device_trigger_reprobe(struct subchannel *);
-
-/* Helper functions for vary on/off. */
-int device_is_online(struct subchannel *);
-void device_kill_io(struct subchannel *);
-void device_set_intretry(struct subchannel *sch);
-int device_trigger_verify(struct subchannel *sch);
-
-/* Machine check helper function. */
-void device_kill_pending_timer(struct subchannel *);
-
 /* Helper functions to build lists for the slow path. */
 void css_schedule_eval(struct subchannel_id schid);
 void css_schedule_eval_all(void);
@@ -145,6 +138,4 @@ int css_sch_is_valid(struct schib *);
 
 extern struct workqueue_struct *slow_path_wq;
 void css_wait_for_slow_path(void);
-
-extern struct attribute_group *subch_attr_groups[];
 #endif
index e22813db74a2b6bb81d2d0e1e27ec64acde946e2..e818d0c54c0949f5a21ae134ccf426da5d079d9c 100644 (file)
@@ -2,8 +2,7 @@
  *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
  *
- *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
- *                      IBM Corporation
+ *    Copyright IBM Corp. 2002,2008
  *    Author(s): Arnd Bergmann (arndb@de.ibm.com)
  *              Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Martin Schwidefsky (schwidefsky@de.ibm.com)
@@ -23,7 +22,9 @@
 #include <asm/cio.h>
 #include <asm/param.h>         /* HZ */
 #include <asm/cmb.h>
+#include <asm/isc.h>
 
+#include "chp.h"
 #include "cio.h"
 #include "cio_debug.h"
 #include "css.h"
@@ -125,19 +126,24 @@ struct bus_type ccw_bus_type;
 static void io_subchannel_irq(struct subchannel *);
 static int io_subchannel_probe(struct subchannel *);
 static int io_subchannel_remove(struct subchannel *);
-static int io_subchannel_notify(struct subchannel *, int);
-static void io_subchannel_verify(struct subchannel *);
-static void io_subchannel_ioterm(struct subchannel *);
 static void io_subchannel_shutdown(struct subchannel *);
+static int io_subchannel_sch_event(struct subchannel *, int);
+static int io_subchannel_chp_event(struct subchannel *, struct chp_link *,
+                                  int);
+
+static struct css_device_id io_subchannel_ids[] = {
+       { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, },
+       { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(css, io_subchannel_ids);
 
 static struct css_driver io_subchannel_driver = {
        .owner = THIS_MODULE,
-       .subchannel_type = SUBCHANNEL_TYPE_IO,
+       .subchannel_type = io_subchannel_ids,
        .name = "io_subchannel",
        .irq = io_subchannel_irq,
-       .notify = io_subchannel_notify,
-       .verify = io_subchannel_verify,
-       .termination = io_subchannel_ioterm,
+       .sch_event = io_subchannel_sch_event,
+       .chp_event = io_subchannel_chp_event,
        .probe = io_subchannel_probe,
        .remove = io_subchannel_remove,
        .shutdown = io_subchannel_shutdown,
@@ -487,25 +493,22 @@ static int online_store_recog_and_online(struct ccw_device *cdev)
                ccw_device_set_online(cdev);
        return 0;
 }
-static void online_store_handle_online(struct ccw_device *cdev, int force)
+static int online_store_handle_online(struct ccw_device *cdev, int force)
 {
        int ret;
 
        ret = online_store_recog_and_online(cdev);
        if (ret)
-               return;
+               return ret;
        if (force && cdev->private->state == DEV_STATE_BOXED) {
                ret = ccw_device_stlck(cdev);
-               if (ret) {
-                       dev_warn(&cdev->dev,
-                                "ccw_device_stlck returned %d!\n", ret);
-                       return;
-               }
+               if (ret)
+                       return ret;
                if (cdev->id.cu_type == 0)
                        cdev->private->state = DEV_STATE_NOT_OPER;
                online_store_recog_and_online(cdev);
        }
-
+       return 0;
 }
 
 static ssize_t online_store (struct device *dev, struct device_attribute *attr,
@@ -538,8 +541,9 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr,
                ret = count;
                break;
        case 1:
-               online_store_handle_online(cdev, force);
-               ret = count;
+               ret = online_store_handle_online(cdev, force);
+               if (!ret)
+                       ret = count;
                break;
        default:
                ret = -EINVAL;
@@ -584,19 +588,14 @@ static DEVICE_ATTR(modalias, 0444, modalias_show, NULL);
 static DEVICE_ATTR(online, 0644, online_show, online_store);
 static DEVICE_ATTR(availability, 0444, available_show, NULL);
 
-static struct attribute * subch_attrs[] = {
+static struct attribute *io_subchannel_attrs[] = {
        &dev_attr_chpids.attr,
        &dev_attr_pimpampom.attr,
        NULL,
 };
 
-static struct attribute_group subch_attr_group = {
-       .attrs = subch_attrs,
-};
-
-struct attribute_group *subch_attr_groups[] = {
-       &subch_attr_group,
-       NULL,
+static struct attribute_group io_subchannel_attr_group = {
+       .attrs = io_subchannel_attrs,
 };
 
 static struct attribute * ccwdev_attrs[] = {
@@ -790,7 +789,7 @@ static void sch_attach_device(struct subchannel *sch,
        sch_set_cdev(sch, cdev);
        cdev->private->schid = sch->schid;
        cdev->ccwlock = sch->lock;
-       device_trigger_reprobe(sch);
+       ccw_device_trigger_reprobe(cdev);
        spin_unlock_irq(sch->lock);
 }
 
@@ -1037,7 +1036,6 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
        struct ccw_device_private *priv;
 
        sch_set_cdev(sch, cdev);
-       sch->driver = &io_subchannel_driver;
        cdev->ccwlock = sch->lock;
 
        /* Init private data. */
@@ -1122,8 +1120,33 @@ static void io_subchannel_irq(struct subchannel *sch)
                dev_fsm_event(cdev, DEV_EVENT_INTERRUPT);
 }
 
-static int
-io_subchannel_probe (struct subchannel *sch)
+static void io_subchannel_init_fields(struct subchannel *sch)
+{
+       if (cio_is_console(sch->schid))
+               sch->opm = 0xff;
+       else
+               sch->opm = chp_get_sch_opm(sch);
+       sch->lpm = sch->schib.pmcw.pam & sch->opm;
+       sch->isc = cio_is_console(sch->schid) ? CONSOLE_ISC : IO_SCH_ISC;
+
+       CIO_MSG_EVENT(6, "Detected device %04x on subchannel 0.%x.%04X"
+                     " - PIM = %02X, PAM = %02X, POM = %02X\n",
+                     sch->schib.pmcw.dev, sch->schid.ssid,
+                     sch->schid.sch_no, sch->schib.pmcw.pim,
+                     sch->schib.pmcw.pam, sch->schib.pmcw.pom);
+       /* Initially set up some fields in the pmcw. */
+       sch->schib.pmcw.ena = 0;
+       sch->schib.pmcw.csense = 1;     /* concurrent sense */
+       if ((sch->lpm & (sch->lpm - 1)) != 0)
+               sch->schib.pmcw.mp = 1; /* multipath mode */
+       /* clean up possible residual cmf stuff */
+       sch->schib.pmcw.mme = 0;
+       sch->schib.pmcw.mbfc = 0;
+       sch->schib.pmcw.mbi = 0;
+       sch->schib.mba = 0;
+}
+
+static int io_subchannel_probe(struct subchannel *sch)
 {
        struct ccw_device *cdev;
        int rc;
@@ -1132,11 +1155,21 @@ io_subchannel_probe (struct subchannel *sch)
 
        cdev = sch_get_cdev(sch);
        if (cdev) {
+               rc = sysfs_create_group(&sch->dev.kobj,
+                                       &io_subchannel_attr_group);
+               if (rc)
+                       CIO_MSG_EVENT(0, "Failed to create io subchannel "
+                                     "attributes for subchannel "
+                                     "0.%x.%04x (rc=%d)\n",
+                                     sch->schid.ssid, sch->schid.sch_no, rc);
                /*
                 * This subchannel already has an associated ccw_device.
-                * Register it and exit. This happens for all early
-                * device, e.g. the console.
+                * Throw the delayed uevent for the subchannel, register
+                * the ccw_device and exit. This happens for all early
+                * devices, e.g. the console.
                 */
+               sch->dev.uevent_suppress = 0;
+               kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
                cdev->dev.groups = ccwdev_attr_groups;
                device_initialize(&cdev->dev);
                ccw_device_register(cdev);
@@ -1152,17 +1185,24 @@ io_subchannel_probe (struct subchannel *sch)
                        get_device(&cdev->dev);
                return 0;
        }
+       io_subchannel_init_fields(sch);
        /*
         * First check if a fitting device may be found amongst the
         * disconnected devices or in the orphanage.
         */
        dev_id.devno = sch->schib.pmcw.dev;
        dev_id.ssid = sch->schid.ssid;
+       rc = sysfs_create_group(&sch->dev.kobj,
+                               &io_subchannel_attr_group);
+       if (rc)
+               return rc;
        /* Allocate I/O subchannel private data. */
        sch->private = kzalloc(sizeof(struct io_subchannel_private),
                               GFP_KERNEL | GFP_DMA);
-       if (!sch->private)
-               return -ENOMEM;
+       if (!sch->private) {
+               rc = -ENOMEM;
+               goto out_err;
+       }
        cdev = get_disc_ccwdev_by_dev_id(&dev_id, NULL);
        if (!cdev)
                cdev = get_orphaned_ccwdev_by_dev_id(to_css(sch->dev.parent),
@@ -1181,8 +1221,8 @@ io_subchannel_probe (struct subchannel *sch)
        }
        cdev = io_subchannel_create_ccwdev(sch);
        if (IS_ERR(cdev)) {
-               kfree(sch->private);
-               return PTR_ERR(cdev);
+               rc = PTR_ERR(cdev);
+               goto out_err;
        }
        rc = io_subchannel_recog(cdev, sch);
        if (rc) {
@@ -1191,9 +1231,12 @@ io_subchannel_probe (struct subchannel *sch)
                spin_unlock_irqrestore(sch->lock, flags);
                if (cdev->dev.release)
                        cdev->dev.release(&cdev->dev);
-               kfree(sch->private);
+               goto out_err;
        }
-
+       return 0;
+out_err:
+       kfree(sch->private);
+       sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
        return rc;
 }
 
@@ -1214,6 +1257,7 @@ io_subchannel_remove (struct subchannel *sch)
        ccw_device_unregister(cdev);
        put_device(&cdev->dev);
        kfree(sch->private);
+       sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
        return 0;
 }
 
@@ -1224,11 +1268,7 @@ static int io_subchannel_notify(struct subchannel *sch, int event)
        cdev = sch_get_cdev(sch);
        if (!cdev)
                return 0;
-       if (!cdev->drv)
-               return 0;
-       if (!cdev->online)
-               return 0;
-       return cdev->drv->notify ? cdev->drv->notify(cdev, event) : 0;
+       return ccw_device_notify(cdev, event);
 }
 
 static void io_subchannel_verify(struct subchannel *sch)
@@ -1240,22 +1280,96 @@ static void io_subchannel_verify(struct subchannel *sch)
                dev_fsm_event(cdev, DEV_EVENT_VERIFY);
 }
 
-static void io_subchannel_ioterm(struct subchannel *sch)
+static int check_for_io_on_path(struct subchannel *sch, int mask)
 {
-       struct ccw_device *cdev;
+       int cc;
 
-       cdev = sch_get_cdev(sch);
-       if (!cdev)
-               return;
-       /* Internal I/O will be retried by the interrupt handler. */
-       if (cdev->private->flags.intretry)
+       cc = stsch(sch->schid, &sch->schib);
+       if (cc)
+               return 0;
+       if (scsw_actl(&sch->schib.scsw) && sch->schib.pmcw.lpum == mask)
+               return 1;
+       return 0;
+}
+
+static void terminate_internal_io(struct subchannel *sch,
+                                 struct ccw_device *cdev)
+{
+       if (cio_clear(sch)) {
+               /* Recheck device in case clear failed. */
+               sch->lpm = 0;
+               if (cdev->online)
+                       dev_fsm_event(cdev, DEV_EVENT_VERIFY);
+               else
+                       css_schedule_eval(sch->schid);
                return;
+       }
        cdev->private->state = DEV_STATE_CLEAR_VERIFY;
+       /* Request retry of internal operation. */
+       cdev->private->flags.intretry = 1;
+       /* Call handler. */
        if (cdev->handler)
                cdev->handler(cdev, cdev->private->intparm,
                              ERR_PTR(-EIO));
 }
 
+static void io_subchannel_terminate_path(struct subchannel *sch, u8 mask)
+{
+       struct ccw_device *cdev;
+
+       cdev = sch_get_cdev(sch);
+       if (!cdev)
+               return;
+       if (check_for_io_on_path(sch, mask)) {
+               if (cdev->private->state == DEV_STATE_ONLINE)
+                       ccw_device_kill_io(cdev);
+               else {
+                       terminate_internal_io(sch, cdev);
+                       /* Re-start path verification. */
+                       dev_fsm_event(cdev, DEV_EVENT_VERIFY);
+               }
+       } else
+               /* trigger path verification. */
+               dev_fsm_event(cdev, DEV_EVENT_VERIFY);
+
+}
+
+static int io_subchannel_chp_event(struct subchannel *sch,
+                                  struct chp_link *link, int event)
+{
+       int mask;
+
+       mask = chp_ssd_get_mask(&sch->ssd_info, link);
+       if (!mask)
+               return 0;
+       switch (event) {
+       case CHP_VARY_OFF:
+               sch->opm &= ~mask;
+               sch->lpm &= ~mask;
+               io_subchannel_terminate_path(sch, mask);
+               break;
+       case CHP_VARY_ON:
+               sch->opm |= mask;
+               sch->lpm |= mask;
+               io_subchannel_verify(sch);
+               break;
+       case CHP_OFFLINE:
+               if (stsch(sch->schid, &sch->schib))
+                       return -ENXIO;
+               if (!css_sch_is_valid(&sch->schib))
+                       return -ENODEV;
+               io_subchannel_terminate_path(sch, mask);
+               break;
+       case CHP_ONLINE:
+               if (stsch(sch->schid, &sch->schib))
+                       return -ENXIO;
+               sch->lpm |= mask & sch->opm;
+               io_subchannel_verify(sch);
+               break;
+       }
+       return 0;
+}
+
 static void
 io_subchannel_shutdown(struct subchannel *sch)
 {
@@ -1285,6 +1399,195 @@ io_subchannel_shutdown(struct subchannel *sch)
        cio_disable_subchannel(sch);
 }
 
+static int io_subchannel_get_status(struct subchannel *sch)
+{
+       struct schib schib;
+
+       if (stsch(sch->schid, &schib) || !schib.pmcw.dnv)
+               return CIO_GONE;
+       if (sch->schib.pmcw.dnv && (schib.pmcw.dev != sch->schib.pmcw.dev))
+               return CIO_REVALIDATE;
+       if (!sch->lpm)
+               return CIO_NO_PATH;
+       return CIO_OPER;
+}
+
+static int device_is_disconnected(struct ccw_device *cdev)
+{
+       if (!cdev)
+               return 0;
+       return (cdev->private->state == DEV_STATE_DISCONNECTED ||
+               cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID);
+}
+
+static int recovery_check(struct device *dev, void *data)
+{
+       struct ccw_device *cdev = to_ccwdev(dev);
+       int *redo = data;
+
+       spin_lock_irq(cdev->ccwlock);
+       switch (cdev->private->state) {
+       case DEV_STATE_DISCONNECTED:
+               CIO_MSG_EVENT(3, "recovery: trigger 0.%x.%04x\n",
+                             cdev->private->dev_id.ssid,
+                             cdev->private->dev_id.devno);
+               dev_fsm_event(cdev, DEV_EVENT_VERIFY);
+               *redo = 1;
+               break;
+       case DEV_STATE_DISCONNECTED_SENSE_ID:
+               *redo = 1;
+               break;
+       }
+       spin_unlock_irq(cdev->ccwlock);
+
+       return 0;
+}
+
+static void recovery_work_func(struct work_struct *unused)
+{
+       int redo = 0;
+
+       bus_for_each_dev(&ccw_bus_type, NULL, &redo, recovery_check);
+       if (redo) {
+               spin_lock_irq(&recovery_lock);
+               if (!timer_pending(&recovery_timer)) {
+                       if (recovery_phase < ARRAY_SIZE(recovery_delay) - 1)
+                               recovery_phase++;
+                       mod_timer(&recovery_timer, jiffies +
+                                 recovery_delay[recovery_phase] * HZ);
+               }
+               spin_unlock_irq(&recovery_lock);
+       } else
+               CIO_MSG_EVENT(4, "recovery: end\n");
+}
+
+static DECLARE_WORK(recovery_work, recovery_work_func);
+
+static void recovery_func(unsigned long data)
+{
+       /*
+        * We can't do our recovery in softirq context and it's not
+        * performance critical, so we schedule it.
+        */
+       schedule_work(&recovery_work);
+}
+
+static void ccw_device_schedule_recovery(void)
+{
+       unsigned long flags;
+
+       CIO_MSG_EVENT(4, "recovery: schedule\n");
+       spin_lock_irqsave(&recovery_lock, flags);
+       if (!timer_pending(&recovery_timer) || (recovery_phase != 0)) {
+               recovery_phase = 0;
+               mod_timer(&recovery_timer, jiffies + recovery_delay[0] * HZ);
+       }
+       spin_unlock_irqrestore(&recovery_lock, flags);
+}
+
+static void device_set_disconnected(struct ccw_device *cdev)
+{
+       if (!cdev)
+               return;
+       ccw_device_set_timeout(cdev, 0);
+       cdev->private->flags.fake_irb = 0;
+       cdev->private->state = DEV_STATE_DISCONNECTED;
+       if (cdev->online)
+               ccw_device_schedule_recovery();
+}
+
+static int io_subchannel_sch_event(struct subchannel *sch, int slow)
+{
+       int event, ret, disc;
+       unsigned long flags;
+       enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE } action;
+       struct ccw_device *cdev;
+
+       spin_lock_irqsave(sch->lock, flags);
+       cdev = sch_get_cdev(sch);
+       disc = device_is_disconnected(cdev);
+       if (disc && slow) {
+               /* Disconnected devices are evaluated directly only.*/
+               spin_unlock_irqrestore(sch->lock, flags);
+               return 0;
+       }
+       /* No interrupt after machine check - kill pending timers. */
+       if (cdev)
+               ccw_device_set_timeout(cdev, 0);
+       if (!disc && !slow) {
+               /* Non-disconnected devices are evaluated on the slow path. */
+               spin_unlock_irqrestore(sch->lock, flags);
+               return -EAGAIN;
+       }
+       event = io_subchannel_get_status(sch);
+       CIO_MSG_EVENT(4, "Evaluating schid 0.%x.%04x, event %d, %s, %s path.\n",
+                     sch->schid.ssid, sch->schid.sch_no, event,
+                     disc ? "disconnected" : "normal",
+                     slow ? "slow" : "fast");
+       /* Analyze subchannel status. */
+       action = NONE;
+       switch (event) {
+       case CIO_NO_PATH:
+               if (disc) {
+                       /* Check if paths have become available. */
+                       action = REPROBE;
+                       break;
+               }
+               /* fall through */
+       case CIO_GONE:
+               /* Prevent unwanted effects when opening lock. */
+               cio_disable_subchannel(sch);
+               device_set_disconnected(cdev);
+               /* Ask driver what to do with device. */
+               action = UNREGISTER;
+               spin_unlock_irqrestore(sch->lock, flags);
+               ret = io_subchannel_notify(sch, event);
+               spin_lock_irqsave(sch->lock, flags);
+               if (ret)
+                       action = NONE;
+               break;
+       case CIO_REVALIDATE:
+               /* Device will be removed, so no notify necessary. */
+               if (disc)
+                       /* Reprobe because immediate unregister might block. */
+                       action = REPROBE;
+               else
+                       action = UNREGISTER_PROBE;
+               break;
+       case CIO_OPER:
+               if (disc)
+                       /* Get device operational again. */
+                       action = REPROBE;
+               break;
+       }
+       /* Perform action. */
+       ret = 0;
+       switch (action) {
+       case UNREGISTER:
+       case UNREGISTER_PROBE:
+               /* Unregister device (will use subchannel lock). */
+               spin_unlock_irqrestore(sch->lock, flags);
+               css_sch_device_unregister(sch);
+               spin_lock_irqsave(sch->lock, flags);
+
+               /* Reset intparm to zeroes. */
+               sch->schib.pmcw.intparm = 0;
+               cio_modify(sch);
+               break;
+       case REPROBE:
+               ccw_device_trigger_reprobe(cdev);
+               break;
+       default:
+               break;
+       }
+       spin_unlock_irqrestore(sch->lock, flags);
+       /* Probe if necessary. */
+       if (action == UNREGISTER_PROBE)
+               ret = css_probe_device(sch->schid);
+
+       return ret;
+}
+
 #ifdef CONFIG_CCW_CONSOLE
 static struct ccw_device console_cdev;
 static struct ccw_device_private console_private;
@@ -1297,14 +1600,16 @@ spinlock_t * cio_get_console_lock(void)
        return &ccw_console_lock;
 }
 
-static int
-ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch)
+static int ccw_device_console_enable(struct ccw_device *cdev,
+                                    struct subchannel *sch)
 {
        int rc;
 
        /* Attach subchannel private data. */
        sch->private = cio_get_console_priv();
        memset(sch->private, 0, sizeof(struct io_subchannel_private));
+       io_subchannel_init_fields(sch);
+       sch->driver = &io_subchannel_driver;
        /* Initialize the ccw_device structure. */
        cdev->dev.parent= &sch->dev;
        rc = io_subchannel_recog(cdev, sch);
@@ -1515,71 +1820,6 @@ ccw_device_get_subchannel_id(struct ccw_device *cdev)
        return sch->schid;
 }
 
-static int recovery_check(struct device *dev, void *data)
-{
-       struct ccw_device *cdev = to_ccwdev(dev);
-       int *redo = data;
-
-       spin_lock_irq(cdev->ccwlock);
-       switch (cdev->private->state) {
-       case DEV_STATE_DISCONNECTED:
-               CIO_MSG_EVENT(4, "recovery: trigger 0.%x.%04x\n",
-                             cdev->private->dev_id.ssid,
-                             cdev->private->dev_id.devno);
-               dev_fsm_event(cdev, DEV_EVENT_VERIFY);
-               *redo = 1;
-               break;
-       case DEV_STATE_DISCONNECTED_SENSE_ID:
-               *redo = 1;
-               break;
-       }
-       spin_unlock_irq(cdev->ccwlock);
-
-       return 0;
-}
-
-static void recovery_work_func(struct work_struct *unused)
-{
-       int redo = 0;
-
-       bus_for_each_dev(&ccw_bus_type, NULL, &redo, recovery_check);
-       if (redo) {
-               spin_lock_irq(&recovery_lock);
-               if (!timer_pending(&recovery_timer)) {
-                       if (recovery_phase < ARRAY_SIZE(recovery_delay) - 1)
-                               recovery_phase++;
-                       mod_timer(&recovery_timer, jiffies +
-                                 recovery_delay[recovery_phase] * HZ);
-               }
-               spin_unlock_irq(&recovery_lock);
-       } else
-               CIO_MSG_EVENT(4, "recovery: end\n");
-}
-
-static DECLARE_WORK(recovery_work, recovery_work_func);
-
-static void recovery_func(unsigned long data)
-{
-       /*
-        * We can't do our recovery in softirq context and it's not
-        * performance critical, so we schedule it.
-        */
-       schedule_work(&recovery_work);
-}
-
-void ccw_device_schedule_recovery(void)
-{
-       unsigned long flags;
-
-       CIO_MSG_EVENT(4, "recovery: schedule\n");
-       spin_lock_irqsave(&recovery_lock, flags);
-       if (!timer_pending(&recovery_timer) || (recovery_phase != 0)) {
-               recovery_phase = 0;
-               mod_timer(&recovery_timer, jiffies + recovery_delay[0] * HZ);
-       }
-       spin_unlock_irqrestore(&recovery_lock, flags);
-}
-
 MODULE_LICENSE("GPL");
 EXPORT_SYMBOL(ccw_device_set_online);
 EXPORT_SYMBOL(ccw_device_set_offline);
index cb08092be39f0e29b3e6218f04c7ef86af27289f..9800a8335a3fa81a195b9c5b3ae83380c21ae5ef 100644 (file)
@@ -88,8 +88,6 @@ int ccw_device_recognition(struct ccw_device *);
 int ccw_device_online(struct ccw_device *);
 int ccw_device_offline(struct ccw_device *);
 
-void ccw_device_schedule_recovery(void);
-
 /* Function prototypes for device status and basic sense stuff. */
 void ccw_device_accumulate_irb(struct ccw_device *, struct irb *);
 void ccw_device_accumulate_basic_sense(struct ccw_device *, struct irb *);
@@ -118,6 +116,11 @@ int ccw_device_call_handler(struct ccw_device *);
 
 int ccw_device_stlck(struct ccw_device *);
 
+/* Helper function for machine check handling. */
+void ccw_device_trigger_reprobe(struct ccw_device *);
+void ccw_device_kill_io(struct ccw_device *);
+int ccw_device_notify(struct ccw_device *, int);
+
 /* qdio needs this. */
 void ccw_device_set_timeout(struct ccw_device *, int);
 extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *);
index e268d5a77c12633c4d80d5493add727229fe94fa..8b5fe57fb2f31ef1684d586aca9f69c9c9e4fab3 100644 (file)
@@ -2,8 +2,7 @@
  * drivers/s390/cio/device_fsm.c
  * finite state machine for device handling
  *
- *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
- *                      IBM Corporation
+ *    Copyright IBM Corp. 2002,2008
  *    Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
 static int timeout_log_enabled;
 
-int
-device_is_online(struct subchannel *sch)
-{
-       struct ccw_device *cdev;
-
-       cdev = sch_get_cdev(sch);
-       if (!cdev)
-               return 0;
-       return (cdev->private->state == DEV_STATE_ONLINE);
-}
-
-int
-device_is_disconnected(struct subchannel *sch)
-{
-       struct ccw_device *cdev;
-
-       cdev = sch_get_cdev(sch);
-       if (!cdev)
-               return 0;
-       return (cdev->private->state == DEV_STATE_DISCONNECTED ||
-               cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID);
-}
-
-void
-device_set_disconnected(struct subchannel *sch)
-{
-       struct ccw_device *cdev;
-
-       cdev = sch_get_cdev(sch);
-       if (!cdev)
-               return;
-       ccw_device_set_timeout(cdev, 0);
-       cdev->private->flags.fake_irb = 0;
-       cdev->private->state = DEV_STATE_DISCONNECTED;
-       if (cdev->online)
-               ccw_device_schedule_recovery();
-}
-
-void device_set_intretry(struct subchannel *sch)
-{
-       struct ccw_device *cdev;
-
-       cdev = sch_get_cdev(sch);
-       if (!cdev)
-               return;
-       cdev->private->flags.intretry = 1;
-}
-
-int device_trigger_verify(struct subchannel *sch)
-{
-       struct ccw_device *cdev;
-
-       cdev = sch_get_cdev(sch);
-       if (!cdev || !cdev->online)
-               return -EINVAL;
-       dev_fsm_event(cdev, DEV_EVENT_VERIFY);
-       return 0;
-}
-
 static int __init ccw_timeout_log_setup(char *unused)
 {
        timeout_log_enabled = 1;
@@ -99,31 +39,43 @@ static void ccw_timeout_log(struct ccw_device *cdev)
        struct schib schib;
        struct subchannel *sch;
        struct io_subchannel_private *private;
+       union orb *orb;
        int cc;
 
        sch = to_subchannel(cdev->dev.parent);
        private = to_io_private(sch);
+       orb = &private->orb;
        cc = stsch(sch->schid, &schib);
 
        printk(KERN_WARNING "cio: ccw device timeout occurred at %llx, "
               "device information:\n", get_clock());
        printk(KERN_WARNING "cio: orb:\n");
        print_hex_dump(KERN_WARNING, "cio:  ", DUMP_PREFIX_NONE, 16, 1,
-                      &private->orb, sizeof(private->orb), 0);
+                      orb, sizeof(*orb), 0);
        printk(KERN_WARNING "cio: ccw device bus id: %s\n", cdev->dev.bus_id);
        printk(KERN_WARNING "cio: subchannel bus id: %s\n", sch->dev.bus_id);
        printk(KERN_WARNING "cio: subchannel lpm: %02x, opm: %02x, "
               "vpm: %02x\n", sch->lpm, sch->opm, sch->vpm);
 
-       if ((void *)(addr_t)private->orb.cpa == &private->sense_ccw ||
-           (void *)(addr_t)private->orb.cpa == cdev->private->iccws)
-               printk(KERN_WARNING "cio: last channel program (intern):\n");
-       else
-               printk(KERN_WARNING "cio: last channel program:\n");
-
-       print_hex_dump(KERN_WARNING, "cio:  ", DUMP_PREFIX_NONE, 16, 1,
-                      (void *)(addr_t)private->orb.cpa,
-                      sizeof(struct ccw1), 0);
+       if (orb->tm.b) {
+               printk(KERN_WARNING "cio: orb indicates transport mode\n");
+               printk(KERN_WARNING "cio: last tcw:\n");
+               print_hex_dump(KERN_WARNING, "cio:  ", DUMP_PREFIX_NONE, 16, 1,
+                              (void *)(addr_t)orb->tm.tcw,
+                              sizeof(struct tcw), 0);
+       } else {
+               printk(KERN_WARNING "cio: orb indicates command mode\n");
+               if ((void *)(addr_t)orb->cmd.cpa == &private->sense_ccw ||
+                   (void *)(addr_t)orb->cmd.cpa == cdev->private->iccws)
+                       printk(KERN_WARNING "cio: last channel program "
+                              "(intern):\n");
+               else
+                       printk(KERN_WARNING "cio: last channel program:\n");
+
+               print_hex_dump(KERN_WARNING, "cio:  ", DUMP_PREFIX_NONE, 16, 1,
+                              (void *)(addr_t)orb->cmd.cpa,
+                              sizeof(struct ccw1), 0);
+       }
        printk(KERN_WARNING "cio: ccw device state: %d\n",
               cdev->private->state);
        printk(KERN_WARNING "cio: store subchannel returned: cc=%d\n", cc);
@@ -171,18 +123,6 @@ ccw_device_set_timeout(struct ccw_device *cdev, int expires)
        add_timer(&cdev->private->timer);
 }
 
-/* Kill any pending timers after machine check. */
-void
-device_kill_pending_timer(struct subchannel *sch)
-{
-       struct ccw_device *cdev;
-
-       cdev = sch_get_cdev(sch);
-       if (!cdev)
-               return;
-       ccw_device_set_timeout(cdev, 0);
-}
-
 /*
  * Cancel running i/o. This is called repeatedly since halt/clear are
  * asynchronous operations. We do one try with cio_cancel, two tries
@@ -205,15 +145,18 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
                /* Not operational -> done. */
                return 0;
        /* Stage 1: cancel io. */
-       if (!(sch->schib.scsw.actl & SCSW_ACTL_HALT_PEND) &&
-           !(sch->schib.scsw.actl & SCSW_ACTL_CLEAR_PEND)) {
-               ret = cio_cancel(sch);
-               if (ret != -EINVAL)
-                       return ret;
-               /* cancel io unsuccessful. From now on it is asynchronous. */
+       if (!(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_HALT_PEND) &&
+           !(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_CLEAR_PEND)) {
+               if (!scsw_is_tm(&sch->schib.scsw)) {
+                       ret = cio_cancel(sch);
+                       if (ret != -EINVAL)
+                               return ret;
+               }
+               /* cancel io unsuccessful or not applicable (transport mode).
+                * Continue with asynchronous instructions. */
                cdev->private->iretry = 3;      /* 3 halt retries. */
        }
-       if (!(sch->schib.scsw.actl & SCSW_ACTL_CLEAR_PEND)) {
+       if (!(scsw_actl(&sch->schib.scsw) & SCSW_ACTL_CLEAR_PEND)) {
                /* Stage 2: halt io. */
                if (cdev->private->iretry) {
                        cdev->private->iretry--;
@@ -388,34 +331,30 @@ ccw_device_sense_id_done(struct ccw_device *cdev, int err)
        }
 }
 
+int ccw_device_notify(struct ccw_device *cdev, int event)
+{
+       if (!cdev->drv)
+               return 0;
+       if (!cdev->online)
+               return 0;
+       return cdev->drv->notify ? cdev->drv->notify(cdev, event) : 0;
+}
+
 static void
 ccw_device_oper_notify(struct work_struct *work)
 {
        struct ccw_device_private *priv;
        struct ccw_device *cdev;
-       struct subchannel *sch;
        int ret;
-       unsigned long flags;
 
        priv = container_of(work, struct ccw_device_private, kick_work);
        cdev = priv->cdev;
-       spin_lock_irqsave(cdev->ccwlock, flags);
-       sch = to_subchannel(cdev->dev.parent);
-       if (sch->driver && sch->driver->notify) {
-               spin_unlock_irqrestore(cdev->ccwlock, flags);
-               ret = sch->driver->notify(sch, CIO_OPER);
-               spin_lock_irqsave(cdev->ccwlock, flags);
-       } else
-               ret = 0;
+       ret = ccw_device_notify(cdev, CIO_OPER);
        if (ret) {
                /* Reenable channel measurements, if needed. */
-               spin_unlock_irqrestore(cdev->ccwlock, flags);
                cmf_reenable(cdev);
-               spin_lock_irqsave(cdev->ccwlock, flags);
                wake_up(&cdev->private->wait_q);
-       }
-       spin_unlock_irqrestore(cdev->ccwlock, flags);
-       if (!ret)
+       } else
                /* Driver doesn't want device back. */
                ccw_device_do_unreg_rereg(work);
 }
@@ -621,10 +560,11 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
                /* Deliver fake irb to device driver, if needed. */
                if (cdev->private->flags.fake_irb) {
                        memset(&cdev->private->irb, 0, sizeof(struct irb));
-                       cdev->private->irb.scsw.cc = 1;
-                       cdev->private->irb.scsw.fctl = SCSW_FCTL_START_FUNC;
-                       cdev->private->irb.scsw.actl = SCSW_ACTL_START_PEND;
-                       cdev->private->irb.scsw.stctl = SCSW_STCTL_STATUS_PEND;
+                       cdev->private->irb.scsw.cmd.cc = 1;
+                       cdev->private->irb.scsw.cmd.fctl = SCSW_FCTL_START_FUNC;
+                       cdev->private->irb.scsw.cmd.actl = SCSW_ACTL_START_PEND;
+                       cdev->private->irb.scsw.cmd.stctl =
+                               SCSW_STCTL_STATUS_PEND;
                        cdev->private->flags.fake_irb = 0;
                        if (cdev->handler)
                                cdev->handler(cdev, cdev->private->intparm,
@@ -718,13 +658,10 @@ ccw_device_offline(struct ccw_device *cdev)
        sch = to_subchannel(cdev->dev.parent);
        if (stsch(sch->schid, &sch->schib) || !sch->schib.pmcw.dnv)
                return -ENODEV;
-       if (cdev->private->state != DEV_STATE_ONLINE) {
-               if (sch->schib.scsw.actl != 0)
-                       return -EBUSY;
-               return -EINVAL;
-       }
-       if (sch->schib.scsw.actl != 0)
+       if (scsw_actl(&sch->schib.scsw) != 0)
                return -EBUSY;
+       if (cdev->private->state != DEV_STATE_ONLINE)
+               return -EINVAL;
        /* Are we doing path grouping? */
        if (!cdev->private->options.pgroup) {
                /* No, set state offline immediately. */
@@ -799,9 +736,9 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
         */
        stsch(sch->schid, &sch->schib);
 
-       if (sch->schib.scsw.actl != 0 ||
-           (sch->schib.scsw.stctl & SCSW_STCTL_STATUS_PEND) ||
-           (cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) {
+       if (scsw_actl(&sch->schib.scsw) != 0 ||
+           (scsw_stctl(&sch->schib.scsw) & SCSW_STCTL_STATUS_PEND) ||
+           (scsw_stctl(&cdev->private->irb.scsw) & SCSW_STCTL_STATUS_PEND)) {
                /*
                 * No final status yet or final status not yet delivered
                 * to the device driver. Can't do path verfication now,
@@ -823,13 +760,13 @@ static void
 ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event)
 {
        struct irb *irb;
+       int is_cmd;
 
        irb = (struct irb *) __LC_IRB;
+       is_cmd = !scsw_is_tm(&irb->scsw);
        /* Check for unsolicited interrupt. */
-       if ((irb->scsw.stctl ==
-                       (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS))
-           && (!irb->scsw.cc)) {
-               if ((irb->scsw.dstat & DEV_STAT_UNIT_CHECK) &&
+       if (!scsw_is_solicited(&irb->scsw)) {
+               if (is_cmd && (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) &&
                    !irb->esw.esw0.erw.cons) {
                        /* Unit check but no sense data. Need basic sense. */
                        if (ccw_device_do_sense(cdev, irb) != 0)
@@ -848,7 +785,7 @@ call_handler_unsol:
        }
        /* Accumulate status and find out if a basic sense is needed. */
        ccw_device_accumulate_irb(cdev, irb);
-       if (cdev->private->flags.dosense) {
+       if (is_cmd && cdev->private->flags.dosense) {
                if (ccw_device_do_sense(cdev, irb) == 0) {
                        cdev->private->state = DEV_STATE_W4SENSE;
                }
@@ -892,9 +829,9 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
 
        irb = (struct irb *) __LC_IRB;
        /* Check for unsolicited interrupt. */
-       if (irb->scsw.stctl ==
-                       (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
-               if (irb->scsw.cc == 1)
+       if (scsw_stctl(&irb->scsw) ==
+           (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
+               if (scsw_cc(&irb->scsw) == 1)
                        /* Basic sense hasn't started. Try again. */
                        ccw_device_do_sense(cdev, irb);
                else {
@@ -912,7 +849,8 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
         * only deliver the halt/clear interrupt to the device driver as if it
         * had killed the original request.
         */
-       if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) {
+       if (scsw_fctl(&irb->scsw) &
+           (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) {
                /* Retry Basic Sense if requested. */
                if (cdev->private->flags.intretry) {
                        cdev->private->flags.intretry = 0;
@@ -986,12 +924,10 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
                              ERR_PTR(-EIO));
 }
 
-void device_kill_io(struct subchannel *sch)
+void ccw_device_kill_io(struct ccw_device *cdev)
 {
        int ret;
-       struct ccw_device *cdev;
 
-       cdev = sch_get_cdev(sch);
        ret = ccw_device_cancel_halt_clear(cdev);
        if (ret == -EBUSY) {
                ccw_device_set_timeout(cdev, 3*HZ);
@@ -1021,9 +957,9 @@ ccw_device_stlck_done(struct ccw_device *cdev, enum dev_event dev_event)
        case DEV_EVENT_INTERRUPT:
                irb = (struct irb *) __LC_IRB;
                /* Check for unsolicited interrupt. */
-               if ((irb->scsw.stctl ==
+               if ((scsw_stctl(&irb->scsw) ==
                     (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) &&
-                   (!irb->scsw.cc))
+                   (!scsw_cc(&irb->scsw)))
                        /* FIXME: we should restart stlck here, but this
                         * is extremely unlikely ... */
                        goto out_wakeup;
@@ -1055,17 +991,14 @@ ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
        ccw_device_sense_id_start(cdev);
 }
 
-void
-device_trigger_reprobe(struct subchannel *sch)
+void ccw_device_trigger_reprobe(struct ccw_device *cdev)
 {
-       struct ccw_device *cdev;
+       struct subchannel *sch;
 
-       cdev = sch_get_cdev(sch);
-       if (!cdev)
-               return;
        if (cdev->private->state != DEV_STATE_DISCONNECTED)
                return;
 
+       sch = to_subchannel(cdev->dev.parent);
        /* Update some values. */
        if (stsch(sch->schid, &sch->schib))
                return;
@@ -1081,7 +1014,6 @@ device_trigger_reprobe(struct subchannel *sch)
        sch->schib.pmcw.ena = 0;
        if ((sch->lpm & (sch->lpm - 1)) != 0)
                sch->schib.pmcw.mp = 1;
-       sch->schib.pmcw.intparm = (u32)(addr_t)sch;
        /* We should also udate ssd info, but this has to wait. */
        /* Check if this is another device which appeared on the same sch. */
        if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) {
index cba7020517edbaa300e5fd2cfc3b80d52380aea3..1bdaa614e34fef0dbebe6d6f5f03aa7de7ed25a9 100644 (file)
@@ -196,7 +196,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
        irb = &cdev->private->irb;
 
        /* Check the error cases. */
-       if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
+       if (irb->scsw.cmd.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
                /* Retry Sense ID if requested. */
                if (cdev->private->flags.intretry) {
                        cdev->private->flags.intretry = 0;
@@ -234,10 +234,10 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
                              irb->ecw[6], irb->ecw[7]);
                return -EAGAIN;
        }
-       if (irb->scsw.cc == 3) {
+       if (irb->scsw.cmd.cc == 3) {
                u8 lpm;
 
-               lpm = to_io_private(sch)->orb.lpm;
+               lpm = to_io_private(sch)->orb.cmd.lpm;
                if ((lpm & sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0)
                        CIO_MSG_EVENT(4, "SenseID : path %02X for device %04x "
                                      "on subchannel 0.%x.%04x is "
@@ -248,9 +248,9 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
        }
 
        /* Did we get a proper answer ? */
-       if (irb->scsw.cc == 0 && cdev->private->senseid.cu_type != 0xFFFF &&
+       if (irb->scsw.cmd.cc == 0 && cdev->private->senseid.cu_type != 0xFFFF &&
            cdev->private->senseid.reserved == 0xFF) {
-               if (irb->scsw.count < sizeof(struct senseid) - 8)
+               if (irb->scsw.cmd.count < sizeof(struct senseid) - 8)
                        cdev->private->flags.esid = 1;
                return 0; /* Success */
        }
@@ -260,7 +260,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
                      "subchannel 0.%x.%04x returns status %02X%02X\n",
                      cdev->private->dev_id.devno, sch->schid.ssid,
                      sch->schid.sch_no,
-                     irb->scsw.dstat, irb->scsw.cstat);
+                     irb->scsw.cmd.dstat, irb->scsw.cmd.cstat);
        return -EAGAIN;
 }
 
@@ -277,9 +277,9 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event)
        sch = to_subchannel(cdev->dev.parent);
        irb = (struct irb *) __LC_IRB;
        /* Retry sense id, if needed. */
-       if (irb->scsw.stctl ==
+       if (irb->scsw.cmd.stctl ==
            (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
-               if ((irb->scsw.cc == 1) || !irb->scsw.actl) {
+               if ((irb->scsw.cmd.cc == 1) || !irb->scsw.cmd.actl) {
                        ret = __ccw_device_sense_id_start(cdev);
                        if (ret && ret != -EBUSY)
                                ccw_device_sense_id_done(cdev, ret);
index f308ad55a6d5bed173b2fc5ee71197069bd764cc..ee1a28310fbb11945c07714fc9dfef94b4a20752 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/ccwdev.h>
 #include <asm/idals.h>
 #include <asm/chpid.h>
+#include <asm/fcx.h>
 
 #include "cio.h"
 #include "cio_debug.h"
@@ -179,8 +180,8 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
                        return -EBUSY;
        }
        if (cdev->private->state != DEV_STATE_ONLINE ||
-           ((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&
-            !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) ||
+           ((sch->schib.scsw.cmd.stctl & SCSW_STCTL_PRIM_STATUS) &&
+            !(sch->schib.scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS)) ||
            cdev->private->flags.doverify)
                return -EBUSY;
        ret = cio_set_options (sch, flags);
@@ -379,7 +380,7 @@ int ccw_device_resume(struct ccw_device *cdev)
        if (cdev->private->state == DEV_STATE_NOT_OPER)
                return -ENODEV;
        if (cdev->private->state != DEV_STATE_ONLINE ||
-           !(sch->schib.scsw.actl & SCSW_ACTL_SUSPENDED))
+           !(sch->schib.scsw.cmd.actl & SCSW_ACTL_SUSPENDED))
                return -EINVAL;
        return cio_resume(sch);
 }
@@ -404,7 +405,7 @@ ccw_device_call_handler(struct ccw_device *cdev)
         *  - fast notification was requested (primary status)
         *  - unsolicited interrupts
         */
-       stctl = cdev->private->irb.scsw.stctl;
+       stctl = scsw_stctl(&cdev->private->irb.scsw);
        ending_status = (stctl & SCSW_STCTL_SEC_STATUS) ||
                (stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) ||
                (stctl == SCSW_STCTL_STATUS_PEND);
@@ -528,14 +529,15 @@ ccw_device_stlck(struct ccw_device *cdev)
                cio_disable_subchannel(sch); //FIXME: return code?
                goto out_unlock;
        }
-       cdev->private->irb.scsw.actl |= SCSW_ACTL_START_PEND;
+       cdev->private->irb.scsw.cmd.actl |= SCSW_ACTL_START_PEND;
        spin_unlock_irqrestore(sch->lock, flags);
-       wait_event(cdev->private->wait_q, cdev->private->irb.scsw.actl == 0);
+       wait_event(cdev->private->wait_q,
+                  cdev->private->irb.scsw.cmd.actl == 0);
        spin_lock_irqsave(sch->lock, flags);
        cio_disable_subchannel(sch); //FIXME: return code?
-       if ((cdev->private->irb.scsw.dstat !=
+       if ((cdev->private->irb.scsw.cmd.dstat !=
             (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ||
-           (cdev->private->irb.scsw.cstat != 0))
+           (cdev->private->irb.scsw.cmd.cstat != 0))
                ret = -EIO;
        /* Clear irb. */
        memset(&cdev->private->irb, 0, sizeof(struct irb));
@@ -568,6 +570,122 @@ void ccw_device_get_id(struct ccw_device *cdev, struct ccw_dev_id *dev_id)
 }
 EXPORT_SYMBOL(ccw_device_get_id);
 
+/**
+ * ccw_device_tm_start_key - perform start function
+ * @cdev: ccw device on which to perform the start function
+ * @tcw: transport-command word to be started
+ * @intparm: user defined parameter to be passed to the interrupt handler
+ * @lpm: mask of paths to use
+ * @key: storage key to use for storage access
+ *
+ * Start the tcw on the given ccw device. Return zero on success, non-zero
+ * otherwise.
+ */
+int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,
+                           unsigned long intparm, u8 lpm, u8 key)
+{
+       struct subchannel *sch;
+       int rc;
+
+       sch = to_subchannel(cdev->dev.parent);
+       if (cdev->private->state != DEV_STATE_ONLINE)
+               return -EIO;
+       /* Adjust requested path mask to excluded varied off paths. */
+       if (lpm) {
+               lpm &= sch->opm;
+               if (lpm == 0)
+                       return -EACCES;
+       }
+       rc = cio_tm_start_key(sch, tcw, lpm, key);
+       if (rc == 0)
+               cdev->private->intparm = intparm;
+       return rc;
+}
+EXPORT_SYMBOL(ccw_device_tm_start_key);
+
+/**
+ * ccw_device_tm_start_timeout_key - perform start function
+ * @cdev: ccw device on which to perform the start function
+ * @tcw: transport-command word to be started
+ * @intparm: user defined parameter to be passed to the interrupt handler
+ * @lpm: mask of paths to use
+ * @key: storage key to use for storage access
+ * @expires: time span in jiffies after which to abort request
+ *
+ * Start the tcw on the given ccw device. Return zero on success, non-zero
+ * otherwise.
+ */
+int ccw_device_tm_start_timeout_key(struct ccw_device *cdev, struct tcw *tcw,
+                                   unsigned long intparm, u8 lpm, u8 key,
+                                   int expires)
+{
+       int ret;
+
+       ccw_device_set_timeout(cdev, expires);
+       ret = ccw_device_tm_start_key(cdev, tcw, intparm, lpm, key);
+       if (ret != 0)
+               ccw_device_set_timeout(cdev, 0);
+       return ret;
+}
+EXPORT_SYMBOL(ccw_device_tm_start_timeout_key);
+
+/**
+ * ccw_device_tm_start - perform start function
+ * @cdev: ccw device on which to perform the start function
+ * @tcw: transport-command word to be started
+ * @intparm: user defined parameter to be passed to the interrupt handler
+ * @lpm: mask of paths to use
+ *
+ * Start the tcw on the given ccw device. Return zero on success, non-zero
+ * otherwise.
+ */
+int ccw_device_tm_start(struct ccw_device *cdev, struct tcw *tcw,
+                       unsigned long intparm, u8 lpm)
+{
+       return ccw_device_tm_start_key(cdev, tcw, intparm, lpm,
+                                      PAGE_DEFAULT_KEY);
+}
+EXPORT_SYMBOL(ccw_device_tm_start);
+
+/**
+ * ccw_device_tm_start_timeout - perform start function
+ * @cdev: ccw device on which to perform the start function
+ * @tcw: transport-command word to be started
+ * @intparm: user defined parameter to be passed to the interrupt handler
+ * @lpm: mask of paths to use
+ * @expires: time span in jiffies after which to abort request
+ *
+ * Start the tcw on the given ccw device. Return zero on success, non-zero
+ * otherwise.
+ */
+int ccw_device_tm_start_timeout(struct ccw_device *cdev, struct tcw *tcw,
+                              unsigned long intparm, u8 lpm, int expires)
+{
+       return ccw_device_tm_start_timeout_key(cdev, tcw, intparm, lpm,
+                                              PAGE_DEFAULT_KEY, expires);
+}
+EXPORT_SYMBOL(ccw_device_tm_start_timeout);
+
+/**
+ * ccw_device_tm_intrg - perform interrogate function
+ * @cdev: ccw device on which to perform the interrogate function
+ *
+ * Perform an interrogate function on the given ccw device. Return zero on
+ * success, non-zero otherwise.
+ */
+int ccw_device_tm_intrg(struct ccw_device *cdev)
+{
+       struct subchannel *sch = to_subchannel(cdev->dev.parent);
+
+       if (cdev->private->state != DEV_STATE_ONLINE)
+               return -EIO;
+       if (!scsw_is_tm(&sch->schib.scsw) ||
+           !(scsw_actl(&sch->schib.scsw) | SCSW_ACTL_START_PEND))
+               return -EINVAL;
+       return cio_tm_intrg(sch);
+}
+EXPORT_SYMBOL(ccw_device_tm_intrg);
+
 // FIXME: these have to go:
 
 int
index 5cf7be008e981232742c7d57420e0359dd33e977..86bc94eb607f4b35f1094cd2148314f2e99932b2 100644 (file)
  * Helper function called from interrupt context to decide whether an
  * operation should be tried again.
  */
-static int __ccw_device_should_retry(struct scsw *scsw)
+static int __ccw_device_should_retry(union scsw *scsw)
 {
        /* CC is only valid if start function bit is set. */
-       if ((scsw->fctl & SCSW_FCTL_START_FUNC) && scsw->cc == 1)
+       if ((scsw->cmd.fctl & SCSW_FCTL_START_FUNC) && scsw->cmd.cc == 1)
                return 1;
        /* No more activity. For sense and set PGID we stubbornly try again. */
-       if (!scsw->actl)
+       if (!scsw->cmd.actl)
                return 1;
        return 0;
 }
@@ -125,7 +125,7 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
 
        sch = to_subchannel(cdev->dev.parent);
        irb = &cdev->private->irb;
-       if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
+       if (irb->scsw.cmd.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
                /* Retry Sense PGID if requested. */
                if (cdev->private->flags.intretry) {
                        cdev->private->flags.intretry = 0;
@@ -155,10 +155,10 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
                              irb->ecw[6], irb->ecw[7]);
                return -EAGAIN;
        }
-       if (irb->scsw.cc == 3) {
+       if (irb->scsw.cmd.cc == 3) {
                u8 lpm;
 
-               lpm = to_io_private(sch)->orb.lpm;
+               lpm = to_io_private(sch)->orb.cmd.lpm;
                CIO_MSG_EVENT(3, "SNID - Device %04x on Subchannel 0.%x.%04x,"
                              " lpm %02X, became 'not operational'\n",
                              cdev->private->dev_id.devno, sch->schid.ssid,
@@ -188,7 +188,7 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event)
 
        irb = (struct irb *) __LC_IRB;
 
-       if (irb->scsw.stctl ==
+       if (irb->scsw.cmd.stctl ==
            (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
                if (__ccw_device_should_retry(&irb->scsw)) {
                        ret = __ccw_device_sense_pgid_start(cdev);
@@ -331,7 +331,7 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
 
        sch = to_subchannel(cdev->dev.parent);
        irb = &cdev->private->irb;
-       if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
+       if (irb->scsw.cmd.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
                /* Retry Set PGID if requested. */
                if (cdev->private->flags.intretry) {
                        cdev->private->flags.intretry = 0;
@@ -355,7 +355,7 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
                              irb->ecw[6], irb->ecw[7]);
                return -EAGAIN;
        }
-       if (irb->scsw.cc == 3) {
+       if (irb->scsw.cmd.cc == 3) {
                CIO_MSG_EVENT(3, "SPID - Device %04x on Subchannel 0.%x.%04x,"
                              " lpm %02X, became 'not operational'\n",
                              cdev->private->dev_id.devno, sch->schid.ssid,
@@ -376,7 +376,7 @@ static int __ccw_device_check_nop(struct ccw_device *cdev)
 
        sch = to_subchannel(cdev->dev.parent);
        irb = &cdev->private->irb;
-       if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
+       if (irb->scsw.cmd.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
                /* Retry NOP if requested. */
                if (cdev->private->flags.intretry) {
                        cdev->private->flags.intretry = 0;
@@ -384,7 +384,7 @@ static int __ccw_device_check_nop(struct ccw_device *cdev)
                }
                return -ETIME;
        }
-       if (irb->scsw.cc == 3) {
+       if (irb->scsw.cmd.cc == 3) {
                CIO_MSG_EVENT(3, "NOP - Device %04x on Subchannel 0.%x.%04x,"
                              " lpm %02X, became 'not operational'\n",
                              cdev->private->dev_id.devno, sch->schid.ssid,
@@ -438,7 +438,7 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event)
 
        irb = (struct irb *) __LC_IRB;
 
-       if (irb->scsw.stctl ==
+       if (irb->scsw.cmd.stctl ==
            (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
                if (__ccw_device_should_retry(&irb->scsw))
                        __ccw_device_verify_start(cdev);
@@ -544,7 +544,7 @@ ccw_device_disband_irq(struct ccw_device *cdev, enum dev_event dev_event)
 
        irb = (struct irb *) __LC_IRB;
 
-       if (irb->scsw.stctl ==
+       if (irb->scsw.cmd.stctl ==
            (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
                if (__ccw_device_should_retry(&irb->scsw))
                        __ccw_device_disband_start(cdev);
index 4a38993000f2123d5e104af71ffa5ad0bcd2cd59..1b03c5423be207152d01786d41ccb1c799f8795d 100644 (file)
 static void
 ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
 {
-       if (!(irb->scsw.cstat & (SCHN_STAT_CHN_DATA_CHK |
-                                SCHN_STAT_CHN_CTRL_CHK |
-                                SCHN_STAT_INTF_CTRL_CHK)))
+       char dbf_text[15];
+
+       if (!scsw_is_valid_cstat(&irb->scsw) ||
+           !(scsw_cstat(&irb->scsw) & (SCHN_STAT_CHN_DATA_CHK |
+             SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK)))
                return;
        CIO_MSG_EVENT(0, "Channel-Check or Interface-Control-Check "
                      "received"
@@ -39,15 +41,10 @@ ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
                      ": %02X sch_stat : %02X\n",
                      cdev->private->dev_id.devno, cdev->private->schid.ssid,
                      cdev->private->schid.sch_no,
-                     irb->scsw.dstat, irb->scsw.cstat);
-
-       if (irb->scsw.cc != 3) {
-               char dbf_text[15];
-
-               sprintf(dbf_text, "chk%x", cdev->private->schid.sch_no);
-               CIO_TRACE_EVENT(0, dbf_text);
-               CIO_HEX_EVENT(0, irb, sizeof (struct irb));
-       }
+                     scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw));
+       sprintf(dbf_text, "chk%x", cdev->private->schid.sch_no);
+       CIO_TRACE_EVENT(0, dbf_text);
+       CIO_HEX_EVENT(0, irb, sizeof(struct irb));
 }
 
 /*
@@ -81,12 +78,12 @@ ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb)
         * are condition that have to be met for the extended control
         * bit to have meaning. Sick.
         */
-       cdev->private->irb.scsw.ectl = 0;
-       if ((irb->scsw.stctl & SCSW_STCTL_ALERT_STATUS) &&
-           !(irb->scsw.stctl & SCSW_STCTL_INTER_STATUS))
-               cdev->private->irb.scsw.ectl = irb->scsw.ectl;
+       cdev->private->irb.scsw.cmd.ectl = 0;
+       if ((irb->scsw.cmd.stctl & SCSW_STCTL_ALERT_STATUS) &&
+           !(irb->scsw.cmd.stctl & SCSW_STCTL_INTER_STATUS))
+               cdev->private->irb.scsw.cmd.ectl = irb->scsw.cmd.ectl;
        /* Check if extended control word is valid. */
-       if (!cdev->private->irb.scsw.ectl)
+       if (!cdev->private->irb.scsw.cmd.ectl)
                return;
        /* Copy concurrent sense / model dependent information. */
        memcpy (&cdev->private->irb.ecw, irb->ecw, sizeof (irb->ecw));
@@ -98,11 +95,12 @@ ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb)
 static int
 ccw_device_accumulate_esw_valid(struct irb *irb)
 {
-       if (!irb->scsw.eswf && irb->scsw.stctl == SCSW_STCTL_STATUS_PEND)
+       if (!irb->scsw.cmd.eswf &&
+           (irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND))
                return 0;
-       if (irb->scsw.stctl == 
-                       (SCSW_STCTL_INTER_STATUS|SCSW_STCTL_STATUS_PEND) &&
-           !(irb->scsw.actl & SCSW_ACTL_SUSPENDED))
+       if (irb->scsw.cmd.stctl ==
+                       (SCSW_STCTL_INTER_STATUS|SCSW_STCTL_STATUS_PEND) &&
+           !(irb->scsw.cmd.actl & SCSW_ACTL_SUSPENDED))
                return 0;
        return 1;
 }
@@ -125,7 +123,7 @@ ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb)
        cdev_irb->esw.esw1.lpum = irb->esw.esw1.lpum;
 
        /* Copy subchannel logout information if esw is of format 0. */
-       if (irb->scsw.eswf) {
+       if (irb->scsw.cmd.eswf) {
                cdev_sublog = &cdev_irb->esw.esw0.sublog;
                sublog = &irb->esw.esw0.sublog;
                /* Copy extended status flags. */
@@ -134,7 +132,7 @@ ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb)
                 * Copy fields that have a meaning for channel data check
                 * channel control check and interface control check.
                 */
-               if (irb->scsw.cstat & (SCHN_STAT_CHN_DATA_CHK |
+               if (irb->scsw.cmd.cstat & (SCHN_STAT_CHN_DATA_CHK |
                                       SCHN_STAT_CHN_CTRL_CHK |
                                       SCHN_STAT_INTF_CTRL_CHK)) {
                        /* Copy ancillary report bit. */
@@ -155,7 +153,7 @@ ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb)
                /* Copy i/o-error alert. */
                cdev_sublog->ioerr = sublog->ioerr;
                /* Copy channel path timeout bit. */
-               if (irb->scsw.cstat & SCHN_STAT_INTF_CTRL_CHK)
+               if (irb->scsw.cmd.cstat & SCHN_STAT_INTF_CTRL_CHK)
                        cdev_irb->esw.esw0.erw.cpt = irb->esw.esw0.erw.cpt;
                /* Copy failing storage address validity flag. */
                cdev_irb->esw.esw0.erw.fsavf = irb->esw.esw0.erw.fsavf;
@@ -200,24 +198,24 @@ ccw_device_accumulate_irb(struct ccw_device *cdev, struct irb *irb)
         * If not, the remaining bit have no meaning and we must ignore them.
         * The esw is not meaningful as well...
         */
-       if (!(irb->scsw.stctl & SCSW_STCTL_STATUS_PEND))
+       if (!(scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND))
                return;
 
        /* Check for channel checks and interface control checks. */
        ccw_device_msg_control_check(cdev, irb);
 
        /* Check for path not operational. */
-       if (irb->scsw.pno && irb->scsw.fctl != 0 &&
-           (!(irb->scsw.stctl & SCSW_STCTL_INTER_STATUS) ||
-            (irb->scsw.actl & SCSW_ACTL_SUSPENDED)))
+       if (scsw_is_valid_pno(&irb->scsw) && scsw_pno(&irb->scsw))
                ccw_device_path_notoper(cdev);
-
+       /* No irb accumulation for transport mode irbs. */
+       if (scsw_is_tm(&irb->scsw)) {
+               memcpy(&cdev->private->irb, irb, sizeof(struct irb));
+               return;
+       }
        /*
         * Don't accumulate unsolicited interrupts.
         */
-       if ((irb->scsw.stctl ==
-            (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) &&
-           (!irb->scsw.cc))
+       if (!scsw_is_solicited(&irb->scsw))
                return;
 
        cdev_irb = &cdev->private->irb;
@@ -227,62 +225,63 @@ ccw_device_accumulate_irb(struct ccw_device *cdev, struct irb *irb)
         * status at the subchannel has been cleared and we must not pass
         * intermediate accumulated status to the device driver.
         */
-       if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC)
+       if (irb->scsw.cmd.fctl & SCSW_FCTL_CLEAR_FUNC)
                memset(&cdev->private->irb, 0, sizeof(struct irb));
 
        /* Copy bits which are valid only for the start function. */
-       if (irb->scsw.fctl & SCSW_FCTL_START_FUNC) {
+       if (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) {
                /* Copy key. */
-               cdev_irb->scsw.key = irb->scsw.key;
+               cdev_irb->scsw.cmd.key = irb->scsw.cmd.key;
                /* Copy suspend control bit. */
-               cdev_irb->scsw.sctl = irb->scsw.sctl;
+               cdev_irb->scsw.cmd.sctl = irb->scsw.cmd.sctl;
                /* Accumulate deferred condition code. */
-               cdev_irb->scsw.cc |= irb->scsw.cc;
+               cdev_irb->scsw.cmd.cc |= irb->scsw.cmd.cc;
                /* Copy ccw format bit. */
-               cdev_irb->scsw.fmt = irb->scsw.fmt;
+               cdev_irb->scsw.cmd.fmt = irb->scsw.cmd.fmt;
                /* Copy prefetch bit. */
-               cdev_irb->scsw.pfch = irb->scsw.pfch;
+               cdev_irb->scsw.cmd.pfch = irb->scsw.cmd.pfch;
                /* Copy initial-status-interruption-control. */
-               cdev_irb->scsw.isic = irb->scsw.isic;
+               cdev_irb->scsw.cmd.isic = irb->scsw.cmd.isic;
                /* Copy address limit checking control. */
-               cdev_irb->scsw.alcc = irb->scsw.alcc;
+               cdev_irb->scsw.cmd.alcc = irb->scsw.cmd.alcc;
                /* Copy suppress suspend bit. */
-               cdev_irb->scsw.ssi = irb->scsw.ssi;
+               cdev_irb->scsw.cmd.ssi = irb->scsw.cmd.ssi;
        }
 
        /* Take care of the extended control bit and extended control word. */
        ccw_device_accumulate_ecw(cdev, irb);
            
        /* Accumulate function control. */
-       cdev_irb->scsw.fctl |= irb->scsw.fctl;
+       cdev_irb->scsw.cmd.fctl |= irb->scsw.cmd.fctl;
        /* Copy activity control. */
-       cdev_irb->scsw.actl= irb->scsw.actl;
+       cdev_irb->scsw.cmd.actl = irb->scsw.cmd.actl;
        /* Accumulate status control. */
-       cdev_irb->scsw.stctl |= irb->scsw.stctl;
+       cdev_irb->scsw.cmd.stctl |= irb->scsw.cmd.stctl;
        /*
         * Copy ccw address if it is valid. This is a bit simplified
         * but should be close enough for all practical purposes.
         */
-       if ((irb->scsw.stctl & SCSW_STCTL_PRIM_STATUS) ||
-           ((irb->scsw.stctl == 
+       if ((irb->scsw.cmd.stctl & SCSW_STCTL_PRIM_STATUS) ||
+           ((irb->scsw.cmd.stctl ==
              (SCSW_STCTL_INTER_STATUS|SCSW_STCTL_STATUS_PEND)) &&
-            (irb->scsw.actl & SCSW_ACTL_DEVACT) &&
-            (irb->scsw.actl & SCSW_ACTL_SCHACT)) ||
-           (irb->scsw.actl & SCSW_ACTL_SUSPENDED))
-               cdev_irb->scsw.cpa = irb->scsw.cpa;
+            (irb->scsw.cmd.actl & SCSW_ACTL_DEVACT) &&
+            (irb->scsw.cmd.actl & SCSW_ACTL_SCHACT)) ||
+           (irb->scsw.cmd.actl & SCSW_ACTL_SUSPENDED))
+               cdev_irb->scsw.cmd.cpa = irb->scsw.cmd.cpa;
        /* Accumulate device status, but not the device busy flag. */
-       cdev_irb->scsw.dstat &= ~DEV_STAT_BUSY;
+       cdev_irb->scsw.cmd.dstat &= ~DEV_STAT_BUSY;
        /* dstat is not always valid. */
-       if (irb->scsw.stctl &
+       if (irb->scsw.cmd.stctl &
            (SCSW_STCTL_PRIM_STATUS | SCSW_STCTL_SEC_STATUS
             | SCSW_STCTL_INTER_STATUS | SCSW_STCTL_ALERT_STATUS))
-               cdev_irb->scsw.dstat |= irb->scsw.dstat;
+               cdev_irb->scsw.cmd.dstat |= irb->scsw.cmd.dstat;
        /* Accumulate subchannel status. */
-       cdev_irb->scsw.cstat |= irb->scsw.cstat;
+       cdev_irb->scsw.cmd.cstat |= irb->scsw.cmd.cstat;
        /* Copy residual count if it is valid. */
-       if ((irb->scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&
-           (irb->scsw.cstat & ~(SCHN_STAT_PCI | SCHN_STAT_INCORR_LEN)) == 0)
-               cdev_irb->scsw.count = irb->scsw.count;
+       if ((irb->scsw.cmd.stctl & SCSW_STCTL_PRIM_STATUS) &&
+           (irb->scsw.cmd.cstat & ~(SCHN_STAT_PCI | SCHN_STAT_INCORR_LEN))
+            == 0)
+               cdev_irb->scsw.cmd.count = irb->scsw.cmd.count;
 
        /* Take care of bits in the extended status word. */
        ccw_device_accumulate_esw(cdev, irb);
@@ -299,7 +298,7 @@ ccw_device_accumulate_irb(struct ccw_device *cdev, struct irb *irb)
         *       sense facility available/supported when enabling the
         *       concurrent sense facility.
         */
-       if ((cdev_irb->scsw.dstat & DEV_STAT_UNIT_CHECK) &&
+       if ((cdev_irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) &&
            !(cdev_irb->esw.esw0.erw.cons))
                cdev->private->flags.dosense = 1;
 }
@@ -317,7 +316,7 @@ ccw_device_do_sense(struct ccw_device *cdev, struct irb *irb)
        sch = to_subchannel(cdev->dev.parent);
 
        /* A sense is required, can we do it now ? */
-       if ((irb->scsw.actl  & (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)) != 0)
+       if (scsw_actl(&irb->scsw) & (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT))
                /*
                 * we received an Unit Check but we have no final
                 *  status yet, therefore we must delay the SENSE
@@ -355,20 +354,18 @@ ccw_device_accumulate_basic_sense(struct ccw_device *cdev, struct irb *irb)
         * If not, the remaining bit have no meaning and we must ignore them.
         * The esw is not meaningful as well...
         */
-       if (!(irb->scsw.stctl & SCSW_STCTL_STATUS_PEND))
+       if (!(scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND))
                return;
 
        /* Check for channel checks and interface control checks. */
        ccw_device_msg_control_check(cdev, irb);
 
        /* Check for path not operational. */
-       if (irb->scsw.pno && irb->scsw.fctl != 0 &&
-           (!(irb->scsw.stctl & SCSW_STCTL_INTER_STATUS) ||
-            (irb->scsw.actl & SCSW_ACTL_SUSPENDED)))
+       if (scsw_is_valid_pno(&irb->scsw) && scsw_pno(&irb->scsw))
                ccw_device_path_notoper(cdev);
 
-       if (!(irb->scsw.dstat & DEV_STAT_UNIT_CHECK) &&
-           (irb->scsw.dstat & DEV_STAT_CHN_END)) {
+       if (!(irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) &&
+           (irb->scsw.cmd.dstat & DEV_STAT_CHN_END)) {
                cdev->private->irb.esw.esw0.erw.cons = 1;
                cdev->private->flags.dosense = 0;
        }
@@ -386,11 +383,11 @@ int
 ccw_device_accumulate_and_sense(struct ccw_device *cdev, struct irb *irb)
 {
        ccw_device_accumulate_irb(cdev, irb);
-       if ((irb->scsw.actl  & (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)) != 0)
+       if ((irb->scsw.cmd.actl  & (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)) != 0)
                return -EBUSY;
        /* Check for basic sense. */
        if (cdev->private->flags.dosense &&
-           !(irb->scsw.dstat & DEV_STAT_UNIT_CHECK)) {
+           !(irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)) {
                cdev->private->irb.esw.esw0.erw.cons = 1;
                cdev->private->flags.dosense = 0;
                return 0;
diff --git a/drivers/s390/cio/fcx.c b/drivers/s390/cio/fcx.c
new file mode 100644 (file)
index 0000000..61677df
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ *  Functions for assembling fcx enabled I/O control blocks.
+ *
+ *    Copyright IBM Corp. 2008
+ *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <asm/fcx.h>
+#include "cio.h"
+
+/**
+ * tcw_get_intrg - return pointer to associated interrogate tcw
+ * @tcw: pointer to the original tcw
+ *
+ * Return a pointer to the interrogate tcw associated with the specified tcw
+ * or %NULL if there is no associated interrogate tcw.
+ */
+struct tcw *tcw_get_intrg(struct tcw *tcw)
+{
+       return (struct tcw *) ((addr_t) tcw->intrg);
+}
+EXPORT_SYMBOL(tcw_get_intrg);
+
+/**
+ * tcw_get_data - return pointer to input/output data associated with tcw
+ * @tcw: pointer to the tcw
+ *
+ * Return the input or output data address specified in the tcw depending
+ * on whether the r-bit or the w-bit is set. If neither bit is set, return
+ * %NULL.
+ */
+void *tcw_get_data(struct tcw *tcw)
+{
+       if (tcw->r)
+               return (void *) ((addr_t) tcw->input);
+       if (tcw->w)
+               return (void *) ((addr_t) tcw->output);
+       return NULL;
+}
+EXPORT_SYMBOL(tcw_get_data);
+
+/**
+ * tcw_get_tccb - return pointer to tccb associated with tcw
+ * @tcw: pointer to the tcw
+ *
+ * Return pointer to the tccb associated with this tcw.
+ */
+struct tccb *tcw_get_tccb(struct tcw *tcw)
+{
+       return (struct tccb *) ((addr_t) tcw->tccb);
+}
+EXPORT_SYMBOL(tcw_get_tccb);
+
+/**
+ * tcw_get_tsb - return pointer to tsb associated with tcw
+ * @tcw: pointer to the tcw
+ *
+ * Return pointer to the tsb associated with this tcw.
+ */
+struct tsb *tcw_get_tsb(struct tcw *tcw)
+{
+       return (struct tsb *) ((addr_t) tcw->tsb);
+}
+EXPORT_SYMBOL(tcw_get_tsb);
+
+/**
+ * tcw_init - initialize tcw data structure
+ * @tcw: pointer to the tcw to be initialized
+ * @r: initial value of the r-bit
+ * @w: initial value of the w-bit
+ *
+ * Initialize all fields of the specified tcw data structure with zero and
+ * fill in the format, flags, r and w fields.
+ */
+void tcw_init(struct tcw *tcw, int r, int w)
+{
+       memset(tcw, 0, sizeof(struct tcw));
+       tcw->format = TCW_FORMAT_DEFAULT;
+       tcw->flags = TCW_FLAGS_TIDAW_FORMAT(TCW_TIDAW_FORMAT_DEFAULT);
+       if (r)
+               tcw->r = 1;
+       if (w)
+               tcw->w = 1;
+}
+EXPORT_SYMBOL(tcw_init);
+
+static inline size_t tca_size(struct tccb *tccb)
+{
+       return tccb->tcah.tcal - 12;
+}
+
+static u32 calc_dcw_count(struct tccb *tccb)
+{
+       int offset;
+       struct dcw *dcw;
+       u32 count = 0;
+       size_t size;
+
+       size = tca_size(tccb);
+       for (offset = 0; offset < size;) {
+               dcw = (struct dcw *) &tccb->tca[offset];
+               count += dcw->count;
+               if (!(dcw->flags & DCW_FLAGS_CC))
+                       break;
+               offset += sizeof(struct dcw) + ALIGN((int) dcw->cd_count, 4);
+       }
+       return count;
+}
+
+static u32 calc_cbc_size(struct tidaw *tidaw, int num)
+{
+       int i;
+       u32 cbc_data;
+       u32 cbc_count = 0;
+       u64 data_count = 0;
+
+       for (i = 0; i < num; i++) {
+               if (tidaw[i].flags & TIDAW_FLAGS_LAST)
+                       break;
+               /* TODO: find out if padding applies to total of data
+                * transferred or data transferred by this tidaw. Assumption:
+                * applies to total. */
+               data_count += tidaw[i].count;
+               if (tidaw[i].flags & TIDAW_FLAGS_INSERT_CBC) {
+                       cbc_data = 4 + ALIGN(data_count, 4) - data_count;
+                       cbc_count += cbc_data;
+                       data_count += cbc_data;
+               }
+       }
+       return cbc_count;
+}
+
+/**
+ * tcw_finalize - finalize tcw length fields and tidaw list
+ * @tcw: pointer to the tcw
+ * @num_tidaws: the number of tidaws used to address input/output data or zero
+ * if no tida is used
+ *
+ * Calculate the input-/output-count and tccbl field in the tcw, add a
+ * tcat the tccb and terminate the data tidaw list if used.
+ *
+ * Note: in case input- or output-tida is used, the tidaw-list must be stored
+ * in contiguous storage (no ttic). The tcal field in the tccb must be
+ * up-to-date.
+ */
+void tcw_finalize(struct tcw *tcw, int num_tidaws)
+{
+       struct tidaw *tidaw;
+       struct tccb *tccb;
+       struct tccb_tcat *tcat;
+       u32 count;
+
+       /* Terminate tidaw list. */
+       tidaw = tcw_get_data(tcw);
+       if (num_tidaws > 0)
+               tidaw[num_tidaws - 1].flags |= TIDAW_FLAGS_LAST;
+       /* Add tcat to tccb. */
+       tccb = tcw_get_tccb(tcw);
+       tcat = (struct tccb_tcat *) &tccb->tca[tca_size(tccb)];
+       memset(tcat, 0, sizeof(tcat));
+       /* Calculate tcw input/output count and tcat transport count. */
+       count = calc_dcw_count(tccb);
+       if (tcw->w && (tcw->flags & TCW_FLAGS_OUTPUT_TIDA))
+               count += calc_cbc_size(tidaw, num_tidaws);
+       if (tcw->r)
+               tcw->input_count = count;
+       else if (tcw->w)
+               tcw->output_count = count;
+       tcat->count = ALIGN(count, 4) + 4;
+       /* Calculate tccbl. */
+       tcw->tccbl = (sizeof(struct tccb) + tca_size(tccb) +
+                     sizeof(struct tccb_tcat) - 20) >> 2;
+}
+EXPORT_SYMBOL(tcw_finalize);
+
+/**
+ * tcw_set_intrg - set the interrogate tcw address of a tcw
+ * @tcw: the tcw address
+ * @intrg_tcw: the address of the interrogate tcw
+ *
+ * Set the address of the interrogate tcw in the specified tcw.
+ */
+void tcw_set_intrg(struct tcw *tcw, struct tcw *intrg_tcw)
+{
+       tcw->intrg = (u32) ((addr_t) intrg_tcw);
+}
+EXPORT_SYMBOL(tcw_set_intrg);
+
+/**
+ * tcw_set_data - set data address and tida flag of a tcw
+ * @tcw: the tcw address
+ * @data: the data address
+ * @use_tidal: zero of the data address specifies a contiguous block of data,
+ * non-zero if it specifies a list if tidaws.
+ *
+ * Set the input/output data address of a tcw (depending on the value of the
+ * r-flag and w-flag). If @use_tidal is non-zero, the corresponding tida flag
+ * is set as well.
+ */
+void tcw_set_data(struct tcw *tcw, void *data, int use_tidal)
+{
+       if (tcw->r) {
+               tcw->input = (u64) ((addr_t) data);
+               if (use_tidal)
+                       tcw->flags |= TCW_FLAGS_INPUT_TIDA;
+       } else if (tcw->w) {
+               tcw->output = (u64) ((addr_t) data);
+               if (use_tidal)
+                       tcw->flags |= TCW_FLAGS_OUTPUT_TIDA;
+       }
+}
+EXPORT_SYMBOL(tcw_set_data);
+
+/**
+ * tcw_set_tccb - set tccb address of a tcw
+ * @tcw: the tcw address
+ * @tccb: the tccb address
+ *
+ * Set the address of the tccb in the specified tcw.
+ */
+void tcw_set_tccb(struct tcw *tcw, struct tccb *tccb)
+{
+       tcw->tccb = (u64) ((addr_t) tccb);
+}
+EXPORT_SYMBOL(tcw_set_tccb);
+
+/**
+ * tcw_set_tsb - set tsb address of a tcw
+ * @tcw: the tcw address
+ * @tsb: the tsb address
+ *
+ * Set the address of the tsb in the specified tcw.
+ */
+void tcw_set_tsb(struct tcw *tcw, struct tsb *tsb)
+{
+       tcw->tsb = (u64) ((addr_t) tsb);
+}
+EXPORT_SYMBOL(tcw_set_tsb);
+
+/**
+ * tccb_init - initialize tccb
+ * @tccb: the tccb address
+ * @size: the maximum size of the tccb
+ * @sac: the service-action-code to be user
+ *
+ * Initialize the header of the specified tccb by resetting all values to zero
+ * and filling in defaults for format, sac and initial tcal fields.
+ */
+void tccb_init(struct tccb *tccb, size_t size, u32 sac)
+{
+       memset(tccb, 0, size);
+       tccb->tcah.format = TCCB_FORMAT_DEFAULT;
+       tccb->tcah.sac = sac;
+       tccb->tcah.tcal = 12;
+}
+EXPORT_SYMBOL(tccb_init);
+
+/**
+ * tsb_init - initialize tsb
+ * @tsb: the tsb address
+ *
+ * Initialize the specified tsb by resetting all values to zero.
+ */
+void tsb_init(struct tsb *tsb)
+{
+       memset(tsb, 0, sizeof(tsb));
+}
+EXPORT_SYMBOL(tsb_init);
+
+/**
+ * tccb_add_dcw - add a dcw to the tccb
+ * @tccb: the tccb address
+ * @tccb_size: the maximum tccb size
+ * @cmd: the dcw command
+ * @flags: flags for the dcw
+ * @cd: pointer to control data for this dcw or NULL if none is required
+ * @cd_count: number of control data bytes for this dcw
+ * @count: number of data bytes for this dcw
+ *
+ * Add a new dcw to the specified tccb by writing the dcw information specified
+ * by @cmd, @flags, @cd, @cd_count and @count to the tca of the tccb. Return
+ * a pointer to the newly added dcw on success or -%ENOSPC if the new dcw
+ * would exceed the available space as defined by @tccb_size.
+ *
+ * Note: the tcal field of the tccb header will be updates to reflect added
+ * content.
+ */
+struct dcw *tccb_add_dcw(struct tccb *tccb, size_t tccb_size, u8 cmd, u8 flags,
+                        void *cd, u8 cd_count, u32 count)
+{
+       struct dcw *dcw;
+       int size;
+       int tca_offset;
+
+       /* Check for space. */
+       tca_offset = tca_size(tccb);
+       size = ALIGN(sizeof(struct dcw) + cd_count, 4);
+       if (sizeof(struct tccb_tcah) + tca_offset + size +
+           sizeof(struct tccb_tcat) > tccb_size)
+               return ERR_PTR(-ENOSPC);
+       /* Add dcw to tca. */
+       dcw = (struct dcw *) &tccb->tca[tca_offset];
+       memset(dcw, 0, size);
+       dcw->cmd = cmd;
+       dcw->flags = flags;
+       dcw->count = count;
+       dcw->cd_count = cd_count;
+       if (cd)
+               memcpy(&dcw->cd[0], cd, cd_count);
+       tccb->tcah.tcal += size;
+       return dcw;
+}
+EXPORT_SYMBOL(tccb_add_dcw);
+
+/**
+ * tcw_add_tidaw - add a tidaw to a tcw
+ * @tcw: the tcw address
+ * @num_tidaws: the current number of tidaws
+ * @flags: flags for the new tidaw
+ * @addr: address value for the new tidaw
+ * @count: count value for the new tidaw
+ *
+ * Add a new tidaw to the input/output data tidaw-list of the specified tcw
+ * (depending on the value of the r-flag and w-flag) and return a pointer to
+ * the new tidaw.
+ *
+ * Note: the tidaw-list is assumed to be contiguous with no ttics. The caller
+ * must ensure that there is enough space for the new tidaw. The last-tidaw
+ * flag for the last tidaw in the list will be set by tcw_finalize.
+ */
+struct tidaw *tcw_add_tidaw(struct tcw *tcw, int num_tidaws, u8 flags,
+                           void *addr, u32 count)
+{
+       struct tidaw *tidaw;
+
+       /* Add tidaw to tidaw-list. */
+       tidaw = ((struct tidaw *) tcw_get_data(tcw)) + num_tidaws;
+       memset(tidaw, 0, sizeof(struct tidaw));
+       tidaw->flags = flags;
+       tidaw->count = count;
+       tidaw->addr = (u64) ((addr_t) addr);
+       return tidaw;
+}
+EXPORT_SYMBOL(tcw_add_tidaw);
index 144466ab8c15258e8f049e340c3e48d8dcdbebab..528065cb50212adc78c5c326197ee42d58e7351a 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef S390_IDSET_H
 #define S390_IDSET_H S390_IDSET_H
 
-#include "schid.h"
+#include <asm/schid.h>
 
 struct idset;
 
index 8c613160bfceb0e3b2ec905b95083eef55c14a76..3f8f1cf69c76d9082d3bad69d37d2a1dc0f5d123 100644 (file)
@@ -1,12 +1,12 @@
 #ifndef S390_IO_SCH_H
 #define S390_IO_SCH_H
 
-#include "schid.h"
+#include <asm/schid.h>
 
 /*
- * operation request block
+ * command-mode operation request block
  */
-struct orb {
+struct cmd_orb {
        u32 intparm;    /* interruption parameter */
        u32 key  : 4;   /* flags, like key, suspend control, etc. */
        u32 spnd : 1;   /* suspend control */
@@ -28,8 +28,36 @@ struct orb {
        u32 cpa;        /* channel program address */
 }  __attribute__ ((packed, aligned(4)));
 
+/*
+ * transport-mode operation request block
+ */
+struct tm_orb {
+       u32 intparm;
+       u32 key:4;
+       u32 :9;
+       u32 b:1;
+       u32 :2;
+       u32 lpm:8;
+       u32 :7;
+       u32 x:1;
+       u32 tcw;
+       u32 prio:8;
+       u32 :8;
+       u32 rsvpgm:8;
+       u32 :8;
+       u32 :32;
+       u32 :32;
+       u32 :32;
+       u32 :32;
+}  __attribute__ ((packed, aligned(4)));
+
+union orb {
+       struct cmd_orb cmd;
+       struct tm_orb tm;
+}  __attribute__ ((packed, aligned(4)));
+
 struct io_subchannel_private {
-       struct orb orb;         /* operation request block */
+       union orb orb;          /* operation request block */
        struct ccw1 sense_ccw;  /* static ccw for sense command */
 } __attribute__ ((aligned(8)));
 
@@ -95,16 +123,18 @@ struct ccw_device_private {
        void *cmb_wait;                 /* deferred cmb enable/disable */
 };
 
-static inline int ssch(struct subchannel_id schid, volatile struct orb *addr)
+static inline int ssch(struct subchannel_id schid, volatile union orb *addr)
 {
        register struct subchannel_id reg1 asm("1") = schid;
-       int ccode;
+       int ccode = -EIO;
 
        asm volatile(
                "       ssch    0(%2)\n"
-               "       ipm     %0\n"
-               "       srl     %0,28"
-               : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
+               "0:     ipm     %0\n"
+               "       srl     %0,28\n"
+               "1:\n"
+               EX_TABLE(0b, 1b)
+               : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
        return ccode;
 }
 
index 652ea3625f9def33d92e8c4dde4ec50373adb091..9fa2ac13ac85cc94faf822f88f69d85072d57930 100644 (file)
@@ -2,7 +2,7 @@
 #define S390_CIO_IOASM_H
 
 #include <asm/chpid.h>
-#include "schid.h"
+#include <asm/schid.h>
 
 /*
  * TPI info structure
diff --git a/drivers/s390/cio/isc.c b/drivers/s390/cio/isc.c
new file mode 100644 (file)
index 0000000..c592087
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Functions for registration of I/O interruption subclasses on s390.
+ *
+ * Copyright IBM Corp. 2008
+ * Authors: Sebastian Ott <sebott@linux.vnet.ibm.com>
+ */
+
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <asm/isc.h>
+
+static unsigned int isc_refs[MAX_ISC + 1];
+static DEFINE_SPINLOCK(isc_ref_lock);
+
+
+/**
+ * isc_register - register an I/O interruption subclass.
+ * @isc: I/O interruption subclass to register
+ *
+ * The number of users for @isc is increased. If this is the first user to
+ * register @isc, the corresponding I/O interruption subclass mask is enabled.
+ *
+ * Context:
+ *   This function must not be called in interrupt context.
+ */
+void isc_register(unsigned int isc)
+{
+       if (isc > MAX_ISC) {
+               WARN_ON(1);
+               return;
+       }
+
+       spin_lock(&isc_ref_lock);
+       if (isc_refs[isc] == 0)
+               ctl_set_bit(6, 31 - isc);
+       isc_refs[isc]++;
+       spin_unlock(&isc_ref_lock);
+}
+EXPORT_SYMBOL_GPL(isc_register);
+
+/**
+ * isc_unregister - unregister an I/O interruption subclass.
+ * @isc: I/O interruption subclass to unregister
+ *
+ * The number of users for @isc is decreased. If this is the last user to
+ * unregister @isc, the corresponding I/O interruption subclass mask is
+ * disabled.
+ * Note: This function must not be called if isc_register() hasn't been called
+ * before by the driver for @isc.
+ *
+ * Context:
+ *   This function must not be called in interrupt context.
+ */
+void isc_unregister(unsigned int isc)
+{
+       spin_lock(&isc_ref_lock);
+       /* check for misuse */
+       if (isc > MAX_ISC || isc_refs[isc] == 0) {
+               WARN_ON(1);
+               goto out_unlock;
+       }
+       if (isc_refs[isc] == 1)
+               ctl_clear_bit(6, 31 - isc);
+       isc_refs[isc]--;
+out_unlock:
+       spin_unlock(&isc_ref_lock);
+}
+EXPORT_SYMBOL_GPL(isc_unregister);
diff --git a/drivers/s390/cio/itcw.c b/drivers/s390/cio/itcw.c
new file mode 100644 (file)
index 0000000..17da9ab
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ *  Functions for incremental construction of fcx enabled I/O control blocks.
+ *
+ *    Copyright IBM Corp. 2008
+ *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <asm/fcx.h>
+#include <asm/itcw.h>
+
+/**
+ * struct itcw - incremental tcw helper data type
+ *
+ * This structure serves as a handle for the incremental construction of a
+ * tcw and associated tccb, tsb, data tidaw-list plus an optional interrogate
+ * tcw and associated data. The data structures are contained inside a single
+ * contiguous buffer provided by the user.
+ *
+ * The itcw construction functions take care of overall data integrity:
+ * - reset unused fields to zero
+ * - fill in required pointers
+ * - ensure required alignment for data structures
+ * - prevent data structures to cross 4k-byte boundary where required
+ * - calculate tccb-related length fields
+ * - optionally provide ready-made interrogate tcw and associated structures
+ *
+ * Restrictions apply to the itcws created with these construction functions:
+ * - tida only supported for data address, not for tccb
+ * - only contiguous tidaw-lists (no ttic)
+ * - total number of bytes required per itcw may not exceed 4k bytes
+ * - either read or write operation (may not work with r=0 and w=0)
+ *
+ * Example:
+ * struct itcw *itcw;
+ * void *buffer;
+ * size_t size;
+ *
+ * size = itcw_calc_size(1, 2, 0);
+ * buffer = kmalloc(size, GFP_DMA);
+ * if (!buffer)
+ *     return -ENOMEM;
+ * itcw = itcw_init(buffer, size, ITCW_OP_READ, 1, 2, 0);
+ * if (IS_ERR(itcw))
+ *     return PTR_ER(itcw);
+ * itcw_add_dcw(itcw, 0x2, 0, NULL, 0, 72);
+ * itcw_add_tidaw(itcw, 0, 0x30000, 20);
+ * itcw_add_tidaw(itcw, 0, 0x40000, 52);
+ * itcw_finalize(itcw);
+ *
+ */
+struct itcw {
+       struct tcw *tcw;
+       struct tcw *intrg_tcw;
+       int num_tidaws;
+       int max_tidaws;
+       int intrg_num_tidaws;
+       int intrg_max_tidaws;
+};
+
+/**
+ * itcw_get_tcw - return pointer to tcw associated with the itcw
+ * @itcw: address of the itcw
+ *
+ * Return pointer to the tcw associated with the itcw.
+ */
+struct tcw *itcw_get_tcw(struct itcw *itcw)
+{
+       return itcw->tcw;
+}
+EXPORT_SYMBOL(itcw_get_tcw);
+
+/**
+ * itcw_calc_size - return the size of an itcw with the given parameters
+ * @intrg: if non-zero, add an interrogate tcw
+ * @max_tidaws: maximum number of tidaws to be used for data addressing or zero
+ * if no tida is to be used.
+ * @intrg_max_tidaws: maximum number of tidaws to be used for data addressing
+ * by the interrogate tcw, if specified
+ *
+ * Calculate and return the number of bytes required to hold an itcw with the
+ * given parameters and assuming tccbs with maximum size.
+ *
+ * Note that the resulting size also contains bytes needed for alignment
+ * padding as well as padding to ensure that data structures don't cross a
+ * 4k-boundary where required.
+ */
+size_t itcw_calc_size(int intrg, int max_tidaws, int intrg_max_tidaws)
+{
+       size_t len;
+
+       /* Main data. */
+       len = sizeof(struct itcw);
+       len += /* TCW */ sizeof(struct tcw) + /* TCCB */ TCCB_MAX_SIZE +
+              /* TSB */ sizeof(struct tsb) +
+              /* TIDAL */ max_tidaws * sizeof(struct tidaw);
+       /* Interrogate data. */
+       if (intrg) {
+               len += /* TCW */ sizeof(struct tcw) + /* TCCB */ TCCB_MAX_SIZE +
+                      /* TSB */ sizeof(struct tsb) +
+                      /* TIDAL */ intrg_max_tidaws * sizeof(struct tidaw);
+       }
+       /* Maximum required alignment padding. */
+       len += /* Initial TCW */ 63 + /* Interrogate TCCB */ 7;
+       /* Maximum padding for structures that may not cross 4k boundary. */
+       if ((max_tidaws > 0) || (intrg_max_tidaws > 0))
+               len += max(max_tidaws, intrg_max_tidaws) *
+                      sizeof(struct tidaw) - 1;
+       return len;
+}
+EXPORT_SYMBOL(itcw_calc_size);
+
+#define CROSS4K(x, l)  (((x) & ~4095) != ((x + l) & ~4095))
+
+static inline void *fit_chunk(addr_t *start, addr_t end, size_t len,
+                             int align, int check_4k)
+{
+       addr_t addr;
+
+       addr = ALIGN(*start, align);
+       if (check_4k && CROSS4K(addr, len)) {
+               addr = ALIGN(addr, 4096);
+               addr = ALIGN(addr, align);
+       }
+       if (addr + len > end)
+               return ERR_PTR(-ENOSPC);
+       *start = addr + len;
+       return (void *) addr;
+}
+
+/**
+ * itcw_init - initialize incremental tcw data structure
+ * @buffer: address of buffer to use for data structures
+ * @size: number of bytes in buffer
+ * @op: %ITCW_OP_READ for a read operation tcw, %ITCW_OP_WRITE for a write
+ * operation tcw
+ * @intrg: if non-zero, add and initialize an interrogate tcw
+ * @max_tidaws: maximum number of tidaws to be used for data addressing or zero
+ * if no tida is to be used.
+ * @intrg_max_tidaws: maximum number of tidaws to be used for data addressing
+ * by the interrogate tcw, if specified
+ *
+ * Prepare the specified buffer to be used as an incremental tcw, i.e. a
+ * helper data structure that can be used to construct a valid tcw by
+ * successive calls to other helper functions. Note: the buffer needs to be
+ * located below the 2G address limit. The resulting tcw has the following
+ * restrictions:
+ *  - no tccb tidal
+ *  - input/output tidal is contiguous (no ttic)
+ *  - total data should not exceed 4k
+ *  - tcw specifies either read or write operation
+ *
+ * On success, return pointer to the resulting incremental tcw data structure,
+ * ERR_PTR otherwise.
+ */
+struct itcw *itcw_init(void *buffer, size_t size, int op, int intrg,
+                      int max_tidaws, int intrg_max_tidaws)
+{
+       struct itcw *itcw;
+       void *chunk;
+       addr_t start;
+       addr_t end;
+
+       /* Check for 2G limit. */
+       start = (addr_t) buffer;
+       end = start + size;
+       if (end > (1 << 31))
+               return ERR_PTR(-EINVAL);
+       memset(buffer, 0, size);
+       /* ITCW. */
+       chunk = fit_chunk(&start, end, sizeof(struct itcw), 1, 0);
+       if (IS_ERR(chunk))
+               return chunk;
+       itcw = chunk;
+       itcw->max_tidaws = max_tidaws;
+       itcw->intrg_max_tidaws = intrg_max_tidaws;
+       /* Main TCW. */
+       chunk = fit_chunk(&start, end, sizeof(struct tcw), 64, 0);
+       if (IS_ERR(chunk))
+               return chunk;
+       itcw->tcw = chunk;
+       tcw_init(itcw->tcw, (op == ITCW_OP_READ) ? 1 : 0,
+                (op == ITCW_OP_WRITE) ? 1 : 0);
+       /* Interrogate TCW. */
+       if (intrg) {
+               chunk = fit_chunk(&start, end, sizeof(struct tcw), 64, 0);
+               if (IS_ERR(chunk))
+                       return chunk;
+               itcw->intrg_tcw = chunk;
+               tcw_init(itcw->intrg_tcw, 1, 0);
+               tcw_set_intrg(itcw->tcw, itcw->intrg_tcw);
+       }
+       /* Data TIDAL. */
+       if (max_tidaws > 0) {
+               chunk = fit_chunk(&start, end, sizeof(struct tidaw) *
+                                 max_tidaws, 16, 1);
+               if (IS_ERR(chunk))
+                       return chunk;
+               tcw_set_data(itcw->tcw, chunk, 1);
+       }
+       /* Interrogate data TIDAL. */
+       if (intrg && (intrg_max_tidaws > 0)) {
+               chunk = fit_chunk(&start, end, sizeof(struct tidaw) *
+                                 intrg_max_tidaws, 16, 1);
+               if (IS_ERR(chunk))
+                       return chunk;
+               tcw_set_data(itcw->intrg_tcw, chunk, 1);
+       }
+       /* TSB. */
+       chunk = fit_chunk(&start, end, sizeof(struct tsb), 8, 0);
+       if (IS_ERR(chunk))
+               return chunk;
+       tsb_init(chunk);
+       tcw_set_tsb(itcw->tcw, chunk);
+       /* Interrogate TSB. */
+       if (intrg) {
+               chunk = fit_chunk(&start, end, sizeof(struct tsb), 8, 0);
+               if (IS_ERR(chunk))
+                       return chunk;
+               tsb_init(chunk);
+               tcw_set_tsb(itcw->intrg_tcw, chunk);
+       }
+       /* TCCB. */
+       chunk = fit_chunk(&start, end, TCCB_MAX_SIZE, 8, 0);
+       if (IS_ERR(chunk))
+               return chunk;
+       tccb_init(chunk, TCCB_MAX_SIZE, TCCB_SAC_DEFAULT);
+       tcw_set_tccb(itcw->tcw, chunk);
+       /* Interrogate TCCB. */
+       if (intrg) {
+               chunk = fit_chunk(&start, end, TCCB_MAX_SIZE, 8, 0);
+               if (IS_ERR(chunk))
+                       return chunk;
+               tccb_init(chunk, TCCB_MAX_SIZE, TCCB_SAC_INTRG);
+               tcw_set_tccb(itcw->intrg_tcw, chunk);
+               tccb_add_dcw(chunk, TCCB_MAX_SIZE, DCW_CMD_INTRG, 0, NULL,
+                            sizeof(struct dcw_intrg_data), 0);
+               tcw_finalize(itcw->intrg_tcw, 0);
+       }
+       return itcw;
+}
+EXPORT_SYMBOL(itcw_init);
+
+/**
+ * itcw_add_dcw - add a dcw to the itcw
+ * @itcw: address of the itcw
+ * @cmd: the dcw command
+ * @flags: flags for the dcw
+ * @cd: address of control data for this dcw or NULL if none is required
+ * @cd_count: number of control data bytes for this dcw
+ * @count: number of data bytes for this dcw
+ *
+ * Add a new dcw to the specified itcw by writing the dcw information specified
+ * by @cmd, @flags, @cd, @cd_count and @count to the tca of the tccb. Return
+ * a pointer to the newly added dcw on success or -%ENOSPC if the new dcw
+ * would exceed the available space.
+ *
+ * Note: the tcal field of the tccb header will be updated to reflect added
+ * content.
+ */
+struct dcw *itcw_add_dcw(struct itcw *itcw, u8 cmd, u8 flags, void *cd,
+                        u8 cd_count, u32 count)
+{
+       return tccb_add_dcw(tcw_get_tccb(itcw->tcw), TCCB_MAX_SIZE, cmd,
+                           flags, cd, cd_count, count);
+}
+EXPORT_SYMBOL(itcw_add_dcw);
+
+/**
+ * itcw_add_tidaw - add a tidaw to the itcw
+ * @itcw: address of the itcw
+ * @flags: flags for the new tidaw
+ * @addr: address value for the new tidaw
+ * @count: count value for the new tidaw
+ *
+ * Add a new tidaw to the input/output data tidaw-list of the specified itcw
+ * (depending on the value of the r-flag and w-flag). Return a pointer to
+ * the new tidaw on success or -%ENOSPC if the new tidaw would exceed the
+ * available space.
+ *
+ * Note: the tidaw-list is assumed to be contiguous with no ttics. The
+ * last-tidaw flag for the last tidaw in the list will be set by itcw_finalize.
+ */
+struct tidaw *itcw_add_tidaw(struct itcw *itcw, u8 flags, void *addr, u32 count)
+{
+       if (itcw->num_tidaws >= itcw->max_tidaws)
+               return ERR_PTR(-ENOSPC);
+       return tcw_add_tidaw(itcw->tcw, itcw->num_tidaws++, flags, addr, count);
+}
+EXPORT_SYMBOL(itcw_add_tidaw);
+
+/**
+ * itcw_set_data - set data address and tida flag of the itcw
+ * @itcw: address of the itcw
+ * @addr: the data address
+ * @use_tidal: zero of the data address specifies a contiguous block of data,
+ * non-zero if it specifies a list if tidaws.
+ *
+ * Set the input/output data address of the itcw (depending on the value of the
+ * r-flag and w-flag). If @use_tidal is non-zero, the corresponding tida flag
+ * is set as well.
+ */
+void itcw_set_data(struct itcw *itcw, void *addr, int use_tidal)
+{
+       tcw_set_data(itcw->tcw, addr, use_tidal);
+}
+EXPORT_SYMBOL(itcw_set_data);
+
+/**
+ * itcw_finalize - calculate length and count fields of the itcw
+ * @itcw: address of the itcw
+ *
+ * Calculate tcw input-/output-count and tccbl fields and add a tcat the tccb.
+ * In case input- or output-tida is used, the tidaw-list must be stored in
+ * continuous storage (no ttic). The tcal field in the tccb must be
+ * up-to-date.
+ */
+void itcw_finalize(struct itcw *itcw)
+{
+       tcw_finalize(itcw->tcw, itcw->num_tidaws);
+}
+EXPORT_SYMBOL(itcw_finalize);
index 445cf364e461f353cf8dee05b6d98a3eb15e756c..2bf36e14b10214d4457a98c5fff8de69db1a306c 100644 (file)
@@ -2082,7 +2082,6 @@ qdio_timeout_handler(struct ccw_device *cdev)
        default:
                BUG();
        }
-       ccw_device_set_timeout(cdev, 0);
        wake_up(&cdev->private->wait_q);
 }
 
@@ -2121,6 +2120,8 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                case -EIO:
                        QDIO_PRINT_ERR("i/o error on device %s\n",
                                       cdev->dev.bus_id);
+                       qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
+                       wake_up(&cdev->private->wait_q);
                        return;
                case -ETIMEDOUT:
                        qdio_timeout_handler(cdev);
@@ -2139,8 +2140,8 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
        QDIO_DBF_TEXT4(0, trace, dbf_text);
 #endif /* CONFIG_QDIO_DEBUG */
 
-        cstat = irb->scsw.cstat;
-        dstat = irb->scsw.dstat;
+       cstat = irb->scsw.cmd.cstat;
+       dstat = irb->scsw.cmd.dstat;
 
        switch (irq_ptr->state) {
        case QDIO_IRQ_STATE_INACTIVE:
@@ -2353,9 +2354,6 @@ tiqdio_check_chsc_availability(void)
 {
        char dbf_text[15];
 
-       if (!css_characteristics_avail)
-               return -EIO;
-
        /* Check for bit 41. */
        if (!css_general_characteristics.aif) {
                QDIO_PRINT_WARN("Adapter interruption facility not " \
@@ -2667,12 +2665,12 @@ qdio_shutdown(struct ccw_device *cdev, int how)
                spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
        } else if (rc == 0) {
                qdio_set_state(irq_ptr, QDIO_IRQ_STATE_CLEANUP);
-               ccw_device_set_timeout(cdev, timeout);
                spin_unlock_irqrestore(get_ccwdev_lock(cdev),flags);
 
-               wait_event(cdev->private->wait_q,
-                          irq_ptr->state == QDIO_IRQ_STATE_INACTIVE ||
-                          irq_ptr->state == QDIO_IRQ_STATE_ERR);
+               wait_event_interruptible_timeout(cdev->private->wait_q,
+                       irq_ptr->state == QDIO_IRQ_STATE_INACTIVE ||
+                       irq_ptr->state == QDIO_IRQ_STATE_ERR,
+                       timeout);
        } else {
                QDIO_PRINT_INFO("ccw_device_{halt,clear} returned %d for "
                                "device %s\n", result, cdev->dev.bus_id);
@@ -2692,7 +2690,6 @@ qdio_shutdown(struct ccw_device *cdev, int how)
 
        /* Ignore errors. */
        qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
-       ccw_device_set_timeout(cdev, 0);
 out:
        up(&irq_ptr->setting_up_sema);
        return result;
@@ -2907,13 +2904,10 @@ qdio_establish_handle_irq(struct ccw_device *cdev, int cstat, int dstat)
        QDIO_DBF_TEXT0(0,setup,dbf_text);
        QDIO_DBF_TEXT0(0,trace,dbf_text);
 
-       if (qdio_establish_irq_check_for_errors(cdev, cstat, dstat)) {
-               ccw_device_set_timeout(cdev, 0);
+       if (qdio_establish_irq_check_for_errors(cdev, cstat, dstat))
                return;
-       }
 
        qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ESTABLISHED);
-       ccw_device_set_timeout(cdev, 0);
 }
 
 int
@@ -3196,8 +3190,6 @@ qdio_establish(struct qdio_initialize *init_data)
                                irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
                                result, result2);
                result=result2;
-               if (result)
-                       ccw_device_set_timeout(cdev, 0);
        }
 
        spin_unlock_irqrestore(get_ccwdev_lock(cdev),saveflags);
@@ -3279,7 +3271,6 @@ qdio_activate(struct ccw_device *cdev, int flags)
 
        spin_lock_irqsave(get_ccwdev_lock(cdev),saveflags);
 
-       ccw_device_set_timeout(cdev, 0);
        ccw_device_set_options(cdev, CCWDEV_REPORT_ALL);
        result=ccw_device_start(cdev,&irq_ptr->ccw,QDIO_DOING_ACTIVATE,
                                0, DOIO_DENY_PREFETCH);
@@ -3722,7 +3713,8 @@ tiqdio_register_thinints(void)
        char dbf_text[20];
 
        tiqdio_ind =
-               s390_register_adapter_interrupt(&tiqdio_thinint_handler, NULL);
+               s390_register_adapter_interrupt(&tiqdio_thinint_handler, NULL,
+                                               TIQDIO_THININT_ISC);
        if (IS_ERR(tiqdio_ind)) {
                sprintf(dbf_text, "regthn%lx", PTR_ERR(tiqdio_ind));
                QDIO_DBF_TEXT0(0,setup,dbf_text);
@@ -3738,7 +3730,8 @@ static void
 tiqdio_unregister_thinints(void)
 {
        if (tiqdio_ind)
-               s390_unregister_adapter_interrupt(tiqdio_ind);
+               s390_unregister_adapter_interrupt(tiqdio_ind,
+                                                 TIQDIO_THININT_ISC);
 }
 
 static int
@@ -3899,6 +3892,7 @@ init_QDIO(void)
                                            qdio_mempool_alloc,
                                            qdio_mempool_free, NULL);
 
+       isc_register(QDIO_AIRQ_ISC);
        if (tiqdio_check_chsc_availability())
                QDIO_PRINT_ERR("Not all CHSCs supported. Continuing.\n");
 
@@ -3911,6 +3905,7 @@ static void __exit
 cleanup_QDIO(void)
 {
        tiqdio_unregister_thinints();
+       isc_unregister(QDIO_AIRQ_ISC);
        qdio_remove_procfs_entry();
        qdio_release_qdio_memory();
        qdio_unregister_dbf_views();
index c3df6b2c38b76c2d2c99a3bb8528c0598cd44ecf..7656081a24d284b33bc893571412e466e21b9585 100644 (file)
@@ -2,8 +2,8 @@
 #define _CIO_QDIO_H
 
 #include <asm/page.h>
-
-#include "schid.h"
+#include <asm/isc.h>
+#include <asm/schid.h>
 
 #ifdef CONFIG_QDIO_DEBUG
 #define QDIO_VERBOSE_LEVEL 9
@@ -26,7 +26,7 @@
  */
 #define IQDIO_FILL_LEVEL_TO_POLL 4
 
-#define TIQDIO_THININT_ISC 3
+#define TIQDIO_THININT_ISC QDIO_AIRQ_ISC
 #define TIQDIO_DELAY_TARGET 0
 #define QDIO_BUSY_BIT_PATIENCE 100 /* in microsecs */
 #define QDIO_BUSY_BIT_GIVE_UP 10000000 /* 10 seconds */
diff --git a/drivers/s390/cio/schid.h b/drivers/s390/cio/schid.h
deleted file mode 100644 (file)
index 54328fe..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef S390_SCHID_H
-#define S390_SCHID_H
-
-struct subchannel_id {
-       __u32 reserved:13;
-       __u32 ssid:2;
-       __u32 one:1;
-       __u32 sch_no:16;
-} __attribute__ ((packed,aligned(4)));
-
-
-/* Helper function for sane state of pre-allocated subchannel_id. */
-static inline void
-init_subchannel_id(struct subchannel_id *schid)
-{
-       memset(schid, 0, sizeof(struct subchannel_id));
-       schid->one = 1;
-}
-
-static inline int
-schid_equal(struct subchannel_id *schid1, struct subchannel_id *schid2)
-{
-       return !memcmp(schid1, schid2, sizeof(struct subchannel_id));
-}
-
-#endif /* S390_SCHID_H */
diff --git a/drivers/s390/cio/scsw.c b/drivers/s390/cio/scsw.c
new file mode 100644 (file)
index 0000000..f8da25a
--- /dev/null
@@ -0,0 +1,843 @@
+/*
+ *  Helper functions for scsw access.
+ *
+ *    Copyright IBM Corp. 2008
+ *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <asm/cio.h>
+#include "css.h"
+#include "chsc.h"
+
+/**
+ * scsw_is_tm - check for transport mode scsw
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the specified scsw is a transport mode scsw, zero
+ * otherwise.
+ */
+int scsw_is_tm(union scsw *scsw)
+{
+       return css_general_characteristics.fcx && (scsw->tm.x == 1);
+}
+EXPORT_SYMBOL(scsw_is_tm);
+
+/**
+ * scsw_key - return scsw key field
+ * @scsw: pointer to scsw
+ *
+ * Return the value of the key field of the specified scsw, regardless of
+ * whether it is a transport mode or command mode scsw.
+ */
+u32 scsw_key(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw->tm.key;
+       else
+               return scsw->cmd.key;
+}
+EXPORT_SYMBOL(scsw_key);
+
+/**
+ * scsw_eswf - return scsw eswf field
+ * @scsw: pointer to scsw
+ *
+ * Return the value of the eswf field of the specified scsw, regardless of
+ * whether it is a transport mode or command mode scsw.
+ */
+u32 scsw_eswf(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw->tm.eswf;
+       else
+               return scsw->cmd.eswf;
+}
+EXPORT_SYMBOL(scsw_eswf);
+
+/**
+ * scsw_cc - return scsw cc field
+ * @scsw: pointer to scsw
+ *
+ * Return the value of the cc field of the specified scsw, regardless of
+ * whether it is a transport mode or command mode scsw.
+ */
+u32 scsw_cc(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw->tm.cc;
+       else
+               return scsw->cmd.cc;
+}
+EXPORT_SYMBOL(scsw_cc);
+
+/**
+ * scsw_ectl - return scsw ectl field
+ * @scsw: pointer to scsw
+ *
+ * Return the value of the ectl field of the specified scsw, regardless of
+ * whether it is a transport mode or command mode scsw.
+ */
+u32 scsw_ectl(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw->tm.ectl;
+       else
+               return scsw->cmd.ectl;
+}
+EXPORT_SYMBOL(scsw_ectl);
+
+/**
+ * scsw_pno - return scsw pno field
+ * @scsw: pointer to scsw
+ *
+ * Return the value of the pno field of the specified scsw, regardless of
+ * whether it is a transport mode or command mode scsw.
+ */
+u32 scsw_pno(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw->tm.pno;
+       else
+               return scsw->cmd.pno;
+}
+EXPORT_SYMBOL(scsw_pno);
+
+/**
+ * scsw_fctl - return scsw fctl field
+ * @scsw: pointer to scsw
+ *
+ * Return the value of the fctl field of the specified scsw, regardless of
+ * whether it is a transport mode or command mode scsw.
+ */
+u32 scsw_fctl(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw->tm.fctl;
+       else
+               return scsw->cmd.fctl;
+}
+EXPORT_SYMBOL(scsw_fctl);
+
+/**
+ * scsw_actl - return scsw actl field
+ * @scsw: pointer to scsw
+ *
+ * Return the value of the actl field of the specified scsw, regardless of
+ * whether it is a transport mode or command mode scsw.
+ */
+u32 scsw_actl(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw->tm.actl;
+       else
+               return scsw->cmd.actl;
+}
+EXPORT_SYMBOL(scsw_actl);
+
+/**
+ * scsw_stctl - return scsw stctl field
+ * @scsw: pointer to scsw
+ *
+ * Return the value of the stctl field of the specified scsw, regardless of
+ * whether it is a transport mode or command mode scsw.
+ */
+u32 scsw_stctl(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw->tm.stctl;
+       else
+               return scsw->cmd.stctl;
+}
+EXPORT_SYMBOL(scsw_stctl);
+
+/**
+ * scsw_dstat - return scsw dstat field
+ * @scsw: pointer to scsw
+ *
+ * Return the value of the dstat field of the specified scsw, regardless of
+ * whether it is a transport mode or command mode scsw.
+ */
+u32 scsw_dstat(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw->tm.dstat;
+       else
+               return scsw->cmd.dstat;
+}
+EXPORT_SYMBOL(scsw_dstat);
+
+/**
+ * scsw_cstat - return scsw cstat field
+ * @scsw: pointer to scsw
+ *
+ * Return the value of the cstat field of the specified scsw, regardless of
+ * whether it is a transport mode or command mode scsw.
+ */
+u32 scsw_cstat(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw->tm.cstat;
+       else
+               return scsw->cmd.cstat;
+}
+EXPORT_SYMBOL(scsw_cstat);
+
+/**
+ * scsw_cmd_is_valid_key - check key field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the key field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_key(union scsw *scsw)
+{
+       return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_key);
+
+/**
+ * scsw_cmd_is_valid_sctl - check fctl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the fctl field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_sctl(union scsw *scsw)
+{
+       return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_sctl);
+
+/**
+ * scsw_cmd_is_valid_eswf - check eswf field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the eswf field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_eswf(union scsw *scsw)
+{
+       return (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_eswf);
+
+/**
+ * scsw_cmd_is_valid_cc - check cc field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the cc field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_cc(union scsw *scsw)
+{
+       return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC) &&
+              (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_cc);
+
+/**
+ * scsw_cmd_is_valid_fmt - check fmt field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the fmt field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_fmt(union scsw *scsw)
+{
+       return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_fmt);
+
+/**
+ * scsw_cmd_is_valid_pfch - check pfch field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the pfch field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_pfch(union scsw *scsw)
+{
+       return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_pfch);
+
+/**
+ * scsw_cmd_is_valid_isic - check isic field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the isic field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_isic(union scsw *scsw)
+{
+       return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_isic);
+
+/**
+ * scsw_cmd_is_valid_alcc - check alcc field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the alcc field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_alcc(union scsw *scsw)
+{
+       return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_alcc);
+
+/**
+ * scsw_cmd_is_valid_ssi - check ssi field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the ssi field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_ssi(union scsw *scsw)
+{
+       return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_ssi);
+
+/**
+ * scsw_cmd_is_valid_zcc - check zcc field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the zcc field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_zcc(union scsw *scsw)
+{
+       return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC) &&
+              (scsw->cmd.stctl & SCSW_STCTL_INTER_STATUS);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_zcc);
+
+/**
+ * scsw_cmd_is_valid_ectl - check ectl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the ectl field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_ectl(union scsw *scsw)
+{
+       return (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND) &&
+              !(scsw->cmd.stctl & SCSW_STCTL_INTER_STATUS) &&
+              (scsw->cmd.stctl & SCSW_STCTL_ALERT_STATUS);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_ectl);
+
+/**
+ * scsw_cmd_is_valid_pno - check pno field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the pno field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_pno(union scsw *scsw)
+{
+       return (scsw->cmd.fctl != 0) &&
+              (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND) &&
+              (!(scsw->cmd.stctl & SCSW_STCTL_INTER_STATUS) ||
+                ((scsw->cmd.stctl & SCSW_STCTL_INTER_STATUS) &&
+                 (scsw->cmd.actl & SCSW_ACTL_SUSPENDED)));
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_pno);
+
+/**
+ * scsw_cmd_is_valid_fctl - check fctl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the fctl field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_fctl(union scsw *scsw)
+{
+       /* Only valid if pmcw.dnv == 1*/
+       return 1;
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_fctl);
+
+/**
+ * scsw_cmd_is_valid_actl - check actl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the actl field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_actl(union scsw *scsw)
+{
+       /* Only valid if pmcw.dnv == 1*/
+       return 1;
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_actl);
+
+/**
+ * scsw_cmd_is_valid_stctl - check stctl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the stctl field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_stctl(union scsw *scsw)
+{
+       /* Only valid if pmcw.dnv == 1*/
+       return 1;
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_stctl);
+
+/**
+ * scsw_cmd_is_valid_dstat - check dstat field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the dstat field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_dstat(union scsw *scsw)
+{
+       return (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND) &&
+              (scsw->cmd.cc != 3);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_dstat);
+
+/**
+ * scsw_cmd_is_valid_cstat - check cstat field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the cstat field of the specified command mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_cmd_is_valid_cstat(union scsw *scsw)
+{
+       return (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND) &&
+              (scsw->cmd.cc != 3);
+}
+EXPORT_SYMBOL(scsw_cmd_is_valid_cstat);
+
+/**
+ * scsw_tm_is_valid_key - check key field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the key field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_key(union scsw *scsw)
+{
+       return (scsw->tm.fctl & SCSW_FCTL_START_FUNC);
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_key);
+
+/**
+ * scsw_tm_is_valid_eswf - check eswf field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the eswf field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_eswf(union scsw *scsw)
+{
+       return (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND);
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_eswf);
+
+/**
+ * scsw_tm_is_valid_cc - check cc field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the cc field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_cc(union scsw *scsw)
+{
+       return (scsw->tm.fctl & SCSW_FCTL_START_FUNC) &&
+              (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND);
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_cc);
+
+/**
+ * scsw_tm_is_valid_fmt - check fmt field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the fmt field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_fmt(union scsw *scsw)
+{
+       return 1;
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_fmt);
+
+/**
+ * scsw_tm_is_valid_x - check x field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the x field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_x(union scsw *scsw)
+{
+       return 1;
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_x);
+
+/**
+ * scsw_tm_is_valid_q - check q field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the q field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_q(union scsw *scsw)
+{
+       return 1;
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_q);
+
+/**
+ * scsw_tm_is_valid_ectl - check ectl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the ectl field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_ectl(union scsw *scsw)
+{
+       return (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND) &&
+              !(scsw->tm.stctl & SCSW_STCTL_INTER_STATUS) &&
+              (scsw->tm.stctl & SCSW_STCTL_ALERT_STATUS);
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_ectl);
+
+/**
+ * scsw_tm_is_valid_pno - check pno field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the pno field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_pno(union scsw *scsw)
+{
+       return (scsw->tm.fctl != 0) &&
+              (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND) &&
+              (!(scsw->tm.stctl & SCSW_STCTL_INTER_STATUS) ||
+                ((scsw->tm.stctl & SCSW_STCTL_INTER_STATUS) &&
+                 (scsw->tm.actl & SCSW_ACTL_SUSPENDED)));
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_pno);
+
+/**
+ * scsw_tm_is_valid_fctl - check fctl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the fctl field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_fctl(union scsw *scsw)
+{
+       /* Only valid if pmcw.dnv == 1*/
+       return 1;
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_fctl);
+
+/**
+ * scsw_tm_is_valid_actl - check actl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the actl field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_actl(union scsw *scsw)
+{
+       /* Only valid if pmcw.dnv == 1*/
+       return 1;
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_actl);
+
+/**
+ * scsw_tm_is_valid_stctl - check stctl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the stctl field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_stctl(union scsw *scsw)
+{
+       /* Only valid if pmcw.dnv == 1*/
+       return 1;
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_stctl);
+
+/**
+ * scsw_tm_is_valid_dstat - check dstat field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the dstat field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_dstat(union scsw *scsw)
+{
+       return (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND) &&
+              (scsw->tm.cc != 3);
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_dstat);
+
+/**
+ * scsw_tm_is_valid_cstat - check cstat field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the cstat field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_cstat(union scsw *scsw)
+{
+       return (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND) &&
+              (scsw->tm.cc != 3);
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_cstat);
+
+/**
+ * scsw_tm_is_valid_fcxs - check fcxs field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the fcxs field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_fcxs(union scsw *scsw)
+{
+       return 1;
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_fcxs);
+
+/**
+ * scsw_tm_is_valid_schxs - check schxs field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the schxs field of the specified transport mode scsw is
+ * valid, zero otherwise.
+ */
+int scsw_tm_is_valid_schxs(union scsw *scsw)
+{
+       return (scsw->tm.cstat & (SCHN_STAT_PROG_CHECK |
+                                 SCHN_STAT_INTF_CTRL_CHK |
+                                 SCHN_STAT_PROT_CHECK |
+                                 SCHN_STAT_CHN_DATA_CHK));
+}
+EXPORT_SYMBOL(scsw_tm_is_valid_schxs);
+
+/**
+ * scsw_is_valid_actl - check actl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the actl field of the specified scsw is valid,
+ * regardless of whether it is a transport mode or command mode scsw.
+ * Return zero if the field does not contain a valid value.
+ */
+int scsw_is_valid_actl(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw_tm_is_valid_actl(scsw);
+       else
+               return scsw_cmd_is_valid_actl(scsw);
+}
+EXPORT_SYMBOL(scsw_is_valid_actl);
+
+/**
+ * scsw_is_valid_cc - check cc field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the cc field of the specified scsw is valid,
+ * regardless of whether it is a transport mode or command mode scsw.
+ * Return zero if the field does not contain a valid value.
+ */
+int scsw_is_valid_cc(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw_tm_is_valid_cc(scsw);
+       else
+               return scsw_cmd_is_valid_cc(scsw);
+}
+EXPORT_SYMBOL(scsw_is_valid_cc);
+
+/**
+ * scsw_is_valid_cstat - check cstat field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the cstat field of the specified scsw is valid,
+ * regardless of whether it is a transport mode or command mode scsw.
+ * Return zero if the field does not contain a valid value.
+ */
+int scsw_is_valid_cstat(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw_tm_is_valid_cstat(scsw);
+       else
+               return scsw_cmd_is_valid_cstat(scsw);
+}
+EXPORT_SYMBOL(scsw_is_valid_cstat);
+
+/**
+ * scsw_is_valid_dstat - check dstat field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the dstat field of the specified scsw is valid,
+ * regardless of whether it is a transport mode or command mode scsw.
+ * Return zero if the field does not contain a valid value.
+ */
+int scsw_is_valid_dstat(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw_tm_is_valid_dstat(scsw);
+       else
+               return scsw_cmd_is_valid_dstat(scsw);
+}
+EXPORT_SYMBOL(scsw_is_valid_dstat);
+
+/**
+ * scsw_is_valid_ectl - check ectl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the ectl field of the specified scsw is valid,
+ * regardless of whether it is a transport mode or command mode scsw.
+ * Return zero if the field does not contain a valid value.
+ */
+int scsw_is_valid_ectl(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw_tm_is_valid_ectl(scsw);
+       else
+               return scsw_cmd_is_valid_ectl(scsw);
+}
+EXPORT_SYMBOL(scsw_is_valid_ectl);
+
+/**
+ * scsw_is_valid_eswf - check eswf field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the eswf field of the specified scsw is valid,
+ * regardless of whether it is a transport mode or command mode scsw.
+ * Return zero if the field does not contain a valid value.
+ */
+int scsw_is_valid_eswf(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw_tm_is_valid_eswf(scsw);
+       else
+               return scsw_cmd_is_valid_eswf(scsw);
+}
+EXPORT_SYMBOL(scsw_is_valid_eswf);
+
+/**
+ * scsw_is_valid_fctl - check fctl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the fctl field of the specified scsw is valid,
+ * regardless of whether it is a transport mode or command mode scsw.
+ * Return zero if the field does not contain a valid value.
+ */
+int scsw_is_valid_fctl(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw_tm_is_valid_fctl(scsw);
+       else
+               return scsw_cmd_is_valid_fctl(scsw);
+}
+EXPORT_SYMBOL(scsw_is_valid_fctl);
+
+/**
+ * scsw_is_valid_key - check key field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the key field of the specified scsw is valid,
+ * regardless of whether it is a transport mode or command mode scsw.
+ * Return zero if the field does not contain a valid value.
+ */
+int scsw_is_valid_key(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw_tm_is_valid_key(scsw);
+       else
+               return scsw_cmd_is_valid_key(scsw);
+}
+EXPORT_SYMBOL(scsw_is_valid_key);
+
+/**
+ * scsw_is_valid_pno - check pno field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the pno field of the specified scsw is valid,
+ * regardless of whether it is a transport mode or command mode scsw.
+ * Return zero if the field does not contain a valid value.
+ */
+int scsw_is_valid_pno(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw_tm_is_valid_pno(scsw);
+       else
+               return scsw_cmd_is_valid_pno(scsw);
+}
+EXPORT_SYMBOL(scsw_is_valid_pno);
+
+/**
+ * scsw_is_valid_stctl - check stctl field validity
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the stctl field of the specified scsw is valid,
+ * regardless of whether it is a transport mode or command mode scsw.
+ * Return zero if the field does not contain a valid value.
+ */
+int scsw_is_valid_stctl(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw_tm_is_valid_stctl(scsw);
+       else
+               return scsw_cmd_is_valid_stctl(scsw);
+}
+EXPORT_SYMBOL(scsw_is_valid_stctl);
+
+/**
+ * scsw_cmd_is_solicited - check for solicited scsw
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the command mode scsw indicates that the associated
+ * status condition is solicited, zero if it is unsolicited.
+ */
+int scsw_cmd_is_solicited(union scsw *scsw)
+{
+       return (scsw->cmd.cc != 0) || (scsw->cmd.stctl !=
+               (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS));
+}
+EXPORT_SYMBOL(scsw_cmd_is_solicited);
+
+/**
+ * scsw_tm_is_solicited - check for solicited scsw
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the transport mode scsw indicates that the associated
+ * status condition is solicited, zero if it is unsolicited.
+ */
+int scsw_tm_is_solicited(union scsw *scsw)
+{
+       return (scsw->tm.cc != 0) || (scsw->tm.stctl !=
+               (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS));
+}
+EXPORT_SYMBOL(scsw_tm_is_solicited);
+
+/**
+ * scsw_is_solicited - check for solicited scsw
+ * @scsw: pointer to scsw
+ *
+ * Return non-zero if the transport or command mode scsw indicates that the
+ * associated status condition is solicited, zero if it is unsolicited.
+ */
+int scsw_is_solicited(union scsw *scsw)
+{
+       if (scsw_is_tm(scsw))
+               return scsw_tm_is_solicited(scsw);
+       else
+               return scsw_cmd_is_solicited(scsw);
+}
+EXPORT_SYMBOL(scsw_is_solicited);
index a1ab3e3efd11dae257e6c8c0b1fb13c5f9bec524..62b6b55230d0d4e509910df984de16364b8c99f9 100644 (file)
 #include <linux/mutex.h>
 #include <asm/s390_rdev.h>
 #include <asm/reset.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
 
 #include "ap_bus.h"
 
 /* Some prototypes. */
 static void ap_scan_bus(struct work_struct *);
 static void ap_poll_all(unsigned long);
-static void ap_poll_timeout(unsigned long);
+static enum hrtimer_restart ap_poll_timeout(struct hrtimer *);
 static int ap_poll_thread_start(void);
 static void ap_poll_thread_stop(void);
 static void ap_request_timeout(unsigned long);
@@ -80,12 +82,15 @@ static DECLARE_WORK(ap_config_work, ap_scan_bus);
 /*
  * Tasklet & timer for AP request polling.
  */
-static struct timer_list ap_poll_timer = TIMER_INITIALIZER(ap_poll_timeout,0,0);
 static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0);
 static atomic_t ap_poll_requests = ATOMIC_INIT(0);
 static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
 static struct task_struct *ap_poll_kthread = NULL;
 static DEFINE_MUTEX(ap_poll_thread_mutex);
+static struct hrtimer ap_poll_timer;
+/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
+ * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
+static unsigned long long poll_timeout = 250000;
 
 /**
  * ap_intructions_available() - Test if AP instructions are available.
@@ -636,11 +641,39 @@ static ssize_t ap_poll_thread_store(struct bus_type *bus,
 
 static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
 
+static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
+}
+
+static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
+                                 size_t count)
+{
+       unsigned long long time;
+       ktime_t hr_time;
+
+       /* 120 seconds = maximum poll interval */
+       if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 || time > 120000000000)
+               return -EINVAL;
+       poll_timeout = time;
+       hr_time = ktime_set(0, poll_timeout);
+
+       if (!hrtimer_is_queued(&ap_poll_timer) ||
+           !hrtimer_forward(&ap_poll_timer, ap_poll_timer.expires, hr_time)) {
+               ap_poll_timer.expires = hr_time;
+               hrtimer_start(&ap_poll_timer, hr_time, HRTIMER_MODE_ABS);
+       }
+       return count;
+}
+
+static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
+
 static struct bus_attribute *const ap_bus_attrs[] = {
        &bus_attr_ap_domain,
        &bus_attr_config_time,
        &bus_attr_poll_thread,
-       NULL
+       &bus_attr_poll_timeout,
+       NULL,
 };
 
 /**
@@ -895,9 +928,10 @@ ap_config_timeout(unsigned long ptr)
  */
 static inline void ap_schedule_poll_timer(void)
 {
-       if (timer_pending(&ap_poll_timer))
+       if (hrtimer_is_queued(&ap_poll_timer))
                return;
-       mod_timer(&ap_poll_timer, jiffies + AP_POLL_TIME);
+       hrtimer_start(&ap_poll_timer, ktime_set(0, poll_timeout),
+                     HRTIMER_MODE_ABS);
 }
 
 /**
@@ -1115,13 +1149,14 @@ EXPORT_SYMBOL(ap_cancel_message);
 
 /**
  * ap_poll_timeout(): AP receive polling for finished AP requests.
- * @unused: Unused variable.
+ * @unused: Unused pointer.
  *
- * Schedules the AP tasklet.
+ * Schedules the AP tasklet using a high resolution timer.
  */
-static void ap_poll_timeout(unsigned long unused)
+static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
 {
        tasklet_schedule(&ap_tasklet);
+       return HRTIMER_NORESTART;
 }
 
 /**
@@ -1344,6 +1379,14 @@ int __init ap_module_init(void)
        ap_config_timer.expires = jiffies + ap_config_time * HZ;
        add_timer(&ap_config_timer);
 
+       /* Setup the high resultion poll timer.
+        * If we are running under z/VM adjust polling to z/VM polling rate.
+        */
+       if (MACHINE_IS_VM)
+               poll_timeout = 1500000;
+       hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+       ap_poll_timer.function = ap_poll_timeout;
+
        /* Start the low priority AP bus poll thread. */
        if (ap_thread_flag) {
                rc = ap_poll_thread_start();
@@ -1355,7 +1398,7 @@ int __init ap_module_init(void)
 
 out_work:
        del_timer_sync(&ap_config_timer);
-       del_timer_sync(&ap_poll_timer);
+       hrtimer_cancel(&ap_poll_timer);
        destroy_workqueue(ap_work_queue);
 out_root:
        s390_root_dev_unregister(ap_root_device);
@@ -1386,7 +1429,7 @@ void ap_module_exit(void)
        ap_reset_domain();
        ap_poll_thread_stop();
        del_timer_sync(&ap_config_timer);
-       del_timer_sync(&ap_poll_timer);
+       hrtimer_cancel(&ap_poll_timer);
        destroy_workqueue(ap_work_queue);
        tasklet_kill(&ap_tasklet);
        s390_root_dev_unregister(ap_root_device);
index c1e1200c43fc7a211b68a10048207470e810aef4..446378b308fcf2ca6447816cfc2daab59c481536 100644 (file)
@@ -92,6 +92,8 @@ struct ap_queue_status {
 #define AP_DEVICE_TYPE_PCIXCC  5
 #define AP_DEVICE_TYPE_CEX2A   6
 #define AP_DEVICE_TYPE_CEX2C   7
+#define AP_DEVICE_TYPE_CEX2A2  8
+#define AP_DEVICE_TYPE_CEX2C2  9
 
 /*
  * AP reset flag states
index 4d36e805a2348b40995c76625986559f735c5978..8a4964f3584bf46eb3621463cdb260e73a97fcce 100644 (file)
@@ -1068,10 +1068,8 @@ static int zcrypt_status_write(struct file *file, const char __user *buffer,
 
 #define LBUFSIZE 1200UL
        lbuf = kmalloc(LBUFSIZE, GFP_KERNEL);
-       if (!lbuf) {
-               PRINTK("kmalloc failed!\n");
+       if (!lbuf)
                return 0;
-       }
 
        local_count = min(LBUFSIZE - 1, count);
        if (copy_from_user(lbuf, buffer, local_count) != 0) {
@@ -1081,23 +1079,15 @@ static int zcrypt_status_write(struct file *file, const char __user *buffer,
        lbuf[local_count] = '\0';
 
        ptr = strstr(lbuf, "Online devices");
-       if (!ptr) {
-               PRINTK("Unable to parse data (missing \"Online devices\")\n");
+       if (!ptr)
                goto out;
-       }
        ptr = strstr(ptr, "\n");
-       if (!ptr) {
-               PRINTK("Unable to parse data (missing newline "
-                      "after \"Online devices\")\n");
+       if (!ptr)
                goto out;
-       }
        ptr++;
 
-       if (strstr(ptr, "Waiting work element counts") == NULL) {
-               PRINTK("Unable to parse data (missing "
-                      "\"Waiting work element counts\")\n");
+       if (strstr(ptr, "Waiting work element counts") == NULL)
                goto out;
-       }
 
        for (j = 0; j < 64 && *ptr; ptr++) {
                /*
@@ -1197,16 +1187,12 @@ int __init zcrypt_api_init(void)
 
        /* Register the request sprayer. */
        rc = misc_register(&zcrypt_misc_device);
-       if (rc < 0) {
-               PRINTKW(KERN_ERR "misc_register (minor %d) failed with %d\n",
-                       zcrypt_misc_device.minor, rc);
+       if (rc < 0)
                goto out;
-       }
 
        /* Set up the proc file system */
        zcrypt_entry = create_proc_entry("driver/z90crypt", 0644, NULL);
        if (!zcrypt_entry) {
-               PRINTK("Couldn't create z90crypt proc entry\n");
                rc = -ENOMEM;
                goto out_misc;
        }
index 5c6e222b2ac4201a55b2e4da9d748a23cb753372..1d1ec74dadb223701d6d7dacf180bf5a4754b2f2 100644 (file)
 #ifndef _ZCRYPT_API_H_
 #define _ZCRYPT_API_H_
 
-/**
- * Macro definitions
- *
- * PDEBUG debugs in the form "zcrypt: function_name -> message"
- *
- * PRINTK is like PDEBUG, except that it is always enabled
- * PRINTKN is like PRINTK, except that it does not include the function name
- * PRINTKW is like PRINTK, except that it uses KERN_WARNING
- * PRINTKC is like PRINTK, except that it uses KERN_CRIT
- */
-#define DEV_NAME       "zcrypt"
-
-#define PRINTK(fmt, args...) \
-       printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __func__ , ## args)
-#define PRINTKN(fmt, args...) \
-       printk(KERN_DEBUG DEV_NAME ": " fmt, ## args)
-#define PRINTKW(fmt, args...) \
-       printk(KERN_WARNING DEV_NAME ": %s -> " fmt, __func__ , ## args)
-#define PRINTKC(fmt, args...) \
-       printk(KERN_CRIT DEV_NAME ": %s -> " fmt, __func__ , ## args)
-
-#ifdef ZCRYPT_DEBUG
-#define PDEBUG(fmt, args...) \
-       printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __func__ , ## args)
-#else
-#define PDEBUG(fmt, args...) do {} while (0)
-#endif
-
 #include "ap_bus.h"
 #include <asm/zcrypt.h>
 
index 08657f604b8c7c392397d9ae8b5aa3f6a8c18e4b..54f4cbc3be9e44eae1d56902df6d68c5adc6c531 100644 (file)
@@ -49,6 +49,7 @@
 
 static struct ap_device_id zcrypt_cex2a_ids[] = {
        { AP_DEVICE(AP_DEVICE_TYPE_CEX2A) },
+       { AP_DEVICE(AP_DEVICE_TYPE_CEX2A2) },
        { /* end of list */ },
 };
 
@@ -242,9 +243,6 @@ static int convert_response(struct zcrypt_device *zdev,
                return convert_type80(zdev, reply,
                                      outputdata, outputdatalength);
        default: /* Unknown response type, this should NEVER EVER happen */
-               PRINTK("Unrecognized Message Header: %08x%08x\n",
-                      *(unsigned int *) reply->message,
-                      *(unsigned int *) (reply->message+4));
                zdev->online = 0;
                return -EAGAIN; /* repeat the request on a different device. */
        }
index 3e27fe77d2074f6e5884efcf9655d1f672d44a45..03ba27f05f9203931a6b381bfd07ba1af3ddefa7 100644 (file)
@@ -92,10 +92,6 @@ static inline int convert_error(struct zcrypt_device *zdev,
 {
        struct error_hdr *ehdr = reply->message;
 
-       PRINTK("Hardware error : Type %02x Message Header: %08x%08x\n",
-              ehdr->type, *(unsigned int *) reply->message,
-              *(unsigned int *) (reply->message + 4));
-
        switch (ehdr->reply_code) {
        case REP82_ERROR_OPERAND_INVALID:
        case REP82_ERROR_OPERAND_SIZE:
@@ -123,8 +119,6 @@ static inline int convert_error(struct zcrypt_device *zdev,
                zdev->online = 0;
                return -EAGAIN;
        default:
-               PRINTKW("unknown type %02x reply code = %d\n",
-                       ehdr->type, ehdr->reply_code);
                zdev->online = 0;
                return -EAGAIN; /* repeat the request on a different device. */
        }
index 6e93b4751782c4806501df1c2ce00f9120abf5dd..12da4815ba8eea3ffa8fbdbf773661dbb5650697 100644 (file)
@@ -226,9 +226,6 @@ static int convert_response(struct zcrypt_device *zdev,
                return convert_type84(zdev, reply,
                                      outputdata, outputdatalength);
        default: /* Unknown response type, this should NEVER EVER happen */
-               PRINTK("Unrecognized Message Header: %08x%08x\n",
-                      *(unsigned int *) reply->message,
-                      *(unsigned int *) (reply->message+4));
                zdev->online = 0;
                return -EAGAIN; /* repeat the request on a different device. */
        }
index 17ea56ce1c1141731a33790d800ca6b0de487529..779952cb19fc85a101485461077d75448387d89c 100644 (file)
@@ -361,26 +361,18 @@ static int convert_type86(struct zcrypt_device *zdev,
        service_rc = le16_to_cpu(msg->cprb.ccp_rtcode);
        if (unlikely(service_rc != 0)) {
                service_rs = le16_to_cpu(msg->cprb.ccp_rscode);
-               if (service_rc == 8 && service_rs == 66) {
-                       PDEBUG("Bad block format on PCICC\n");
+               if (service_rc == 8 && service_rs == 66)
                        return -EINVAL;
-               }
-               if (service_rc == 8 && service_rs == 65) {
-                       PDEBUG("Probably an even modulus on PCICC\n");
+               if (service_rc == 8 && service_rs == 65)
                        return -EINVAL;
-               }
                if (service_rc == 8 && service_rs == 770) {
-                       PDEBUG("Invalid key length on PCICC\n");
                        zdev->max_mod_size = PCICC_MAX_MOD_SIZE_OLD;
                        return -EAGAIN;
                }
                if (service_rc == 8 && service_rs == 783) {
-                       PDEBUG("Extended bitlengths not enabled on PCICC\n");
                        zdev->max_mod_size = PCICC_MAX_MOD_SIZE_OLD;
                        return -EAGAIN;
                }
-               PRINTK("Unknown service rc/rs (PCICC): %d/%d\n",
-                      service_rc, service_rs);
                zdev->online = 0;
                return -EAGAIN; /* repeat the request on a different device. */
        }
@@ -434,9 +426,6 @@ static int convert_response(struct zcrypt_device *zdev,
                                              outputdata, outputdatalength);
                /* no break, incorrect cprb version is an unknown response */
        default: /* Unknown response type, this should NEVER EVER happen */
-               PRINTK("Unrecognized Message Header: %08x%08x\n",
-                      *(unsigned int *) reply->message,
-                      *(unsigned int *) (reply->message+4));
                zdev->online = 0;
                return -EAGAIN; /* repeat the request on a different device. */
        }
index 0bc9b3188e64964ab2b98049e8f8ff518f3209b6..d8ad36f8154032ae5fab9e4cd998a2752aded0fb 100644 (file)
@@ -72,6 +72,7 @@ struct response_type {
 static struct ap_device_id zcrypt_pcixcc_ids[] = {
        { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },
        { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },
+       { AP_DEVICE(AP_DEVICE_TYPE_CEX2C2) },
        { /* end of list */ },
 };
 
@@ -289,38 +290,19 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
        ap_msg->length = sizeof(struct type6_hdr) +
                CEIL4(xcRB->request_control_blk_length) +
                xcRB->request_data_length;
-       if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE) {
-               PRINTK("Combined message is too large (%ld/%d/%d).\n",
-                   sizeof(struct type6_hdr),
-                   xcRB->request_control_blk_length,
-                   xcRB->request_data_length);
+       if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE)
                return -EFAULT;
-       }
-       if (CEIL4(xcRB->reply_control_blk_length) >
-           PCIXCC_MAX_XCRB_REPLY_SIZE) {
-               PDEBUG("Reply CPRB length is too large (%d).\n",
-                   xcRB->request_control_blk_length);
+       if (CEIL4(xcRB->reply_control_blk_length) > PCIXCC_MAX_XCRB_REPLY_SIZE)
                return -EFAULT;
-       }
-       if (CEIL4(xcRB->reply_data_length) > PCIXCC_MAX_XCRB_DATA_SIZE) {
-               PDEBUG("Reply data block length is too large (%d).\n",
-                   xcRB->reply_data_length);
+       if (CEIL4(xcRB->reply_data_length) > PCIXCC_MAX_XCRB_DATA_SIZE)
                return -EFAULT;
-       }
        replylen = CEIL4(xcRB->reply_control_blk_length) +
                CEIL4(xcRB->reply_data_length) +
                sizeof(struct type86_fmt2_msg);
        if (replylen > PCIXCC_MAX_XCRB_RESPONSE_SIZE) {
-               PDEBUG("Reply CPRB + data block > PCIXCC_MAX_XCRB_RESPONSE_SIZE"
-                      " (%d/%d/%d).\n",
-                      sizeof(struct type86_fmt2_msg),
-                      xcRB->reply_control_blk_length,
-                      xcRB->reply_data_length);
                xcRB->reply_control_blk_length = PCIXCC_MAX_XCRB_RESPONSE_SIZE -
                        (sizeof(struct type86_fmt2_msg) +
                            CEIL4(xcRB->reply_data_length));
-               PDEBUG("Capping Reply CPRB length at %d\n",
-                      xcRB->reply_control_blk_length);
        }
 
        /* prepare type6 header */
@@ -339,11 +321,8 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
                    xcRB->request_control_blk_length))
                return -EFAULT;
        if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
-           xcRB->request_control_blk_length) {
-               PDEBUG("cprb_len too large (%d/%d)\n", msg->cprbx.cprb_len,
-                   xcRB->request_control_blk_length);
+           xcRB->request_control_blk_length)
                return -EFAULT;
-       }
        function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
        memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
 
@@ -471,29 +450,18 @@ static int convert_type86_ica(struct zcrypt_device *zdev,
        service_rc = msg->cprbx.ccp_rtcode;
        if (unlikely(service_rc != 0)) {
                service_rs = msg->cprbx.ccp_rscode;
-               if (service_rc == 8 && service_rs == 66) {
-                       PDEBUG("Bad block format on PCIXCC/CEX2C\n");
+               if (service_rc == 8 && service_rs == 66)
                        return -EINVAL;
-               }
-               if (service_rc == 8 && service_rs == 65) {
-                       PDEBUG("Probably an even modulus on PCIXCC/CEX2C\n");
+               if (service_rc == 8 && service_rs == 65)
                        return -EINVAL;
-               }
-               if (service_rc == 8 && service_rs == 770) {
-                       PDEBUG("Invalid key length on PCIXCC/CEX2C\n");
+               if (service_rc == 8 && service_rs == 770)
                        return -EINVAL;
-               }
                if (service_rc == 8 && service_rs == 783) {
-                       PDEBUG("Extended bitlengths not enabled on PCIXCC/CEX2C\n");
                        zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
                        return -EAGAIN;
                }
-               if (service_rc == 12 && service_rs == 769) {
-                       PDEBUG("Invalid key on PCIXCC/CEX2C\n");
+               if (service_rc == 12 && service_rs == 769)
                        return -EINVAL;
-               }
-               PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n",
-                      service_rc, service_rs);
                zdev->online = 0;
                return -EAGAIN; /* repeat the request on a different device. */
        }
@@ -569,11 +537,8 @@ static int convert_type86_rng(struct zcrypt_device *zdev,
        } __attribute__((packed)) *msg = reply->message;
        char *data = reply->message;
 
-       if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) {
-               PDEBUG("RNG response error on PCIXCC/CEX2C rc=%hu/rs=%hu\n",
-                      rc, rs);
+       if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0)
                return -EINVAL;
-       }
        memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
        return msg->fmt2.count2;
 }
@@ -598,9 +563,6 @@ static int convert_response_ica(struct zcrypt_device *zdev,
                                                  outputdata, outputdatalength);
                /* no break, incorrect cprb version is an unknown response */
        default: /* Unknown response type, this should NEVER EVER happen */
-               PRINTK("Unrecognized Message Header: %08x%08x\n",
-                      *(unsigned int *) reply->message,
-                      *(unsigned int *) (reply->message+4));
                zdev->online = 0;
                return -EAGAIN; /* repeat the request on a different device. */
        }
@@ -627,9 +589,6 @@ static int convert_response_xcrb(struct zcrypt_device *zdev,
                        return convert_type86_xcrb(zdev, reply, xcRB);
                /* no break, incorrect cprb version is an unknown response */
        default: /* Unknown response type, this should NEVER EVER happen */
-               PRINTK("Unrecognized Message Header: %08x%08x\n",
-                      *(unsigned int *) reply->message,
-                      *(unsigned int *) (reply->message+4));
                xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
                zdev->online = 0;
                return -EAGAIN; /* repeat the request on a different device. */
@@ -653,9 +612,6 @@ static int convert_response_rng(struct zcrypt_device *zdev,
                        return convert_type86_rng(zdev, reply, data);
                /* no break, incorrect cprb version is an unknown response */
        default: /* Unknown response type, this should NEVER EVER happen */
-               PRINTK("Unrecognized Message Header: %08x%08x\n",
-                      *(unsigned int *) reply->message,
-                      *(unsigned int *) (reply->message+4));
                zdev->online = 0;
                return -EAGAIN; /* repeat the request on a different device. */
        }
@@ -700,10 +656,7 @@ static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
                        memcpy(msg->message, reply->message, length);
                        break;
                default:
-                       PRINTK("Invalid internal response type: %i\n",
-                           resp_type->type);
-                       memcpy(msg->message, &error_reply,
-                           sizeof error_reply);
+                       memcpy(msg->message, &error_reply, sizeof error_reply);
                }
        } else
                memcpy(msg->message, reply->message, sizeof error_reply);
index 04a1d7bf678c0c0b19ca4f239655683cc2170ecf..c644669a75c283278f023697b91c54d44d0f63ec 100644 (file)
@@ -703,7 +703,8 @@ claw_irq_handler(struct ccw_device *cdev,
        if (!cdev->dev.driver_data) {
                 printk(KERN_WARNING "claw: unsolicited interrupt for device:"
                        "%s received c-%02x d-%02x\n",
-                        cdev->dev.bus_id,irb->scsw.cstat, irb->scsw.dstat);
+                      cdev->dev.bus_id, irb->scsw.cmd.cstat,
+                      irb->scsw.cmd.dstat);
 #ifdef FUNCTRACE
                 printk(KERN_INFO "claw: %s() "
                        "exit on line %d\n",__func__,__LINE__);
@@ -732,22 +733,23 @@ claw_irq_handler(struct ccw_device *cdev,
 #ifdef IOTRACE
         printk(KERN_INFO "%s: interrupt for device: %04x "
                "received c-%02x d-%02x state-%02x\n",
-                dev->name, p_ch->devno, irb->scsw.cstat,
-               irb->scsw.dstat, p_ch->claw_state);
+              dev->name, p_ch->devno, irb->scsw.cmd.cstat,
+              irb->scsw.cmd.dstat, p_ch->claw_state);
 #endif
 
        /* Copy interruption response block. */
        memcpy(p_ch->irb, irb, sizeof(struct irb));
 
         /* Check for good subchannel return code, otherwise error message */
-        if (irb->scsw.cstat  &&  !(irb->scsw.cstat & SCHN_STAT_PCI)) {
+       if (irb->scsw.cmd.cstat && !(irb->scsw.cmd.cstat & SCHN_STAT_PCI)) {
                 printk(KERN_INFO "%s: subchannel check for device: %04x -"
                        " Sch Stat %02x  Dev Stat %02x CPA - %04x\n",
                         dev->name, p_ch->devno,
-                       irb->scsw.cstat, irb->scsw.dstat,irb->scsw.cpa);
+                       irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
+                       irb->scsw.cmd.cpa);
 #ifdef IOTRACE
                dumpit((char *)irb,sizeof(struct irb));
-               dumpit((char *)(unsigned long)irb->scsw.cpa,
+               dumpit((char *)(unsigned long)irb->scsw.cmd.cpa,
                        sizeof(struct ccw1));
 #endif
 #ifdef FUNCTRACE
@@ -759,22 +761,24 @@ claw_irq_handler(struct ccw_device *cdev,
         }
 
         /* Check the reason-code of a unit check */
-        if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
+       if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK)
                 ccw_check_unit_check(p_ch, irb->ecw[0]);
-        }
 
         /* State machine to bring the connection up, down and to restart */
-        p_ch->last_dstat = irb->scsw.dstat;
+       p_ch->last_dstat = irb->scsw.cmd.dstat;
 
         switch (p_ch->claw_state) {
                 case CLAW_STOP:/* HALT_IO by claw_release (halt sequence) */
 #ifdef DEBUGMSG
                         printk(KERN_INFO "%s: CLAW_STOP enter\n", dev->name);
 #endif
-                        if (!((p_ch->irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
-                       (p_ch->irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
-                       (p_ch->irb->scsw.stctl ==
-                       (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+                       if (!((p_ch->irb->scsw.cmd.stctl &
+                              SCSW_STCTL_SEC_STATUS) ||
+                           (p_ch->irb->scsw.cmd.stctl ==
+                               SCSW_STCTL_STATUS_PEND) ||
+                           (p_ch->irb->scsw.cmd.stctl ==
+                               (SCSW_STCTL_ALERT_STATUS |
+                                SCSW_STCTL_STATUS_PEND)))) {
 #ifdef FUNCTRACE
                                 printk(KERN_INFO "%s:%s Exit on line %d\n",
                                        dev->name,__func__,__LINE__);
@@ -798,10 +802,13 @@ claw_irq_handler(struct ccw_device *cdev,
                         printk(KERN_INFO "%s: process CLAW_STAT_HALT_IO\n",
                                dev->name);
 #endif
-                        if (!((p_ch->irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
-                       (p_ch->irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
-                       (p_ch->irb->scsw.stctl ==
-                       (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+                       if (!((p_ch->irb->scsw.cmd.stctl &
+                              SCSW_STCTL_SEC_STATUS) ||
+                           (p_ch->irb->scsw.cmd.stctl ==
+                            SCSW_STCTL_STATUS_PEND) ||
+                           (p_ch->irb->scsw.cmd.stctl ==
+                            (SCSW_STCTL_ALERT_STATUS |
+                             SCSW_STCTL_STATUS_PEND)))) {
 #ifdef FUNCTRACE
                                printk(KERN_INFO "%s:%s Exit on line %d\n",
                                        dev->name,__func__,__LINE__);
@@ -828,8 +835,8 @@ claw_irq_handler(struct ccw_device *cdev,
                                        "interrupt for device:"
                                        "%s received c-%02x d-%02x\n",
                                        cdev->dev.bus_id,
-                                       irb->scsw.cstat,
-                                       irb->scsw.dstat);
+                                       irb->scsw.cmd.cstat,
+                                       irb->scsw.cmd.dstat);
                                return;
                                }
 #ifdef DEBUGMSG
@@ -844,7 +851,7 @@ claw_irq_handler(struct ccw_device *cdev,
                         return;
                 case CLAW_START_READ:
                        CLAW_DBF_TEXT(4,trace,"ReadIRQ");
-                        if (p_ch->irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
+                       if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
                                 clear_bit(0, (void *)&p_ch->IO_active);
                                 if ((p_ch->irb->ecw[0] & 0x41) == 0x41 ||
                                     (p_ch->irb->ecw[0] & 0x40) == 0x40 ||
@@ -863,8 +870,8 @@ claw_irq_handler(struct ccw_device *cdev,
                                        CLAW_DBF_TEXT(4,trace,"notrdy");
                                         return;
                         }
-                        if ((p_ch->irb->scsw.cstat & SCHN_STAT_PCI) &&
-                           (p_ch->irb->scsw.dstat==0)) {
+                       if ((p_ch->irb->scsw.cmd.cstat & SCHN_STAT_PCI) &&
+                           (p_ch->irb->scsw.cmd.dstat == 0)) {
                                 if (test_and_set_bit(CLAW_BH_ACTIVE,
                                        (void *)&p_ch->flag_a) == 0) {
                                        tasklet_schedule(&p_ch->tasklet);
@@ -879,10 +886,13 @@ claw_irq_handler(struct ccw_device *cdev,
                                CLAW_DBF_TEXT(4,trace,"PCI_read");
                                 return;
                         }
-                        if(!((p_ch->irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
-                        (p_ch->irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
-                        (p_ch->irb->scsw.stctl ==
-                        (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+                       if (!((p_ch->irb->scsw.cmd.stctl &
+                              SCSW_STCTL_SEC_STATUS) ||
+                            (p_ch->irb->scsw.cmd.stctl ==
+                             SCSW_STCTL_STATUS_PEND) ||
+                            (p_ch->irb->scsw.cmd.stctl ==
+                             (SCSW_STCTL_ALERT_STATUS |
+                              SCSW_STCTL_STATUS_PEND)))) {
 #ifdef FUNCTRACE
                                printk(KERN_INFO "%s:%s Exit on line %d\n",
                                        dev->name,__func__,__LINE__);
@@ -911,7 +921,7 @@ claw_irq_handler(struct ccw_device *cdev,
                        CLAW_DBF_TEXT(4,trace,"RdIRQXit");
                         return;
                 case CLAW_START_WRITE:
-                        if (p_ch->irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
+                       if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
                                 printk(KERN_INFO "%s: Unit Check Occured in "
                                        "write channel\n",dev->name);
                                 clear_bit(0, (void *)&p_ch->IO_active);
@@ -934,16 +944,19 @@ claw_irq_handler(struct ccw_device *cdev,
                                CLAW_DBF_TEXT(4,trace,"rstrtwrt");
                                 return;
                         }
-                        if (p_ch->irb->scsw.dstat & DEV_STAT_UNIT_EXCEP) {
+                       if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_EXCEP) {
                                         clear_bit(0, (void *)&p_ch->IO_active);
                                         printk(KERN_INFO "%s: Unit Exception "
                                                "Occured in write channel\n",
                                                dev->name);
                         }
-                        if(!((p_ch->irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
-                       (p_ch->irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
-                       (p_ch->irb->scsw.stctl ==
-                       (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+                       if (!((p_ch->irb->scsw.cmd.stctl &
+                              SCSW_STCTL_SEC_STATUS) ||
+                            (p_ch->irb->scsw.cmd.stctl ==
+                             SCSW_STCTL_STATUS_PEND) ||
+                            (p_ch->irb->scsw.cmd.stctl ==
+                             (SCSW_STCTL_ALERT_STATUS |
+                              SCSW_STCTL_STATUS_PEND)))) {
 #ifdef FUNCTRACE
                                printk(KERN_INFO "%s:%s Exit on line %d\n",
                                        dev->name,__func__,__LINE__);
index 2a106f3a076d1af655f5d2e0678f6515a3b0edae..7e6bd387f4d889f628929bd3fe08d5d212abc082 100644 (file)
@@ -257,9 +257,9 @@ static void chx_txdone(fsm_instance *fi, int event, void *arg)
        if (duration > ch->prof.tx_time)
                ch->prof.tx_time = duration;
 
-       if (ch->irb->scsw.count != 0)
+       if (ch->irb->scsw.cmd.count != 0)
                ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
-                            dev->name, ch->irb->scsw.count);
+                            dev->name, ch->irb->scsw.cmd.count);
        fsm_deltimer(&ch->timer);
        while ((skb = skb_dequeue(&ch->io_queue))) {
                priv->stats.tx_packets++;
@@ -353,7 +353,7 @@ static void chx_rx(fsm_instance *fi, int event, void *arg)
        struct channel *ch = arg;
        struct net_device *dev = ch->netdev;
        struct ctcm_priv *priv = dev->priv;
-       int len = ch->max_bufsize - ch->irb->scsw.count;
+       int len = ch->max_bufsize - ch->irb->scsw.cmd.count;
        struct sk_buff *skb = ch->trans_skb;
        __u16 block_len = *((__u16 *)skb->data);
        int check_len;
@@ -1234,9 +1234,9 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg)
        if (duration > ch->prof.tx_time)
                ch->prof.tx_time = duration;
 
-       if (ch->irb->scsw.count != 0)
+       if (ch->irb->scsw.cmd.count != 0)
                ctcm_pr_debug("%s: TX not complete, remaining %d bytes\n",
-                               dev->name, ch->irb->scsw.count);
+                               dev->name, ch->irb->scsw.cmd.count);
        fsm_deltimer(&ch->timer);
        while ((skb = skb_dequeue(&ch->io_queue))) {
                priv->stats.tx_packets++;
@@ -1394,7 +1394,7 @@ static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg)
        struct sk_buff          *skb = ch->trans_skb;
        struct sk_buff          *new_skb;
        unsigned long   saveflags = 0;  /* avoids compiler warning */
-       int len = ch->max_bufsize - ch->irb->scsw.count;
+       int len = ch->max_bufsize - ch->irb->scsw.cmd.count;
 
        if (do_debug_data) {
                CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, "mpc_ch_rx %s cp:%i %s\n",
index d52843da4f558c5afe916cf5955e705e2cd514a4..6b13c1c1beb81daccb09cb42a9967267e704f0cc 100644 (file)
@@ -1236,8 +1236,8 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
        /* Check for unsolicited interrupts. */
        if (cgdev == NULL) {
                ctcm_pr_warn("ctcm: Got unsolicited irq: %s c-%02x d-%02x\n",
-                           cdev->dev.bus_id, irb->scsw.cstat,
-                           irb->scsw.dstat);
+                           cdev->dev.bus_id, irb->scsw.cmd.cstat,
+                           irb->scsw.cmd.dstat);
                return;
        }
 
@@ -1266,40 +1266,40 @@ static void ctcm_irq_handler(struct ccw_device *cdev,
                                "received c-%02x d-%02x\n",
                                dev->name,
                                ch->id,
-                               irb->scsw.cstat,
-                               irb->scsw.dstat);
+                               irb->scsw.cmd.cstat,
+                               irb->scsw.cmd.dstat);
 
        /* Copy interruption response block. */
        memcpy(ch->irb, irb, sizeof(struct irb));
 
        /* Check for good subchannel return code, otherwise error message */
-       if (irb->scsw.cstat) {
+       if (irb->scsw.cmd.cstat) {
                fsm_event(ch->fsm, CTC_EVENT_SC_UNKNOWN, ch);
                ctcm_pr_warn("%s: subchannel check for dev: %s - %02x %02x\n",
-                           dev->name, ch->id, irb->scsw.cstat,
-                           irb->scsw.dstat);
+                           dev->name, ch->id, irb->scsw.cmd.cstat,
+                           irb->scsw.cmd.dstat);
                return;
        }
 
        /* Check the reason-code of a unit check */
-       if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
+       if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
                ccw_unit_check(ch, irb->ecw[0]);
                return;
        }
-       if (irb->scsw.dstat & DEV_STAT_BUSY) {
-               if (irb->scsw.dstat & DEV_STAT_ATTENTION)
+       if (irb->scsw.cmd.dstat & DEV_STAT_BUSY) {
+               if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION)
                        fsm_event(ch->fsm, CTC_EVENT_ATTNBUSY, ch);
                else
                        fsm_event(ch->fsm, CTC_EVENT_BUSY, ch);
                return;
        }
-       if (irb->scsw.dstat & DEV_STAT_ATTENTION) {
+       if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
                fsm_event(ch->fsm, CTC_EVENT_ATTN, ch);
                return;
        }
-       if ((irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
-           (irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
-           (irb->scsw.stctl ==
+       if ((irb->scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS) ||
+           (irb->scsw.cmd.stctl == SCSW_STCTL_STATUS_PEND) ||
+           (irb->scsw.cmd.stctl ==
             (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))
                fsm_event(ch->fsm, CTC_EVENT_FINSTAT, ch);
        else
index 8e7697305a4cd9ab6d871f1d569d6d1e9ef31b4b..f4a32375c037410d78935033aa047f1ccdb8b2e9 100644 (file)
@@ -36,7 +36,6 @@ const char *cu3088_type[] = {
        "CTC/A",
        "ESCON channel",
        "FICON channel",
-       "P390 LCS card",
        "OSA LCS card",
        "CLAW channel device",
        "unknown channel type",
@@ -49,7 +48,6 @@ static struct ccw_device_id cu3088_ids[] = {
        { CCW_DEVICE(0x3088, 0x08), .driver_info = channel_type_parallel },
        { CCW_DEVICE(0x3088, 0x1f), .driver_info = channel_type_escon },
        { CCW_DEVICE(0x3088, 0x1e), .driver_info = channel_type_ficon },
-       { CCW_DEVICE(0x3088, 0x01), .driver_info = channel_type_p390 },
        { CCW_DEVICE(0x3088, 0x60), .driver_info = channel_type_osa2 },
        { CCW_DEVICE(0x3088, 0x61), .driver_info = channel_type_claw },
        { /* end of list */ }
index 1753661f702a196325968df22cffec4485743f5e..d8558a7105a59446c5624fa66b8de5d2c951ce14 100644 (file)
@@ -17,9 +17,6 @@ enum channel_types {
        /* Device is a FICON channel */
        channel_type_ficon,
 
-       /* Device is a P390 LCS card */
-       channel_type_p390,
-
        /* Device is a OSA2 card */
        channel_type_osa2,
 
index dd22f4b37037ebaa25e25c49bda17de8670dddd6..6de28385b3546c08cf2899cffab0f2a09ff61bda 100644 (file)
@@ -1327,8 +1327,8 @@ lcs_get_problem(struct ccw_device *cdev, struct irb *irb)
        char *sense;
 
        sense = (char *) irb->ecw;
-       cstat = irb->scsw.cstat;
-       dstat = irb->scsw.dstat;
+       cstat = irb->scsw.cmd.cstat;
+       dstat = irb->scsw.cmd.dstat;
 
        if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
                     SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
@@ -1388,11 +1388,13 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
        else
                channel = &card->write;
 
-       cstat = irb->scsw.cstat;
-       dstat = irb->scsw.dstat;
+       cstat = irb->scsw.cmd.cstat;
+       dstat = irb->scsw.cmd.dstat;
        LCS_DBF_TEXT_(5, trace, "Rint%s",cdev->dev.bus_id);
-       LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.cstat, irb->scsw.dstat);
-       LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.fctl, irb->scsw.actl);
+       LCS_DBF_TEXT_(5, trace, "%4x%4x", irb->scsw.cmd.cstat,
+                     irb->scsw.cmd.dstat);
+       LCS_DBF_TEXT_(5, trace, "%4x%4x", irb->scsw.cmd.fctl,
+                     irb->scsw.cmd.actl);
 
        /* Check for channel and device errors presented */
        rc = lcs_get_problem(cdev, irb);
@@ -1410,11 +1412,11 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
        }
        /* How far in the ccw chain have we processed? */
        if ((channel->state != LCS_CH_STATE_INIT) &&
-           (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) {
-               index = (struct ccw1 *) __va((addr_t) irb->scsw.cpa)
+           (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC)) {
+               index = (struct ccw1 *) __va((addr_t) irb->scsw.cmd.cpa)
                        - channel->ccws;
-               if ((irb->scsw.actl & SCSW_ACTL_SUSPENDED) ||
-                   (irb->scsw.cstat & SCHN_STAT_PCI))
+               if ((irb->scsw.cmd.actl & SCSW_ACTL_SUSPENDED) ||
+                   (irb->scsw.cmd.cstat & SCHN_STAT_PCI))
                        /* Bloody io subsystem tells us lies about cpa... */
                        index = (index - 1) & (LCS_NUM_BUFFS - 1);
                while (channel->io_idx != index) {
@@ -1425,25 +1427,24 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                }
        }
 
-       if ((irb->scsw.dstat & DEV_STAT_DEV_END) ||
-           (irb->scsw.dstat & DEV_STAT_CHN_END) ||
-           (irb->scsw.dstat & DEV_STAT_UNIT_CHECK))
+       if ((irb->scsw.cmd.dstat & DEV_STAT_DEV_END) ||
+           (irb->scsw.cmd.dstat & DEV_STAT_CHN_END) ||
+           (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK))
                /* Mark channel as stopped. */
                channel->state = LCS_CH_STATE_STOPPED;
-       else if (irb->scsw.actl & SCSW_ACTL_SUSPENDED)
+       else if (irb->scsw.cmd.actl & SCSW_ACTL_SUSPENDED)
                /* CCW execution stopped on a suspend bit. */
                channel->state = LCS_CH_STATE_SUSPENDED;
-       if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) {
-               if (irb->scsw.cc != 0) {
+       if (irb->scsw.cmd.fctl & SCSW_FCTL_HALT_FUNC) {
+               if (irb->scsw.cmd.cc != 0) {
                        ccw_device_halt(channel->ccwdev, (addr_t) channel);
                        return;
                }
                /* The channel has been stopped by halt_IO. */
                channel->state = LCS_CH_STATE_HALTED;
        }
-       if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) {
+       if (irb->scsw.cmd.fctl & SCSW_FCTL_CLEAR_FUNC)
                channel->state = LCS_CH_STATE_CLEARED;
-       }
        /* Do the rest in the tasklet. */
        tasklet_schedule(&channel->irq_tasklet);
 }
@@ -1761,7 +1762,7 @@ lcs_get_control(struct lcs_card *card, struct lcs_cmd *cmd)
                                netif_carrier_off(card->dev);
                        break;
                default:
-                       PRINT_INFO("UNRECOGNIZED LGW COMMAND\n");
+                       LCS_DBF_TEXT(5, trace, "noLGWcmd");
                        break;
                }
        } else
@@ -2042,13 +2043,12 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev)
        LCS_DBF_TEXT(2, setup, "add_dev");
         card = lcs_alloc_card();
         if (!card) {
-                PRINT_ERR("Allocation of lcs card failed\n");
+               LCS_DBF_TEXT_(2, setup, "  rc%d", -ENOMEM);
                put_device(&ccwgdev->dev);
                 return -ENOMEM;
         }
        ret = sysfs_create_group(&ccwgdev->dev.kobj, &lcs_attr_group);
        if (ret) {
-                PRINT_ERR("Creating attributes failed");
                lcs_free_card(card);
                put_device(&ccwgdev->dev);
                return ret;
@@ -2140,7 +2140,6 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
        default:
                LCS_DBF_TEXT(3, setup, "errinit");
                PRINT_ERR("LCS: Initialization failed\n");
-               PRINT_ERR("LCS: No device found!\n");
                goto out;
        }
        if (!dev)
@@ -2269,7 +2268,6 @@ lcs_remove_device(struct ccwgroup_device *ccwgdev)
        if (!card)
                return;
 
-       PRINT_INFO("Removing lcs group device ....\n");
        LCS_DBF_TEXT(3, setup, "remdev");
        LCS_DBF_HEX(3, setup, &card, sizeof(void*));
        if (ccwgdev->state == CCWGROUP_ONLINE) {
index e4ba6a0372acb6360124839afe6e651c1a6cec87..9242b5acc66ba8f63e0344569a8e9cf5e6c478e5 100644 (file)
@@ -625,9 +625,6 @@ static void netiucv_unpack_skb(struct iucv_connection *conn,
                offset += header->next;
                header->next -= NETIUCV_HDRLEN;
                if (skb_tailroom(pskb) < header->next) {
-                       PRINT_WARN("%s: Illegal next field in iucv header: "
-                              "%d > %d\n",
-                              dev->name, header->next, skb_tailroom(pskb));
                        IUCV_DBF_TEXT_(data, 2, "Illegal next field: %d > %d\n",
                                header->next, skb_tailroom(pskb));
                        return;
@@ -636,8 +633,6 @@ static void netiucv_unpack_skb(struct iucv_connection *conn,
                skb_reset_mac_header(pskb);
                skb = dev_alloc_skb(pskb->len);
                if (!skb) {
-                       PRINT_WARN("%s Out of memory in netiucv_unpack_skb\n",
-                              dev->name);
                        IUCV_DBF_TEXT(data, 2,
                                "Out of memory in netiucv_unpack_skb\n");
                        privptr->stats.rx_dropped++;
@@ -674,7 +669,6 @@ static void conn_action_rx(fsm_instance *fi, int event, void *arg)
 
        if (!conn->netdev) {
                iucv_message_reject(conn->path, msg);
-               PRINT_WARN("Received data for unlinked connection\n");
                IUCV_DBF_TEXT(data, 2,
                              "Received data for unlinked connection\n");
                return;
@@ -682,8 +676,6 @@ static void conn_action_rx(fsm_instance *fi, int event, void *arg)
        if (msg->length > conn->max_buffsize) {
                iucv_message_reject(conn->path, msg);
                privptr->stats.rx_dropped++;
-               PRINT_WARN("msglen %d > max_buffsize %d\n",
-                          msg->length, conn->max_buffsize);
                IUCV_DBF_TEXT_(data, 2, "msglen %d > max_buffsize %d\n",
                               msg->length, conn->max_buffsize);
                return;
@@ -695,7 +687,6 @@ static void conn_action_rx(fsm_instance *fi, int event, void *arg)
                                  msg->length, NULL);
        if (rc || msg->length < 5) {
                privptr->stats.rx_errors++;
-               PRINT_WARN("iucv_receive returned %08x\n", rc);
                IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_receive\n", rc);
                return;
        }
@@ -778,7 +769,6 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
                fsm_newstate(fi, CONN_STATE_IDLE);
                if (privptr)
                        privptr->stats.tx_errors += txpackets;
-               PRINT_WARN("iucv_send returned %08x\n", rc);
                IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_send\n", rc);
        } else {
                if (privptr) {
@@ -806,8 +796,6 @@ static void conn_action_connaccept(fsm_instance *fi, int event, void *arg)
        path->flags = 0;
        rc = iucv_path_accept(path, &netiucv_handler, NULL, conn);
        if (rc) {
-               PRINT_WARN("%s: IUCV accept failed with error %d\n",
-                      netdev->name, rc);
                IUCV_DBF_TEXT_(setup, 2, "rc %d from iucv_accept", rc);
                return;
        }
@@ -873,7 +861,7 @@ static void conn_action_start(fsm_instance *fi, int event, void *arg)
        IUCV_DBF_TEXT(trace, 3, __func__);
 
        fsm_newstate(fi, CONN_STATE_STARTWAIT);
-       PRINT_DEBUG("%s('%s'): connecting ...\n",
+       IUCV_DBF_TEXT_(setup, 2, "%s('%s'): connecting ...\n",
                    conn->netdev->name, conn->userid);
 
        /*
@@ -968,8 +956,8 @@ static void conn_action_inval(fsm_instance *fi, int event, void *arg)
        struct iucv_connection *conn = arg;
        struct net_device *netdev = conn->netdev;
 
-       PRINT_WARN("%s: Cannot connect without username\n", netdev->name);
-       IUCV_DBF_TEXT(data, 2, "conn_action_inval called\n");
+       IUCV_DBF_TEXT_(data, 2, "%s('%s'): conn_action_inval called\n",
+               netdev->name, conn->userid);
 }
 
 static const fsm_node conn_fsm[] = {
@@ -1077,9 +1065,6 @@ dev_action_connup(fsm_instance *fi, int event, void *arg)
                                "connection is up and running\n");
                        break;
                case DEV_STATE_STOPWAIT:
-                       PRINT_INFO(
-                              "%s: got connection UP event during shutdown!\n",
-                              dev->name);
                        IUCV_DBF_TEXT(data, 2,
                                "dev_action_connup: in DEV_STATE_STOPWAIT\n");
                        break;
@@ -1174,8 +1159,6 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
                        nskb = alloc_skb(skb->len + NETIUCV_HDRLEN +
                                         NETIUCV_HDRLEN, GFP_ATOMIC | GFP_DMA);
                        if (!nskb) {
-                               PRINT_WARN("%s: Could not allocate tx_skb\n",
-                                      conn->netdev->name);
                                IUCV_DBF_TEXT(data, 2, "alloc_skb failed\n");
                                rc = -ENOMEM;
                                return rc;
@@ -1223,7 +1206,6 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
                                skb_pull(skb, NETIUCV_HDRLEN);
                                skb_trim(skb, skb->len - NETIUCV_HDRLEN);
                        }
-                       PRINT_WARN("iucv_send returned %08x\n", rc);
                        IUCV_DBF_TEXT_(data, 2, "rc %d from iucv_send\n", rc);
                } else {
                        if (copied)
@@ -1293,14 +1275,11 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
         * Some sanity checks ...
         */
        if (skb == NULL) {
-               PRINT_WARN("%s: NULL sk_buff passed\n", dev->name);
                IUCV_DBF_TEXT(data, 2, "netiucv_tx: skb is NULL\n");
                privptr->stats.tx_dropped++;
                return 0;
        }
        if (skb_headroom(skb) < NETIUCV_HDRLEN) {
-               PRINT_WARN("%s: Got sk_buff with head room < %ld bytes\n",
-                      dev->name, NETIUCV_HDRLEN);
                IUCV_DBF_TEXT(data, 2,
                        "netiucv_tx: skb_headroom < NETIUCV_HDRLEN\n");
                dev_kfree_skb(skb);
@@ -1393,7 +1372,6 @@ static ssize_t user_write(struct device *dev, struct device_attribute *attr,
 
        IUCV_DBF_TEXT(trace, 3, __func__);
        if (count > 9) {
-               PRINT_WARN("netiucv: username too long (%d)!\n", (int) count);
                IUCV_DBF_TEXT_(setup, 2,
                               "%d is length of username\n", (int) count);
                return -EINVAL;
@@ -1409,7 +1387,6 @@ static ssize_t user_write(struct device *dev, struct device_attribute *attr,
                        /* trailing lf, grr */
                        break;
                }
-               PRINT_WARN("netiucv: Invalid char %c in username!\n", *p);
                IUCV_DBF_TEXT_(setup, 2,
                               "username: invalid character %c\n", *p);
                return -EINVAL;
@@ -1421,18 +1398,15 @@ static ssize_t user_write(struct device *dev, struct device_attribute *attr,
        if (memcmp(username, priv->conn->userid, 9) &&
            (ndev->flags & (IFF_UP | IFF_RUNNING))) {
                /* username changed while the interface is active. */
-               PRINT_WARN("netiucv: device %s active, connected to %s\n",
-                          dev->bus_id, priv->conn->userid);
-               PRINT_WARN("netiucv: user cannot be updated\n");
                IUCV_DBF_TEXT(setup, 2, "user_write: device active\n");
-               return -EBUSY;
+               return -EPERM;
        }
        read_lock_bh(&iucv_connection_rwlock);
        list_for_each_entry(cp, &iucv_connection_list, list) {
                if (!strncmp(username, cp->userid, 9) && cp->netdev != ndev) {
                        read_unlock_bh(&iucv_connection_rwlock);
-                       PRINT_WARN("netiucv: Connection to %s already "
-                                  "exists\n", username);
+                       IUCV_DBF_TEXT_(setup, 2, "user_write: Connection "
+                               "to %s already exists\n", username);
                        return -EEXIST;
                }
        }
@@ -1466,13 +1440,10 @@ static ssize_t buffer_write (struct device *dev, struct device_attribute *attr,
        bs1 = simple_strtoul(buf, &e, 0);
 
        if (e && (!isspace(*e))) {
-               PRINT_WARN("netiucv: Invalid character in buffer!\n");
                IUCV_DBF_TEXT_(setup, 2, "buffer_write: invalid char %c\n", *e);
                return -EINVAL;
        }
        if (bs1 > NETIUCV_BUFSIZE_MAX) {
-               PRINT_WARN("netiucv: Given buffer size %d too large.\n",
-                       bs1);
                IUCV_DBF_TEXT_(setup, 2,
                        "buffer_write: buffer size %d too large\n",
                        bs1);
@@ -1480,16 +1451,12 @@ static ssize_t buffer_write (struct device *dev, struct device_attribute *attr,
        }
        if ((ndev->flags & IFF_RUNNING) &&
            (bs1 < (ndev->mtu + NETIUCV_HDRLEN + 2))) {
-               PRINT_WARN("netiucv: Given buffer size %d too small.\n",
-                       bs1);
                IUCV_DBF_TEXT_(setup, 2,
                        "buffer_write: buffer size %d too small\n",
                        bs1);
                return -EINVAL;
        }
        if (bs1 < (576 + NETIUCV_HDRLEN + NETIUCV_HDRLEN)) {
-               PRINT_WARN("netiucv: Given buffer size %d too small.\n",
-                       bs1);
                IUCV_DBF_TEXT_(setup, 2,
                        "buffer_write: buffer size %d too small\n",
                        bs1);
@@ -1963,7 +1930,6 @@ static ssize_t conn_write(struct device_driver *drv,
 
        IUCV_DBF_TEXT(trace, 3, __func__);
        if (count>9) {
-               PRINT_WARN("netiucv: username too long (%d)!\n", (int)count);
                IUCV_DBF_TEXT(setup, 2, "conn_write: too long\n");
                return -EINVAL;
        }
@@ -1976,7 +1942,6 @@ static ssize_t conn_write(struct device_driver *drv,
                if (*p == '\n')
                        /* trailing lf, grr */
                        break;
-               PRINT_WARN("netiucv: Invalid character in username!\n");
                IUCV_DBF_TEXT_(setup, 2,
                               "conn_write: invalid character %c\n", *p);
                return -EINVAL;
@@ -1989,8 +1954,8 @@ static ssize_t conn_write(struct device_driver *drv,
        list_for_each_entry(cp, &iucv_connection_list, list) {
                if (!strncmp(username, cp->userid, 9)) {
                        read_unlock_bh(&iucv_connection_rwlock);
-                       PRINT_WARN("netiucv: Connection to %s already "
-                                  "exists\n", username);
+                       IUCV_DBF_TEXT_(setup, 2, "conn_write: Connection "
+                               "to %s already exists\n", username);
                        return -EEXIST;
                }
        }
@@ -1998,9 +1963,6 @@ static ssize_t conn_write(struct device_driver *drv,
 
        dev = netiucv_init_netdevice(username);
        if (!dev) {
-               PRINT_WARN("netiucv: Could not allocate network device "
-                          "structure for user '%s'\n",
-                          netiucv_printname(username));
                IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_init_netdevice\n");
                return -ENODEV;
        }
@@ -2020,15 +1982,12 @@ static ssize_t conn_write(struct device_driver *drv,
        if (rc)
                goto out_unreg;
 
-       PRINT_INFO("%s: '%s'\n", dev->name, netiucv_printname(username));
 
        return count;
 
 out_unreg:
        netiucv_unregister_device(priv->dev);
 out_free_ndev:
-       PRINT_WARN("netiucv: Could not register '%s'\n", dev->name);
-       IUCV_DBF_TEXT(setup, 2, "conn_write: could not register\n");
        netiucv_free_netdevice(dev);
        return rc;
 }
@@ -2073,14 +2032,13 @@ static ssize_t remove_write (struct device_driver *drv,
                         PRINT_WARN("netiucv: %s cannot be removed\n",
                                   ndev->name);
                        IUCV_DBF_TEXT(data, 2, "remove_write: still active\n");
-                        return -EBUSY;
+                       return -EPERM;
                 }
                 unregister_netdev(ndev);
                 netiucv_unregister_device(dev);
                 return count;
         }
        read_unlock_bh(&iucv_connection_rwlock);
-        PRINT_WARN("netiucv: net device %s unknown\n", name);
        IUCV_DBF_TEXT(data, 2, "remove_write: unknown device\n");
         return -EINVAL;
 }
@@ -2148,7 +2106,6 @@ static int __init netiucv_init(void)
        netiucv_driver.groups = netiucv_drv_attr_groups;
        rc = driver_register(&netiucv_driver);
        if (rc) {
-               PRINT_ERR("NETIUCV: failed to register driver.\n");
                IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_register\n", rc);
                goto out_iucv;
        }
index 9a71dae223e81d94343d1ae72b54636bca290e12..0ac54dc638c21280f09dacf6c6a6ce2405111452 100644 (file)
@@ -420,7 +420,7 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
                                QETH_DBF_TEXT(TRACE, 3, "urla");
                                break;
                        default:
-                               PRINT_WARN("Received data is IPA "
+                               QETH_DBF_MESSAGE(2, "Received data is IPA "
                                           "but not a reply!\n");
                                break;
                        }
@@ -735,8 +735,8 @@ static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
        char *sense;
 
        sense = (char *) irb->ecw;
-       cstat = irb->scsw.cstat;
-       dstat = irb->scsw.dstat;
+       cstat = irb->scsw.cmd.cstat;
+       dstat = irb->scsw.cmd.dstat;
 
        if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
                     SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
@@ -823,8 +823,8 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
 
        if (__qeth_check_irb_error(cdev, intparm, irb))
                return;
-       cstat = irb->scsw.cstat;
-       dstat = irb->scsw.dstat;
+       cstat = irb->scsw.cmd.cstat;
+       dstat = irb->scsw.cmd.dstat;
 
        card = CARD_FROM_CDEV(cdev);
        if (!card)
@@ -842,10 +842,10 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
        }
        atomic_set(&channel->irq_pending, 0);
 
-       if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC))
+       if (irb->scsw.cmd.fctl & (SCSW_FCTL_CLEAR_FUNC))
                channel->state = CH_STATE_STOPPED;
 
-       if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC))
+       if (irb->scsw.cmd.fctl & (SCSW_FCTL_HALT_FUNC))
                channel->state = CH_STATE_HALTED;
 
        /*let's wake up immediately on data channel*/
@@ -4092,7 +4092,6 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
 
        rc = qeth_determine_card_type(card);
        if (rc) {
-               PRINT_WARN("%s: not a valid card type\n", __func__);
                QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc);
                goto err_card;
        }
index 999552c83bbe144c7082d1b8a55929df333f3375..06deaee50f6d1ce00e72bc837d23d6f483be4e7e 100644 (file)
@@ -944,15 +944,8 @@ static int qeth_l3_deregister_addr_entry(struct qeth_card *card,
        else
                rc = qeth_l3_send_setdelip(card, addr, IPA_CMD_DELIP,
                                        addr->del_flags);
-       if (rc) {
+       if (rc)
                QETH_DBF_TEXT(TRACE, 2, "failed");
-               /* TODO: re-activate this warning as soon as we have a
-                * clean mirco code
-               qeth_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
-               PRINT_WARN("Could not deregister IP address %s (rc=%x)\n",
-                          buf, rc);
-               */
-       }
 
        return rc;
 }
index 8735a415a116feba2fc8a2b14befd0a6bae86e22..164e090c2625b03b8218c1e90286ca4b04b4559e 100644 (file)
@@ -156,11 +156,8 @@ static int __init smsg_init(void)
        if (rc != 0)
                goto out;
        rc = iucv_register(&smsg_handler, 1);
-       if (rc) {
-               printk(KERN_ERR "SMSGIUCV: failed to register to iucv");
-               rc = -EIO;      /* better errno ? */
+       if (rc)
                goto out_driver;
-       }
        smsg_path = iucv_path_alloc(255, 0, GFP_KERNEL);
        if (!smsg_path) {
                rc = -ENOMEM;
@@ -168,11 +165,8 @@ static int __init smsg_init(void)
        }
        rc = iucv_path_connect(smsg_path, &smsg_handler, "*MSG    ",
                               NULL, NULL, NULL);
-       if (rc) {
-               printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG");
-               rc = -EIO;      /* better errno ? */
+       if (rc)
                goto out_free;
-       }
        cpcmd("SET SMSG IUCV", NULL, 0, NULL);
        return 0;
 
index 5bfbe76598303be074518a4597f83305202960a8..834e9ee7e934f0e3222d17d0e7e929db565a615d 100644 (file)
@@ -2,10 +2,10 @@
  *  drivers/s390/s390mach.c
  *   S/390 machine check handler
  *
- *  S390 version
- *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2000,2008
  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
  *              Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *              Cornelia Huck <cornelia.huck@de.ibm.com>
  */
 
 #include <linux/init.h>
 #include <asm/etr.h>
 #include <asm/lowcore.h>
 #include <asm/cio.h>
-#include "cio/cio.h"
-#include "cio/chsc.h"
-#include "cio/css.h"
-#include "cio/chp.h"
 #include "s390mach.h"
 
 static struct semaphore m_sem;
@@ -36,13 +32,40 @@ s390_handle_damage(char *msg)
        for(;;);
 }
 
+static crw_handler_t crw_handlers[NR_RSCS];
+
+/**
+ * s390_register_crw_handler() - register a channel report word handler
+ * @rsc: reporting source code to handle
+ * @handler: handler to be registered
+ *
+ * Returns %0 on success and a negative error value otherwise.
+ */
+int s390_register_crw_handler(int rsc, crw_handler_t handler)
+{
+       if ((rsc < 0) || (rsc >= NR_RSCS))
+               return -EINVAL;
+       if (!cmpxchg(&crw_handlers[rsc], NULL, handler))
+               return 0;
+       return -EBUSY;
+}
+
+/**
+ * s390_unregister_crw_handler() - unregister a channel report word handler
+ * @rsc: reporting source code to handle
+ */
+void s390_unregister_crw_handler(int rsc)
+{
+       if ((rsc < 0) || (rsc >= NR_RSCS))
+               return;
+       xchg(&crw_handlers[rsc], NULL);
+       synchronize_sched();
+}
+
 /*
  * Retrieve CRWs and call function to handle event.
- *
- * Note : we currently process CRWs for io and chsc subchannels only
  */
-static int
-s390_collect_crw_info(void *param)
+static int s390_collect_crw_info(void *param)
 {
        struct crw crw[2];
        int ccode;
@@ -84,57 +107,24 @@ repeat:
                       crw[chain].rsid);
                /* Check for overflows. */
                if (crw[chain].oflw) {
+                       int i;
+
                        pr_debug("%s: crw overflow detected!\n", __func__);
-                       css_schedule_eval_all();
+                       for (i = 0; i < NR_RSCS; i++) {
+                               if (crw_handlers[i])
+                                       crw_handlers[i](NULL, NULL, 1);
+                       }
                        chain = 0;
                        continue;
                }
-               switch (crw[chain].rsc) {
-               case CRW_RSC_SCH:
-                       if (crw[0].chn && !chain)
-                               break;
-                       pr_debug("source is subchannel %04X\n", crw[0].rsid);
-                       css_process_crw(crw[0].rsid, chain ? crw[1].rsid : 0);
-                       break;
-               case CRW_RSC_MONITOR:
-                       pr_debug("source is monitoring facility\n");
-                       break;
-               case CRW_RSC_CPATH:
-                       pr_debug("source is channel path %02X\n", crw[0].rsid);
-                       /*
-                        * Check for solicited machine checks. These are
-                        * created by reset channel path and need not be
-                        * reported to the common I/O layer.
-                        */
-                       if (crw[chain].slct) {
-                               pr_debug("solicited machine check for "
-                                        "channel path %02X\n", crw[0].rsid);
-                               break;
-                       }
-                       switch (crw[0].erc) {
-                       case CRW_ERC_IPARM: /* Path has come. */
-                               chp_process_crw(crw[0].rsid, 1);
-                               break;
-                       case CRW_ERC_PERRI: /* Path has gone. */
-                       case CRW_ERC_PERRN:
-                               chp_process_crw(crw[0].rsid, 0);
-                               break;
-                       default:
-                               pr_debug("Don't know how to handle erc=%x\n",
-                                        crw[0].erc);
-                       }
-                       break;
-               case CRW_RSC_CONFIG:
-                       pr_debug("source is configuration-alert facility\n");
-                       break;
-               case CRW_RSC_CSS:
-                       pr_debug("source is channel subsystem\n");
-                       chsc_process_crw();
-                       break;
-               default:
-                       pr_debug("unknown source\n");
-                       break;
+               if (crw[0].chn && !chain) {
+                       chain++;
+                       continue;
                }
+               if (crw_handlers[crw[chain].rsc])
+                       crw_handlers[crw[chain].rsc](&crw[0],
+                                                    chain ? &crw[1] : NULL,
+                                                    0);
                /* chain is always 0 or 1 here. */
                chain = crw[chain].chn ? chain + 1 : 0;
        }
@@ -468,6 +458,10 @@ s390_do_machine_check(struct pt_regs *regs)
                        etr_sync_check();
                if (S390_lowcore.external_damage_code & (1U << ED_ETR_SWITCH))
                        etr_switch_to_local();
+               if (S390_lowcore.external_damage_code & (1U << ED_STP_SYNC))
+                       stp_sync_check();
+               if (S390_lowcore.external_damage_code & (1U << ED_STP_ISLAND))
+                       stp_island_check();
        }
 
        if (mci->se)
index ca681f9b67fccb36b037a5beccd23e2cd4f7d73c..d39f8b697d271d00311cfac4847676ddb102dd9d 100644 (file)
@@ -72,6 +72,13 @@ struct crw {
        __u32 rsid    : 16;   /* reporting-source ID */
 } __attribute__ ((packed));
 
+typedef void (*crw_handler_t)(struct crw *, struct crw *, int);
+
+extern int s390_register_crw_handler(int rsc, crw_handler_t handler);
+extern void s390_unregister_crw_handler(int rsc);
+
+#define NR_RSCS 16
+
 #define CRW_RSC_MONITOR  0x2  /* monitoring facility */
 #define CRW_RSC_SCH      0x3  /* subchannel */
 #define CRW_RSC_CPATH    0x4  /* channel path */
@@ -105,6 +112,9 @@ static inline int stcrw(struct crw *pcrw )
 #define ED_ETR_SYNC    12      /* External damage ETR sync check */
 #define ED_ETR_SWITCH  13      /* External damage ETR switch to local */
 
+#define ED_STP_SYNC    7       /* External damage STP sync check */
+#define ED_STP_ISLAND  6       /* External damage STP island check */
+
 struct pt_regs;
 
 void s390_handle_mcck(void);
index a0b6d414953dda3128acc7477827a7dcfbdd429b..59fbef08d690763920af4b7fac52752f30be0570 100644 (file)
@@ -2359,6 +2359,24 @@ void scsi_esp_unregister(struct esp *esp)
 }
 EXPORT_SYMBOL(scsi_esp_unregister);
 
+static int esp_target_alloc(struct scsi_target *starget)
+{
+       struct esp *esp = shost_priv(dev_to_shost(&starget->dev));
+       struct esp_target_data *tp = &esp->target[starget->id];
+
+       tp->starget = starget;
+
+       return 0;
+}
+
+static void esp_target_destroy(struct scsi_target *starget)
+{
+       struct esp *esp = shost_priv(dev_to_shost(&starget->dev));
+       struct esp_target_data *tp = &esp->target[starget->id];
+
+       tp->starget = NULL;
+}
+
 static int esp_slave_alloc(struct scsi_device *dev)
 {
        struct esp *esp = shost_priv(dev->host);
@@ -2370,8 +2388,6 @@ static int esp_slave_alloc(struct scsi_device *dev)
                return -ENOMEM;
        dev->hostdata = lp;
 
-       tp->starget = dev->sdev_target;
-
        spi_min_period(tp->starget) = esp->min_period;
        spi_max_offset(tp->starget) = 15;
 
@@ -2608,6 +2624,8 @@ struct scsi_host_template scsi_esp_template = {
        .name                   = "esp",
        .info                   = esp_info,
        .queuecommand           = esp_queuecommand,
+       .target_alloc           = esp_target_alloc,
+       .target_destroy         = esp_target_destroy,
        .slave_alloc            = esp_slave_alloc,
        .slave_configure        = esp_slave_configure,
        .slave_destroy          = esp_slave_destroy,
index 999e91ea745139bba95caf0b9bd5224254ff9190..e7a3a655442562186328d81df9d81be9f744f5f6 100644 (file)
@@ -71,6 +71,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/libata.h>
+#include <linux/hdreg.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/processor.h>
@@ -4913,8 +4914,11 @@ static int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
        struct ipr_resource_entry *res;
 
        res = (struct ipr_resource_entry *)sdev->hostdata;
-       if (res && ipr_is_gata(res))
+       if (res && ipr_is_gata(res)) {
+               if (cmd == HDIO_GET_IDENTITY)
+                       return -ENOTTY;
                return ata_scsi_ioctl(sdev, cmd, arg);
+       }
 
        return -EINVAL;
 }
index a82d2fe80fb544da5afb86d835e6fbafb3a74533..cbf55d59a54ce4f289c4aeb28948df583aaf445d 100644 (file)
@@ -207,6 +207,15 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
         */
        blk_execute_rq(req->q, NULL, req, 1);
 
+       /*
+        * Some devices (USB mass-storage in particular) may transfer
+        * garbage data together with a residue indicating that the data
+        * is invalid.  Prevent the garbage from being misinterpreted
+        * and prevent security leaks by zeroing out the excess data.
+        */
+       if (unlikely(req->data_len > 0 && req->data_len <= bufflen))
+               memset(buffer + (bufflen - req->data_len), 0, req->data_len);
+
        ret = req->errors;
  out:
        blk_put_request(req);
index 45df83b9d847122abac77e2d7a9d5a59eb2cfb95..0fe031f003e7e8e5082dc91469204e53b35067b5 100644 (file)
@@ -61,7 +61,7 @@ static int ses_probe(struct device *dev)
        return err;
 }
 
-#define SES_TIMEOUT 30
+#define SES_TIMEOUT (30 * HZ)
 #define SES_RETRIES 3
 
 static int ses_recv_diag(struct scsi_device *sdev, int page_code,
index ea0edd1b2e76692ce520a56bbcc5d62666f75fff..fe694f0ee19a80a6bc2895d84970f9a8e7e264ad 100644 (file)
@@ -182,8 +182,9 @@ static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp,
                         int tablesize);
 static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
                           Sg_request * srp);
-static ssize_t sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
-                           int blocking, int read_only, Sg_request ** o_srp);
+static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
+                       const char __user *buf, size_t count, int blocking,
+                       int read_only, Sg_request **o_srp);
 static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
                           unsigned char *cmnd, int timeout, int blocking);
 static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind,
@@ -204,7 +205,6 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
 static Sg_request *sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static int sg_res_in_use(Sg_fd * sfp);
-static int sg_allow_access(unsigned char opcode, char dev_type);
 static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
 static Sg_device *sg_get_dev(int dev);
 #ifdef CONFIG_SCSI_PROC_FS
@@ -544,7 +544,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
                return -EFAULT;
        blocking = !(filp->f_flags & O_NONBLOCK);
        if (old_hdr.reply_len < 0)
-               return sg_new_write(sfp, buf, count, blocking, 0, NULL);
+               return sg_new_write(sfp, filp, buf, count, blocking, 0, NULL);
        if (count < (SZ_SG_HEADER + 6))
                return -EIO;    /* The minimum scsi command length is 6 bytes. */
 
@@ -621,8 +621,9 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
 }
 
 static ssize_t
-sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
-            int blocking, int read_only, Sg_request ** o_srp)
+sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
+                size_t count, int blocking, int read_only,
+                Sg_request **o_srp)
 {
        int k;
        Sg_request *srp;
@@ -678,8 +679,7 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
                sg_remove_request(sfp, srp);
                return -EFAULT;
        }
-       if (read_only &&
-           (!sg_allow_access(cmnd[0], sfp->parentdp->device->type))) {
+       if (read_only && !blk_verify_command(file, cmnd)) {
                sg_remove_request(sfp, srp);
                return -EPERM;
        }
@@ -799,7 +799,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
                        if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR))
                                return -EFAULT;
                        result =
-                           sg_new_write(sfp, p, SZ_SG_IO_HDR,
+                           sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
                                         blocking, read_only, &srp);
                        if (result < 0)
                                return result;
@@ -1048,7 +1048,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
 
                        if (copy_from_user(&opcode, siocp->data, 1))
                                return -EFAULT;
-                       if (!sg_allow_access(opcode, sdp->device->type))
+                       if (!blk_verify_command(filp, &opcode))
                                return -EPERM;
                }
                return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p);
@@ -2502,30 +2502,6 @@ sg_page_free(struct page *page, int size)
        __free_pages(page, order);
 }
 
-#ifndef MAINTENANCE_IN_CMD
-#define MAINTENANCE_IN_CMD 0xa3
-#endif
-
-static unsigned char allow_ops[] = { TEST_UNIT_READY, REQUEST_SENSE,
-       INQUIRY, READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12,
-       READ_16, MODE_SENSE, MODE_SENSE_10, LOG_SENSE, REPORT_LUNS,
-       SERVICE_ACTION_IN, RECEIVE_DIAGNOSTIC, READ_LONG, MAINTENANCE_IN_CMD
-};
-
-static int
-sg_allow_access(unsigned char opcode, char dev_type)
-{
-       int k;
-
-       if (TYPE_SCANNER == dev_type)   /* TYPE_ROM maybe burner */
-               return 1;
-       for (k = 0; k < sizeof (allow_ops); ++k) {
-               if (opcode == allow_ops[k])
-                       return 1;
-       }
-       return 0;
-}
-
 #ifdef CONFIG_SCSI_PROC_FS
 static int
 sg_idr_max_id(int id, void *p, void *data)
index c82df8bd4d8931cc72d3654a74edde4e4c9dd75b..27f5bfd1def343e205c2710a587571650026410f 100644 (file)
@@ -673,24 +673,20 @@ fail:
 static void get_sectorsize(struct scsi_cd *cd)
 {
        unsigned char cmd[10];
-       unsigned char *buffer;
+       unsigned char buffer[8];
        int the_result, retries = 3;
        int sector_size;
        struct request_queue *queue;
 
-       buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
-       if (!buffer)
-               goto Enomem;
-
        do {
                cmd[0] = READ_CAPACITY;
                memset((void *) &cmd[1], 0, 9);
-               memset(buffer, 0, 8);
+               memset(buffer, 0, sizeof(buffer));
 
                /* Do the command and wait.. */
                the_result = scsi_execute_req(cd->device, cmd, DMA_FROM_DEVICE,
-                                             buffer, 8, NULL, SR_TIMEOUT,
-                                             MAX_RETRIES);
+                                             buffer, sizeof(buffer), NULL,
+                                             SR_TIMEOUT, MAX_RETRIES);
 
                retries--;
 
@@ -745,14 +741,8 @@ static void get_sectorsize(struct scsi_cd *cd)
 
        queue = cd->device->request_queue;
        blk_queue_hardsect_size(queue, sector_size);
-out:
-       kfree(buffer);
-       return;
 
-Enomem:
-       cd->capacity = 0x1fffff;
-       cd->device->sector_size = 2048; /* A guess, just in case */
-       goto out;
+       return;
 }
 
 static void get_capabilities(struct scsi_cd *cd)
index 1bc00b721e9dac70693f20b85c4f72776f214eb2..be95e55b228b83077ace9af42764d75f8a286d11 100644 (file)
@@ -2623,6 +2623,9 @@ static struct console serial8250_console = {
 
 static int __init serial8250_console_init(void)
 {
+       if (nr_uarts > UART_NR)
+               nr_uarts = UART_NR;
+
        serial8250_isa_init_ports();
        register_console(&serial8250_console);
        return 0;
index c9b64e73c9879d10d7bd7e7e4055bd257c083e73..42d2e108b67968406ebc1da8ac8b316d532f578a 100644 (file)
@@ -1991,7 +1991,9 @@ struct uart_match {
 static int serial_match_port(struct device *dev, void *data)
 {
        struct uart_match *match = data;
-       dev_t devt = MKDEV(match->driver->major, match->driver->minor) + match->port->line;
+       struct tty_driver *tty_drv = match->driver->tty_driver;
+       dev_t devt = MKDEV(tty_drv->major, tty_drv->minor_start) +
+               match->port->line;
 
        return dev->devt == devt; /* Actually, only one tty per port */
 }
index 799337f7fde1b5a5971ff11c6378121e20cc5451..f5b60c70389b771bc752be6178ed38cfed2730f9 100644 (file)
@@ -167,14 +167,14 @@ spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
 
        mutex_lock(&spidev->buf_lock);
        status = spidev_sync_read(spidev, count);
-       if (status == 0) {
+       if (status > 0) {
                unsigned long   missing;
 
-               missing = copy_to_user(buf, spidev->buffer, count);
-               if (count && missing == count)
+               missing = copy_to_user(buf, spidev->buffer, status);
+               if (missing == status)
                        status = -EFAULT;
                else
-                       status = count - missing;
+                       status = status - missing;
        }
        mutex_unlock(&spidev->buf_lock);
 
@@ -200,8 +200,6 @@ spidev_write(struct file *filp, const char __user *buf,
        missing = copy_from_user(spidev->buffer, buf, count);
        if (missing == 0) {
                status = spidev_sync_write(spidev, count);
-               if (status == 0)
-                       status = count;
        } else
                status = -EFAULT;
        mutex_unlock(&spidev->buf_lock);
index d28c53868093ce533c88e9b88a80334d9ac5ebca..538c570df3373e147c399a2d0907cf3b20d16762 100644 (file)
@@ -537,6 +537,13 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
        int err = 0;
        u32 tmp;
 
+       if (dev->bus->bustype != SSB_BUSTYPE_PCI) {
+               /* This SSB device is not on a PCI host-bus. So the IRQs are
+                * not routed through the PCI core.
+                * So we must not enable routing through the PCI core. */
+               goto out;
+       }
+
        if (!pdev)
                goto out;
        bus = pdev->bus;
index 4b628526df097562a94004a653a9ba16eed9dd18..a86e952ed4ca4de05891b19d54ef185802048bfc 100644 (file)
@@ -12,3 +12,12 @@ menuconfig THERMAL
          cooling devices.
          All platforms with ACPI thermal support can use this driver.
          If you want this support, you should say Y or M here.
+
+config THERMAL_HWMON
+       bool "Hardware monitoring support"
+       depends on HWMON=y || HWMON=THERMAL
+       help
+         The generic thermal sysfs driver's hardware monitoring support
+         requires a 2.10.7/3.0.2 or later lm-sensors userspace.
+
+         Say Y if your user-space is new enough.
index 6098787341f3d6ada67a195b7ee59d307b6a9c34..fe07462d5947fec44a4eb559a552670e84744a08 100644 (file)
@@ -295,8 +295,8 @@ thermal_cooling_device_trip_point_show(struct device *dev,
 
 /* Device management */
 
-#if defined(CONFIG_HWMON) ||   \
-       (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE))
+#if defined(CONFIG_THERMAL_HWMON)
+
 /* hwmon sys I/F */
 #include <linux/hwmon.h>
 static LIST_HEAD(thermal_hwmon_list);
index 63c34043b4d91e0bfb2864672704be838f518fef..c3201affa0b6f99c17ff6d28c71e3cd08adb58c6 100644 (file)
@@ -1125,9 +1125,6 @@ static void stop_data_traffic(struct acm *acm)
        for (i = 0; i < acm->rx_buflimit; i++)
                usb_kill_urb(acm->ru[i].urb);
 
-       INIT_LIST_HEAD(&acm->filled_read_bufs);
-       INIT_LIST_HEAD(&acm->spare_read_bufs);
-
        tasklet_enable(&acm->urb_task);
 
        cancel_work_sync(&acm->work);
index 09a53e7f33278ad58f555b15792c7b89c676a458..42a436478b78bba99c05a9cf609ea89e4e11adfe 100644 (file)
@@ -924,6 +924,15 @@ static int register_root_hub(struct usb_hcd *hcd)
        return retval;
 }
 
+void usb_enable_root_hub_irq (struct usb_bus *bus)
+{
+       struct usb_hcd *hcd;
+
+       hcd = container_of (bus, struct usb_hcd, self);
+       if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT)
+               hcd->driver->hub_irq_enable (hcd);
+}
+
 
 /*-------------------------------------------------------------------------*/
 
@@ -1684,19 +1693,30 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
 irqreturn_t usb_hcd_irq (int irq, void *__hcd)
 {
        struct usb_hcd          *hcd = __hcd;
-       int                     start = hcd->state;
+       unsigned long           flags;
+       irqreturn_t             rc;
 
-       if (unlikely(start == HC_STATE_HALT ||
-           !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
-               return IRQ_NONE;
-       if (hcd->driver->irq (hcd) == IRQ_NONE)
-               return IRQ_NONE;
+       /* IRQF_DISABLED doesn't work correctly with shared IRQs
+        * when the first handler doesn't use it.  So let's just
+        * assume it's never used.
+        */
+       local_irq_save(flags);
 
-       set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+       if (unlikely(hcd->state == HC_STATE_HALT ||
+                    !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
+               rc = IRQ_NONE;
+       } else if (hcd->driver->irq(hcd) == IRQ_NONE) {
+               rc = IRQ_NONE;
+       } else {
+               set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+
+               if (unlikely(hcd->state == HC_STATE_HALT))
+                       usb_hc_died(hcd);
+               rc = IRQ_HANDLED;
+       }
 
-       if (unlikely(hcd->state == HC_STATE_HALT))
-               usb_hc_died (hcd);
-       return IRQ_HANDLED;
+       local_irq_restore(flags);
+       return rc;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1860,6 +1880,13 @@ int usb_add_hcd(struct usb_hcd *hcd,
 
        /* enable irqs just before we start the controller */
        if (hcd->driver->irq) {
+
+               /* IRQF_DISABLED doesn't work as advertised when used together
+                * with IRQF_SHARED. As usb_hcd_irq() will always disable
+                * interrupts we can remove it here.
+                */
+               irqflags &= ~IRQF_DISABLED;
+
                snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
                                hcd->driver->description, hcd->self.busnum);
                if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
index a0bf5df6cb6fa3eb77636bd32f49c702822794ab..b9de1569b39e792f8de8301b5b3c8b27782100ee 100644 (file)
@@ -210,6 +210,8 @@ struct hc_driver {
        int     (*bus_suspend)(struct usb_hcd *);
        int     (*bus_resume)(struct usb_hcd *);
        int     (*start_port_reset)(struct usb_hcd *, unsigned port_num);
+       void    (*hub_irq_enable)(struct usb_hcd *);
+               /* Needed only if port-change IRQs are level-triggered */
 
                /* force handover of high-speed port to full-speed companion */
        void    (*relinquish_port)(struct usb_hcd *, int);
index 94789be54ca3a8c66bfd0e4b5e21c9b9112b5ab9..4cfe32a16c37fb689e8bab4796b6918a36728382 100644 (file)
@@ -713,18 +713,11 @@ static void hub_restart(struct usb_hub *hub, int type)
                }
 
                /* Was the power session lost while we were suspended? */
-               switch (type) {
-               case HUB_RESET_RESUME:
-                       portstatus = 0;
-                       portchange = USB_PORT_STAT_C_CONNECTION;
-                       break;
+               status = hub_port_status(hub, port1, &portstatus, &portchange);
 
-               case HUB_RESET:
-               case HUB_RESUME:
-                       status = hub_port_status(hub, port1,
-                                       &portstatus, &portchange);
-                       break;
-               }
+               /* If the device is gone, khubd will handle it later */
+               if (status == 0 && !(portstatus & USB_PORT_STAT_CONNECTION))
+                       continue;
 
                /* For "USB_PERSIST"-enabled children we must
                 * mark the child device for reset-resume and
@@ -2080,6 +2073,8 @@ int usb_port_resume(struct usb_device *udev)
        }
 
        clear_bit(port1, hub->busy_bits);
+       if (!hub->hdev->parent && !hub->busy_bits[0])
+               usb_enable_root_hub_irq(hub->hdev->bus);
 
        if (status == 0)
                status = finish_port_resume(udev);
@@ -3009,6 +3004,11 @@ static void hub_events(void)
 
                hub->activating = 0;
 
+               /* If this is a root hub, tell the HCD it's okay to
+                * re-enable port-change interrupts now. */
+               if (!hdev->parent && !hub->busy_bits[0])
+                       usb_enable_root_hub_irq(hdev->bus);
+
 loop_autopm:
                /* Allow autosuspend if we're not going to run again */
                if (list_empty(&hub->event_list))
@@ -3234,6 +3234,8 @@ int usb_reset_device(struct usb_device *udev)
                        break;
        }
        clear_bit(port1, parent_hub->busy_bits);
+       if (!parent_hdev->parent && !parent_hub->busy_bits[0])
+               usb_enable_root_hub_irq(parent_hdev->bus);
 
        if (ret < 0)
                goto re_enumerate;
index 35a03095757ea3b2ae225e203bab757abb4aceb6..90245fd8bac4dd234390ec96e636570ef4e98c73 100644 (file)
@@ -177,6 +177,15 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action)
 static inline void
 timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
 {
+       /* Don't override timeouts which shrink or (later) disable
+        * the async ring; just the I/O watchdog.  Note that if a
+        * SHRINK were pending, OFF would never be requested.
+        */
+       if (timer_pending(&ehci->watchdog)
+                       && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
+                               & ehci->actions))
+               return;
+
        if (!test_and_set_bit (action, &ehci->actions)) {
                unsigned long t;
 
@@ -192,15 +201,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
                        t = EHCI_SHRINK_JIFFIES;
                        break;
                }
-               t += jiffies;
-               // all timings except IAA watchdog can be overridden.
-               // async queue SHRINK often precedes IAA.  while it's ready
-               // to go OFF neither can matter, and afterwards the IO
-               // watchdog stops unless there's still periodic traffic.
-               if (time_before_eq(t, ehci->watchdog.expires)
-                               && timer_pending (&ehci->watchdog))
-                       return;
-               mod_timer (&ehci->watchdog, t);
+               mod_timer(&ehci->watchdog, t + jiffies);
        }
 }
 
index c96db1153dcf6d595d2e42fc3bc3c18899f7b187..e534f9de0f05f9bbfc20c4f9938cb29c66a31f7a 100644 (file)
@@ -261,6 +261,7 @@ static const struct hc_driver ohci_at91_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 1b9abdba920b9d18a8a53723a8eabc58342eaf0d..68c17f5ea8ea15c4ebfcc34e95ff4fb625978309 100644 (file)
@@ -8,7 +8,7 @@
  * Bus Glue for AMD Alchemy Au1xxx
  *
  * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Rusell King et al.
+ * Based on fragments of previous driver by Russell King et al.
  *
  * Modified for LH7A404 from ohci-sa1111.c
  *  by Durgesh Pattamatta <pattamattad@sharpsec.com>
@@ -288,6 +288,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 06aadfb0ec29a4683830a1d47191174e3f99b500..5adaf36e47d05627dd1d9a884895ceaa28608aef 100644 (file)
@@ -135,6 +135,7 @@ static struct hc_driver ohci_ep93xx_hc_driver = {
        .get_frame_number       = ohci_get_frame,
        .hub_status_data        = ohci_hub_status_data,
        .hub_control            = ohci_hub_control,
+       .hub_irq_enable         = ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend            = ohci_bus_suspend,
        .bus_resume             = ohci_bus_resume,
index 33f1c1c32edf75ecc5a93e4a171c0afa2806a123..a8160d65f32be3f3be08fc4f2813f7b2c5b3def6 100644 (file)
@@ -1054,7 +1054,7 @@ MODULE_LICENSE ("GPL");
 
 #ifdef CONFIG_MFD_SM501
 #include "ohci-sm501.c"
-#define PLATFORM_DRIVER                ohci_hcd_sm501_driver
+#define SM501_OHCI_DRIVER      ohci_hcd_sm501_driver
 #endif
 
 #if    !defined(PCI_DRIVER) &&         \
@@ -1062,6 +1062,7 @@ MODULE_LICENSE ("GPL");
        !defined(OF_PLATFORM_DRIVER) && \
        !defined(SA1111_DRIVER) &&      \
        !defined(PS3_SYSTEM_BUS_DRIVER) && \
+       !defined(SM501_OHCI_DRIVER) && \
        !defined(SSB_OHCI_DRIVER)
 #error "missing bus glue for ohci-hcd"
 #endif
@@ -1121,9 +1122,18 @@ static int __init ohci_hcd_mod_init(void)
                goto error_ssb;
 #endif
 
+#ifdef SM501_OHCI_DRIVER
+       retval = platform_driver_register(&SM501_OHCI_DRIVER);
+       if (retval < 0)
+               goto error_sm501;
+#endif
+
        return retval;
 
        /* Error path */
+#ifdef SM501_OHCI_DRIVER
+ error_sm501:
+#endif
 #ifdef SSB_OHCI_DRIVER
  error_ssb:
 #endif
@@ -1159,6 +1169,9 @@ module_init(ohci_hcd_mod_init);
 
 static void __exit ohci_hcd_mod_exit(void)
 {
+#ifdef SM501_OHCI_DRIVER
+       platform_driver_unregister(&SM501_OHCI_DRIVER);
+#endif
 #ifdef SSB_OHCI_DRIVER
        ssb_driver_unregister(&SSB_OHCI_DRIVER);
 #endif
index 79a78029f896869892fa2696bd8f1764cc79f9e7..b56739221d11f27d6d6e1b8d04c833fe56bdbd6c 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
+/* hcd->hub_irq_enable() */
+static void ohci_rhsc_enable (struct usb_hcd *hcd)
+{
+       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
+
+       spin_lock_irq(&ohci->lock);
+       if (!ohci->autostop)
+               del_timer(&hcd->rh_timer);      /* Prevent next poll */
+       ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+       spin_unlock_irq(&ohci->lock);
+}
+
 #define OHCI_SCHED_ENABLES \
        (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
 
@@ -362,28 +374,18 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
                int any_connected)
 {
        int     poll_rh = 1;
-       int     rhsc;
 
-       rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC;
        switch (ohci->hc_control & OHCI_CTRL_HCFS) {
 
        case OHCI_USB_OPER:
-               /* If no status changes are pending, enable status-change
-                * interrupts.
-                */
-               if (!rhsc && !changed) {
-                       rhsc = OHCI_INTR_RHSC;
-                       ohci_writel(ohci, rhsc, &ohci->regs->intrenable);
-               }
-
-               /* Keep on polling until we know a device is connected
-                * and RHSC is enabled, or until we autostop.
-                */
+               /* keep on polling until we know a device is connected
+                * and RHSC is enabled */
                if (!ohci->autostop) {
                        if (any_connected ||
                                        !device_may_wakeup(&ohci_to_hcd(ohci)
                                                ->self.root_hub->dev)) {
-                               if (rhsc)
+                               if (ohci_readl(ohci, &ohci->regs->intrenable) &
+                                               OHCI_INTR_RHSC)
                                        poll_rh = 0;
                        } else {
                                ohci->autostop = 1;
@@ -396,13 +398,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
                                ohci->autostop = 0;
                                ohci->next_statechange = jiffies +
                                                STATECHANGE_DELAY;
-                       } else if (rhsc && time_after_eq(jiffies,
+                       } else if (time_after_eq(jiffies,
                                                ohci->next_statechange)
                                        && !ohci->ed_rm_list
                                        && !(ohci->hc_control &
                                                OHCI_SCHED_ENABLES)) {
                                ohci_rh_suspend(ohci, 1);
-                               poll_rh = 0;
                        }
                }
                break;
@@ -416,12 +417,6 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
                        else
                                usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
                } else {
-                       if (!rhsc && (ohci->autostop ||
-                                       ohci_to_hcd(ohci)->self.root_hub->
-                                               do_remote_wakeup))
-                               ohci_writel(ohci, OHCI_INTR_RHSC,
-                                               &ohci->regs->intrenable);
-
                        /* everything is idle, no need for polling */
                        poll_rh = 0;
                }
@@ -443,16 +438,12 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci)
 static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
                int any_connected)
 {
-       /* If RHSC is enabled, don't poll */
-       if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
-               return 0;
+       int     poll_rh = 1;
 
-       /* If no status changes are pending, enable status-change interrupts */
-       if (!changed) {
-               ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
-               return 0;
-       }
-       return 1;
+       /* keep on polling until RHSC is enabled */
+       if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
+               poll_rh = 0;
+       return poll_rh;
 }
 
 #endif /* CONFIG_PM */
index 96d14fa1d8331b7ee2a587d9138246b99e4bceec..1ef5d482c145324f8638b45ec1c9d82dbf54e672 100644 (file)
@@ -8,7 +8,7 @@
  * Bus Glue for Sharp LH7A404
  *
  * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Rusell King et al.
+ * Based on fragments of previous driver by Russell King et al.
  *
  * Modified for LH7A404 from ohci-sa1111.c
  *  by Durgesh Pattamatta <pattamattad@sharpsec.com>
@@ -193,6 +193,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 6859fb5f1d6f6a5d2f9dd29b0c3d063697c15233..3a7c24c03671199680a435cd93370b415bcfa52c 100644 (file)
@@ -466,6 +466,7 @@ static const struct hc_driver ohci_omap_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 3bf175d95a2303b17d80a3561fc38a727ce13c84..4696cc912e16203540a5185568a27e02bb7c15e2 100644 (file)
@@ -327,6 +327,7 @@ static const struct hc_driver ohci_pci_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 664f07ee87320e2a568c727d95bbf82b8d446894..28b458f20cc3013749503821119e5e741e58a85f 100644 (file)
@@ -280,6 +280,7 @@ static const struct hc_driver ohci_pnx4008_hc_driver = {
         */
        .hub_status_data = ohci_hub_status_data,
        .hub_control = ohci_hub_control,
+       .hub_irq_enable = ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend = ohci_bus_suspend,
        .bus_resume = ohci_bus_resume,
index 28467e288a93d54607c7cb244e1e904dc6136395..605d59cba28e79d46bbbb3215cfc9ccd1b6f6a5b 100644 (file)
@@ -201,6 +201,7 @@ static const struct hc_driver ohci_pnx8550_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 50e55db13636ece797f64ae65e1a01a58800fabe..a6725279122315bf7566b255164d29c7f8130bbd 100644 (file)
@@ -72,6 +72,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index cd3398b675b2dea8c2402fd2178cee58c23a52e4..523c30125577d39a8c24287ce30ae2b2532929e2 100644 (file)
@@ -172,6 +172,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index bfdeb0d22d050576755f6d1054d9d4b561bb7e3a..c1935ae537f80a90779d6eaea502dd4d02ee267d 100644 (file)
@@ -68,6 +68,7 @@ static const struct hc_driver ps3_ohci_hc_driver = {
        .get_frame_number       = ohci_get_frame,
        .hub_status_data        = ohci_hub_status_data,
        .hub_control            = ohci_hub_control,
+       .hub_irq_enable         = ohci_rhsc_enable,
        .start_port_reset       = ohci_start_port_reset,
 #if defined(CONFIG_PM)
        .bus_suspend            = ohci_bus_suspend,
index 70b0d4b459e753bf13ed622eb32fd7b458c9d38c..d4ee27d92be8fd69874f50b1e16785257a1066c1 100644 (file)
@@ -298,6 +298,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef  CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 9c9f3b59186f6c65d3d33cbfa16dced198de10eb..9b547407c9342fd41b02700adda126c0382cd74e 100644 (file)
@@ -952,6 +952,7 @@ rescan_this:
                        struct urb      *urb;
                        urb_priv_t      *urb_priv;
                        __hc32          savebits;
+                       u32             tdINFO;
 
                        td = list_entry (entry, struct td, td_list);
                        urb = td->urb;
@@ -966,6 +967,17 @@ rescan_this:
                        savebits = *prev & ~cpu_to_hc32 (ohci, TD_MASK);
                        *prev = td->hwNextTD | savebits;
 
+                       /* If this was unlinked, the TD may not have been
+                        * retired ... so manually save the data toggle.
+                        * The controller ignores the value we save for
+                        * control and ISO endpoints.
+                        */
+                       tdINFO = hc32_to_cpup(ohci, &td->hwINFO);
+                       if ((tdINFO & TD_T) == TD_T_DATA0)
+                               ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_C);
+                       else if ((tdINFO & TD_T) == TD_T_DATA1)
+                               ed->hwHeadP |= cpu_to_hc32(ohci, ED_C);
+
                        /* HC may have partly processed this TD */
                        td_done (ohci, urb, td);
                        urb_priv->td_cnt++;
index a73d2ff322e28d862184ad83188da0302386f61c..3c7a740cfe0ca6fbf1ab14a69972c6d6002c7dce 100644 (file)
@@ -8,7 +8,7 @@
  * USB Bus Glue for Samsung S3C2410
  *
  * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Rusell King et al.
+ * Based on fragments of previous driver by Russell King et al.
  *
  * Modified for S3C2410 from ohci-sa1111.c, ohci-omap.c and ohci-lh7a40.c
  *     by Ben Dooks, <ben@simtec.co.uk>
@@ -466,6 +466,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
         */
        .hub_status_data =      ohci_s3c2410_hub_status_data,
        .hub_control =          ohci_s3c2410_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 99438c65981b4f8cd98e87066092c2ea1b9251b3..2e9dceb9bb9980055a8735988f7124a910f5494b 100644 (file)
@@ -8,7 +8,7 @@
  * SA1111 Bus Glue
  *
  * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Rusell King et al.
+ * Based on fragments of previous driver by Russell King et al.
  *
  * This file is licenced under the GPL.
  */
@@ -231,6 +231,7 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index 60f03cc7ec4f20a4f80d228b59faebe715ae1148..e7ee607278fece8b92570beb5b839e74ca8aa2db 100644 (file)
@@ -68,6 +68,7 @@ static const struct hc_driver ohci_sh_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index e899a77dfb8340ae69e3502dcc8c5c2482a93a70..e610698c6b60ca55eadf234599f3a3b254e5309b 100644 (file)
@@ -75,6 +75,7 @@ static const struct hc_driver ohci_sm501_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index c4265caec78023993e62607c5be548560d34fbf4..7275186db31556baf8278ec300da9d0d8600a98f 100644 (file)
@@ -81,6 +81,7 @@ static const struct hc_driver ssb_ohci_hc_driver = {
 
        .hub_status_data        = ohci_hub_status_data,
        .hub_control            = ohci_hub_control,
+       .hub_irq_enable         = ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend            = ohci_bus_suspend,
        .bus_resume             = ohci_bus_resume,
index f29307405bb36aa45ef4a764f9d483d99dfeef6e..9b6323f768b242523495d352134f5533c423566d 100644 (file)
@@ -2934,6 +2934,16 @@ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
                return 0;
 }
 
+static void u132_hub_irq_enable(struct usb_hcd *hcd)
+{
+       struct u132 *u132 = hcd_to_u132(hcd);
+       if (u132->going > 1) {
+               dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                       , u132->going);
+       } else if (u132->going > 0)
+               dev_err(&u132->platform_dev->dev, "device is being removed\n");
+}
+
 
 #ifdef CONFIG_PM
 static int u132_bus_suspend(struct usb_hcd *hcd)
@@ -2985,6 +2995,7 @@ static struct hc_driver u132_hc_driver = {
        .bus_suspend = u132_bus_suspend,
        .bus_resume = u132_bus_resume,
        .start_port_reset = u132_start_port_reset,
+       .hub_irq_enable = u132_hub_irq_enable,
 };
 
 /*
index cb7fa0eaf3ae9e264bc4fea418a6e70afe979021..33182f4c2267ad69ddab0106e76cf39e2bff8436 100644 (file)
@@ -3264,8 +3264,6 @@ static void sisusb_disconnect(struct usb_interface *intf)
 
        /* decrement our usage count */
        kref_put(&sisusb->kref, sisusb_delete);
-
-       dev_info(&sisusb->sisusb_dev->dev, "Disconnected\n");
 }
 
 static struct usb_device_id sisusb_table [] = {
index 5234e7a3bd2c715278d4afabdd54ca9a8957d17e..0ff4a3971e45a95ce0e7047a0e6bb7411646c493 100644 (file)
@@ -637,6 +637,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
+       { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
        { },                                    /* Optional parameter entry */
        { }                                     /* Terminating entry */
 };
index 06e0ecabb3eb7d90e31003e008c27e36675241d4..8302eca893ea334f61c5d0d64c2b3a0ccfad91fa 100644 (file)
 /* Propox devices */
 #define FTDI_PROPOX_JTAGCABLEII_PID    0xD738
 
+/* Rig Expert Ukraine devices */
+#define FTDI_REU_TINY_PID              0xED22  /* RigExpert Tiny */
+
 /* Commands */
 #define FTDI_SIO_RESET                 0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL    1 /* Set the modem control register */
index ea924dc48496de2b8ca7341c5de69217c3ad8a7e..d9fb3768a2d7b1ba869e4275bcc6ec9d29d1ed2c 100644 (file)
@@ -570,7 +570,12 @@ static struct usb_serial_driver ipaq_device = {
        .description =          "PocketPC PDA",
        .usb_driver =           &ipaq_driver,
        .id_table =             ipaq_id_table,
-       .num_ports =            2,
+       /*
+        * some devices have an extra endpoint, which
+        * must be ignored as it would make the core
+        * create a second port which oopses when used
+        */
+       .num_ports =            1,
        .open =                 ipaq_open,
        .close =                ipaq_close,
        .attach =               ipaq_startup,
index 43cfde83a93b96e24c680a47b783cb829359df49..a73420dd052a511846be7466050355380d0b970d 100644 (file)
@@ -306,6 +306,7 @@ static struct usb_device_id option_ids[] = {
        { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
        { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
+       { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
        { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
index 103195abd41710c39133344d8668bab283003819..2a0dd1b50dc43b8dc884f0964c4f6624bfac1921 100644 (file)
@@ -57,6 +57,7 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_PHAROS) },
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ALDIGA) },
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) },
+       { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) },
        { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
        { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
        { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
index cff160abb13045d555893c325a8eced36bda15db..6ac3bbcf7a22903b392d2281e2627f5db92e93fc 100644 (file)
@@ -15,6 +15,7 @@
 #define PL2303_PRODUCT_ID_RSAQ3                0xaaa2
 #define PL2303_PRODUCT_ID_ALDIGA       0x0611
 #define PL2303_PRODUCT_ID_MMX          0x0612
+#define PL2303_PRODUCT_ID_GPRS         0x0609
 
 #define ATEN_VENDOR_ID         0x0557
 #define ATEN_VENDOR_ID2                0x0547
index 45fe3663fa7f7c320f47f805ddfa73441efdcbb5..39a7c11795c49bbce9a320eff2189de7cc63eb07 100644 (file)
@@ -402,11 +402,19 @@ UNUSUAL_DEV(  0x04a5, 0x3010, 0x0100, 0x0100,
                US_FL_IGNORE_RESIDUE ),
 
 #ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB
+/* CY7C68300 : support atacb */
 UNUSUAL_DEV(  0x04b4, 0x6830, 0x0000, 0x9999,
                "Cypress",
                "Cypress AT2LP",
                US_SC_CYP_ATACB, US_PR_DEVICE, NULL,
                0),
+
+/* CY7C68310 : support atacb and atacb2 */
+UNUSUAL_DEV(  0x04b4, 0x6831, 0x0000, 0x9999,
+               "Cypress",
+               "Cypress ISD-300LP",
+               US_SC_CYP_ATACB, US_PR_DEVICE, NULL,
+               0),
 #endif
 
 /* Reported by Simon Levitt <simon@whattf.com>
index 002b61b4f0f6d9fba9c48a9f3216068f816b9ce4..9b887ef64ff1c27c857602833211dd2b6b2d7716 100644 (file)
@@ -7,7 +7,7 @@ menu "Graphics support"
 
 source "drivers/char/agp/Kconfig"
 
-source "drivers/char/drm/Kconfig"
+source "drivers/gpu/drm/Kconfig"
 
 config VGASTATE
        tristate
@@ -1825,12 +1825,13 @@ config FB_FSL_DIU
 
 config FB_W100
        tristate "W100 frame buffer support"
-       depends on FB && PXA_SHARPSL
+       depends on FB && ARCH_PXA
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        ---help---
          Frame buffer driver for the w100 as found on the Sharp SL-Cxx series.
+         It can also drive the w3220 chip found on iPAQ hx4700.
 
          This driver is also available as a module ( = code which can be
          inserted and removed from the running kernel whenever you want). The
index 24843fdd5395d981c0d27000b895fd0dc8ba32d9..59df132cc3756deda96bfcce5d453a309e803a15 100644 (file)
@@ -74,6 +74,7 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma,
 {
        struct fb_info *info = vma->vm_private_data;
        struct fb_deferred_io *fbdefio = info->fbdefio;
+       struct page *cur;
 
        /* this is a callback we get when userspace first tries to
        write to the page. we schedule a workqueue. that workqueue
@@ -83,7 +84,24 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma,
 
        /* protect against the workqueue changing the page list */
        mutex_lock(&fbdefio->lock);
-       list_add(&page->lru, &fbdefio->pagelist);
+
+       /* we loop through the pagelist before adding in order
+       to keep the pagelist sorted */
+       list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+               /* this check is to catch the case where a new
+               process could start writing to the same page
+               through a new pte. this new access can cause the
+               mkwrite even when the original ps's pte is marked
+               writable */
+               if (unlikely(cur == page))
+                       goto page_already_added;
+               else if (cur->index > page->index)
+                       break;
+       }
+
+       list_add_tail(&page->lru, &cur->lru);
+
+page_already_added:
        mutex_unlock(&fbdefio->lock);
 
        /* come back after delay to process the deferred IO */
index 0a2785361ca3541681fead9c9a5b1838f784178c..09d7e22c6fefa3ee277cba3d5c85191dddc86ecb 100644 (file)
@@ -286,7 +286,7 @@ static struct diu_pool pool;
  *     rheap and make the furture large allocation fail.
  */
 
-void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys)
+static void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys)
 {
        void *virt;
 
@@ -311,12 +311,12 @@ void *fsl_diu_alloc(unsigned long size, phys_addr_t *phys)
                memset(virt, 0, size);
        }
 
-       pr_debug("rh virt=%p phys=%lx\n", virt, *phys);
+       pr_debug("rh virt=%p phys=%llx\n", virt, (unsigned long long)*phys);
 
        return virt;
 }
 
-void fsl_diu_free(void *p, unsigned long size)
+static void fsl_diu_free(void *p, unsigned long size)
 {
        pr_debug("p=%p size=%lu\n", p, size);
 
@@ -770,7 +770,7 @@ static int map_video_memory(struct fb_info *info)
        info->fix.smem_len = info->fix.line_length * info->var.yres_virtual;
        pr_debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len);
        info->screen_base = fsl_diu_alloc(info->fix.smem_len, &phys);
-       if (info->screen_base == 0) {
+       if (info->screen_base == NULL) {
                printk(KERN_ERR "Unable to allocate fb memory\n");
                return -ENOMEM;
        }
@@ -788,7 +788,7 @@ static int map_video_memory(struct fb_info *info)
 static void unmap_video_memory(struct fb_info *info)
 {
        fsl_diu_free(info->screen_base, info->fix.smem_len);
-       info->screen_base = 0;
+       info->screen_base = NULL;
        info->fix.smem_start = 0;
        info->fix.smem_len = 0;
 }
@@ -1158,7 +1158,7 @@ static int init_fbinfo(struct fb_info *info)
        return 0;
 }
 
-static int install_fb(struct fb_info *info)
+static int __devinit install_fb(struct fb_info *info)
 {
        int rc;
        struct mfb_info *mfbi = info->par;
@@ -1233,7 +1233,7 @@ static int install_fb(struct fb_info *info)
        return 0;
 }
 
-static void __exit uninstall_fb(struct fb_info *info)
+static void uninstall_fb(struct fb_info *info)
 {
        struct mfb_info *mfbi = info->par;
 
@@ -1287,7 +1287,7 @@ static int request_irq_local(int irq)
        /* Read to clear the status */
        status = in_be32(&hw->int_status);
 
-       ret = request_irq(irq, fsl_diu_isr, 0, "diu", 0);
+       ret = request_irq(irq, fsl_diu_isr, 0, "diu", NULL);
        if (ret)
                pr_info("Request diu IRQ failed.\n");
        else {
@@ -1312,7 +1312,7 @@ static void free_irq_local(int irq)
        /* Disable all LCDC interrupt */
        out_be32(&hw->int_mask, 0x1f);
 
-       free_irq(irq, 0);
+       free_irq(irq, NULL);
 }
 
 #ifdef CONFIG_PM
@@ -1353,7 +1353,8 @@ static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
        dma_addr_t paddr = 0;
 
        ssize = size + bytes_align;
-       buf->vaddr = dma_alloc_coherent(0, ssize, &paddr, GFP_DMA | __GFP_ZERO);
+       buf->vaddr = dma_alloc_coherent(NULL, ssize, &paddr, GFP_DMA |
+                                                            __GFP_ZERO);
        if (!buf->vaddr)
                return -ENOMEM;
 
@@ -1371,7 +1372,7 @@ static int allocate_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
 
 static void free_buf(struct diu_addr *buf, u32 size, u32 bytes_align)
 {
-       dma_free_coherent(0, size + bytes_align,
+       dma_free_coherent(NULL, size + bytes_align,
                                buf->vaddr, (buf->paddr - buf->offset));
        return;
 }
@@ -1411,7 +1412,7 @@ static ssize_t show_monitor(struct device *device,
        return diu_ops.show_monitor_port(machine_data->monitor_port, buf);
 }
 
-static int fsl_diu_probe(struct of_device *ofdev,
+static int __devinit fsl_diu_probe(struct of_device *ofdev,
        const struct of_device_id *match)
 {
        struct device_node *np = ofdev->node;
index 7dcda187d9ba363e777f060c757b7c1c05bc7db4..fafe7db20d6d2d1652f6e6655039c704e14096dd 100644 (file)
@@ -1246,7 +1246,7 @@ static int pxafb_resume(struct platform_device *dev)
  *      cache.  Once this area is remapped, all virtual memory
  *      access to the video memory should occur at the new region.
  */
-static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
+static int __devinit pxafb_map_video_memory(struct pxafb_info *fbi)
 {
        /*
         * We reserve one page for the palette, plus the size
@@ -1348,7 +1348,7 @@ decode_mode:
        pxafb_decode_mode_info(fbi, inf->modes, inf->num_modes);
 }
 
-static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
+static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
 {
        struct pxafb_info *fbi;
        void *addr;
@@ -1410,7 +1410,7 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
 }
 
 #ifdef CONFIG_FB_PXA_PARAMETERS
-static int __init parse_opt_mode(struct device *dev, const char *this_opt)
+static int __devinit parse_opt_mode(struct device *dev, const char *this_opt)
 {
        struct pxafb_mach_info *inf = dev->platform_data;
 
@@ -1469,7 +1469,7 @@ done:
        return 0;
 }
 
-static int __init parse_opt(struct device *dev, char *this_opt)
+static int __devinit parse_opt(struct device *dev, char *this_opt)
 {
        struct pxafb_mach_info *inf = dev->platform_data;
        struct pxafb_mode_info *mode = &inf->modes[0];
@@ -1567,7 +1567,7 @@ static int __init parse_opt(struct device *dev, char *this_opt)
        return 0;
 }
 
-static int __init pxafb_parse_options(struct device *dev, char *options)
+static int __devinit pxafb_parse_options(struct device *dev, char *options)
 {
        char *this_opt;
        int ret;
@@ -1588,8 +1588,8 @@ static int __init pxafb_parse_options(struct device *dev, char *options)
 
 static char g_options[256] __devinitdata = "";
 
-#ifndef CONFIG_MODULES
-static int __devinit pxafb_setup_options(void)
+#ifndef MODULE
+static int __init pxafb_setup_options(void)
 {
        char *options = NULL;
 
@@ -1613,7 +1613,7 @@ MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
 #define pxafb_setup_options()          (0)
 #endif
 
-static int __init pxafb_probe(struct platform_device *dev)
+static int __devinit pxafb_probe(struct platform_device *dev)
 {
        struct pxafb_info *fbi;
        struct pxafb_mach_info *inf;
@@ -1685,14 +1685,14 @@ static int __init pxafb_probe(struct platform_device *dev)
        if (r == NULL) {
                dev_err(&dev->dev, "no I/O memory resource defined\n");
                ret = -ENODEV;
-               goto failed;
+               goto failed_fbi;
        }
 
        r = request_mem_region(r->start, r->end - r->start + 1, dev->name);
        if (r == NULL) {
                dev_err(&dev->dev, "failed to request I/O memory\n");
                ret = -EBUSY;
-               goto failed;
+               goto failed_fbi;
        }
 
        fbi->mmio_base = ioremap(r->start, r->end - r->start + 1);
@@ -1735,8 +1735,17 @@ static int __init pxafb_probe(struct platform_device *dev)
         * This makes sure that our colour bitfield
         * descriptors are correctly initialised.
         */
-       pxafb_check_var(&fbi->fb.var, &fbi->fb);
-       pxafb_set_par(&fbi->fb);
+       ret = pxafb_check_var(&fbi->fb.var, &fbi->fb);
+       if (ret) {
+               dev_err(&dev->dev, "failed to get suitable mode\n");
+               goto failed_free_irq;
+       }
+
+       ret = pxafb_set_par(&fbi->fb);
+       if (ret) {
+               dev_err(&dev->dev, "Failed to set parameters\n");
+               goto failed_free_irq;
+       }
 
        platform_set_drvdata(dev, fbi);
 
@@ -1744,7 +1753,7 @@ static int __init pxafb_probe(struct platform_device *dev)
        if (ret < 0) {
                dev_err(&dev->dev,
                        "Failed to register framebuffer device: %d\n", ret);
-               goto failed_free_irq;
+               goto failed_free_cmap;
        }
 
 #ifdef CONFIG_CPU_FREQ
@@ -1763,18 +1772,23 @@ static int __init pxafb_probe(struct platform_device *dev)
 
        return 0;
 
+failed_free_cmap:
+       if (fbi->fb.cmap.len)
+               fb_dealloc_cmap(&fbi->fb.cmap);
 failed_free_irq:
        free_irq(irq, fbi);
-failed_free_res:
-       release_mem_region(r->start, r->end - r->start + 1);
-failed_free_io:
-       iounmap(fbi->mmio_base);
 failed_free_mem:
        dma_free_writecombine(&dev->dev, fbi->map_size,
                        fbi->map_cpu, fbi->map_dma);
-failed:
+failed_free_io:
+       iounmap(fbi->mmio_base);
+failed_free_res:
+       release_mem_region(r->start, r->end - r->start + 1);
+failed_fbi:
+       clk_put(fbi->clk);
        platform_set_drvdata(dev, NULL);
        kfree(fbi);
+failed:
        return ret;
 }
 
@@ -1787,7 +1801,7 @@ static struct platform_driver pxafb_driver = {
        },
 };
 
-static int __devinit pxafb_init(void)
+static int __init pxafb_init(void)
 {
        if (pxafb_setup_options())
                return -EINVAL;
index 30469bf906e54b51a6688918624fd030ab6f25cf..d0674f1e3f10820e95a8e9db42160fe871908498 100644 (file)
@@ -1003,6 +1003,7 @@ static struct w100_pll_info xtal_14318000[] = {
 static struct w100_pll_info xtal_16000000[] = {
        /*freq     M   N_int    N_fac  tfgoal  lock_time */
        { 72,      1,   8,       0,     0xe0,        48}, /* tfgoal guessed */
+       { 80,      1,   9,       0,     0xe0,        13}, /* tfgoal guessed */
        { 95,      1,   10,      7,     0xe0,        38}, /* tfgoal guessed */
        { 96,      1,   11,      0,     0xe0,        36}, /* tfgoal guessed */
        {  0,      0,   0,       0,        0,         0},
index 0f86b0ff78796517838399d956e90577924f56e5..9678b3e98c635014bebc845d79552aadaacbc596 100644 (file)
@@ -117,7 +117,7 @@ int xenbus_watch_pathfmt(struct xenbus_device *dev,
        char *path;
 
        va_start(ap, pathfmt);
-       path = kvasprintf(GFP_KERNEL, pathfmt, ap);
+       path = kvasprintf(GFP_NOIO | __GFP_HIGH, pathfmt, ap);
        va_end(ap);
 
        if (!path) {
index 227d53b12a5cc05490687f6e9f3c9e5725b147f2..7f2f91c0e11dc0c8e5a343c6400ec664faadd824 100644 (file)
@@ -283,9 +283,9 @@ static char *join(const char *dir, const char *name)
        char *buffer;
 
        if (strlen(name) == 0)
-               buffer = kasprintf(GFP_KERNEL, "%s", dir);
+               buffer = kasprintf(GFP_NOIO | __GFP_HIGH, "%s", dir);
        else
-               buffer = kasprintf(GFP_KERNEL, "%s/%s", dir, name);
+               buffer = kasprintf(GFP_NOIO | __GFP_HIGH, "%s/%s", dir, name);
        return (!buffer) ? ERR_PTR(-ENOMEM) : buffer;
 }
 
@@ -297,7 +297,7 @@ static char **split(char *strings, unsigned int len, unsigned int *num)
        *num = count_strings(strings, len);
 
        /* Transfer to one big alloc for easy freeing. */
-       ret = kmalloc(*num * sizeof(char *) + len, GFP_KERNEL);
+       ret = kmalloc(*num * sizeof(char *) + len, GFP_NOIO | __GFP_HIGH);
        if (!ret) {
                kfree(strings);
                return ERR_PTR(-ENOMEM);
@@ -751,7 +751,7 @@ static int process_msg(void)
        }
 
 
-       msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+       msg = kmalloc(sizeof(*msg), GFP_NOIO | __GFP_HIGH);
        if (msg == NULL) {
                err = -ENOMEM;
                goto out;
@@ -763,7 +763,7 @@ static int process_msg(void)
                goto out;
        }
 
-       body = kmalloc(msg->hdr.len + 1, GFP_KERNEL);
+       body = kmalloc(msg->hdr.len + 1, GFP_NOIO | __GFP_HIGH);
        if (body == NULL) {
                kfree(msg);
                err = -ENOMEM;
index fd01d90cada545edcdcac367b17da4add13b08f1..57997fa14e69d4260fc5b9a990e030355a321963 100644 (file)
@@ -51,4 +51,4 @@ int v9fs_dir_release(struct inode *inode, struct file *filp);
 int v9fs_file_open(struct inode *inode, struct file *file);
 void v9fs_inode2stat(struct inode *inode, struct p9_stat *stat);
 void v9fs_dentry_release(struct dentry *);
-int v9fs_uflags2omode(int uflags);
+int v9fs_uflags2omode(int uflags, int extended);
index 0d55affe37d4452124471365797ffb472e1ebe52..52944d2249a49a1e05c7fdc05d63919180dc3a29 100644 (file)
@@ -59,7 +59,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 
        P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p \n", inode, file);
        v9ses = v9fs_inode2v9ses(inode);
-       omode = v9fs_uflags2omode(file->f_flags);
+       omode = v9fs_uflags2omode(file->f_flags, v9fs_extended(v9ses));
        fid = file->private_data;
        if (!fid) {
                fid = v9fs_fid_clone(file->f_path.dentry);
@@ -75,6 +75,8 @@ int v9fs_file_open(struct inode *inode, struct file *file)
                        inode->i_size = 0;
                        inode->i_blocks = 0;
                }
+               if ((file->f_flags & O_APPEND) && (!v9fs_extended(v9ses)))
+                       generic_file_llseek(file, 0, SEEK_END);
        }
 
        file->private_data = fid;
index 40fa807bd92928793ff2c66eb82024ea274e4899..c95295c65045a3540959b0ddb9c227e1366472f3 100644 (file)
@@ -132,10 +132,10 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
 /**
  * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits
  * @uflags: flags to convert
- *
+ * @extended: if .u extensions are active
  */
 
-int v9fs_uflags2omode(int uflags)
+int v9fs_uflags2omode(int uflags, int extended)
 {
        int ret;
 
@@ -155,14 +155,16 @@ int v9fs_uflags2omode(int uflags)
                break;
        }
 
-       if (uflags & O_EXCL)
-               ret |= P9_OEXCL;
-
        if (uflags & O_TRUNC)
                ret |= P9_OTRUNC;
 
-       if (uflags & O_APPEND)
-               ret |= P9_OAPPEND;
+       if (extended) {
+               if (uflags & O_EXCL)
+                       ret |= P9_OEXCL;
+
+               if (uflags & O_APPEND)
+                       ret |= P9_OAPPEND;
+       }
 
        return ret;
 }
@@ -506,7 +508,7 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
                flags = O_RDWR;
 
        fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
-                                               v9fs_uflags2omode(flags));
+                               v9fs_uflags2omode(flags, v9fs_extended(v9ses)));
        if (IS_ERR(fid)) {
                err = PTR_ERR(fid);
                fid = NULL;
index cf12c403b8c753b4e8a431ab0c56cb89b5ac588a..2694648cbd1b6e7d235bc6dbb46cffa62482294d 100644 (file)
@@ -830,7 +830,7 @@ config NTFS_FS
          from the project web site.
 
          For more information see <file:Documentation/filesystems/ntfs.txt>
-         and <http://linux-ntfs.sourceforge.net/>.
+         and <http://www.linux-ntfs.org/>.
 
          To compile this file system support as a module, choose M here: the
          module will be called ntfs.
index 1e7a11bd4da116f888a4589925dea958fa6ec5f9..277b079dec9e4751959db2688e69f5d17ed671de 100644 (file)
@@ -19,6 +19,7 @@ else
 obj-y +=       no-block.o
 endif
 
+obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o
 obj-$(CONFIG_INOTIFY)          += inotify.o
 obj-$(CONFIG_INOTIFY_USER)     += inotify_user.o
 obj-$(CONFIG_EPOLL)            += eventpoll.o
diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c
new file mode 100644 (file)
index 0000000..63e2ee6
--- /dev/null
@@ -0,0 +1,719 @@
+/*
+ * bio-integrity.c - bio data integrity extensions
+ *
+ * Copyright (C) 2007, 2008 Oracle Corporation
+ * Written by: Martin K. Petersen <martin.petersen@oracle.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.
+ *
+ * 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/mempool.h>
+#include <linux/bio.h>
+#include <linux/workqueue.h>
+
+static struct kmem_cache *bio_integrity_slab __read_mostly;
+static struct workqueue_struct *kintegrityd_wq;
+
+/**
+ * bio_integrity_alloc_bioset - Allocate integrity payload and attach it to bio
+ * @bio:       bio to attach integrity metadata to
+ * @gfp_mask:  Memory allocation mask
+ * @nr_vecs:   Number of integrity metadata scatter-gather elements
+ * @bs:                bio_set to allocate from
+ *
+ * Description: This function prepares a bio for attaching integrity
+ * metadata.  nr_vecs specifies the maximum number of pages containing
+ * integrity metadata that can be attached.
+ */
+struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *bio,
+                                                        gfp_t gfp_mask,
+                                                        unsigned int nr_vecs,
+                                                        struct bio_set *bs)
+{
+       struct bio_integrity_payload *bip;
+       struct bio_vec *iv;
+       unsigned long idx;
+
+       BUG_ON(bio == NULL);
+
+       bip = mempool_alloc(bs->bio_integrity_pool, gfp_mask);
+       if (unlikely(bip == NULL)) {
+               printk(KERN_ERR "%s: could not alloc bip\n", __func__);
+               return NULL;
+       }
+
+       memset(bip, 0, sizeof(*bip));
+
+       iv = bvec_alloc_bs(gfp_mask, nr_vecs, &idx, bs);
+       if (unlikely(iv == NULL)) {
+               printk(KERN_ERR "%s: could not alloc bip_vec\n", __func__);
+               mempool_free(bip, bs->bio_integrity_pool);
+               return NULL;
+       }
+
+       bip->bip_pool = idx;
+       bip->bip_vec = iv;
+       bip->bip_bio = bio;
+       bio->bi_integrity = bip;
+
+       return bip;
+}
+EXPORT_SYMBOL(bio_integrity_alloc_bioset);
+
+/**
+ * bio_integrity_alloc - Allocate integrity payload and attach it to bio
+ * @bio:       bio to attach integrity metadata to
+ * @gfp_mask:  Memory allocation mask
+ * @nr_vecs:   Number of integrity metadata scatter-gather elements
+ *
+ * Description: This function prepares a bio for attaching integrity
+ * metadata.  nr_vecs specifies the maximum number of pages containing
+ * integrity metadata that can be attached.
+ */
+struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
+                                                 gfp_t gfp_mask,
+                                                 unsigned int nr_vecs)
+{
+       return bio_integrity_alloc_bioset(bio, gfp_mask, nr_vecs, fs_bio_set);
+}
+EXPORT_SYMBOL(bio_integrity_alloc);
+
+/**
+ * bio_integrity_free - Free bio integrity payload
+ * @bio:       bio containing bip to be freed
+ * @bs:                bio_set this bio was allocated from
+ *
+ * Description: Used to free the integrity portion of a bio. Usually
+ * called from bio_free().
+ */
+void bio_integrity_free(struct bio *bio, struct bio_set *bs)
+{
+       struct bio_integrity_payload *bip = bio->bi_integrity;
+
+       BUG_ON(bip == NULL);
+
+       /* A cloned bio doesn't own the integrity metadata */
+       if (!bio_flagged(bio, BIO_CLONED) && bip->bip_buf != NULL)
+               kfree(bip->bip_buf);
+
+       mempool_free(bip->bip_vec, bs->bvec_pools[bip->bip_pool]);
+       mempool_free(bip, bs->bio_integrity_pool);
+
+       bio->bi_integrity = NULL;
+}
+EXPORT_SYMBOL(bio_integrity_free);
+
+/**
+ * bio_integrity_add_page - Attach integrity metadata
+ * @bio:       bio to update
+ * @page:      page containing integrity metadata
+ * @len:       number of bytes of integrity metadata in page
+ * @offset:    start offset within page
+ *
+ * Description: Attach a page containing integrity metadata to bio.
+ */
+int bio_integrity_add_page(struct bio *bio, struct page *page,
+                          unsigned int len, unsigned int offset)
+{
+       struct bio_integrity_payload *bip = bio->bi_integrity;
+       struct bio_vec *iv;
+
+       if (bip->bip_vcnt >= bvec_nr_vecs(bip->bip_pool)) {
+               printk(KERN_ERR "%s: bip_vec full\n", __func__);
+               return 0;
+       }
+
+       iv = bip_vec_idx(bip, bip->bip_vcnt);
+       BUG_ON(iv == NULL);
+       BUG_ON(iv->bv_page != NULL);
+
+       iv->bv_page = page;
+       iv->bv_len = len;
+       iv->bv_offset = offset;
+       bip->bip_vcnt++;
+
+       return len;
+}
+EXPORT_SYMBOL(bio_integrity_add_page);
+
+/**
+ * bio_integrity_enabled - Check whether integrity can be passed
+ * @bio:       bio to check
+ *
+ * Description: Determines whether bio_integrity_prep() can be called
+ * on this bio or not. bio data direction and target device must be
+ * set prior to calling.  The functions honors the write_generate and
+ * read_verify flags in sysfs.
+ */
+int bio_integrity_enabled(struct bio *bio)
+{
+       /* Already protected? */
+       if (bio_integrity(bio))
+               return 0;
+
+       return bdev_integrity_enabled(bio->bi_bdev, bio_data_dir(bio));
+}
+EXPORT_SYMBOL(bio_integrity_enabled);
+
+/**
+ * bio_integrity_hw_sectors - Convert 512b sectors to hardware ditto
+ * @bi:                blk_integrity profile for device
+ * @sectors:   Number of 512 sectors to convert
+ *
+ * Description: The block layer calculates everything in 512 byte
+ * sectors but integrity metadata is done in terms of the hardware
+ * sector size of the storage device.  Convert the block layer sectors
+ * to physical sectors.
+ */
+static inline unsigned int bio_integrity_hw_sectors(struct blk_integrity *bi,
+                                                   unsigned int sectors)
+{
+       /* At this point there are only 512b or 4096b DIF/EPP devices */
+       if (bi->sector_size == 4096)
+               return sectors >>= 3;
+
+       return sectors;
+}
+
+/**
+ * bio_integrity_tag_size - Retrieve integrity tag space
+ * @bio:       bio to inspect
+ *
+ * Description: Returns the maximum number of tag bytes that can be
+ * attached to this bio. Filesystems can use this to determine how
+ * much metadata to attach to an I/O.
+ */
+unsigned int bio_integrity_tag_size(struct bio *bio)
+{
+       struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
+
+       BUG_ON(bio->bi_size == 0);
+
+       return bi->tag_size * (bio->bi_size / bi->sector_size);
+}
+EXPORT_SYMBOL(bio_integrity_tag_size);
+
+int bio_integrity_tag(struct bio *bio, void *tag_buf, unsigned int len, int set)
+{
+       struct bio_integrity_payload *bip = bio->bi_integrity;
+       struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
+       unsigned int nr_sectors;
+
+       BUG_ON(bip->bip_buf == NULL);
+
+       if (bi->tag_size == 0)
+               return -1;
+
+       nr_sectors = bio_integrity_hw_sectors(bi,
+                                       DIV_ROUND_UP(len, bi->tag_size));
+
+       if (nr_sectors * bi->tuple_size > bip->bip_size) {
+               printk(KERN_ERR "%s: tag too big for bio: %u > %u\n",
+                      __func__, nr_sectors * bi->tuple_size, bip->bip_size);
+               return -1;
+       }
+
+       if (set)
+               bi->set_tag_fn(bip->bip_buf, tag_buf, nr_sectors);
+       else
+               bi->get_tag_fn(bip->bip_buf, tag_buf, nr_sectors);
+
+       return 0;
+}
+
+/**
+ * bio_integrity_set_tag - Attach a tag buffer to a bio
+ * @bio:       bio to attach buffer to
+ * @tag_buf:   Pointer to a buffer containing tag data
+ * @len:       Length of the included buffer
+ *
+ * Description: Use this function to tag a bio by leveraging the extra
+ * space provided by devices formatted with integrity protection.  The
+ * size of the integrity buffer must be <= to the size reported by
+ * bio_integrity_tag_size().
+ */
+int bio_integrity_set_tag(struct bio *bio, void *tag_buf, unsigned int len)
+{
+       BUG_ON(bio_data_dir(bio) != WRITE);
+
+       return bio_integrity_tag(bio, tag_buf, len, 1);
+}
+EXPORT_SYMBOL(bio_integrity_set_tag);
+
+/**
+ * bio_integrity_get_tag - Retrieve a tag buffer from a bio
+ * @bio:       bio to retrieve buffer from
+ * @tag_buf:   Pointer to a buffer for the tag data
+ * @len:       Length of the target buffer
+ *
+ * Description: Use this function to retrieve the tag buffer from a
+ * completed I/O. The size of the integrity buffer must be <= to the
+ * size reported by bio_integrity_tag_size().
+ */
+int bio_integrity_get_tag(struct bio *bio, void *tag_buf, unsigned int len)
+{
+       BUG_ON(bio_data_dir(bio) != READ);
+
+       return bio_integrity_tag(bio, tag_buf, len, 0);
+}
+EXPORT_SYMBOL(bio_integrity_get_tag);
+
+/**
+ * bio_integrity_generate - Generate integrity metadata for a bio
+ * @bio:       bio to generate integrity metadata for
+ *
+ * Description: Generates integrity metadata for a bio by calling the
+ * block device's generation callback function.  The bio must have a
+ * bip attached with enough room to accommodate the generated
+ * integrity metadata.
+ */
+static void bio_integrity_generate(struct bio *bio)
+{
+       struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
+       struct blk_integrity_exchg bix;
+       struct bio_vec *bv;
+       sector_t sector = bio->bi_sector;
+       unsigned int i, sectors, total;
+       void *prot_buf = bio->bi_integrity->bip_buf;
+
+       total = 0;
+       bix.disk_name = bio->bi_bdev->bd_disk->disk_name;
+       bix.sector_size = bi->sector_size;
+
+       bio_for_each_segment(bv, bio, i) {
+               void *kaddr = kmap_atomic(bv->bv_page, KM_USER0);
+               bix.data_buf = kaddr + bv->bv_offset;
+               bix.data_size = bv->bv_len;
+               bix.prot_buf = prot_buf;
+               bix.sector = sector;
+
+               bi->generate_fn(&bix);
+
+               sectors = bv->bv_len / bi->sector_size;
+               sector += sectors;
+               prot_buf += sectors * bi->tuple_size;
+               total += sectors * bi->tuple_size;
+               BUG_ON(total > bio->bi_integrity->bip_size);
+
+               kunmap_atomic(kaddr, KM_USER0);
+       }
+}
+
+/**
+ * bio_integrity_prep - Prepare bio for integrity I/O
+ * @bio:       bio to prepare
+ *
+ * Description: Allocates a buffer for integrity metadata, maps the
+ * pages and attaches them to a bio.  The bio must have data
+ * direction, target device and start sector set priot to calling.  In
+ * the WRITE case, integrity metadata will be generated using the
+ * block device's integrity function.  In the READ case, the buffer
+ * will be prepared for DMA and a suitable end_io handler set up.
+ */
+int bio_integrity_prep(struct bio *bio)
+{
+       struct bio_integrity_payload *bip;
+       struct blk_integrity *bi;
+       struct request_queue *q;
+       void *buf;
+       unsigned long start, end;
+       unsigned int len, nr_pages;
+       unsigned int bytes, offset, i;
+       unsigned int sectors;
+
+       bi = bdev_get_integrity(bio->bi_bdev);
+       q = bdev_get_queue(bio->bi_bdev);
+       BUG_ON(bi == NULL);
+       BUG_ON(bio_integrity(bio));
+
+       sectors = bio_integrity_hw_sectors(bi, bio_sectors(bio));
+
+       /* Allocate kernel buffer for protection data */
+       len = sectors * blk_integrity_tuple_size(bi);
+       buf = kmalloc(len, GFP_NOIO | __GFP_NOFAIL | q->bounce_gfp);
+       if (unlikely(buf == NULL)) {
+               printk(KERN_ERR "could not allocate integrity buffer\n");
+               return -EIO;
+       }
+
+       end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       start = ((unsigned long) buf) >> PAGE_SHIFT;
+       nr_pages = end - start;
+
+       /* Allocate bio integrity payload and integrity vectors */
+       bip = bio_integrity_alloc(bio, GFP_NOIO, nr_pages);
+       if (unlikely(bip == NULL)) {
+               printk(KERN_ERR "could not allocate data integrity bioset\n");
+               kfree(buf);
+               return -EIO;
+       }
+
+       bip->bip_buf = buf;
+       bip->bip_size = len;
+       bip->bip_sector = bio->bi_sector;
+
+       /* Map it */
+       offset = offset_in_page(buf);
+       for (i = 0 ; i < nr_pages ; i++) {
+               int ret;
+               bytes = PAGE_SIZE - offset;
+
+               if (len <= 0)
+                       break;
+
+               if (bytes > len)
+                       bytes = len;
+
+               ret = bio_integrity_add_page(bio, virt_to_page(buf),
+                                            bytes, offset);
+
+               if (ret == 0)
+                       return 0;
+
+               if (ret < bytes)
+                       break;
+
+               buf += bytes;
+               len -= bytes;
+               offset = 0;
+       }
+
+       /* Install custom I/O completion handler if read verify is enabled */
+       if (bio_data_dir(bio) == READ) {
+               bip->bip_end_io = bio->bi_end_io;
+               bio->bi_end_io = bio_integrity_endio;
+       }
+
+       /* Auto-generate integrity metadata if this is a write */
+       if (bio_data_dir(bio) == WRITE)
+               bio_integrity_generate(bio);
+
+       return 0;
+}
+EXPORT_SYMBOL(bio_integrity_prep);
+
+/**
+ * bio_integrity_verify - Verify integrity metadata for a bio
+ * @bio:       bio to verify
+ *
+ * Description: This function is called to verify the integrity of a
+ * bio.         The data in the bio io_vec is compared to the integrity
+ * metadata returned by the HBA.
+ */
+static int bio_integrity_verify(struct bio *bio)
+{
+       struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
+       struct blk_integrity_exchg bix;
+       struct bio_vec *bv;
+       sector_t sector = bio->bi_integrity->bip_sector;
+       unsigned int i, sectors, total, ret;
+       void *prot_buf = bio->bi_integrity->bip_buf;
+
+       ret = total = 0;
+       bix.disk_name = bio->bi_bdev->bd_disk->disk_name;
+       bix.sector_size = bi->sector_size;
+
+       bio_for_each_segment(bv, bio, i) {
+               void *kaddr = kmap_atomic(bv->bv_page, KM_USER0);
+               bix.data_buf = kaddr + bv->bv_offset;
+               bix.data_size = bv->bv_len;
+               bix.prot_buf = prot_buf;
+               bix.sector = sector;
+
+               ret = bi->verify_fn(&bix);
+
+               if (ret) {
+                       kunmap_atomic(kaddr, KM_USER0);
+                       break;
+               }
+
+               sectors = bv->bv_len / bi->sector_size;
+               sector += sectors;
+               prot_buf += sectors * bi->tuple_size;
+               total += sectors * bi->tuple_size;
+               BUG_ON(total > bio->bi_integrity->bip_size);
+
+               kunmap_atomic(kaddr, KM_USER0);
+       }
+
+       return ret;
+}
+
+/**
+ * bio_integrity_verify_fn - Integrity I/O completion worker
+ * @work:      Work struct stored in bio to be verified
+ *
+ * Description: This workqueue function is called to complete a READ
+ * request.  The function verifies the transferred integrity metadata
+ * and then calls the original bio end_io function.
+ */
+static void bio_integrity_verify_fn(struct work_struct *work)
+{
+       struct bio_integrity_payload *bip =
+               container_of(work, struct bio_integrity_payload, bip_work);
+       struct bio *bio = bip->bip_bio;
+       int error = bip->bip_error;
+
+       if (bio_integrity_verify(bio)) {
+               clear_bit(BIO_UPTODATE, &bio->bi_flags);
+               error = -EIO;
+       }
+
+       /* Restore original bio completion handler */
+       bio->bi_end_io = bip->bip_end_io;
+
+       if (bio->bi_end_io)
+               bio->bi_end_io(bio, error);
+}
+
+/**
+ * bio_integrity_endio - Integrity I/O completion function
+ * @bio:       Protected bio
+ * @error:     Pointer to errno
+ *
+ * Description: Completion for integrity I/O
+ *
+ * Normally I/O completion is done in interrupt context.  However,
+ * verifying I/O integrity is a time-consuming task which must be run
+ * in process context. This function postpones completion
+ * accordingly.
+ */
+void bio_integrity_endio(struct bio *bio, int error)
+{
+       struct bio_integrity_payload *bip = bio->bi_integrity;
+
+       BUG_ON(bip->bip_bio != bio);
+
+       bip->bip_error = error;
+       INIT_WORK(&bip->bip_work, bio_integrity_verify_fn);
+       queue_work(kintegrityd_wq, &bip->bip_work);
+}
+EXPORT_SYMBOL(bio_integrity_endio);
+
+/**
+ * bio_integrity_mark_head - Advance bip_vec skip bytes
+ * @bip:       Integrity vector to advance
+ * @skip:      Number of bytes to advance it
+ */
+void bio_integrity_mark_head(struct bio_integrity_payload *bip,
+                            unsigned int skip)
+{
+       struct bio_vec *iv;
+       unsigned int i;
+
+       bip_for_each_vec(iv, bip, i) {
+               if (skip == 0) {
+                       bip->bip_idx = i;
+                       return;
+               } else if (skip >= iv->bv_len) {
+                       skip -= iv->bv_len;
+               } else { /* skip < iv->bv_len) */
+                       iv->bv_offset += skip;
+                       iv->bv_len -= skip;
+                       bip->bip_idx = i;
+                       return;
+               }
+       }
+}
+
+/**
+ * bio_integrity_mark_tail - Truncate bip_vec to be len bytes long
+ * @bip:       Integrity vector to truncate
+ * @len:       New length of integrity vector
+ */
+void bio_integrity_mark_tail(struct bio_integrity_payload *bip,
+                            unsigned int len)
+{
+       struct bio_vec *iv;
+       unsigned int i;
+
+       bip_for_each_vec(iv, bip, i) {
+               if (len == 0) {
+                       bip->bip_vcnt = i;
+                       return;
+               } else if (len >= iv->bv_len) {
+                       len -= iv->bv_len;
+               } else { /* len < iv->bv_len) */
+                       iv->bv_len = len;
+                       len = 0;
+               }
+       }
+}
+
+/**
+ * bio_integrity_advance - Advance integrity vector
+ * @bio:       bio whose integrity vector to update
+ * @bytes_done:        number of data bytes that have been completed
+ *
+ * Description: This function calculates how many integrity bytes the
+ * number of completed data bytes correspond to and advances the
+ * integrity vector accordingly.
+ */
+void bio_integrity_advance(struct bio *bio, unsigned int bytes_done)
+{
+       struct bio_integrity_payload *bip = bio->bi_integrity;
+       struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
+       unsigned int nr_sectors;
+
+       BUG_ON(bip == NULL);
+       BUG_ON(bi == NULL);
+
+       nr_sectors = bio_integrity_hw_sectors(bi, bytes_done >> 9);
+       bio_integrity_mark_head(bip, nr_sectors * bi->tuple_size);
+}
+EXPORT_SYMBOL(bio_integrity_advance);
+
+/**
+ * bio_integrity_trim - Trim integrity vector
+ * @bio:       bio whose integrity vector to update
+ * @offset:    offset to first data sector
+ * @sectors:   number of data sectors
+ *
+ * Description: Used to trim the integrity vector in a cloned bio.
+ * The ivec will be advanced corresponding to 'offset' data sectors
+ * and the length will be truncated corresponding to 'len' data
+ * sectors.
+ */
+void bio_integrity_trim(struct bio *bio, unsigned int offset,
+                       unsigned int sectors)
+{
+       struct bio_integrity_payload *bip = bio->bi_integrity;
+       struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
+       unsigned int nr_sectors;
+
+       BUG_ON(bip == NULL);
+       BUG_ON(bi == NULL);
+       BUG_ON(!bio_flagged(bio, BIO_CLONED));
+
+       nr_sectors = bio_integrity_hw_sectors(bi, sectors);
+       bip->bip_sector = bip->bip_sector + offset;
+       bio_integrity_mark_head(bip, offset * bi->tuple_size);
+       bio_integrity_mark_tail(bip, sectors * bi->tuple_size);
+}
+EXPORT_SYMBOL(bio_integrity_trim);
+
+/**
+ * bio_integrity_split - Split integrity metadata
+ * @bio:       Protected bio
+ * @bp:                Resulting bio_pair
+ * @sectors:   Offset
+ *
+ * Description: Splits an integrity page into a bio_pair.
+ */
+void bio_integrity_split(struct bio *bio, struct bio_pair *bp, int sectors)
+{
+       struct blk_integrity *bi;
+       struct bio_integrity_payload *bip = bio->bi_integrity;
+       unsigned int nr_sectors;
+
+       if (bio_integrity(bio) == 0)
+               return;
+
+       bi = bdev_get_integrity(bio->bi_bdev);
+       BUG_ON(bi == NULL);
+       BUG_ON(bip->bip_vcnt != 1);
+
+       nr_sectors = bio_integrity_hw_sectors(bi, sectors);
+
+       bp->bio1.bi_integrity = &bp->bip1;
+       bp->bio2.bi_integrity = &bp->bip2;
+
+       bp->iv1 = bip->bip_vec[0];
+       bp->iv2 = bip->bip_vec[0];
+
+       bp->bip1.bip_vec = &bp->iv1;
+       bp->bip2.bip_vec = &bp->iv2;
+
+       bp->iv1.bv_len = sectors * bi->tuple_size;
+       bp->iv2.bv_offset += sectors * bi->tuple_size;
+       bp->iv2.bv_len -= sectors * bi->tuple_size;
+
+       bp->bip1.bip_sector = bio->bi_integrity->bip_sector;
+       bp->bip2.bip_sector = bio->bi_integrity->bip_sector + nr_sectors;
+
+       bp->bip1.bip_vcnt = bp->bip2.bip_vcnt = 1;
+       bp->bip1.bip_idx = bp->bip2.bip_idx = 0;
+}
+EXPORT_SYMBOL(bio_integrity_split);
+
+/**
+ * bio_integrity_clone - Callback for cloning bios with integrity metadata
+ * @bio:       New bio
+ * @bio_src:   Original bio
+ * @bs:                bio_set to allocate bip from
+ *
+ * Description:        Called to allocate a bip when cloning a bio
+ */
+int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
+                       struct bio_set *bs)
+{
+       struct bio_integrity_payload *bip_src = bio_src->bi_integrity;
+       struct bio_integrity_payload *bip;
+
+       BUG_ON(bip_src == NULL);
+
+       bip = bio_integrity_alloc_bioset(bio, GFP_NOIO, bip_src->bip_vcnt, bs);
+
+       if (bip == NULL)
+               return -EIO;
+
+       memcpy(bip->bip_vec, bip_src->bip_vec,
+              bip_src->bip_vcnt * sizeof(struct bio_vec));
+
+       bip->bip_sector = bip_src->bip_sector;
+       bip->bip_vcnt = bip_src->bip_vcnt;
+       bip->bip_idx = bip_src->bip_idx;
+
+       return 0;
+}
+EXPORT_SYMBOL(bio_integrity_clone);
+
+int bioset_integrity_create(struct bio_set *bs, int pool_size)
+{
+       bs->bio_integrity_pool = mempool_create_slab_pool(pool_size,
+                                                         bio_integrity_slab);
+       if (!bs->bio_integrity_pool)
+               return -1;
+
+       return 0;
+}
+EXPORT_SYMBOL(bioset_integrity_create);
+
+void bioset_integrity_free(struct bio_set *bs)
+{
+       if (bs->bio_integrity_pool)
+               mempool_destroy(bs->bio_integrity_pool);
+}
+EXPORT_SYMBOL(bioset_integrity_free);
+
+void __init bio_integrity_init_slab(void)
+{
+       bio_integrity_slab = KMEM_CACHE(bio_integrity_payload,
+                                       SLAB_HWCACHE_ALIGN|SLAB_PANIC);
+}
+EXPORT_SYMBOL(bio_integrity_init_slab);
+
+static int __init integrity_init(void)
+{
+       kintegrityd_wq = create_workqueue("kintegrityd");
+
+       if (!kintegrityd_wq)
+               panic("Failed to create kintegrityd\n");
+
+       return 0;
+}
+subsys_initcall(integrity_init);
index 78562574cb524d87b06883bce5002542b77b5865..88322b066acb68f8279e79eeca5842c6b02bd8ce 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
 #include <linux/blktrace_api.h>
 #include <scsi/sg.h>           /* for struct sg_iovec */
 
-#define BIO_POOL_SIZE 2
-
 static struct kmem_cache *bio_slab __read_mostly;
 
-#define BIOVEC_NR_POOLS 6
-
-/*
- * a small number of entries is fine, not going to be performance critical.
- * basically we just need to survive
- */
-#define BIO_SPLIT_ENTRIES 2
 mempool_t *bio_split_pool __read_mostly;
 
-struct biovec_slab {
-       int nr_vecs;
-       char *name; 
-       struct kmem_cache *slab;
-};
-
 /*
  * if you change this list, also change bvec_alloc or things will
  * break badly! cannot be bigger than what you can fit into an
@@ -59,24 +44,18 @@ static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = {
 };
 #undef BV
 
-/*
- * bio_set is used to allow other portions of the IO system to
- * allocate their own private memory pools for bio and iovec structures.
- * These memory pools in turn all allocate from the bio_slab
- * and the bvec_slabs[].
- */
-struct bio_set {
-       mempool_t *bio_pool;
-       mempool_t *bvec_pools[BIOVEC_NR_POOLS];
-};
-
 /*
  * fs_bio_set is the bio_set containing bio and iovec memory pools used by
  * IO code that does not need private memory pools.
  */
-static struct bio_set *fs_bio_set;
+struct bio_set *fs_bio_set;
+
+unsigned int bvec_nr_vecs(unsigned short idx)
+{
+       return bvec_slabs[idx].nr_vecs;
+}
 
-static inline struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct bio_set *bs)
+struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct bio_set *bs)
 {
        struct bio_vec *bvl;
 
@@ -117,6 +96,9 @@ void bio_free(struct bio *bio, struct bio_set *bio_set)
                mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]);
        }
 
+       if (bio_integrity(bio))
+               bio_integrity_free(bio, bio_set);
+
        mempool_free(bio, bio_set->bio_pool);
 }
 
@@ -275,9 +257,19 @@ struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
 {
        struct bio *b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, fs_bio_set);
 
-       if (b) {
-               b->bi_destructor = bio_fs_destructor;
-               __bio_clone(b, bio);
+       if (!b)
+               return NULL;
+
+       b->bi_destructor = bio_fs_destructor;
+       __bio_clone(b, bio);
+
+       if (bio_integrity(bio)) {
+               int ret;
+
+               ret = bio_integrity_clone(b, bio, fs_bio_set);
+
+               if (ret < 0)
+                       return NULL;
        }
 
        return b;
@@ -333,10 +325,19 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
                if (page == prev->bv_page &&
                    offset == prev->bv_offset + prev->bv_len) {
                        prev->bv_len += len;
-                       if (q->merge_bvec_fn &&
-                           q->merge_bvec_fn(q, bio, prev) < len) {
-                               prev->bv_len -= len;
-                               return 0;
+
+                       if (q->merge_bvec_fn) {
+                               struct bvec_merge_data bvm = {
+                                       .bi_bdev = bio->bi_bdev,
+                                       .bi_sector = bio->bi_sector,
+                                       .bi_size = bio->bi_size,
+                                       .bi_rw = bio->bi_rw,
+                               };
+
+                               if (q->merge_bvec_fn(q, &bvm, prev) < len) {
+                                       prev->bv_len -= len;
+                                       return 0;
+                               }
                        }
 
                        goto done;
@@ -377,11 +378,18 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page
         * queue to get further control
         */
        if (q->merge_bvec_fn) {
+               struct bvec_merge_data bvm = {
+                       .bi_bdev = bio->bi_bdev,
+                       .bi_sector = bio->bi_sector,
+                       .bi_size = bio->bi_size,
+                       .bi_rw = bio->bi_rw,
+               };
+
                /*
                 * merge_bvec_fn() returns number of bytes it can accept
                 * at this offset
                 */
-               if (q->merge_bvec_fn(q, bio, bvec) < len) {
+               if (q->merge_bvec_fn(q, &bvm, bvec) < len) {
                        bvec->bv_page = NULL;
                        bvec->bv_len = 0;
                        bvec->bv_offset = 0;
@@ -1249,6 +1257,9 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
        bp->bio1.bi_private = bi;
        bp->bio2.bi_private = pool;
 
+       if (bio_integrity(bi))
+               bio_integrity_split(bi, bp, first_sectors);
+
        return bp;
 }
 
@@ -1290,6 +1301,7 @@ void bioset_free(struct bio_set *bs)
        if (bs->bio_pool)
                mempool_destroy(bs->bio_pool);
 
+       bioset_integrity_free(bs);
        biovec_free_pools(bs);
 
        kfree(bs);
@@ -1306,6 +1318,9 @@ struct bio_set *bioset_create(int bio_pool_size, int bvec_pool_size)
        if (!bs->bio_pool)
                goto bad;
 
+       if (bioset_integrity_create(bs, bio_pool_size))
+               goto bad;
+
        if (!biovec_create_pools(bs, bvec_pool_size))
                return bs;
 
@@ -1332,6 +1347,7 @@ static int __init init_bio(void)
 {
        bio_slab = KMEM_CACHE(bio, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 
+       bio_integrity_init_slab();
        biovec_init_slabs();
 
        fs_bio_set = bioset_create(BIO_POOL_SIZE, 2);
index 470c10ceb0fb3a33dc8f28e7e8b2d3535042075b..10d8a0aa871a096eb3d8577b01d285aa9c1fa433 100644 (file)
@@ -931,8 +931,16 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part)
        struct gendisk *disk;
        int ret;
        int part;
+       int perm = 0;
 
-       ret = devcgroup_inode_permission(bdev->bd_inode, file->f_mode);
+       if (file->f_mode & FMODE_READ)
+               perm |= MAY_READ;
+       if (file->f_mode & FMODE_WRITE)
+               perm |= MAY_WRITE;
+       /*
+        * hooks: /n/, see "layering violations".
+        */
+       ret = devcgroup_inode_permission(bdev->bd_inode, perm);
        if (ret != 0)
                return ret;
 
index a073f3f4f013c5c349afede7edb715672bfd4928..0f51c0f7c266ee7ebf940d94f869081a4d80b084 100644 (file)
@@ -821,7 +821,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
                                 * contents - it is a noop if I/O is still in
                                 * flight on potentially older contents.
                                 */
-                               ll_rw_block(SWRITE, 1, &bh);
+                               ll_rw_block(SWRITE_SYNC, 1, &bh);
                                brelse(bh);
                                spin_lock(lock);
                        }
@@ -2940,16 +2940,19 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
        for (i = 0; i < nr; i++) {
                struct buffer_head *bh = bhs[i];
 
-               if (rw == SWRITE)
+               if (rw == SWRITE || rw == SWRITE_SYNC)
                        lock_buffer(bh);
                else if (test_set_buffer_locked(bh))
                        continue;
 
-               if (rw == WRITE || rw == SWRITE) {
+               if (rw == WRITE || rw == SWRITE || rw == SWRITE_SYNC) {
                        if (test_clear_buffer_dirty(bh)) {
                                bh->b_end_io = end_buffer_write_sync;
                                get_bh(bh);
-                               submit_bh(WRITE, bh);
+                               if (rw == SWRITE_SYNC)
+                                       submit_bh(WRITE_SYNC, bh);
+                               else
+                                       submit_bh(WRITE, bh);
                                continue;
                        }
                } else {
@@ -2978,7 +2981,7 @@ int sync_dirty_buffer(struct buffer_head *bh)
        if (test_clear_buffer_dirty(bh)) {
                get_bh(bh);
                bh->b_end_io = end_buffer_write_sync;
-               ret = submit_bh(WRITE, bh);
+               ret = submit_bh(WRITE_SYNC, bh);
                wait_on_buffer(bh);
                if (buffer_eopnotsupp(bh)) {
                        clear_buffer_eopnotsupp(bh);
index 34902cff540059988efa9e014b76cc63a8b10d15..0e9fc2ba90ee23998c33e1125b6186c8f8150ac5 100644 (file)
 static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
        {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
        {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
-       {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"},
-       {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
-       {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(544), 0, 0, 0} }, "root"},
-       {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(545), 0, 0, 0} }, "users"},
-       {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"} }
+       {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"},
+       {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
+       {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(544), 0, 0, 0} }, "root"},
+       {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(545), 0, 0, 0} }, "users"},
+       {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(546), 0, 0, 0} }, "guest"} }
 ;
 
 
index 722be543ceec1ec9f4f086d149247b12d6ac3b7a..2e904bd111c8f5996045302fe66bfe99c5753bf9 100644 (file)
@@ -219,15 +219,15 @@ int cifs_get_inode_info_unix(struct inode **pinode,
        rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data,
                                  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
-       if (rc) {
-               if (rc == -EREMOTE && !is_dfs_referral) {
-                       is_dfs_referral = true;
-                       cFYI(DBG2, ("DFS ref"));
-                       /* for DFS, server does not give us real inode data */
-                       fill_fake_finddataunix(&find_data, sb);
-                       rc = 0;
-               }
-       }
+       if (rc == -EREMOTE && !is_dfs_referral) {
+               is_dfs_referral = true;
+               cFYI(DBG2, ("DFS ref"));
+               /* for DFS, server does not give us real inode data */
+               fill_fake_finddataunix(&find_data, sb);
+               rc = 0;
+       } else if (rc)
+               goto cgiiu_exit;
+
        num_of_bytes = le64_to_cpu(find_data.NumOfBytes);
        end_of_file = le64_to_cpu(find_data.EndOfFile);
 
@@ -236,7 +236,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                *pinode = new_inode(sb);
                if (*pinode == NULL) {
                        rc = -ENOMEM;
-               goto cgiiu_exit;
+                       goto cgiiu_exit;
                }
                /* Is an i_ino of zero legal? */
                /* note ino incremented to unique num in new_inode */
index 3ee588d5f585b54d7aa50358648521b64423b3f8..6068c25b393ca21f5faf8c9ca1fdf8d6051fc836 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/syscalls.h>
 #include <linux/string.h>
 #include <linux/mm.h>
+#include <linux/fdtable.h>
 #include <linux/fs.h>
 #include <linux/fsnotify.h>
 #include <linux/slab.h>
@@ -106,9 +107,10 @@ static void dentry_lru_remove(struct dentry *dentry)
 /*
  * Release the dentry's inode, using the filesystem
  * d_iput() operation if defined.
- * Called with dcache_lock and per dentry lock held, drops both.
  */
 static void dentry_iput(struct dentry * dentry)
+       __releases(dentry->d_lock)
+       __releases(dcache_lock)
 {
        struct inode *inode = dentry->d_inode;
        if (inode) {
@@ -132,12 +134,13 @@ static void dentry_iput(struct dentry * dentry)
  * d_kill - kill dentry and return parent
  * @dentry: dentry to kill
  *
- * Called with dcache_lock and d_lock, releases both.  The dentry must
- * already be unhashed and removed from the LRU.
+ * The dentry must already be unhashed and removed from the LRU.
  *
  * If this is the root of the dentry tree, return NULL.
  */
 static struct dentry *d_kill(struct dentry *dentry)
+       __releases(dentry->d_lock)
+       __releases(dcache_lock)
 {
        struct dentry *parent;
 
@@ -383,11 +386,11 @@ restart:
  * Try to prune ancestors as well.  This is necessary to prevent
  * quadratic behavior of shrink_dcache_parent(), but is also expected
  * to be beneficial in reducing dentry cache fragmentation.
- *
- * Called with dcache_lock, drops it and then regains.
- * Called with dentry->d_lock held, drops it.
  */
 static void prune_one_dentry(struct dentry * dentry)
+       __releases(dentry->d_lock)
+       __releases(dcache_lock)
+       __acquires(dcache_lock)
 {
        __d_drop(dentry);
        dentry = d_kill(dentry);
@@ -1604,10 +1607,9 @@ static int d_isparent(struct dentry *p1, struct dentry *p2)
  *
  * Note: If ever the locking in lock_rename() changes, then please
  * remember to update this too...
- *
- * On return, dcache_lock will have been unlocked.
  */
 static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias)
+       __releases(dcache_lock)
 {
        struct mutex *m1 = NULL, *m2 = NULL;
        struct dentry *ret;
@@ -1743,11 +1745,9 @@ out_nolock:
 shouldnt_be_hashed:
        spin_unlock(&dcache_lock);
        BUG();
-       goto shouldnt_be_hashed;
 }
 
-static int prepend(char **buffer, int *buflen, const char *str,
-                         int namelen)
+static int prepend(char **buffer, int *buflen, const char *str, int namelen)
 {
        *buflen -= namelen;
        if (*buflen < 0)
@@ -1757,8 +1757,13 @@ static int prepend(char **buffer, int *buflen, const char *str,
        return 0;
 }
 
+static int prepend_name(char **buffer, int *buflen, struct qstr *name)
+{
+       return prepend(buffer, buflen, name->name, name->len);
+}
+
 /**
- * d_path - return the path of a dentry
+ * __d_path - return the path of a dentry
  * @path: the dentry/vfsmount to report
  * @root: root vfsmnt/dentry (may be modified by this function)
  * @buffer: buffer to return value in
@@ -1779,9 +1784,10 @@ char *__d_path(const struct path *path, struct path *root,
 {
        struct dentry *dentry = path->dentry;
        struct vfsmount *vfsmnt = path->mnt;
-       char * end = buffer+buflen;
-       char * retval;
+       char *end = buffer + buflen;
+       char *retval;
 
+       spin_lock(&vfsmount_lock);
        prepend(&end, &buflen, "\0", 1);
        if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
                (prepend(&end, &buflen, " (deleted)", 10) != 0))
@@ -1800,38 +1806,37 @@ char *__d_path(const struct path *path, struct path *root,
                        break;
                if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
                        /* Global root? */
-                       spin_lock(&vfsmount_lock);
                        if (vfsmnt->mnt_parent == vfsmnt) {
-                               spin_unlock(&vfsmount_lock);
                                goto global_root;
                        }
                        dentry = vfsmnt->mnt_mountpoint;
                        vfsmnt = vfsmnt->mnt_parent;
-                       spin_unlock(&vfsmount_lock);
                        continue;
                }
                parent = dentry->d_parent;
                prefetch(parent);
-               if ((prepend(&end, &buflen, dentry->d_name.name,
-                               dentry->d_name.len) != 0) ||
+               if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
                    (prepend(&end, &buflen, "/", 1) != 0))
                        goto Elong;
                retval = end;
                dentry = parent;
        }
 
+out:
+       spin_unlock(&vfsmount_lock);
        return retval;
 
 global_root:
        retval += 1;    /* hit the slash */
-       if (prepend(&retval, &buflen, dentry->d_name.name,
-                   dentry->d_name.len) != 0)
+       if (prepend_name(&retval, &buflen, &dentry->d_name) != 0)
                goto Elong;
        root->mnt = vfsmnt;
        root->dentry = dentry;
-       return retval;
+       goto out;
+
 Elong:
-       return ERR_PTR(-ENAMETOOLONG);
+       retval = ERR_PTR(-ENAMETOOLONG);
+       goto out;
 }
 
 /**
@@ -1845,9 +1850,9 @@ Elong:
  *
  * Returns the buffer or an error code if the path was too long.
  *
- * "buflen" should be positive. Caller holds the dcache_lock.
+ * "buflen" should be positive.
  */
-char *d_path(struct path *path, char *buf, int buflen)
+char *d_path(const struct path *path, char *buf, int buflen)
 {
        char *res;
        struct path root;
@@ -1915,16 +1920,11 @@ char *dentry_path(struct dentry *dentry, char *buf, int buflen)
        retval = end-1;
        *retval = '/';
 
-       for (;;) {
-               struct dentry *parent;
-               if (IS_ROOT(dentry))
-                       break;
+       while (!IS_ROOT(dentry)) {
+               struct dentry *parent = dentry->d_parent;
 
-               parent = dentry->d_parent;
                prefetch(parent);
-
-               if ((prepend(&end, &buflen, dentry->d_name.name,
-                               dentry->d_name.len) != 0) ||
+               if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
                    (prepend(&end, &buflen, "/", 1) != 0))
                        goto Elong;
 
@@ -1975,7 +1975,7 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
        error = -ENOENT;
        /* Has the current directory has been unlinked? */
        spin_lock(&dcache_lock);
-       if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) {
+       if (IS_ROOT(pwd.dentry) || !d_unhashed(pwd.dentry)) {
                unsigned long len;
                struct path tmp = root;
                char * cwd;
index 50c994a249a5d7183d729564227a891fd4fb65a5..09a4522f65e6c26311bd896b515b20faf516a025 100644 (file)
@@ -575,13 +575,11 @@ int ecryptfs_init_ecryptfs_miscdev(void)
        int rc;
 
        atomic_set(&ecryptfs_num_miscdev_opens, 0);
-       mutex_lock(&ecryptfs_daemon_hash_mux);
        rc = misc_register(&ecryptfs_miscdev);
        if (rc)
                printk(KERN_ERR "%s: Failed to register miscellaneous device "
                       "for communications with userspace daemons; rc = [%d]\n",
                       __func__, rc);
-       mutex_unlock(&ecryptfs_daemon_hash_mux);
        return rc;
 }
 
index da94a6f05df3ef6dfd9db450e8f813c513b6a47d..fd9234379e8d2816965ff924ace687160ff0c365 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -610,7 +610,7 @@ int setup_arg_pages(struct linux_binprm *bprm,
        bprm->exec -= stack_shift;
 
        down_write(&mm->mmap_sem);
-       vm_flags = vma->vm_flags;
+       vm_flags = VM_STACK_FLAGS;
 
        /*
         * Adjust stack execute permissions; explicitly enable for
index fe3119a71adacb65172cdc6be3c390f55e234679..2845425077e857c85ac7413a9613786d0dd0ac25 100644 (file)
@@ -2875,8 +2875,10 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
                blk++;
        }
 out:
-       if (len == towrite)
+       if (len == towrite) {
+               mutex_unlock(&inode->i_mutex);
                return err;
+       }
        if (inode->i_size < off+len-towrite) {
                i_size_write(inode, off+len-towrite);
                EXT3_I(inode)->i_disksize = inode->i_size;
index cb96f127c36684eab7ddff36e97a64b3d1be0d2c..02bf2434397981e223d62fbcb4cd73a03667049e 100644 (file)
@@ -3337,8 +3337,10 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
                blk++;
        }
 out:
-       if (len == towrite)
+       if (len == towrite) {
+               mutex_unlock(&inode->i_mutex);
                return err;
+       }
        if (inode->i_size < off+len-towrite) {
                i_size_write(inode, off+len-towrite);
                EXT4_I(inode)->i_disksize = inode->i_size;
index 892d41cb3382842a8c1a4b205f6a67fbd38c888b..baeb71ee1cde7a0c372c134e83bf43ef5b32c098 100644 (file)
@@ -512,6 +512,20 @@ void simple_release_fs(struct vfsmount **mount, int *count)
        mntput(mnt);
 }
 
+/**
+ * simple_read_from_buffer - copy data from the buffer to user space
+ * @to: the user space buffer to read to
+ * @count: the maximum number of bytes to read
+ * @ppos: the current position in the buffer
+ * @from: the buffer to read from
+ * @available: the size of the buffer
+ *
+ * The simple_read_from_buffer() function reads up to @count bytes from the
+ * buffer @from at offset @ppos into the user space address starting at @to.
+ *
+ * On success, the number of bytes read is returned and the offset @ppos is
+ * advanced by this number, or negative value is returned on error.
+ **/
 ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos,
                                const void *from, size_t available)
 {
@@ -528,6 +542,20 @@ ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos,
        return count;
 }
 
+/**
+ * memory_read_from_buffer - copy data from the buffer
+ * @to: the kernel space buffer to read to
+ * @count: the maximum number of bytes to read
+ * @ppos: the current position in the buffer
+ * @from: the buffer to read from
+ * @available: the size of the buffer
+ *
+ * The memory_read_from_buffer() function reads up to @count bytes from the
+ * buffer @from at offset @ppos into the kernel space address starting at @to.
+ *
+ * On success, the number of bytes read is returned and the offset @ppos is
+ * advanced by this number, or negative value is returned on error.
+ **/
 ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
                                const void *from, size_t available)
 {
index 11dbf08651b70861d31530ef73436dc2e3beffc1..dce8c747371c77e618ee387158c37451daf63c97 100644 (file)
@@ -561,9 +561,6 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl)
        /* insert into file's list */
        fl->fl_next = *pos;
        *pos = fl;
-
-       if (fl->fl_ops && fl->fl_ops->fl_insert)
-               fl->fl_ops->fl_insert(fl);
 }
 
 /*
@@ -586,9 +583,6 @@ static void locks_delete_lock(struct file_lock **thisfl_p)
                fl->fl_fasync = NULL;
        }
 
-       if (fl->fl_ops && fl->fl_ops->fl_remove)
-               fl->fl_ops->fl_remove(fl);
-
        if (fl->fl_nspid) {
                put_pid(fl->fl_nspid);
                fl->fl_nspid = NULL;
index c7e43536c49ad06433c5963c446ce936e0f94e9f..01e67dddcc3d2033a2038c37f9f791ba0921a781 100644 (file)
@@ -581,15 +581,13 @@ static __always_inline int link_path_walk(const char *name, struct nameidata *nd
        int result;
 
        /* make sure the stuff we saved doesn't go away */
-       dget(save.dentry);
-       mntget(save.mnt);
+       path_get(&save);
 
        result = __link_path_walk(name, nd);
        if (result == -ESTALE) {
                /* nd->path had been dropped */
                nd->path = save;
-               dget(nd->path.dentry);
-               mntget(nd->path.mnt);
+               path_get(&nd->path);
                nd->flags |= LOOKUP_REVAL;
                result = __link_path_walk(name, nd);
        }
@@ -1216,8 +1214,9 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
        nd->flags = flags;
        nd->depth = 0;
 
-       nd->path.mnt = mntget(mnt);
-       nd->path.dentry = dget(dentry);
+       nd->path.dentry = dentry;
+       nd->path.mnt = mnt;
+       path_get(&nd->path);
 
        retval = path_walk(name, nd);
        if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry &&
@@ -2857,16 +2856,17 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 {
        struct nameidata nd;
        void *cookie;
+       int res;
 
        nd.depth = 0;
        cookie = dentry->d_inode->i_op->follow_link(dentry, &nd);
-       if (!IS_ERR(cookie)) {
-               int res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd));
-               if (dentry->d_inode->i_op->put_link)
-                       dentry->d_inode->i_op->put_link(dentry, &nd, cookie);
-               cookie = ERR_PTR(res);
-       }
-       return PTR_ERR(cookie);
+       if (IS_ERR(cookie))
+               return PTR_ERR(cookie);
+
+       res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd));
+       if (dentry->d_inode->i_op->put_link)
+               dentry->d_inode->i_op->put_link(dentry, &nd, cookie);
+       return res;
 }
 
 int vfs_follow_link(struct nameidata *nd, const char *link)
index 4fc302c2a0e0f886e4026288bcdc50888ddf3551..4f6f7635b59c93c0c2a86a8deff1f59c567de9f5 100644 (file)
@@ -750,7 +750,7 @@ struct proc_fs_info {
        const char *str;
 };
 
-static void show_sb_opts(struct seq_file *m, struct super_block *sb)
+static int show_sb_opts(struct seq_file *m, struct super_block *sb)
 {
        static const struct proc_fs_info fs_info[] = {
                { MS_SYNCHRONOUS, ",sync" },
@@ -764,6 +764,8 @@ static void show_sb_opts(struct seq_file *m, struct super_block *sb)
                if (sb->s_flags & fs_infop->flag)
                        seq_puts(m, fs_infop->str);
        }
+
+       return security_sb_show_options(m, sb);
 }
 
 static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt)
@@ -806,11 +808,14 @@ static int show_vfsmnt(struct seq_file *m, void *v)
        seq_putc(m, ' ');
        show_type(m, mnt->mnt_sb);
        seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw");
-       show_sb_opts(m, mnt->mnt_sb);
+       err = show_sb_opts(m, mnt->mnt_sb);
+       if (err)
+               goto out;
        show_mnt_opts(m, mnt);
        if (mnt->mnt_sb->s_op->show_options)
                err = mnt->mnt_sb->s_op->show_options(m, mnt);
        seq_puts(m, " 0 0\n");
+out:
        return err;
 }
 
@@ -865,10 +870,13 @@ static int show_mountinfo(struct seq_file *m, void *v)
        seq_putc(m, ' ');
        mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
        seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw");
-       show_sb_opts(m, sb);
+       err = show_sb_opts(m, sb);
+       if (err)
+               goto out;
        if (sb->s_op->show_options)
                err = sb->s_op->show_options(m, mnt);
        seq_putc(m, '\n');
+out:
        return err;
 }
 
index 58d43daec0842ad2be1e16ac8e97e38ea38b474f..982a2064fe4cdd3755946ced633b6909e6d58d4e 100644 (file)
@@ -204,7 +204,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
         * Note: assumes we have exclusive access to this mapping either
         *       through inode->i_mutex or some other mechanism.
         */
-       if (page->index == 0 && invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1) < 0) {
+       if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) {
                /* Should never happen */
                nfs_zap_mapping(inode, inode->i_mapping);
        }
index efc015c6128aecc9aae54772dbf71c9a88b39211..44f87caf36834fda999768a06448953afcaa6ef4 100644 (file)
@@ -606,7 +606,9 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm,
 
        res->last_used = 0;
 
+       spin_lock(&dlm->spinlock);
        list_add_tail(&res->tracking, &dlm->tracking_list);
+       spin_unlock(&dlm->spinlock);
 
        memset(res->lvb, 0, DLM_LVB_LEN);
        memset(res->refmap, 0, sizeof(res->refmap));
index 394d25a131a54d406b4fd9422639cde7c1d7c320..80e20d9f27808da3b4896706de7c5ed30ca6eff5 100644 (file)
@@ -1554,8 +1554,8 @@ out:
  */
 int ocfs2_file_lock(struct file *file, int ex, int trylock)
 {
-       int ret, level = ex ? LKM_EXMODE : LKM_PRMODE;
-       unsigned int lkm_flags = trylock ? LKM_NOQUEUE : 0;
+       int ret, level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
+       unsigned int lkm_flags = trylock ? DLM_LKF_NOQUEUE : 0;
        unsigned long flags;
        struct ocfs2_file_private *fp = file->private_data;
        struct ocfs2_lock_res *lockres = &fp->fp_flock;
@@ -1582,7 +1582,7 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock)
                 * Get the lock at NLMODE to start - that way we
                 * can cancel the upconvert request if need be.
                 */
-               ret = ocfs2_lock_create(osb, lockres, LKM_NLMODE, 0);
+               ret = ocfs2_lock_create(osb, lockres, DLM_LOCK_NL, 0);
                if (ret < 0) {
                        mlog_errno(ret);
                        goto out;
@@ -1597,7 +1597,7 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock)
        }
 
        lockres->l_action = OCFS2_AST_CONVERT;
-       lkm_flags |= LKM_CONVERT;
+       lkm_flags |= DLM_LKF_CONVERT;
        lockres->l_requested = level;
        lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
 
@@ -1664,7 +1664,7 @@ void ocfs2_file_unlock(struct file *file)
        if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED))
                return;
 
-       if (lockres->l_level == LKM_NLMODE)
+       if (lockres->l_level == DLM_LOCK_NL)
                return;
 
        mlog(0, "Unlock: \"%s\" flags: 0x%lx, level: %d, act: %d\n",
@@ -1678,11 +1678,11 @@ void ocfs2_file_unlock(struct file *file)
        lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);
        lockres->l_blocking = DLM_LOCK_EX;
 
-       gen = ocfs2_prepare_downconvert(lockres, LKM_NLMODE);
+       gen = ocfs2_prepare_downconvert(lockres, DLM_LOCK_NL);
        lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
        spin_unlock_irqrestore(&lockres->l_lock, flags);
 
-       ret = ocfs2_downconvert_lock(osb, lockres, LKM_NLMODE, 0, gen);
+       ret = ocfs2_downconvert_lock(osb, lockres, DLM_LOCK_NL, 0, gen);
        if (ret) {
                mlog_errno(ret);
                return;
index a1450086e92f87e64007351ab673bf6274037e70..a99ad09c3197a1f60e4332f86520183cffa50bbd 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -16,6 +16,7 @@
 #include <linux/namei.h>
 #include <linux/backing-dev.h>
 #include <linux/capability.h>
+#include <linux/securebits.h>
 #include <linux/security.h>
 #include <linux/mount.h>
 #include <linux/vfs.h>
@@ -425,7 +426,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
 {
        struct nameidata nd;
        int old_fsuid, old_fsgid;
-       kernel_cap_t old_cap;
+       kernel_cap_t uninitialized_var(old_cap);  /* !SECURE_NO_SETUID_FIXUP */
        int res;
 
        if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
@@ -433,23 +434,27 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
 
        old_fsuid = current->fsuid;
        old_fsgid = current->fsgid;
-       old_cap = current->cap_effective;
 
        current->fsuid = current->uid;
        current->fsgid = current->gid;
 
-       /*
-        * Clear the capabilities if we switch to a non-root user
-        *
-        * FIXME: There is a race here against sys_capset.  The
-        * capabilities can change yet we will restore the old
-        * value below.  We should hold task_capabilities_lock,
-        * but we cannot because user_path_walk can sleep.
-        */
-       if (current->uid)
-               cap_clear(current->cap_effective);
-       else
-               current->cap_effective = current->cap_permitted;
+       if (!issecure(SECURE_NO_SETUID_FIXUP)) {
+               /*
+                * Clear the capabilities if we switch to a non-root user
+                */
+#ifndef CONFIG_SECURITY_FILE_CAPABILITIES
+               /*
+                * FIXME: There is a race here against sys_capset.  The
+                * capabilities can change yet we will restore the old
+                * value below.  We should hold task_capabilities_lock,
+                * but we cannot because user_path_walk can sleep.
+                */
+#endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */
+               if (current->uid)
+                       old_cap = cap_set_effective(__cap_empty_set);
+               else
+                       old_cap = cap_set_effective(current->cap_permitted);
+       }
 
        res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
        if (res)
@@ -478,7 +483,9 @@ out_path_release:
 out:
        current->fsuid = old_fsuid;
        current->fsgid = old_fsgid;
-       current->cap_effective = old_cap;
+
+       if (!issecure(SECURE_NO_SETUID_FIXUP))
+               cap_set_effective(old_cap);
 
        return res;
 }
index ec228bc9f8824128ea99c5cb24abc743063e00bb..700f4e0d9572170a4de51527bc1698768a848afe 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1003,8 +1003,7 @@ struct file *create_write_pipe(void)
 void free_write_pipe(struct file *f)
 {
        free_pipe_info(f->f_dentry->d_inode);
-       dput(f->f_path.dentry);
-       mntput(f->f_path.mnt);
+       path_put(&f->f_path);
        put_filp(f);
 }
 
@@ -1015,8 +1014,8 @@ struct file *create_read_pipe(struct file *wrf)
                return ERR_PTR(-ENFILE);
 
        /* Grab pipe from the writer */
-       f->f_path.mnt = mntget(wrf->f_path.mnt);
-       f->f_path.dentry = dget(wrf->f_path.dentry);
+       f->f_path = wrf->f_path;
+       path_get(&wrf->f_path);
        f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;
 
        f->f_pos = 0;
@@ -1068,8 +1067,7 @@ int do_pipe(int *fd)
  err_fdr:
        put_unused_fd(fdr);
  err_read_pipe:
-       dput(fr->f_dentry);
-       mntput(fr->f_vfsmnt);
+       path_put(&fr->f_path);
        put_filp(fr);
  err_write_pipe:
        free_write_pipe(fw);
index 3b455371e7ff50981229d98359344ef92a228d0e..58c3e6a8e15e160ec3d6af3aabe6138b666b00b8 100644 (file)
@@ -233,7 +233,7 @@ static int check_mem_permission(struct task_struct *task)
         */
        if (task->parent == current && (task->ptrace & PT_PTRACED) &&
            task_is_stopped_or_traced(task) &&
-           ptrace_may_attach(task))
+           ptrace_may_access(task, PTRACE_MODE_ATTACH))
                return 0;
 
        /*
@@ -251,7 +251,8 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
        task_lock(task);
        if (task->mm != mm)
                goto out;
-       if (task->mm != current->mm && __ptrace_may_attach(task) < 0)
+       if (task->mm != current->mm &&
+           __ptrace_may_access(task, PTRACE_MODE_READ) < 0)
                goto out;
        task_unlock(task);
        return mm;
@@ -518,7 +519,7 @@ static int proc_fd_access_allowed(struct inode *inode)
         */
        task = get_proc_task(inode);
        if (task) {
-               allowed = ptrace_may_attach(task);
+               allowed = ptrace_may_access(task, PTRACE_MODE_READ);
                put_task_struct(task);
        }
        return allowed;
@@ -904,7 +905,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
        if (!task)
                goto out_no_task;
 
-       if (!ptrace_may_attach(task))
+       if (!ptrace_may_access(task, PTRACE_MODE_READ))
                goto out;
 
        ret = -ENOMEM;
index ab8ccc9d14ff6df10abdd715076d870dafb32a85..164bd9f9ede3024188285d071bbc6caa47cb94f8 100644 (file)
@@ -210,7 +210,7 @@ static int show_map(struct seq_file *m, void *v)
        dev_t dev = 0;
        int len;
 
-       if (maps_protect && !ptrace_may_attach(task))
+       if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
                return -EACCES;
 
        if (file) {
@@ -476,10 +476,10 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
                return -ESRCH;
        mm = get_task_mm(task);
        if (mm) {
-               static struct mm_walk clear_refs_walk;
-               memset(&clear_refs_walk, 0, sizeof(clear_refs_walk));
-               clear_refs_walk.pmd_entry = clear_refs_pte_range;
-               clear_refs_walk.mm = mm;
+               struct mm_walk clear_refs_walk = {
+                       .pmd_entry = clear_refs_pte_range,
+                       .mm = mm,
+               };
                down_read(&mm->mmap_sem);
                for (vma = mm->mmap; vma; vma = vma->vm_next) {
                        clear_refs_walk.private = vma;
@@ -602,11 +602,6 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
        return err;
 }
 
-static struct mm_walk pagemap_walk = {
-       .pmd_entry = pagemap_pte_range,
-       .pte_hole = pagemap_pte_hole
-};
-
 /*
  * /proc/pid/pagemap - an array mapping virtual pages to pfns
  *
@@ -641,12 +636,17 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
        struct pagemapread pm;
        int pagecount;
        int ret = -ESRCH;
+       struct mm_walk pagemap_walk;
+       unsigned long src;
+       unsigned long svpfn;
+       unsigned long start_vaddr;
+       unsigned long end_vaddr;
 
        if (!task)
                goto out;
 
        ret = -EACCES;
-       if (!ptrace_may_attach(task))
+       if (!ptrace_may_access(task, PTRACE_MODE_READ))
                goto out_task;
 
        ret = -EINVAL;
@@ -659,11 +659,15 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
        if (!mm)
                goto out_task;
 
-       ret = -ENOMEM;
+
        uaddr = (unsigned long)buf & PAGE_MASK;
        uend = (unsigned long)(buf + count);
        pagecount = (PAGE_ALIGN(uend) - uaddr) / PAGE_SIZE;
-       pages = kmalloc(pagecount * sizeof(struct page *), GFP_KERNEL);
+       ret = 0;
+       if (pagecount == 0)
+               goto out_mm;
+       pages = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL);
+       ret = -ENOMEM;
        if (!pages)
                goto out_mm;
 
@@ -684,33 +688,33 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
        pm.out = (u64 *)buf;
        pm.end = (u64 *)(buf + count);
 
-       if (!ptrace_may_attach(task)) {
-               ret = -EIO;
-       } else {
-               unsigned long src = *ppos;
-               unsigned long svpfn = src / PM_ENTRY_BYTES;
-               unsigned long start_vaddr = svpfn << PAGE_SHIFT;
-               unsigned long end_vaddr = TASK_SIZE_OF(task);
-
-               /* watch out for wraparound */
-               if (svpfn > TASK_SIZE_OF(task) >> PAGE_SHIFT)
-                       start_vaddr = end_vaddr;
-
-               /*
-                * The odds are that this will stop walking way
-                * before end_vaddr, because the length of the
-                * user buffer is tracked in "pm", and the walk
-                * will stop when we hit the end of the buffer.
-                */
-               ret = walk_page_range(start_vaddr, end_vaddr,
-                                       &pagemap_walk);
-               if (ret == PM_END_OF_BUFFER)
-                       ret = 0;
-               /* don't need mmap_sem for these, but this looks cleaner */
-               *ppos += (char *)pm.out - buf;
-               if (!ret)
-                       ret = (char *)pm.out - buf;
-       }
+       pagemap_walk.pmd_entry = pagemap_pte_range;
+       pagemap_walk.pte_hole = pagemap_pte_hole;
+       pagemap_walk.mm = mm;
+       pagemap_walk.private = &pm;
+
+       src = *ppos;
+       svpfn = src / PM_ENTRY_BYTES;
+       start_vaddr = svpfn << PAGE_SHIFT;
+       end_vaddr = TASK_SIZE_OF(task);
+
+       /* watch out for wraparound */
+       if (svpfn > TASK_SIZE_OF(task) >> PAGE_SHIFT)
+               start_vaddr = end_vaddr;
+
+       /*
+        * The odds are that this will stop walking way
+        * before end_vaddr, because the length of the
+        * user buffer is tracked in "pm", and the walk
+        * will stop when we hit the end of the buffer.
+        */
+       ret = walk_page_range(start_vaddr, end_vaddr, &pagemap_walk);
+       if (ret == PM_END_OF_BUFFER)
+               ret = 0;
+       /* don't need mmap_sem for these, but this looks cleaner */
+       *ppos += (char *)pm.out - buf;
+       if (!ret)
+               ret = (char *)pm.out - buf;
 
 out_pages:
        for (; pagecount; pagecount--) {
@@ -743,7 +747,7 @@ static int show_numa_map_checked(struct seq_file *m, void *v)
        struct proc_maps_private *priv = m->private;
        struct task_struct *task = priv->task;
 
-       if (maps_protect && !ptrace_may_attach(task))
+       if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
                return -EACCES;
 
        return show_numa_map(m, v);
index 4b4f9cc2f186a72705a2525367b8861b6889a0ad..5d84e7121df819cd0d9eb8b9bd54973edf5b77ed 100644 (file)
@@ -113,7 +113,7 @@ static int show_map(struct seq_file *m, void *_vml)
        struct proc_maps_private *priv = m->private;
        struct task_struct *task = priv->task;
 
-       if (maps_protect && !ptrace_may_attach(task))
+       if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
                return -EACCES;
 
        return nommu_vma_show(m, vml->vma);
index 9590b90243002f084cc4a51e8b1bd25ca0cef8f4..78f613cb9c7638529f9a587c3d65e69f3154841f 100644 (file)
@@ -45,6 +45,7 @@ const struct file_operations ramfs_file_operations = {
        .mmap           = generic_file_mmap,
        .fsync          = simple_sync_file,
        .splice_read    = generic_file_splice_read,
+       .splice_write   = generic_file_splice_write,
        .llseek         = generic_file_llseek,
 };
 
index 0989bc2c2f6921be4d54b57066c6f1e163f9f546..52312ec93ff4ae5c0753cdb37af0991f1f733a4c 100644 (file)
@@ -43,6 +43,7 @@ const struct file_operations ramfs_file_operations = {
        .aio_write              = generic_file_aio_write,
        .fsync                  = simple_sync_file,
        .splice_read            = generic_file_splice_read,
+       .splice_write           = generic_file_splice_write,
        .llseek                 = generic_file_llseek,
 };
 
index 57917932212eb33d68a0f626766c79fb608c442a..192269698a8ac44b3b7c58a327d7fde6d35db375 100644 (file)
@@ -45,6 +45,8 @@ void reiserfs_delete_inode(struct inode *inode)
                        goto out;
                reiserfs_update_inode_transaction(inode);
 
+               reiserfs_discard_prealloc(&th, inode);
+
                err = reiserfs_delete_object(&th, inode);
 
                /* Do quota update inside a transaction for journaled quotas. We must do that
index ed424d708e6987777b4a2085f88d81df651c86a8..1d40f2bd197081284dce1ff34c6d1f828082304f 100644 (file)
@@ -2165,8 +2165,10 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
                blk++;
        }
 out:
-       if (len == towrite)
+       if (len == towrite) {
+               mutex_unlock(&inode->i_mutex);
                return err;
+       }
        if (inode->i_size < off + len - towrite)
                i_size_write(inode, off + len - towrite);
        inode->i_version++;
index aa5f6f60b3055f8a35b59084f0c652cb0e5c2125..399442179d89d5821b4caccc488fb0180e4e35c0 100644 (file)
@@ -379,13 +379,22 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
                                lock_page(page);
 
                        /*
-                        * page was truncated, stop here. if this isn't the
-                        * first page, we'll just complete what we already
-                        * added
+                        * Page was truncated, or invalidated by the
+                        * filesystem.  Redo the find/create, but this time the
+                        * page is kept locked, so there's no chance of another
+                        * race with truncate/invalidate.
                         */
                        if (!page->mapping) {
                                unlock_page(page);
-                               break;
+                               page = find_or_create_page(mapping, index,
+                                               mapping_gfp_mask(mapping));
+
+                               if (!page) {
+                                       error = -ENOMEM;
+                                       break;
+                               }
+                               page_cache_release(pages[page_nr]);
+                               pages[page_nr] = page;
                        }
                        /*
                         * page was already under io and is now done, great
index 7a5f69be6ac2127de968661bd6d5e134712940b3..44cc702f96cc994919170bbee7621c841347b0ea 100644 (file)
@@ -682,38 +682,26 @@ static int udf_vrs(struct super_block *sb, int silent)
 /*
  * Check whether there is an anchor block in the given block
  */
-static int udf_check_anchor_block(struct super_block *sb, sector_t block,
-                                       bool varconv)
+static int udf_check_anchor_block(struct super_block *sb, sector_t block)
 {
-       struct buffer_head *bh = NULL;
-       tag *t;
+       struct buffer_head *bh;
        uint16_t ident;
-       uint32_t location;
 
-       if (varconv) {
-               if (udf_fixed_to_variable(block) >=
-                   sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
-                       return 0;
-               bh = sb_bread(sb, udf_fixed_to_variable(block));
-       }
-       else
-               bh = sb_bread(sb, block);
+       if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) &&
+           udf_fixed_to_variable(block) >=
+           sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits)
+               return 0;
 
+       bh = udf_read_tagged(sb, block, block, &ident);
        if (!bh)
                return 0;
-
-       t = (tag *)bh->b_data;
-       ident = le16_to_cpu(t->tagIdent);
-       location = le32_to_cpu(t->tagLocation);
        brelse(bh);
-       if (ident != TAG_IDENT_AVDP)
-               return 0;
-       return location == block;
+
+       return ident == TAG_IDENT_AVDP;
 }
 
 /* Search for an anchor volume descriptor pointer */
-static sector_t udf_scan_anchors(struct super_block *sb, bool varconv,
-                                       sector_t lastblock)
+static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock)
 {
        sector_t last[6];
        int i;
@@ -739,7 +727,7 @@ static sector_t udf_scan_anchors(struct super_block *sb, bool varconv,
                                sb->s_blocksize_bits)
                        continue;
 
-               if (udf_check_anchor_block(sb, last[i], varconv)) {
+               if (udf_check_anchor_block(sb, last[i])) {
                        sbi->s_anchor[0] = last[i];
                        sbi->s_anchor[1] = last[i] - 256;
                        return last[i];
@@ -748,17 +736,17 @@ static sector_t udf_scan_anchors(struct super_block *sb, bool varconv,
                if (last[i] < 256)
                        continue;
 
-               if (udf_check_anchor_block(sb, last[i] - 256, varconv)) {
+               if (udf_check_anchor_block(sb, last[i] - 256)) {
                        sbi->s_anchor[1] = last[i] - 256;
                        return last[i];
                }
        }
 
-       if (udf_check_anchor_block(sb, sbi->s_session + 256, varconv)) {
+       if (udf_check_anchor_block(sb, sbi->s_session + 256)) {
                sbi->s_anchor[0] = sbi->s_session + 256;
                return last[0];
        }
-       if (udf_check_anchor_block(sb, sbi->s_session + 512, varconv)) {
+       if (udf_check_anchor_block(sb, sbi->s_session + 512)) {
                sbi->s_anchor[0] = sbi->s_session + 512;
                return last[0];
        }
@@ -780,23 +768,24 @@ static void udf_find_anchor(struct super_block *sb)
        int i;
        struct udf_sb_info *sbi = UDF_SB(sb);
 
-       lastblock = udf_scan_anchors(sb, 0, sbi->s_last_block);
+       lastblock = udf_scan_anchors(sb, sbi->s_last_block);
        if (lastblock)
                goto check_anchor;
 
        /* No anchor found? Try VARCONV conversion of block numbers */
+       UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
        /* Firstly, we try to not convert number of the last block */
-       lastblock = udf_scan_anchors(sb, 1,
+       lastblock = udf_scan_anchors(sb,
                                udf_variable_to_fixed(sbi->s_last_block));
-       if (lastblock) {
-               UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
+       if (lastblock)
                goto check_anchor;
-       }
 
        /* Secondly, we try with converted number of the last block */
-       lastblock = udf_scan_anchors(sb, 1, sbi->s_last_block);
-       if (lastblock)
-               UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
+       lastblock = udf_scan_anchors(sb, sbi->s_last_block);
+       if (!lastblock) {
+               /* VARCONV didn't help. Clear it. */
+               UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV);
+       }
 
 check_anchor:
        /*
index af059d5cb485df8289eda123380f4937c0c7b77c..b6b664e7145ec7e0debea47c041b7c3faa9a0aee 100644 (file)
@@ -40,14 +40,9 @@ asmlinkage long sys_utime(char __user *filename, struct utimbuf __user *times)
 
 #endif
 
-static bool nsec_special(long nsec)
-{
-       return nsec == UTIME_OMIT || nsec == UTIME_NOW;
-}
-
 static bool nsec_valid(long nsec)
 {
-       if (nsec_special(nsec))
+       if (nsec == UTIME_OMIT || nsec == UTIME_NOW)
                return true;
 
        return nsec >= 0 && nsec <= 999999999;
@@ -102,7 +97,11 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
        if (error)
                goto dput_and_out;
 
-       /* Don't worry, the checks are done in inode_change_ok() */
+       if (times && times[0].tv_nsec == UTIME_NOW &&
+                    times[1].tv_nsec == UTIME_NOW)
+               times = NULL;
+
+       /* In most cases, the checks are done in inode_change_ok() */
        newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
        if (times) {
                error = -EPERM;
@@ -124,28 +123,34 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
                        newattrs.ia_mtime.tv_nsec = times[1].tv_nsec;
                        newattrs.ia_valid |= ATTR_MTIME_SET;
                }
-       }
 
-       /*
-        * If times is NULL or both times are either UTIME_OMIT or
-        * UTIME_NOW, then need to check permissions, because
-        * inode_change_ok() won't do it.
-        */
-       if (!times || (nsec_special(times[0].tv_nsec) &&
-                      nsec_special(times[1].tv_nsec))) {
+               /*
+                * For the UTIME_OMIT/UTIME_NOW and UTIME_NOW/UTIME_OMIT
+                * cases, we need to make an extra check that is not done by
+                * inode_change_ok().
+                */
+               if (((times[0].tv_nsec == UTIME_NOW &&
+                           times[1].tv_nsec == UTIME_OMIT)
+                    ||
+                    (times[0].tv_nsec == UTIME_OMIT &&
+                           times[1].tv_nsec == UTIME_NOW))
+                   && !is_owner_or_cap(inode))
+                       goto mnt_drop_write_and_out;
+       } else {
+
+               /*
+                * If times is NULL (or both times are UTIME_NOW),
+                * then we need to check permissions, because
+                * inode_change_ok() won't do it.
+                */
                error = -EACCES;
                 if (IS_IMMUTABLE(inode))
                        goto mnt_drop_write_and_out;
 
                if (!is_owner_or_cap(inode)) {
-                       if (f) {
-                               if (!(f->f_mode & FMODE_WRITE))
-                                       goto mnt_drop_write_and_out;
-                       } else {
-                               error = vfs_permission(&nd, MAY_WRITE);
-                               if (error)
-                                       goto mnt_drop_write_and_out;
-                       }
+                       error = permission(inode, MAY_WRITE, NULL);
+                       if (error)
+                               goto mnt_drop_write_and_out;
                }
        }
        mutex_lock(&inode->i_mutex);
@@ -169,14 +174,6 @@ asmlinkage long sys_utimensat(int dfd, char __user *filename, struct timespec __
        if (utimes) {
                if (copy_from_user(&tstimes, utimes, sizeof(tstimes)))
                        return -EFAULT;
-               if ((tstimes[0].tv_nsec == UTIME_OMIT ||
-                    tstimes[0].tv_nsec == UTIME_NOW) &&
-                   tstimes[0].tv_sec != 0)
-                       return -EINVAL;
-               if ((tstimes[1].tv_nsec == UTIME_OMIT ||
-                    tstimes[1].tv_nsec == UTIME_NOW) &&
-                   tstimes[1].tv_sec != 0)
-                       return -EINVAL;
 
                /* Nothing to do, we must not even check the path.  */
                if (tstimes[0].tv_nsec == UTIME_OMIT &&
index afaee301b0ee1fa2e1c491f5bd2109ed277fabf1..ad3d26ddfe3160739908362ab2f2054d0bfb530e 100644 (file)
@@ -2427,13 +2427,20 @@ restart:
        if (iclog->ic_size - iclog->ic_offset < 2*sizeof(xlog_op_header_t)) {
                xlog_state_switch_iclogs(log, iclog, iclog->ic_size);
 
-               /* If I'm the only one writing to this iclog, sync it to disk */
-               if (atomic_read(&iclog->ic_refcnt) == 1) {
+               /*
+                * If I'm the only one writing to this iclog, sync it to disk.
+                * We need to do an atomic compare and decrement here to avoid
+                * racing with concurrent atomic_dec_and_lock() calls in
+                * xlog_state_release_iclog() when there is more than one
+                * reference to the iclog.
+                */
+               if (!atomic_add_unless(&iclog->ic_refcnt, -1, 1)) {
+                       /* we are the only one */
                        spin_unlock(&log->l_icloglock);
-                       if ((error = xlog_state_release_iclog(log, iclog)))
+                       error = xlog_state_release_iclog(log, iclog);
+                       if (error)
                                return error;
                } else {
-                       atomic_dec(&iclog->ic_refcnt);
                        spin_unlock(&log->l_icloglock);
                }
                goto restart;
index b52288774345deaf39d422aaa380c85590b36772..bdca155028ecd343b4ebf0182904dc83f1e61469 100644 (file)
@@ -4,5 +4,6 @@ header-y += sound/
 header-y += mtd/
 header-y += rdma/
 header-y += video/
+header-y += drm/
 
 header-y += asm-$(ARCH)/
index ea3070ff13a528872b55915195c707ae1079f764..ff5b7cf6be4dd8065bffb566065de245a3f4020e 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2004-2006 Atmel Corporation
  *
  * Based on linux/include/asm-arm/setup.h
- *   Copyright (C) 1997-1999 Russel King
+ *   Copyright (C) 1997-1999 Russell King
  *
  * 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
index d3a12a9079f78f672615c3b5a31ed1bb7921e37f..7742ec000cc474d018c6378705395ce9e0b43688 100644 (file)
@@ -87,7 +87,7 @@ do {                                                          \
 } while(0)
 
 #define irqs_disabled() \
-       ({unsigned long flags; local_save_flags(flags); flags; })
+       ({unsigned long flags; local_save_flags(flags); !!flags; })
 
 #define        local_irq_save(flags)                   \
 do {                                           \
index 92a6d91d0c1adb1d6974c0fb863917d77c396ed6..7cd25b8e7c9a4b891fcf00fd60b3985e5d48c59e 100644 (file)
@@ -1,6 +1,6 @@
 header-y  += kvm.h
 
-ifeq ($(wildcard include/asm-$(SRCARCH)/a.out.h),include/asm-$(SRCARCH)/a.out.h)
+ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/a.out.h),)
 unifdef-y += a.out.h
 endif
 unifdef-y += auxvec.h
index 85fd0aa27a8cd3f48a8ee9a9b47646316ddbed15..4ec0a296bdec8413394dbecedbf779bb19bfcf4b 100644 (file)
@@ -2,7 +2,7 @@
 #define _ASM_GENERIC_ATOMIC_H
 /*
  * Copyright (C) 2005 Silicon Graphics, Inc.
- *     Christoph Lameter <clameter@sgi.com>
+ *     Christoph Lameter
  *
  * Allows to provide arch independent atomic definitions without the need to
  * edit all arch specific atomic.h files.
index a798d6299a7927ee22d706e9a46c10f4ed9a73a0..1232be3885b01caa879576f3a9a1fd6dc91c8dbc 100644 (file)
@@ -283,10 +283,10 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
                "       beqz    %0, 2f                                  \n"
                "        subu   %0, %1, %3                              \n"
                "       .set    reorder                                 \n"
-               "1:                                                     \n"
                "       .subsection 2                                   \n"
                "2:     b       1b                                      \n"
                "       .previous                                       \n"
+               "1:                                                     \n"
                "       .set    mips0                                   \n"
                : "=&r" (result), "=&r" (temp), "=m" (v->counter)
                : "Ir" (i), "m" (v->counter)
@@ -664,10 +664,10 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
                "       beqz    %0, 2f                                  \n"
                "        dsubu  %0, %1, %3                              \n"
                "       .set    reorder                                 \n"
-               "1:                                                     \n"
                "       .subsection 2                                   \n"
                "2:     b       1b                                      \n"
                "       .previous                                       \n"
+               "1:                                                     \n"
                "       .set    mips0                                   \n"
                : "=&r" (result), "=&r" (temp), "=m" (v->counter)
                : "Ir" (i), "m" (v->counter)
index dae4eca2417e847fd47a3eb8f2009814f8c07a77..892b7f168eb47df60d0b18cf2d0abb26848ac552 100644 (file)
@@ -204,6 +204,14 @@ typedef struct     psc_i2s {
        u32     psc_i2sudf;
 } psc_i2s_t;
 
+#define PSC_I2SCFG_OFFSET      0x08
+#define PSC_I2SMASK_OFFSET     0x0C
+#define PSC_I2SPCR_OFFSET      0x10
+#define PSC_I2SSTAT_OFFSET     0x14
+#define PSC_I2SEVENT_OFFSET    0x18
+#define PSC_I2SRXTX_OFFSET     0x1C
+#define PSC_I2SUDF_OFFSET      0x20
+
 /* I2S Config Register. */
 #define PSC_I2SCFG_RT_MASK     (3 << 30)
 #define PSC_I2SCFG_RT_FIFO1    (0 << 30)
index 7381916dfcbb298a8e1e6e66628b5b6c5a2de6fa..bca352e033c39ff78c2adf71c6f1038e3620eaaf 100644 (file)
@@ -1,6 +1,5 @@
 include include/asm-generic/Kbuild.asm
 
-header-y += a.out.h
 header-y += auxvec.h
 header-y += ioctls.h
 header-y += mman.h
index 649c6c3b87b38a590be3e820c9ff415dc14f7fab..be32ff02f4a0a6ac174e176a2e87ec3eecc9c23d 100644 (file)
@@ -49,12 +49,6 @@ static inline pte_t huge_pte_wrprotect(pte_t pte)
        return pte_wrprotect(pte);
 }
 
-static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
-                                          unsigned long addr, pte_t *ptep)
-{
-       ptep_set_wrprotect(mm, addr, ptep);
-}
-
 static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
                                             unsigned long addr, pte_t *ptep,
                                             pte_t pte, int dirty)
index cc6a43ba41d0fd5d1bca0df28d4b5e310008cb05..7686569a0bef396dd5828fcc8b194eca96db2036 100644 (file)
@@ -314,6 +314,16 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
        old = pte_update(mm, addr, ptep, _PAGE_RW, 0);
 }
 
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+                                          unsigned long addr, pte_t *ptep)
+{
+       unsigned long old;
+
+       if ((pte_val(*ptep) & _PAGE_RW) == 0)
+               return;
+       old = pte_update(mm, addr, ptep, _PAGE_RW, 1);
+}
+
 /*
  * We currently remove entries from the hashtable regardless of whether
  * the entry was young or dirty. The generic routines only flush if the
index 13c9805349f170deda0308100707ba856390a730..09f312501eb5f82828b3231ecadc06e9356411d0 100644 (file)
@@ -8,6 +8,9 @@ header-y += ucontext.h
 header-y += vtoc.h
 header-y += zcrypt.h
 header-y += kvm.h
+header-y += schid.h
+header-y += chsc.h
 
 unifdef-y += cmb.h
 unifdef-y += debug.h
+unifdef-y += chpid.h
index 41d028cb52a4a96843024966d60ed56c7df37d20..1ac80d6b05887815f0fceec4ed6e428c11849d99 100644 (file)
@@ -13,7 +13,7 @@
 
 typedef void (*adapter_int_handler_t)(void *, void *);
 
-void *s390_register_adapter_interrupt(adapter_int_handler_t, void *);
-void s390_unregister_adapter_interrupt(void *);
+void *s390_register_adapter_interrupt(adapter_int_handler_t, void *, u8);
+void s390_unregister_adapter_interrupt(void *, u8);
 
 #endif /* _ASM_S390_AIRQ_H */
index 066aa70518ce0b0c94e4d0380abd9940c520c02f..ba007d8df9411867260f9b75591219ed8872da0d 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
+#include <asm/fcx.h>
 
 /* structs from asm/cio.h */
 struct irb;
@@ -157,6 +158,17 @@ extern int ccw_device_start_timeout_key(struct ccw_device *, struct ccw1 *,
 extern int ccw_device_resume(struct ccw_device *);
 extern int ccw_device_halt(struct ccw_device *, unsigned long);
 extern int ccw_device_clear(struct ccw_device *, unsigned long);
+int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw,
+                           unsigned long intparm, u8 lpm, u8 key);
+int ccw_device_tm_start_key(struct ccw_device *, struct tcw *,
+                           unsigned long, u8, u8);
+int ccw_device_tm_start_timeout_key(struct ccw_device *, struct tcw *,
+                           unsigned long, u8, u8, int);
+int ccw_device_tm_start(struct ccw_device *, struct tcw *,
+                           unsigned long, u8);
+int ccw_device_tm_start_timeout(struct ccw_device *, struct tcw *,
+                           unsigned long, u8, int);
+int ccw_device_tm_intrg(struct ccw_device *cdev);
 
 extern int ccw_device_set_online(struct ccw_device *cdev);
 extern int ccw_device_set_offline(struct ccw_device *cdev);
index b203336fd892596b7422a8506bb822044574dda7..606844d0a5c34c84af18863a204c21d4e157e4d3 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <linux/string.h>
 #include <asm/types.h>
-#include <asm/cio.h>
 
 #define __MAX_CHPID 255
 
@@ -41,6 +40,9 @@ static inline void chp_id_next(struct chp_id *chpid)
        }
 }
 
+#ifdef __KERNEL__
+#include <asm/cio.h>
+
 static inline int chp_id_is_valid(struct chp_id *chpid)
 {
        return (chpid->cssid <= __MAX_CSSID);
@@ -49,5 +51,6 @@ static inline int chp_id_is_valid(struct chp_id *chpid)
 
 #define chp_id_for_each(c) \
        for (chp_id_init(c); chp_id_is_valid(c); chp_id_next(c))
+#endif /* __KERNEL */
 
 #endif /* _ASM_S390_CHPID_H */
diff --git a/include/asm-s390/chsc.h b/include/asm-s390/chsc.h
new file mode 100644 (file)
index 0000000..d38d0cf
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * ioctl interface for /dev/chsc
+ *
+ * Copyright 2008 IBM Corp.
+ * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
+ */
+
+#ifndef _ASM_CHSC_H
+#define _ASM_CHSC_H
+
+#include <asm/chpid.h>
+#include <asm/schid.h>
+
+struct chsc_async_header {
+       __u16 length;
+       __u16 code;
+       __u32 cmd_dependend;
+       __u32 key : 4;
+       __u32 : 28;
+       struct subchannel_id sid;
+} __attribute__ ((packed));
+
+struct chsc_async_area {
+       struct chsc_async_header header;
+       __u8 data[PAGE_SIZE - 16 /* size of chsc_async_header */];
+} __attribute__ ((packed));
+
+
+struct chsc_response_struct {
+       __u16 length;
+       __u16 code;
+       __u32 parms;
+       __u8 data[PAGE_SIZE - 8];
+} __attribute__ ((packed));
+
+struct chsc_chp_cd {
+       struct chp_id chpid;
+       int m;
+       int fmt;
+       struct chsc_response_struct cpcb;
+};
+
+struct chsc_cu_cd {
+       __u16 cun;
+       __u8 cssid;
+       int m;
+       int fmt;
+       struct chsc_response_struct cucb;
+};
+
+struct chsc_sch_cud {
+       struct subchannel_id schid;
+       int fmt;
+       struct chsc_response_struct scub;
+};
+
+struct conf_id {
+       int m;
+       __u8 cssid;
+       __u8 ssid;
+};
+
+struct chsc_conf_info {
+       struct conf_id id;
+       int fmt;
+       struct chsc_response_struct scid;
+};
+
+struct ccl_parm_chpid {
+       int m;
+       struct chp_id chp;
+};
+
+struct ccl_parm_cssids {
+       __u8 f_cssid;
+       __u8 l_cssid;
+};
+
+struct chsc_comp_list {
+       struct {
+               enum {
+                       CCL_CU_ON_CHP = 1,
+                       CCL_CHP_TYPE_CAP = 2,
+                       CCL_CSS_IMG = 4,
+                       CCL_CSS_IMG_CONF_CHAR = 5,
+                       CCL_IOP_CHP = 6,
+               } ctype;
+               int fmt;
+               struct ccl_parm_chpid chpid;
+               struct ccl_parm_cssids cssids;
+       } req;
+       struct chsc_response_struct sccl;
+};
+
+struct chsc_dcal {
+       struct {
+               enum {
+                       DCAL_CSS_IID_PN = 4,
+               } atype;
+               __u32 list_parm[2];
+               int fmt;
+       } req;
+       struct chsc_response_struct sdcal;
+};
+
+struct chsc_cpd_info {
+       struct chp_id chpid;
+       int m;
+       int fmt;
+       int rfmt;
+       int c;
+       struct chsc_response_struct chpdb;
+};
+
+#define CHSC_IOCTL_MAGIC 'c'
+
+#define CHSC_START _IOWR(CHSC_IOCTL_MAGIC, 0x81, struct chsc_async_area)
+#define CHSC_INFO_CHANNEL_PATH _IOWR(CHSC_IOCTL_MAGIC, 0x82, \
+                                   struct chsc_chp_cd)
+#define CHSC_INFO_CU _IOWR(CHSC_IOCTL_MAGIC, 0x83, struct chsc_cu_cd)
+#define CHSC_INFO_SCH_CU _IOWR(CHSC_IOCTL_MAGIC, 0x84, struct chsc_sch_cud)
+#define CHSC_INFO_CI _IOWR(CHSC_IOCTL_MAGIC, 0x85, struct chsc_conf_info)
+#define CHSC_INFO_CCL _IOWR(CHSC_IOCTL_MAGIC, 0x86, struct chsc_comp_list)
+#define CHSC_INFO_CPD _IOWR(CHSC_IOCTL_MAGIC, 0x87, struct chsc_cpd_info)
+#define CHSC_INFO_DCAL _IOWR(CHSC_IOCTL_MAGIC, 0x88, struct chsc_dcal)
+
+#endif
index 0818ecd30ca6d1b84536ac16ae87fc0f9fee6bcb..6dccb071aec3df5158f84b4b4d1afce3ce5cd354 100644 (file)
@@ -16,7 +16,7 @@
 #define __MAX_CSSID 0
 
 /**
- * struct scsw - subchannel status word
+ * struct cmd_scsw - command-mode subchannel status word
  * @key: subchannel key
  * @sctl: suspend control
  * @eswf: esw format
@@ -38,7 +38,7 @@
  * @cstat: subchannel status
  * @count: residual count
  */
-struct scsw {
+struct cmd_scsw {
        __u32 key  : 4;
        __u32 sctl : 1;
        __u32 eswf : 1;
@@ -61,6 +61,114 @@ struct scsw {
        __u32 count : 16;
 } __attribute__ ((packed));
 
+/**
+ * struct tm_scsw - transport-mode subchannel status word
+ * @key: subchannel key
+ * @eswf: esw format
+ * @cc: deferred condition code
+ * @fmt: format
+ * @x: IRB-format control
+ * @q: interrogate-complete
+ * @ectl: extended control
+ * @pno: path not operational
+ * @fctl: function control
+ * @actl: activity control
+ * @stctl: status control
+ * @tcw: TCW address
+ * @dstat: device status
+ * @cstat: subchannel status
+ * @fcxs: FCX status
+ * @schxs: subchannel-extended status
+ */
+struct tm_scsw {
+       u32 key:4;
+       u32 :1;
+       u32 eswf:1;
+       u32 cc:2;
+       u32 fmt:3;
+       u32 x:1;
+       u32 q:1;
+       u32 :1;
+       u32 ectl:1;
+       u32 pno:1;
+       u32 :1;
+       u32 fctl:3;
+       u32 actl:7;
+       u32 stctl:5;
+       u32 tcw;
+       u32 dstat:8;
+       u32 cstat:8;
+       u32 fcxs:8;
+       u32 schxs:8;
+} __attribute__ ((packed));
+
+/**
+ * union scsw - subchannel status word
+ * @cmd: command-mode SCSW
+ * @tm: transport-mode SCSW
+ */
+union scsw {
+       struct cmd_scsw cmd;
+       struct tm_scsw tm;
+} __attribute__ ((packed));
+
+int scsw_is_tm(union scsw *scsw);
+u32 scsw_key(union scsw *scsw);
+u32 scsw_eswf(union scsw *scsw);
+u32 scsw_cc(union scsw *scsw);
+u32 scsw_ectl(union scsw *scsw);
+u32 scsw_pno(union scsw *scsw);
+u32 scsw_fctl(union scsw *scsw);
+u32 scsw_actl(union scsw *scsw);
+u32 scsw_stctl(union scsw *scsw);
+u32 scsw_dstat(union scsw *scsw);
+u32 scsw_cstat(union scsw *scsw);
+int scsw_is_solicited(union scsw *scsw);
+int scsw_is_valid_key(union scsw *scsw);
+int scsw_is_valid_eswf(union scsw *scsw);
+int scsw_is_valid_cc(union scsw *scsw);
+int scsw_is_valid_ectl(union scsw *scsw);
+int scsw_is_valid_pno(union scsw *scsw);
+int scsw_is_valid_fctl(union scsw *scsw);
+int scsw_is_valid_actl(union scsw *scsw);
+int scsw_is_valid_stctl(union scsw *scsw);
+int scsw_is_valid_dstat(union scsw *scsw);
+int scsw_is_valid_cstat(union scsw *scsw);
+int scsw_cmd_is_valid_key(union scsw *scsw);
+int scsw_cmd_is_valid_sctl(union scsw *scsw);
+int scsw_cmd_is_valid_eswf(union scsw *scsw);
+int scsw_cmd_is_valid_cc(union scsw *scsw);
+int scsw_cmd_is_valid_fmt(union scsw *scsw);
+int scsw_cmd_is_valid_pfch(union scsw *scsw);
+int scsw_cmd_is_valid_isic(union scsw *scsw);
+int scsw_cmd_is_valid_alcc(union scsw *scsw);
+int scsw_cmd_is_valid_ssi(union scsw *scsw);
+int scsw_cmd_is_valid_zcc(union scsw *scsw);
+int scsw_cmd_is_valid_ectl(union scsw *scsw);
+int scsw_cmd_is_valid_pno(union scsw *scsw);
+int scsw_cmd_is_valid_fctl(union scsw *scsw);
+int scsw_cmd_is_valid_actl(union scsw *scsw);
+int scsw_cmd_is_valid_stctl(union scsw *scsw);
+int scsw_cmd_is_valid_dstat(union scsw *scsw);
+int scsw_cmd_is_valid_cstat(union scsw *scsw);
+int scsw_cmd_is_solicited(union scsw *scsw);
+int scsw_tm_is_valid_key(union scsw *scsw);
+int scsw_tm_is_valid_eswf(union scsw *scsw);
+int scsw_tm_is_valid_cc(union scsw *scsw);
+int scsw_tm_is_valid_fmt(union scsw *scsw);
+int scsw_tm_is_valid_x(union scsw *scsw);
+int scsw_tm_is_valid_q(union scsw *scsw);
+int scsw_tm_is_valid_ectl(union scsw *scsw);
+int scsw_tm_is_valid_pno(union scsw *scsw);
+int scsw_tm_is_valid_fctl(union scsw *scsw);
+int scsw_tm_is_valid_actl(union scsw *scsw);
+int scsw_tm_is_valid_stctl(union scsw *scsw);
+int scsw_tm_is_valid_dstat(union scsw *scsw);
+int scsw_tm_is_valid_cstat(union scsw *scsw);
+int scsw_tm_is_valid_fcxs(union scsw *scsw);
+int scsw_tm_is_valid_schxs(union scsw *scsw);
+int scsw_tm_is_solicited(union scsw *scsw);
+
 #define SCSW_FCTL_CLEAR_FUNC    0x1
 #define SCSW_FCTL_HALT_FUNC     0x2
 #define SCSW_FCTL_START_FUNC    0x4
@@ -303,7 +411,7 @@ struct esw3 {
  * if applicable).
  */
 struct irb {
-       struct scsw scsw;
+       union scsw scsw;
        union {
                struct esw0 esw0;
                struct esw1 esw1;
index b3ac262c4582f94738376cfcefff762cd50a26b1..3cad56923815156107862b27e69bb4b2648b5ad8 100644 (file)
 typedef s390_fp_regs elf_fpregset_t;
 typedef s390_regs elf_gregset_t;
 
+typedef s390_fp_regs compat_elf_fpregset_t;
+typedef s390_compat_regs compat_elf_gregset_t;
+
 #include <linux/sched.h>       /* for task_struct */
 #include <asm/system.h>                /* for save_access_regs */
 #include <asm/mmu_context.h>
@@ -123,6 +126,10 @@ typedef s390_regs elf_gregset_t;
 #define elf_check_arch(x) \
        (((x)->e_machine == EM_S390 || (x)->e_machine == EM_S390_OLD) \
          && (x)->e_ident[EI_CLASS] == ELF_CLASS) 
+#define compat_elf_check_arch(x) \
+       (((x)->e_machine == EM_S390 || (x)->e_machine == EM_S390_OLD) \
+        && (x)->e_ident[EI_CLASS] == ELF_CLASS)
+#define compat_start_thread    start_thread31
 
 /* For SVR4/S390 the function pointer to be registered with `atexit` is
    passed in R14. */
@@ -131,6 +138,7 @@ typedef s390_regs elf_gregset_t;
                _r->gprs[14] = 0; \
        } while (0)
 
+#define CORE_DUMP_USE_REGSET
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE      4096
 
@@ -140,44 +148,6 @@ typedef s390_regs elf_gregset_t;
    that it will "exec", and that there is sufficient room for the brk.  */
 #define ELF_ET_DYN_BASE                (STACK_TOP / 3 * 2)
 
-/* Wow, the "main" arch needs arch dependent functions too.. :) */
-
-/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
-   now struct_user_regs, they are different) */
-
-static inline int dump_regs(struct pt_regs *ptregs, elf_gregset_t *regs)
-{
-       memcpy(&regs->psw, &ptregs->psw, sizeof(regs->psw)+sizeof(regs->gprs));
-       save_access_regs(regs->acrs);
-       regs->orig_gpr2 = ptregs->orig_gpr2;
-       return 1;
-}
-
-#define ELF_CORE_COPY_REGS(pr_reg, regs) dump_regs(regs, &pr_reg);
-
-static inline int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
-{
-       struct pt_regs *ptregs = task_pt_regs(tsk);
-       memcpy(&regs->psw, &ptregs->psw, sizeof(regs->psw)+sizeof(regs->gprs));
-       memcpy(regs->acrs, tsk->thread.acrs, sizeof(regs->acrs));
-       regs->orig_gpr2 = ptregs->orig_gpr2;
-       return 1;
-}
-
-#define ELF_CORE_COPY_TASK_REGS(tsk, regs) dump_task_regs(tsk, regs)
-
-static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
-{
-       if (tsk == current)
-               save_fp_regs(fpregs);
-       else
-               memcpy(fpregs, &tsk->thread.fp_regs, sizeof(elf_fpregset_t));
-       return 1;
-}
-
-#define ELF_CORE_COPY_FPREGS(tsk, fpregs) dump_task_fpu(tsk, fpregs)
-
-
 /* This yields a mask that user programs can use to figure out what
    instruction set this CPU supports. */
 
@@ -204,7 +174,10 @@ do {                                                       \
                set_personality(PER_SVR4);              \
        else if (current->personality != PER_LINUX32)   \
                set_personality(PER_LINUX);             \
-       clear_thread_flag(TIF_31BIT);                   \
+       if ((ex).e_ident[EI_CLASS] == ELFCLASS32)       \
+               set_thread_flag(TIF_31BIT);             \
+       else                                            \
+               clear_thread_flag(TIF_31BIT);           \
 } while (0)
 #endif /* __s390x__ */
 
index b498f19bb9a70c2db83b2f755c0739cff757110a..80ef58c619709b9d7a576772f64339041a734b06 100644 (file)
@@ -122,7 +122,7 @@ struct etr_aib {
 } __attribute__ ((packed,aligned(8)));
 
 /* ETR interruption parameter */
-struct etr_interruption_parameter {
+struct etr_irq_parm {
        unsigned int _pad0      : 8;
        unsigned int pc0        : 1;    /* port 0 state change */
        unsigned int pc1        : 1;    /* port 1 state change */
@@ -213,7 +213,46 @@ static inline int etr_ptff(void *ptff_block, unsigned int func)
 #define ETR_PTFF_SGS   0x43    /* set gross steering rate */
 
 /* Functions needed by the machine check handler */
-extern void etr_switch_to_local(void);
-extern void etr_sync_check(void);
+void etr_switch_to_local(void);
+void etr_sync_check(void);
+
+/* STP interruption parameter */
+struct stp_irq_parm {
+       unsigned int _pad0      : 14;
+       unsigned int tsc        : 1;    /* Timing status change */
+       unsigned int lac        : 1;    /* Link availability change */
+       unsigned int tcpc       : 1;    /* Time control parameter change */
+       unsigned int _pad2      : 15;
+} __attribute__ ((packed));
+
+#define STP_OP_SYNC    1
+#define STP_OP_CTRL    3
+
+struct stp_sstpi {
+       unsigned int rsvd0;
+       unsigned int rsvd1 : 8;
+       unsigned int stratum : 8;
+       unsigned int vbits : 16;
+       unsigned int leaps : 16;
+       unsigned int tmd : 4;
+       unsigned int ctn : 4;
+       unsigned int rsvd2 : 3;
+       unsigned int c : 1;
+       unsigned int tst : 4;
+       unsigned int tzo : 16;
+       unsigned int dsto : 16;
+       unsigned int ctrl : 16;
+       unsigned int rsvd3 : 16;
+       unsigned int tto;
+       unsigned int rsvd4;
+       unsigned int ctnid[3];
+       unsigned int rsvd5;
+       unsigned int todoff[4];
+       unsigned int rsvd6[48];
+} __attribute__ ((packed));
+
+/* Functions needed by the machine check handler */
+void stp_sync_check(void);
+void stp_island_check(void);
 
 #endif /* __S390_ETR_H */
diff --git a/include/asm-s390/fcx.h b/include/asm-s390/fcx.h
new file mode 100644 (file)
index 0000000..8be1f3a
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ *  Functions for assembling fcx enabled I/O control blocks.
+ *
+ *    Copyright IBM Corp. 2008
+ *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
+ */
+
+#ifndef _ASM_S390_FCX_H
+#define _ASM_S390_FCX_H _ASM_S390_FCX_H
+
+#include <linux/types.h>
+
+#define TCW_FORMAT_DEFAULT             0
+#define TCW_TIDAW_FORMAT_DEFAULT       0
+#define TCW_FLAGS_INPUT_TIDA           1 << (23 - 5)
+#define TCW_FLAGS_TCCB_TIDA            1 << (23 - 6)
+#define TCW_FLAGS_OUTPUT_TIDA          1 << (23 - 7)
+#define TCW_FLAGS_TIDAW_FORMAT(x)      ((x) & 3) << (23 - 9)
+#define TCW_FLAGS_GET_TIDAW_FORMAT(x)  (((x) >> (23 - 9)) & 3)
+
+/**
+ * struct tcw - Transport Control Word (TCW)
+ * @format: TCW format
+ * @flags: TCW flags
+ * @tccbl: Transport-Command-Control-Block Length
+ * @r: Read Operations
+ * @w: Write Operations
+ * @output: Output-Data Address
+ * @input: Input-Data Address
+ * @tsb: Transport-Status-Block Address
+ * @tccb: Transport-Command-Control-Block Address
+ * @output_count: Output Count
+ * @input_count: Input Count
+ * @intrg: Interrogate TCW Address
+ */
+struct tcw {
+       u32 format:2;
+       u32 :6;
+       u32 flags:24;
+       u32 :8;
+       u32 tccbl:6;
+       u32 r:1;
+       u32 w:1;
+       u32 :16;
+       u64 output;
+       u64 input;
+       u64 tsb;
+       u64 tccb;
+       u32 output_count;
+       u32 input_count;
+       u32 :32;
+       u32 :32;
+       u32 :32;
+       u32 intrg;
+} __attribute__ ((packed, aligned(64)));
+
+#define TIDAW_FLAGS_LAST               1 << (7 - 0)
+#define TIDAW_FLAGS_SKIP               1 << (7 - 1)
+#define TIDAW_FLAGS_DATA_INT           1 << (7 - 2)
+#define TIDAW_FLAGS_TTIC               1 << (7 - 3)
+#define TIDAW_FLAGS_INSERT_CBC         1 << (7 - 4)
+
+/**
+ * struct tidaw - Transport-Indirect-Addressing Word (TIDAW)
+ * @flags: TIDAW flags. Can be an arithmetic OR of the following constants:
+ * %TIDAW_FLAGS_LAST, %TIDAW_FLAGS_SKIP, %TIDAW_FLAGS_DATA_INT,
+ * %TIDAW_FLAGS_TTIC, %TIDAW_FLAGS_INSERT_CBC
+ * @count: Count
+ * @addr: Address
+ */
+struct tidaw {
+       u32 flags:8;
+       u32 :24;
+       u32 count;
+       u64 addr;
+} __attribute__ ((packed, aligned(16)));
+
+/**
+ * struct tsa_iostat - I/O-Status Transport-Status Area (IO-Stat TSA)
+ * @dev_time: Device Time
+ * @def_time: Defer Time
+ * @queue_time: Queue Time
+ * @dev_busy_time: Device-Busy Time
+ * @dev_act_time: Device-Active-Only Time
+ * @sense: Sense Data (if present)
+ */
+struct tsa_iostat {
+       u32 dev_time;
+       u32 def_time;
+       u32 queue_time;
+       u32 dev_busy_time;
+       u32 dev_act_time;
+       u8 sense[32];
+} __attribute__ ((packed));
+
+/**
+ * struct tsa_ddpcs - Device-Detected-Program-Check Transport-Status Area (DDPC TSA)
+ * @rc: Reason Code
+ * @rcq: Reason Code Qualifier
+ * @sense: Sense Data (if present)
+ */
+struct tsa_ddpc {
+       u32 :24;
+       u32 rc:8;
+       u8 rcq[16];
+       u8 sense[32];
+} __attribute__ ((packed));
+
+#define TSA_INTRG_FLAGS_CU_STATE_VALID         1 << (7 - 0)
+#define TSA_INTRG_FLAGS_DEV_STATE_VALID                1 << (7 - 1)
+#define TSA_INTRG_FLAGS_OP_STATE_VALID         1 << (7 - 2)
+
+/**
+ * struct tsa_intrg - Interrogate Transport-Status Area (Intrg. TSA)
+ * @format: Format
+ * @flags: Flags. Can be an arithmetic OR of the following constants:
+ * %TSA_INTRG_FLAGS_CU_STATE_VALID, %TSA_INTRG_FLAGS_DEV_STATE_VALID,
+ * %TSA_INTRG_FLAGS_OP_STATE_VALID
+ * @cu_state: Controle-Unit State
+ * @dev_state: Device State
+ * @op_state: Operation State
+ * @sd_info: State-Dependent Information
+ * @dl_id: Device-Level Identifier
+ * @dd_data: Device-Dependent Data
+ */
+struct tsa_intrg {
+       u32 format:8;
+       u32 flags:8;
+       u32 cu_state:8;
+       u32 dev_state:8;
+       u32 op_state:8;
+       u32 :24;
+       u8 sd_info[12];
+       u32 dl_id;
+       u8 dd_data[28];
+} __attribute__ ((packed));
+
+#define TSB_FORMAT_NONE                0
+#define TSB_FORMAT_IOSTAT      1
+#define TSB_FORMAT_DDPC                2
+#define TSB_FORMAT_INTRG       3
+
+#define TSB_FLAGS_DCW_OFFSET_VALID     1 << (7 - 0)
+#define TSB_FLAGS_COUNT_VALID          1 << (7 - 1)
+#define TSB_FLAGS_CACHE_MISS           1 << (7 - 2)
+#define TSB_FLAGS_TIME_VALID           1 << (7 - 3)
+#define TSB_FLAGS_FORMAT(x)            ((x) & 7)
+#define TSB_FORMAT(t)                  ((t)->flags & 7)
+
+/**
+ * struct tsb - Transport-Status Block (TSB)
+ * @length: Length
+ * @flags: Flags. Can be an arithmetic OR of the following constants:
+ * %TSB_FLAGS_DCW_OFFSET_VALID, %TSB_FLAGS_COUNT_VALID, %TSB_FLAGS_CACHE_MISS,
+ * %TSB_FLAGS_TIME_VALID
+ * @dcw_offset: DCW Offset
+ * @count: Count
+ * @tsa: Transport-Status-Area
+ */
+struct tsb {
+       u32 length:8;
+       u32 flags:8;
+       u32 dcw_offset:16;
+       u32 count;
+       u32 :32;
+       union {
+               struct tsa_iostat iostat;
+               struct tsa_ddpc ddpc;
+               struct tsa_intrg intrg;
+       } __attribute__ ((packed)) tsa;
+} __attribute__ ((packed, aligned(8)));
+
+#define DCW_INTRG_FORMAT_DEFAULT       0
+
+#define DCW_INTRG_RC_UNSPECIFIED       0
+#define DCW_INTRG_RC_TIMEOUT           1
+
+#define DCW_INTRG_RCQ_UNSPECIFIED      0
+#define DCW_INTRG_RCQ_PRIMARY          1
+#define DCW_INTRG_RCQ_SECONDARY                2
+
+#define DCW_INTRG_FLAGS_MPM            1 < (7 - 0)
+#define DCW_INTRG_FLAGS_PPR            1 < (7 - 1)
+#define DCW_INTRG_FLAGS_CRIT           1 < (7 - 2)
+
+/**
+ * struct dcw_intrg_data - Interrogate DCW data
+ * @format: Format. Should be %DCW_INTRG_FORMAT_DEFAULT
+ * @rc: Reason Code. Can be one of %DCW_INTRG_RC_UNSPECIFIED,
+ * %DCW_INTRG_RC_TIMEOUT
+ * @rcq: Reason Code Qualifier: Can be one of %DCW_INTRG_RCQ_UNSPECIFIED,
+ * %DCW_INTRG_RCQ_PRIMARY, %DCW_INTRG_RCQ_SECONDARY
+ * @lpm: Logical-Path Mask
+ * @pam: Path-Available Mask
+ * @pim: Path-Installed Mask
+ * @timeout: Timeout
+ * @flags: Flags. Can be an arithmetic OR of %DCW_INTRG_FLAGS_MPM,
+ * %DCW_INTRG_FLAGS_PPR, %DCW_INTRG_FLAGS_CRIT
+ * @time: Time
+ * @prog_id: Program Identifier
+ * @prog_data: Program-Dependent Data
+ */
+struct dcw_intrg_data {
+       u32 format:8;
+       u32 rc:8;
+       u32 rcq:8;
+       u32 lpm:8;
+       u32 pam:8;
+       u32 pim:8;
+       u32 timeout:16;
+       u32 flags:8;
+       u32 :24;
+       u32 :32;
+       u64 time;
+       u64 prog_id;
+       u8  prog_data[0];
+} __attribute__ ((packed));
+
+#define DCW_FLAGS_CC           1 << (7 - 1)
+
+#define DCW_CMD_WRITE          0x01
+#define DCW_CMD_READ           0x02
+#define DCW_CMD_CONTROL                0x03
+#define DCW_CMD_SENSE          0x04
+#define DCW_CMD_SENSE_ID       0xe4
+#define DCW_CMD_INTRG          0x40
+
+/**
+ * struct dcw - Device-Command Word (DCW)
+ * @cmd: Command Code. Can be one of %DCW_CMD_WRITE, %DCW_CMD_READ,
+ * %DCW_CMD_CONTROL, %DCW_CMD_SENSE, %DCW_CMD_SENSE_ID, %DCW_CMD_INTRG
+ * @flags: Flags. Can be an arithmetic OR of %DCW_FLAGS_CC
+ * @cd_count: Control-Data Count
+ * @count: Count
+ * @cd: Control Data
+ */
+struct dcw {
+       u32 cmd:8;
+       u32 flags:8;
+       u32 :8;
+       u32 cd_count:8;
+       u32 count;
+       u8 cd[0];
+} __attribute__ ((packed));
+
+#define TCCB_FORMAT_DEFAULT    0x7f
+#define TCCB_MAX_DCW           30
+#define TCCB_MAX_SIZE          (sizeof(struct tccb_tcah) + \
+                                TCCB_MAX_DCW * sizeof(struct dcw) + \
+                                sizeof(struct tccb_tcat))
+#define TCCB_SAC_DEFAULT       0xf901
+#define TCCB_SAC_INTRG         0xf902
+
+/**
+ * struct tccb_tcah - Transport-Command-Area Header (TCAH)
+ * @format: Format. Should be %TCCB_FORMAT_DEFAULT
+ * @tcal: Transport-Command-Area Length
+ * @sac: Service-Action Code. Can be one of %TCCB_SAC_DEFAULT, %TCCB_SAC_INTRG
+ * @prio: Priority
+ */
+struct tccb_tcah {
+       u32 format:8;
+       u32 :24;
+       u32 :24;
+       u32 tcal:8;
+       u32 sac:16;
+       u32 :8;
+       u32 prio:8;
+       u32 :32;
+} __attribute__ ((packed));
+
+/**
+ * struct tccb_tcat - Transport-Command-Area Trailer (TCAT)
+ * @count: Transport Count
+ */
+struct tccb_tcat {
+       u32 :32;
+       u32 count;
+} __attribute__ ((packed));
+
+/**
+ * struct tccb - (partial) Transport-Command-Control Block (TCCB)
+ * @tcah: TCAH
+ * @tca: Transport-Command Area
+ */
+struct tccb {
+       struct tccb_tcah tcah;
+       u8 tca[0];
+} __attribute__ ((packed, aligned(8)));
+
+struct tcw *tcw_get_intrg(struct tcw *tcw);
+void *tcw_get_data(struct tcw *tcw);
+struct tccb *tcw_get_tccb(struct tcw *tcw);
+struct tsb *tcw_get_tsb(struct tcw *tcw);
+
+void tcw_init(struct tcw *tcw, int r, int w);
+void tcw_finalize(struct tcw *tcw, int num_tidaws);
+
+void tcw_set_intrg(struct tcw *tcw, struct tcw *intrg_tcw);
+void tcw_set_data(struct tcw *tcw, void *data, int use_tidal);
+void tcw_set_tccb(struct tcw *tcw, struct tccb *tccb);
+void tcw_set_tsb(struct tcw *tcw, struct tsb *tsb);
+
+void tccb_init(struct tccb *tccb, size_t tccb_size, u32 sac);
+void tsb_init(struct tsb *tsb);
+struct dcw *tccb_add_dcw(struct tccb *tccb, size_t tccb_size, u8 cmd, u8 flags,
+                        void *cd, u8 cd_count, u32 count);
+struct tidaw *tcw_add_tidaw(struct tcw *tcw, int num_tidaws, u8 flags,
+                           void *addr, u32 count);
+
+#endif /* _ASM_S390_FCX_H */
index c1b2e50392bb095dcba90a0b797133eb4583e2c1..eaca6dff5405f9d9dd6b6b3d8f359c77d2f09890 100644 (file)
@@ -56,15 +56,19 @@ struct ipl_block_fcp {
        u8  scp_data[];
 } __attribute__((packed));
 
+#define DIAG308_VMPARM_SIZE    64
+
 struct ipl_block_ccw {
-       u8  load_param[8];
+       u8  load_parm[8];
        u8  reserved1[84];
        u8  reserved2[2];
        u16 devno;
        u8  vm_flags;
        u8  reserved3[3];
        u32 vm_parm_len;
-       u8  reserved4[80];
+       u8  nss_name[8];
+       u8  vm_parm[DIAG308_VMPARM_SIZE];
+       u8  reserved4[8];
 } __attribute__((packed));
 
 struct ipl_parameter_block {
@@ -73,7 +77,7 @@ struct ipl_parameter_block {
                struct ipl_block_fcp fcp;
                struct ipl_block_ccw ccw;
        } ipl_info;
-} __attribute__((packed));
+} __attribute__((packed,aligned(4096)));
 
 /*
  * IPL validity flags
@@ -86,6 +90,8 @@ extern void do_reipl(void);
 extern void do_halt(void);
 extern void do_poff(void);
 extern void ipl_save_parameters(void);
+extern void ipl_update_parameters(void);
+extern void get_ipl_vmparm(char *);
 
 enum {
        IPL_DEVNO_VALID         = 1,
@@ -147,6 +153,11 @@ enum diag308_flags {
        DIAG308_FLAGS_LP_VALID  = 0x80,
 };
 
+enum diag308_vm_flags {
+       DIAG308_VM_FLAGS_NSS_VALID      = 0x80,
+       DIAG308_VM_FLAGS_VP_VALID       = 0x40,
+};
+
 enum diag308_rc {
        DIAG308_RC_OK   = 1,
 };
diff --git a/include/asm-s390/isc.h b/include/asm-s390/isc.h
new file mode 100644 (file)
index 0000000..34bb891
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _ASM_S390_ISC_H
+#define _ASM_S390_ISC_H
+
+#include <linux/types.h>
+
+/*
+ * I/O interruption subclasses used by drivers.
+ * Please add all used iscs here so that it is possible to distribute
+ * isc usage between drivers.
+ * Reminder: 0 is highest priority, 7 lowest.
+ */
+#define MAX_ISC 7
+
+/* Regular I/O interrupts. */
+#define IO_SCH_ISC 3                   /* regular I/O subchannels */
+#define CONSOLE_ISC 1                  /* console I/O subchannel */
+#define CHSC_SCH_ISC 7                 /* CHSC subchannels */
+/* Adapter interrupts. */
+#define QDIO_AIRQ_ISC IO_SCH_ISC       /* I/O subchannel in qdio mode */
+
+/* Functions for registration of I/O interruption subclasses */
+void isc_register(unsigned int isc);
+void isc_unregister(unsigned int isc);
+
+#endif /* _ASM_S390_ISC_H */
diff --git a/include/asm-s390/itcw.h b/include/asm-s390/itcw.h
new file mode 100644 (file)
index 0000000..a9bc5c3
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  Functions for incremental construction of fcx enabled I/O control blocks.
+ *
+ *    Copyright IBM Corp. 2008
+ *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
+ */
+
+#ifndef _ASM_S390_ITCW_H
+#define _ASM_S390_ITCW_H _ASM_S390_ITCW_H
+
+#include <linux/types.h>
+#include <asm/fcx.h>
+
+#define ITCW_OP_READ   0
+#define ITCW_OP_WRITE  1
+
+struct itcw;
+
+struct tcw *itcw_get_tcw(struct itcw *itcw);
+size_t itcw_calc_size(int intrg, int max_tidaws, int intrg_max_tidaws);
+struct itcw *itcw_init(void *buffer, size_t size, int op, int intrg,
+                      int max_tidaws, int intrg_max_tidaws);
+struct dcw *itcw_add_dcw(struct itcw *itcw, u8 cmd, u8 flags, void *cd,
+                        u8 cd_count, u32 count);
+struct tidaw *itcw_add_tidaw(struct itcw *itcw, u8 flags, void *addr,
+                            u32 count);
+void itcw_set_data(struct itcw *itcw, void *addr, int use_tidal);
+void itcw_finalize(struct itcw *itcw);
+
+#endif /* _ASM_S390_ITCW_H */
index c7f4f8e3e297188310955e325c20717510acc590..0bdb704ae051f2bf1d83371702aa52bb7994d286 100644 (file)
@@ -29,6 +29,7 @@
  * the S390 page table tree.
  */
 #ifndef __ASSEMBLY__
+#include <linux/sched.h>
 #include <linux/mm_types.h>
 #include <asm/bitops.h>
 #include <asm/bug.h>
@@ -223,6 +224,9 @@ extern char empty_zero_page[PAGE_SIZE];
 #define _PAGE_SPECIAL  0x004           /* SW associated with special page */
 #define __HAVE_ARCH_PTE_SPECIAL
 
+/* Set of bits not changed in pte_modify */
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_SPECIAL)
+
 /* Six different types of pages. */
 #define _PAGE_TYPE_EMPTY       0x400
 #define _PAGE_TYPE_NONE                0x401
@@ -681,7 +685,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
  */
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-       pte_val(pte) &= PAGE_MASK;
+       pte_val(pte) &= _PAGE_CHG_MASK;
        pte_val(pte) |= pgprot_val(newprot);
        return pte;
 }
index a00f79dd323b540ae31fe01c0e764f7e012f157c..4af80af2a88f8c84ef5af5e2e94145b7537ff377 100644 (file)
@@ -143,11 +143,19 @@ struct stack_frame {
 /*
  * Do necessary setup to start up a new thread.
  */
-#define start_thread(regs, new_psw, new_stackp) do {            \
+#define start_thread(regs, new_psw, new_stackp) do {           \
        set_fs(USER_DS);                                        \
        regs->psw.mask  = psw_user_bits;                        \
-        regs->psw.addr  = new_psw | PSW_ADDR_AMODE;             \
-        regs->gprs[15]  = new_stackp ;                          \
+       regs->psw.addr  = new_psw | PSW_ADDR_AMODE;             \
+       regs->gprs[15]  = new_stackp;                           \
+} while (0)
+
+#define start_thread31(regs, new_psw, new_stackp) do {         \
+       set_fs(USER_DS);                                        \
+       regs->psw.mask  = psw_user32_bits;                      \
+       regs->psw.addr  = new_psw | PSW_ADDR_AMODE;             \
+       regs->gprs[15]  = new_stackp;                           \
+       crst_table_downgrade(current->mm, 1UL << 31);           \
 } while (0)
 
 /* Forward declaration, a strange C thing */
@@ -328,16 +336,6 @@ extern void (*s390_base_mcck_handler_fn)(void);
 extern void (*s390_base_pgm_handler_fn)(void);
 extern void (*s390_base_ext_handler_fn)(void);
 
-/*
- * CPU idle notifier chain.
- */
-#define S390_CPU_IDLE          0
-#define S390_CPU_NOT_IDLE      1
-
-struct notifier_block;
-int register_idle_notifier(struct notifier_block *nb);
-int unregister_idle_notifier(struct notifier_block *nb);
-
 #define ARCH_LOW_ADDRESS_LIMIT 0x7fffffffUL
 
 #endif
index d7d4e2eb3e6f327b8528387d2f1a3822fc8820c6..af2c9ac28a07945eee89ddc0e7fc2e3d592fd25b 100644 (file)
@@ -215,6 +215,12 @@ typedef struct
         unsigned long addr;
 } __attribute__ ((aligned(8))) psw_t;
 
+typedef struct
+{
+       __u32   mask;
+       __u32   addr;
+} __attribute__ ((aligned(8))) psw_compat_t;
+
 #ifndef __s390x__
 
 #define PSW_MASK_PER           0x40000000UL
@@ -292,6 +298,15 @@ typedef struct
        unsigned long orig_gpr2;
 } s390_regs;
 
+typedef struct
+{
+       psw_compat_t    psw;
+       __u32           gprs[NUM_GPRS];
+       __u32           acrs[NUM_ACRS];
+       __u32           orig_gpr2;
+} s390_compat_regs;
+
+
 #ifdef __KERNEL__
 #include <asm/setup.h>
 #include <asm/page.h>
diff --git a/include/asm-s390/schid.h b/include/asm-s390/schid.h
new file mode 100644 (file)
index 0000000..5017ffa
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef ASM_SCHID_H
+#define ASM_SCHID_H
+
+struct subchannel_id {
+       __u32 cssid : 8;
+       __u32 : 4;
+       __u32 m : 1;
+       __u32 ssid : 2;
+       __u32 one : 1;
+       __u32 sch_no : 16;
+} __attribute__ ((packed, aligned(4)));
+
+
+/* Helper function for sane state of pre-allocated subchannel_id. */
+static inline void
+init_subchannel_id(struct subchannel_id *schid)
+{
+       memset(schid, 0, sizeof(struct subchannel_id));
+       schid->one = 1;
+}
+
+static inline int
+schid_equal(struct subchannel_id *schid1, struct subchannel_id *schid2)
+{
+       return !memcmp(schid1, schid2, sizeof(struct subchannel_id));
+}
+
+#endif /* ASM_SCHID_H */
index b5f2843013a346902741fe2cfa8031ff4f3e8ea7..fed7bee650a06868072ef323723d7e6abe2336d7 100644 (file)
@@ -45,9 +45,9 @@ struct sclp_cpu_info {
 int sclp_get_cpu_info(struct sclp_cpu_info *info);
 int sclp_cpu_configure(u8 cpu);
 int sclp_cpu_deconfigure(u8 cpu);
-void sclp_read_info_early(void);
 void sclp_facilities_detect(void);
-unsigned long long sclp_memory_detect(void);
+unsigned long long sclp_get_rnmax(void);
+unsigned long long sclp_get_rzm(void);
 int sclp_sdias_blk_count(void);
 int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
 int sclp_chp_configure(struct chp_id chpid);
index ba69674012a7bf3b622b51d9c873bd6149bab131..f09ee3f729778dee8be898577303dbe4b988abc7 100644 (file)
@@ -8,14 +8,16 @@
 #ifndef _ASM_S390_SETUP_H
 #define _ASM_S390_SETUP_H
 
-#define COMMAND_LINE_SIZE      896
+#define COMMAND_LINE_SIZE      1024
+
+#define ARCH_COMMAND_LINE_SIZE 896
 
 #ifdef __KERNEL__
 
 #include <asm/types.h>
 
 #define PARMAREA               0x10400
-#define MEMORY_CHUNKS          16      /* max 0x7fff */
+#define MEMORY_CHUNKS          256
 
 #ifndef __ASSEMBLY__
 
 struct mem_chunk {
        unsigned long addr;
        unsigned long size;
-       unsigned long type;
+       int type;
 };
 
 extern struct mem_chunk memory_chunk[];
 extern unsigned long real_memory_size;
 
+void detect_memory_layout(struct mem_chunk chunk[]);
+
 #ifdef CONFIG_S390_SWITCH_AMODE
 extern unsigned int switch_amode;
 #else
@@ -61,7 +65,6 @@ extern unsigned long machine_flags;
 
 #define MACHINE_FLAG_VM                (1UL << 0)
 #define MACHINE_FLAG_IEEE      (1UL << 1)
-#define MACHINE_FLAG_P390      (1UL << 2)
 #define MACHINE_FLAG_CSP       (1UL << 3)
 #define MACHINE_FLAG_MVPG      (1UL << 4)
 #define MACHINE_FLAG_DIAG44    (1UL << 5)
@@ -97,7 +100,6 @@ extern unsigned long machine_flags;
 #define MACHINE_HAS_PFMF       (machine_flags & MACHINE_FLAG_PFMF)
 #endif /* __s390x__ */
 
-#define MACHINE_HAS_SCLP       (!MACHINE_IS_P390)
 #define ZFCPDUMP_HSA_SIZE      (32UL<<20)
 
 /*
index 06dfdab6c0e8412a305c1e2bbfba03354dd30176..545d219e6a2d0d4e5dec734d7dc1d55f2906dd72 100644 (file)
@@ -1,15 +1,15 @@
 #ifndef _ASM_S390_SPARSEMEM_H
 #define _ASM_S390_SPARSEMEM_H
 
-#define SECTION_SIZE_BITS      25
-
 #ifdef CONFIG_64BIT
 
+#define SECTION_SIZE_BITS      28
 #define MAX_PHYSADDR_BITS      42
 #define MAX_PHYSMEM_BITS       42
 
 #else
 
+#define SECTION_SIZE_BITS      25
 #define MAX_PHYSADDR_BITS      31
 #define MAX_PHYSMEM_BITS       31
 
index adb34860a543e42abc6b73ddcaf71b04dbbaf76b..d98d79e35cd6f6d6459110b6a0290e5fe59721d4 100644 (file)
@@ -48,6 +48,18 @@ extern int del_virt_timer(struct vtimer_list *timer);
 extern void init_cpu_vtimer(void);
 extern void vtime_init(void);
 
+#ifdef CONFIG_VIRT_TIMER
+
+extern void vtime_start_cpu_timer(void);
+extern void vtime_stop_cpu_timer(void);
+
+#else
+
+static inline void vtime_start_cpu_timer(void) { }
+static inline void vtime_stop_cpu_timer(void) { }
+
+#endif /* CONFIG_VIRT_TIMER */
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_S390_TIMER_H */
index f228f1b86877feabca366cb1db8a8dec1930b6d6..00d3bbd44117fe2093abe6dfca8ec6d6bb3e93cf 100644 (file)
@@ -29,7 +29,7 @@
 
 #define ZCRYPT_VERSION 2
 #define ZCRYPT_RELEASE 1
-#define ZCRYPT_VARIANT 0
+#define ZCRYPT_VARIANT 1
 
 #include <linux/ioctl.h>
 #include <linux/compiler.h>
index 268a012bcd795e7540d831ca4a37381057235fcc..28bddbcb38be7e3d27cd73fc0a725aef68a26ad0 100644 (file)
@@ -192,8 +192,8 @@ static inline void native_set_ldt(const void *addr, unsigned int entries)
                unsigned cpu = smp_processor_id();
                ldt_desc ldt;
 
-               set_tssldt_descriptor(&ldt, (unsigned long)addr,
-                                     DESC_LDT, entries * sizeof(ldt) - 1);
+               set_tssldt_descriptor(&ldt, (unsigned long)addr, DESC_LDT,
+                                     entries * LDT_ENTRY_SIZE - 1);
                write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
                                &ldt, DESC_LDT);
                asm volatile("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
index bfd9900742bfe77426bbf50977cec8594c752b0d..76f392146daa46304adfb404874164a7a628010d 100644 (file)
@@ -71,7 +71,8 @@ static inline long kvm_hypercall0(unsigned int nr)
        long ret;
        asm volatile(KVM_HYPERCALL
                     : "=a"(ret)
-                    : "a"(nr));
+                    : "a"(nr)
+                    : "memory");
        return ret;
 }
 
@@ -80,7 +81,8 @@ static inline long kvm_hypercall1(unsigned int nr, unsigned long p1)
        long ret;
        asm volatile(KVM_HYPERCALL
                     : "=a"(ret)
-                    : "a"(nr), "b"(p1));
+                    : "a"(nr), "b"(p1)
+                    : "memory");
        return ret;
 }
 
@@ -90,7 +92,8 @@ static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
        long ret;
        asm volatile(KVM_HYPERCALL
                     : "=a"(ret)
-                    : "a"(nr), "b"(p1), "c"(p2));
+                    : "a"(nr), "b"(p1), "c"(p2)
+                    : "memory");
        return ret;
 }
 
@@ -100,7 +103,8 @@ static inline long kvm_hypercall3(unsigned int nr, unsigned long p1,
        long ret;
        asm volatile(KVM_HYPERCALL
                     : "=a"(ret)
-                    : "a"(nr), "b"(p1), "c"(p2), "d"(p3));
+                    : "a"(nr), "b"(p1), "c"(p2), "d"(p3)
+                    : "memory");
        return ret;
 }
 
@@ -111,7 +115,8 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
        long ret;
        asm volatile(KVM_HYPERCALL
                     : "=a"(ret)
-                    : "a"(nr), "b"(p1), "c"(p2), "d"(p3), "S"(p4));
+                    : "a"(nr), "b"(p1), "c"(p2), "d"(p3), "S"(p4)
+                    : "memory");
        return ret;
 }
 
index 3707650a169b5704a6ffedce7ce3226effc8a7f8..2b5f2c91db25ce8b3879c6673fa2514cee80b8ce 100644 (file)
@@ -18,7 +18,7 @@ static inline unsigned long long native_read_tscp(unsigned int *aux)
        unsigned long low, high;
        asm volatile(".byte 0x0f,0x01,0xf9"
                     : "=a" (low), "=d" (high), "=c" (*aux));
-       return low | ((u64)high >> 32);
+       return low | ((u64)high << 32);
 }
 
 /*
diff --git a/include/drm/Kbuild b/include/drm/Kbuild
new file mode 100644 (file)
index 0000000..82b6983
--- /dev/null
@@ -0,0 +1,10 @@
+unifdef-y += drm.h drm_sarea.h
+unifdef-y += i810_drm.h
+unifdef-y += i830_drm.h
+unifdef-y += i915_drm.h
+unifdef-y += mga_drm.h
+unifdef-y += r128_drm.h
+unifdef-y += radeon_drm.h
+unifdef-y += sis_drm.h
+unifdef-y += savage_drm.h
+unifdef-y += via_drm.h
diff --git a/include/drm/drm.h b/include/drm/drm.h
new file mode 100644 (file)
index 0000000..38d3c6b
--- /dev/null
@@ -0,0 +1,694 @@
+/**
+ * \file drm.h
+ * Header for the Direct Rendering Manager
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ * \par Acknowledgments:
+ * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic \c cmpxchg.
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DRM_H_
+#define _DRM_H_
+
+#if defined(__linux__)
+#if defined(__KERNEL__)
+#endif
+#include <asm/ioctl.h>         /* For _IO* macros */
+#define DRM_IOCTL_NR(n)                _IOC_NR(n)
+#define DRM_IOC_VOID           _IOC_NONE
+#define DRM_IOC_READ           _IOC_READ
+#define DRM_IOC_WRITE          _IOC_WRITE
+#define DRM_IOC_READWRITE      _IOC_READ|_IOC_WRITE
+#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#if defined(__FreeBSD__) && defined(IN_MODULE)
+/* Prevent name collision when including sys/ioccom.h */
+#undef ioctl
+#include <sys/ioccom.h>
+#define ioctl(a,b,c)           xf86ioctl(a,b,c)
+#else
+#include <sys/ioccom.h>
+#endif                         /* __FreeBSD__ && xf86ioctl */
+#define DRM_IOCTL_NR(n)                ((n) & 0xff)
+#define DRM_IOC_VOID           IOC_VOID
+#define DRM_IOC_READ           IOC_OUT
+#define DRM_IOC_WRITE          IOC_IN
+#define DRM_IOC_READWRITE      IOC_INOUT
+#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
+#endif
+
+#define DRM_MAJOR       226
+#define DRM_MAX_MINOR   15
+
+#define DRM_NAME       "drm"     /**< Name in kernel, /dev, and /proc */
+#define DRM_MIN_ORDER  5         /**< At least 2^5 bytes = 32 bytes */
+#define DRM_MAX_ORDER  22        /**< Up to 2^22 bytes = 4MB */
+#define DRM_RAM_PERCENT 10       /**< How much system ram can we lock? */
+
+#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */
+#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */
+#define _DRM_LOCK_IS_HELD(lock)           ((lock) & _DRM_LOCK_HELD)
+#define _DRM_LOCK_IS_CONT(lock)           ((lock) & _DRM_LOCK_CONT)
+#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
+
+typedef unsigned int drm_handle_t;
+typedef unsigned int drm_context_t;
+typedef unsigned int drm_drawable_t;
+typedef unsigned int drm_magic_t;
+
+/**
+ * Cliprect.
+ *
+ * \warning: If you change this structure, make sure you change
+ * XF86DRIClipRectRec in the server as well
+ *
+ * \note KW: Actually it's illegal to change either for
+ * backwards-compatibility reasons.
+ */
+struct drm_clip_rect {
+       unsigned short x1;
+       unsigned short y1;
+       unsigned short x2;
+       unsigned short y2;
+};
+
+/**
+ * Drawable information.
+ */
+struct drm_drawable_info {
+       unsigned int num_rects;
+       struct drm_clip_rect *rects;
+};
+
+/**
+ * Texture region,
+ */
+struct drm_tex_region {
+       unsigned char next;
+       unsigned char prev;
+       unsigned char in_use;
+       unsigned char padding;
+       unsigned int age;
+};
+
+/**
+ * Hardware lock.
+ *
+ * The lock structure is a simple cache-line aligned integer.  To avoid
+ * processor bus contention on a multiprocessor system, there should not be any
+ * other data stored in the same cache line.
+ */
+struct drm_hw_lock {
+       __volatile__ unsigned int lock;         /**< lock variable */
+       char padding[60];                       /**< Pad to cache line */
+};
+
+/**
+ * DRM_IOCTL_VERSION ioctl argument type.
+ *
+ * \sa drmGetVersion().
+ */
+struct drm_version {
+       int version_major;        /**< Major version */
+       int version_minor;        /**< Minor version */
+       int version_patchlevel;   /**< Patch level */
+       size_t name_len;          /**< Length of name buffer */
+       char __user *name;        /**< Name of driver */
+       size_t date_len;          /**< Length of date buffer */
+       char __user *date;        /**< User-space buffer to hold date */
+       size_t desc_len;          /**< Length of desc buffer */
+       char __user *desc;        /**< User-space buffer to hold desc */
+};
+
+/**
+ * DRM_IOCTL_GET_UNIQUE ioctl argument type.
+ *
+ * \sa drmGetBusid() and drmSetBusId().
+ */
+struct drm_unique {
+       size_t unique_len;        /**< Length of unique */
+       char __user *unique;      /**< Unique name for driver instantiation */
+};
+
+struct drm_list {
+       int count;                /**< Length of user-space structures */
+       struct drm_version __user *version;
+};
+
+struct drm_block {
+       int unused;
+};
+
+/**
+ * DRM_IOCTL_CONTROL ioctl argument type.
+ *
+ * \sa drmCtlInstHandler() and drmCtlUninstHandler().
+ */
+struct drm_control {
+       enum {
+               DRM_ADD_COMMAND,
+               DRM_RM_COMMAND,
+               DRM_INST_HANDLER,
+               DRM_UNINST_HANDLER
+       } func;
+       int irq;
+};
+
+/**
+ * Type of memory to map.
+ */
+enum drm_map_type {
+       _DRM_FRAME_BUFFER = 0,    /**< WC (no caching), no core dump */
+       _DRM_REGISTERS = 1,       /**< no caching, no core dump */
+       _DRM_SHM = 2,             /**< shared, cached */
+       _DRM_AGP = 3,             /**< AGP/GART */
+       _DRM_SCATTER_GATHER = 4,  /**< Scatter/gather memory for PCI DMA */
+       _DRM_CONSISTENT = 5,      /**< Consistent memory for PCI DMA */
+};
+
+/**
+ * Memory mapping flags.
+ */
+enum drm_map_flags {
+       _DRM_RESTRICTED = 0x01,      /**< Cannot be mapped to user-virtual */
+       _DRM_READ_ONLY = 0x02,
+       _DRM_LOCKED = 0x04,          /**< shared, cached, locked */
+       _DRM_KERNEL = 0x08,          /**< kernel requires access */
+       _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
+       _DRM_CONTAINS_LOCK = 0x20,   /**< SHM page that contains lock */
+       _DRM_REMOVABLE = 0x40,       /**< Removable mapping */
+       _DRM_DRIVER = 0x80           /**< Managed by driver */
+};
+
+struct drm_ctx_priv_map {
+       unsigned int ctx_id;     /**< Context requesting private mapping */
+       void *handle;            /**< Handle of map */
+};
+
+/**
+ * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
+ * argument type.
+ *
+ * \sa drmAddMap().
+ */
+struct drm_map {
+       unsigned long offset;    /**< Requested physical address (0 for SAREA)*/
+       unsigned long size;      /**< Requested physical size (bytes) */
+       enum drm_map_type type;  /**< Type of memory to map */
+       enum drm_map_flags flags;        /**< Flags */
+       void *handle;            /**< User-space: "Handle" to pass to mmap() */
+                                /**< Kernel-space: kernel-virtual address */
+       int mtrr;                /**< MTRR slot used */
+       /*   Private data */
+};
+
+/**
+ * DRM_IOCTL_GET_CLIENT ioctl argument type.
+ */
+struct drm_client {
+       int idx;                /**< Which client desired? */
+       int auth;               /**< Is client authenticated? */
+       unsigned long pid;      /**< Process ID */
+       unsigned long uid;      /**< User ID */
+       unsigned long magic;    /**< Magic */
+       unsigned long iocs;     /**< Ioctl count */
+};
+
+enum drm_stat_type {
+       _DRM_STAT_LOCK,
+       _DRM_STAT_OPENS,
+       _DRM_STAT_CLOSES,
+       _DRM_STAT_IOCTLS,
+       _DRM_STAT_LOCKS,
+       _DRM_STAT_UNLOCKS,
+       _DRM_STAT_VALUE,        /**< Generic value */
+       _DRM_STAT_BYTE,         /**< Generic byte counter (1024bytes/K) */
+       _DRM_STAT_COUNT,        /**< Generic non-byte counter (1000/k) */
+
+       _DRM_STAT_IRQ,          /**< IRQ */
+       _DRM_STAT_PRIMARY,      /**< Primary DMA bytes */
+       _DRM_STAT_SECONDARY,    /**< Secondary DMA bytes */
+       _DRM_STAT_DMA,          /**< DMA */
+       _DRM_STAT_SPECIAL,      /**< Special DMA (e.g., priority or polled) */
+       _DRM_STAT_MISSED        /**< Missed DMA opportunity */
+           /* Add to the *END* of the list */
+};
+
+/**
+ * DRM_IOCTL_GET_STATS ioctl argument type.
+ */
+struct drm_stats {
+       unsigned long count;
+       struct {
+               unsigned long value;
+               enum drm_stat_type type;
+       } data[15];
+};
+
+/**
+ * Hardware locking flags.
+ */
+enum drm_lock_flags {
+       _DRM_LOCK_READY = 0x01,      /**< Wait until hardware is ready for DMA */
+       _DRM_LOCK_QUIESCENT = 0x02,  /**< Wait until hardware quiescent */
+       _DRM_LOCK_FLUSH = 0x04,      /**< Flush this context's DMA queue first */
+       _DRM_LOCK_FLUSH_ALL = 0x08,  /**< Flush all DMA queues first */
+       /* These *HALT* flags aren't supported yet
+          -- they will be used to support the
+          full-screen DGA-like mode. */
+       _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
+       _DRM_HALT_CUR_QUEUES = 0x20  /**< Halt all current queues */
+};
+
+/**
+ * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
+ *
+ * \sa drmGetLock() and drmUnlock().
+ */
+struct drm_lock {
+       int context;
+       enum drm_lock_flags flags;
+};
+
+/**
+ * DMA flags
+ *
+ * \warning
+ * These values \e must match xf86drm.h.
+ *
+ * \sa drm_dma.
+ */
+enum drm_dma_flags {
+       /* Flags for DMA buffer dispatch */
+       _DRM_DMA_BLOCK = 0x01,        /**<
+                                      * Block until buffer dispatched.
+                                      *
+                                      * \note The buffer may not yet have
+                                      * been processed by the hardware --
+                                      * getting a hardware lock with the
+                                      * hardware quiescent will ensure
+                                      * that the buffer has been
+                                      * processed.
+                                      */
+       _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
+       _DRM_DMA_PRIORITY = 0x04,     /**< High priority dispatch */
+
+       /* Flags for DMA buffer request */
+       _DRM_DMA_WAIT = 0x10,         /**< Wait for free buffers */
+       _DRM_DMA_SMALLER_OK = 0x20,   /**< Smaller-than-requested buffers OK */
+       _DRM_DMA_LARGER_OK = 0x40     /**< Larger-than-requested buffers OK */
+};
+
+/**
+ * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
+ *
+ * \sa drmAddBufs().
+ */
+struct drm_buf_desc {
+       int count;               /**< Number of buffers of this size */
+       int size;                /**< Size in bytes */
+       int low_mark;            /**< Low water mark */
+       int high_mark;           /**< High water mark */
+       enum {
+               _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
+               _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
+               _DRM_SG_BUFFER = 0x04,  /**< Scatter/gather memory buffer */
+               _DRM_FB_BUFFER = 0x08,  /**< Buffer is in frame buffer */
+               _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */
+       } flags;
+       unsigned long agp_start; /**<
+                                 * Start address of where the AGP buffers are
+                                 * in the AGP aperture
+                                 */
+};
+
+/**
+ * DRM_IOCTL_INFO_BUFS ioctl argument type.
+ */
+struct drm_buf_info {
+       int count;              /**< Entries in list */
+       struct drm_buf_desc __user *list;
+};
+
+/**
+ * DRM_IOCTL_FREE_BUFS ioctl argument type.
+ */
+struct drm_buf_free {
+       int count;
+       int __user *list;
+};
+
+/**
+ * Buffer information
+ *
+ * \sa drm_buf_map.
+ */
+struct drm_buf_pub {
+       int idx;                       /**< Index into the master buffer list */
+       int total;                     /**< Buffer size */
+       int used;                      /**< Amount of buffer in use (for DMA) */
+       void __user *address;          /**< Address of buffer */
+};
+
+/**
+ * DRM_IOCTL_MAP_BUFS ioctl argument type.
+ */
+struct drm_buf_map {
+       int count;              /**< Length of the buffer list */
+       void __user *virtual;           /**< Mmap'd area in user-virtual */
+       struct drm_buf_pub __user *list;        /**< Buffer information */
+};
+
+/**
+ * DRM_IOCTL_DMA ioctl argument type.
+ *
+ * Indices here refer to the offset into the buffer list in drm_buf_get.
+ *
+ * \sa drmDMA().
+ */
+struct drm_dma {
+       int context;                      /**< Context handle */
+       int send_count;                   /**< Number of buffers to send */
+       int __user *send_indices;         /**< List of handles to buffers */
+       int __user *send_sizes;           /**< Lengths of data to send */
+       enum drm_dma_flags flags;         /**< Flags */
+       int request_count;                /**< Number of buffers requested */
+       int request_size;                 /**< Desired size for buffers */
+       int __user *request_indices;      /**< Buffer information */
+       int __user *request_sizes;
+       int granted_count;                /**< Number of buffers granted */
+};
+
+enum drm_ctx_flags {
+       _DRM_CONTEXT_PRESERVED = 0x01,
+       _DRM_CONTEXT_2DONLY = 0x02
+};
+
+/**
+ * DRM_IOCTL_ADD_CTX ioctl argument type.
+ *
+ * \sa drmCreateContext() and drmDestroyContext().
+ */
+struct drm_ctx {
+       drm_context_t handle;
+       enum drm_ctx_flags flags;
+};
+
+/**
+ * DRM_IOCTL_RES_CTX ioctl argument type.
+ */
+struct drm_ctx_res {
+       int count;
+       struct drm_ctx __user *contexts;
+};
+
+/**
+ * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
+ */
+struct drm_draw {
+       drm_drawable_t handle;
+};
+
+/**
+ * DRM_IOCTL_UPDATE_DRAW ioctl argument type.
+ */
+typedef enum {
+       DRM_DRAWABLE_CLIPRECTS,
+} drm_drawable_info_type_t;
+
+struct drm_update_draw {
+       drm_drawable_t handle;
+       unsigned int type;
+       unsigned int num;
+       unsigned long long data;
+};
+
+/**
+ * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
+ */
+struct drm_auth {
+       drm_magic_t magic;
+};
+
+/**
+ * DRM_IOCTL_IRQ_BUSID ioctl argument type.
+ *
+ * \sa drmGetInterruptFromBusID().
+ */
+struct drm_irq_busid {
+       int irq;        /**< IRQ number */
+       int busnum;     /**< bus number */
+       int devnum;     /**< device number */
+       int funcnum;    /**< function number */
+};
+
+enum drm_vblank_seq_type {
+       _DRM_VBLANK_ABSOLUTE = 0x0,     /**< Wait for specific vblank sequence number */
+       _DRM_VBLANK_RELATIVE = 0x1,     /**< Wait for given number of vblanks */
+       _DRM_VBLANK_NEXTONMISS = 0x10000000,    /**< If missed, wait for next vblank */
+       _DRM_VBLANK_SECONDARY = 0x20000000,     /**< Secondary display controller */
+       _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
+};
+
+#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
+#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \
+                               _DRM_VBLANK_NEXTONMISS)
+
+struct drm_wait_vblank_request {
+       enum drm_vblank_seq_type type;
+       unsigned int sequence;
+       unsigned long signal;
+};
+
+struct drm_wait_vblank_reply {
+       enum drm_vblank_seq_type type;
+       unsigned int sequence;
+       long tval_sec;
+       long tval_usec;
+};
+
+/**
+ * DRM_IOCTL_WAIT_VBLANK ioctl argument type.
+ *
+ * \sa drmWaitVBlank().
+ */
+union drm_wait_vblank {
+       struct drm_wait_vblank_request request;
+       struct drm_wait_vblank_reply reply;
+};
+
+/**
+ * DRM_IOCTL_AGP_ENABLE ioctl argument type.
+ *
+ * \sa drmAgpEnable().
+ */
+struct drm_agp_mode {
+       unsigned long mode;     /**< AGP mode */
+};
+
+/**
+ * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
+ *
+ * \sa drmAgpAlloc() and drmAgpFree().
+ */
+struct drm_agp_buffer {
+       unsigned long size;     /**< In bytes -- will round to page boundary */
+       unsigned long handle;   /**< Used for binding / unbinding */
+       unsigned long type;     /**< Type of memory to allocate */
+       unsigned long physical; /**< Physical used by i810 */
+};
+
+/**
+ * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
+ *
+ * \sa drmAgpBind() and drmAgpUnbind().
+ */
+struct drm_agp_binding {
+       unsigned long handle;   /**< From drm_agp_buffer */
+       unsigned long offset;   /**< In bytes -- will round to page boundary */
+};
+
+/**
+ * DRM_IOCTL_AGP_INFO ioctl argument type.
+ *
+ * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(),
+ * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
+ * drmAgpVendorId() and drmAgpDeviceId().
+ */
+struct drm_agp_info {
+       int agp_version_major;
+       int agp_version_minor;
+       unsigned long mode;
+       unsigned long aperture_base;    /* physical address */
+       unsigned long aperture_size;    /* bytes */
+       unsigned long memory_allowed;   /* bytes */
+       unsigned long memory_used;
+
+       /* PCI information */
+       unsigned short id_vendor;
+       unsigned short id_device;
+};
+
+/**
+ * DRM_IOCTL_SG_ALLOC ioctl argument type.
+ */
+struct drm_scatter_gather {
+       unsigned long size;     /**< In bytes -- will round to page boundary */
+       unsigned long handle;   /**< Used for mapping / unmapping */
+};
+
+/**
+ * DRM_IOCTL_SET_VERSION ioctl argument type.
+ */
+struct drm_set_version {
+       int drm_di_major;
+       int drm_di_minor;
+       int drm_dd_major;
+       int drm_dd_minor;
+};
+
+#define DRM_IOCTL_BASE                 'd'
+#define DRM_IO(nr)                     _IO(DRM_IOCTL_BASE,nr)
+#define DRM_IOR(nr,type)               _IOR(DRM_IOCTL_BASE,nr,type)
+#define DRM_IOW(nr,type)               _IOW(DRM_IOCTL_BASE,nr,type)
+#define DRM_IOWR(nr,type)              _IOWR(DRM_IOCTL_BASE,nr,type)
+
+#define DRM_IOCTL_VERSION              DRM_IOWR(0x00, struct drm_version)
+#define DRM_IOCTL_GET_UNIQUE           DRM_IOWR(0x01, struct drm_unique)
+#define DRM_IOCTL_GET_MAGIC            DRM_IOR( 0x02, struct drm_auth)
+#define DRM_IOCTL_IRQ_BUSID            DRM_IOWR(0x03, struct drm_irq_busid)
+#define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, struct drm_map)
+#define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
+#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
+#define DRM_IOCTL_SET_VERSION          DRM_IOWR(0x07, struct drm_set_version)
+
+#define DRM_IOCTL_SET_UNIQUE           DRM_IOW( 0x10, struct drm_unique)
+#define DRM_IOCTL_AUTH_MAGIC           DRM_IOW( 0x11, struct drm_auth)
+#define DRM_IOCTL_BLOCK                        DRM_IOWR(0x12, struct drm_block)
+#define DRM_IOCTL_UNBLOCK              DRM_IOWR(0x13, struct drm_block)
+#define DRM_IOCTL_CONTROL              DRM_IOW( 0x14, struct drm_control)
+#define DRM_IOCTL_ADD_MAP              DRM_IOWR(0x15, struct drm_map)
+#define DRM_IOCTL_ADD_BUFS             DRM_IOWR(0x16, struct drm_buf_desc)
+#define DRM_IOCTL_MARK_BUFS            DRM_IOW( 0x17, struct drm_buf_desc)
+#define DRM_IOCTL_INFO_BUFS            DRM_IOWR(0x18, struct drm_buf_info)
+#define DRM_IOCTL_MAP_BUFS             DRM_IOWR(0x19, struct drm_buf_map)
+#define DRM_IOCTL_FREE_BUFS            DRM_IOW( 0x1a, struct drm_buf_free)
+
+#define DRM_IOCTL_RM_MAP               DRM_IOW( 0x1b, struct drm_map)
+
+#define DRM_IOCTL_SET_SAREA_CTX                DRM_IOW( 0x1c, struct drm_ctx_priv_map)
+#define DRM_IOCTL_GET_SAREA_CTX        DRM_IOWR(0x1d, struct drm_ctx_priv_map)
+
+#define DRM_IOCTL_ADD_CTX              DRM_IOWR(0x20, struct drm_ctx)
+#define DRM_IOCTL_RM_CTX               DRM_IOWR(0x21, struct drm_ctx)
+#define DRM_IOCTL_MOD_CTX              DRM_IOW( 0x22, struct drm_ctx)
+#define DRM_IOCTL_GET_CTX              DRM_IOWR(0x23, struct drm_ctx)
+#define DRM_IOCTL_SWITCH_CTX           DRM_IOW( 0x24, struct drm_ctx)
+#define DRM_IOCTL_NEW_CTX              DRM_IOW( 0x25, struct drm_ctx)
+#define DRM_IOCTL_RES_CTX              DRM_IOWR(0x26, struct drm_ctx_res)
+#define DRM_IOCTL_ADD_DRAW             DRM_IOWR(0x27, struct drm_draw)
+#define DRM_IOCTL_RM_DRAW              DRM_IOWR(0x28, struct drm_draw)
+#define DRM_IOCTL_DMA                  DRM_IOWR(0x29, struct drm_dma)
+#define DRM_IOCTL_LOCK                 DRM_IOW( 0x2a, struct drm_lock)
+#define DRM_IOCTL_UNLOCK               DRM_IOW( 0x2b, struct drm_lock)
+#define DRM_IOCTL_FINISH               DRM_IOW( 0x2c, struct drm_lock)
+
+#define DRM_IOCTL_AGP_ACQUIRE          DRM_IO(  0x30)
+#define DRM_IOCTL_AGP_RELEASE          DRM_IO(  0x31)
+#define DRM_IOCTL_AGP_ENABLE           DRM_IOW( 0x32, struct drm_agp_mode)
+#define DRM_IOCTL_AGP_INFO             DRM_IOR( 0x33, struct drm_agp_info)
+#define DRM_IOCTL_AGP_ALLOC            DRM_IOWR(0x34, struct drm_agp_buffer)
+#define DRM_IOCTL_AGP_FREE             DRM_IOW( 0x35, struct drm_agp_buffer)
+#define DRM_IOCTL_AGP_BIND             DRM_IOW( 0x36, struct drm_agp_binding)
+#define DRM_IOCTL_AGP_UNBIND           DRM_IOW( 0x37, struct drm_agp_binding)
+
+#define DRM_IOCTL_SG_ALLOC             DRM_IOWR(0x38, struct drm_scatter_gather)
+#define DRM_IOCTL_SG_FREE              DRM_IOW( 0x39, struct drm_scatter_gather)
+
+#define DRM_IOCTL_WAIT_VBLANK          DRM_IOWR(0x3a, union drm_wait_vblank)
+
+#define DRM_IOCTL_UPDATE_DRAW          DRM_IOW(0x3f, struct drm_update_draw)
+
+/**
+ * Device specific ioctls should only be in their respective headers
+ * The device specific ioctl range is from 0x40 to 0x99.
+ * Generic IOCTLS restart at 0xA0.
+ *
+ * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
+ * drmCommandReadWrite().
+ */
+#define DRM_COMMAND_BASE                0x40
+#define DRM_COMMAND_END                        0xA0
+
+/* typedef area */
+#ifndef __KERNEL__
+typedef struct drm_clip_rect drm_clip_rect_t;
+typedef struct drm_drawable_info drm_drawable_info_t;
+typedef struct drm_tex_region drm_tex_region_t;
+typedef struct drm_hw_lock drm_hw_lock_t;
+typedef struct drm_version drm_version_t;
+typedef struct drm_unique drm_unique_t;
+typedef struct drm_list drm_list_t;
+typedef struct drm_block drm_block_t;
+typedef struct drm_control drm_control_t;
+typedef enum drm_map_type drm_map_type_t;
+typedef enum drm_map_flags drm_map_flags_t;
+typedef struct drm_ctx_priv_map drm_ctx_priv_map_t;
+typedef struct drm_map drm_map_t;
+typedef struct drm_client drm_client_t;
+typedef enum drm_stat_type drm_stat_type_t;
+typedef struct drm_stats drm_stats_t;
+typedef enum drm_lock_flags drm_lock_flags_t;
+typedef struct drm_lock drm_lock_t;
+typedef enum drm_dma_flags drm_dma_flags_t;
+typedef struct drm_buf_desc drm_buf_desc_t;
+typedef struct drm_buf_info drm_buf_info_t;
+typedef struct drm_buf_free drm_buf_free_t;
+typedef struct drm_buf_pub drm_buf_pub_t;
+typedef struct drm_buf_map drm_buf_map_t;
+typedef struct drm_dma drm_dma_t;
+typedef union drm_wait_vblank drm_wait_vblank_t;
+typedef struct drm_agp_mode drm_agp_mode_t;
+typedef enum drm_ctx_flags drm_ctx_flags_t;
+typedef struct drm_ctx drm_ctx_t;
+typedef struct drm_ctx_res drm_ctx_res_t;
+typedef struct drm_draw drm_draw_t;
+typedef struct drm_update_draw drm_update_draw_t;
+typedef struct drm_auth drm_auth_t;
+typedef struct drm_irq_busid drm_irq_busid_t;
+typedef enum drm_vblank_seq_type drm_vblank_seq_type_t;
+
+typedef struct drm_agp_buffer drm_agp_buffer_t;
+typedef struct drm_agp_binding drm_agp_binding_t;
+typedef struct drm_agp_info drm_agp_info_t;
+typedef struct drm_scatter_gather drm_scatter_gather_t;
+typedef struct drm_set_version drm_set_version_t;
+#endif
+
+#endif
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
new file mode 100644 (file)
index 0000000..0764b66
--- /dev/null
@@ -0,0 +1,1153 @@
+/**
+ * \file drmP.h
+ * Private header for Direct Rendering Manager
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DRM_P_H_
+#define _DRM_P_H_
+
+/* If you want the memory alloc debug functionality, change define below */
+/* #define DEBUG_MEMORY */
+
+#ifdef __KERNEL__
+#ifdef __alpha__
+/* add include of current.h so that "current" is defined
+ * before static inline funcs in wait.h. Doing this so we
+ * can build the DRM (part of PI DRI). 4/21/2000 S + B */
+#include <asm/current.h>
+#endif                         /* __alpha__ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/file.h>
+#include <linux/pci.h>
+#include <linux/jiffies.h>
+#include <linux/smp_lock.h>    /* For (un)lock_kernel */
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#if defined(__alpha__) || defined(__powerpc__)
+#include <asm/pgtable.h>       /* For pte_wrprotect */
+#endif
+#include <asm/io.h>
+#include <asm/mman.h>
+#include <asm/uaccess.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+#if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
+#include <linux/types.h>
+#include <linux/agp_backend.h>
+#endif
+#include <linux/workqueue.h>
+#include <linux/poll.h>
+#include <asm/pgalloc.h>
+#include "drm.h"
+
+#include <linux/idr.h>
+
+#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
+#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
+
+struct drm_file;
+struct drm_device;
+
+#include "drm_os_linux.h"
+#include "drm_hashtab.h"
+
+/***********************************************************************/
+/** \name DRM template customization defaults */
+/*@{*/
+
+/* driver capabilities and requirements mask */
+#define DRIVER_USE_AGP     0x1
+#define DRIVER_REQUIRE_AGP 0x2
+#define DRIVER_USE_MTRR    0x4
+#define DRIVER_PCI_DMA     0x8
+#define DRIVER_SG          0x10
+#define DRIVER_HAVE_DMA    0x20
+#define DRIVER_HAVE_IRQ    0x40
+#define DRIVER_IRQ_SHARED  0x80
+#define DRIVER_IRQ_VBL     0x100
+#define DRIVER_DMA_QUEUE   0x200
+#define DRIVER_FB_DMA      0x400
+#define DRIVER_IRQ_VBL2    0x800
+
+/***********************************************************************/
+/** \name Begin the DRM... */
+/*@{*/
+
+#define DRM_DEBUG_CODE 2         /**< Include debugging code if > 1, then
+                                    also include looping detection. */
+
+#define DRM_MAGIC_HASH_ORDER  4  /**< Size of key hash table. Must be power of 2. */
+#define DRM_KERNEL_CONTEXT    0         /**< Change drm_resctx if changed */
+#define DRM_RESERVED_CONTEXTS 1         /**< Change drm_resctx if changed */
+#define DRM_LOOPING_LIMIT     5000000
+#define DRM_TIME_SLICE       (HZ/20)  /**< Time slice for GLXContexts */
+#define DRM_LOCK_SLICE       1 /**< Time slice for lock, in jiffies */
+
+#define DRM_FLAG_DEBUG   0x01
+
+#define DRM_MEM_DMA       0
+#define DRM_MEM_SAREA     1
+#define DRM_MEM_DRIVER    2
+#define DRM_MEM_MAGIC     3
+#define DRM_MEM_IOCTLS    4
+#define DRM_MEM_MAPS      5
+#define DRM_MEM_VMAS      6
+#define DRM_MEM_BUFS      7
+#define DRM_MEM_SEGS      8
+#define DRM_MEM_PAGES     9
+#define DRM_MEM_FILES    10
+#define DRM_MEM_QUEUES   11
+#define DRM_MEM_CMDS     12
+#define DRM_MEM_MAPPINGS  13
+#define DRM_MEM_BUFLISTS  14
+#define DRM_MEM_AGPLISTS  15
+#define DRM_MEM_TOTALAGP  16
+#define DRM_MEM_BOUNDAGP  17
+#define DRM_MEM_CTXBITMAP 18
+#define DRM_MEM_STUB      19
+#define DRM_MEM_SGLISTS   20
+#define DRM_MEM_CTXLIST   21
+#define DRM_MEM_MM        22
+#define DRM_MEM_HASHTAB   23
+
+#define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
+#define DRM_MAP_HASH_OFFSET 0x10000000
+
+/*@}*/
+
+/***********************************************************************/
+/** \name Macros to make printk easier */
+/*@{*/
+
+/**
+ * Error output.
+ *
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
+#define DRM_ERROR(fmt, arg...) \
+       printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __func__ , ##arg)
+
+/**
+ * Memory error output.
+ *
+ * \param area memory area where the error occurred.
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
+#define DRM_MEM_ERROR(area, fmt, arg...) \
+       printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __func__, \
+              drm_mem_stats[area].name , ##arg)
+
+#define DRM_INFO(fmt, arg...)  printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
+
+/**
+ * Debug output.
+ *
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
+#if DRM_DEBUG_CODE
+#define DRM_DEBUG(fmt, arg...)                                         \
+       do {                                                            \
+               if ( drm_debug )                        \
+                       printk(KERN_DEBUG                               \
+                              "[" DRM_NAME ":%s] " fmt ,       \
+                              __func__ , ##arg);                       \
+       } while (0)
+#else
+#define DRM_DEBUG(fmt, arg...)          do { } while (0)
+#endif
+
+#define DRM_PROC_LIMIT (PAGE_SIZE-80)
+
+#define DRM_PROC_PRINT(fmt, arg...)                                    \
+   len += sprintf(&buf[len], fmt , ##arg);                             \
+   if (len > DRM_PROC_LIMIT) { *eof = 1; return len - offset; }
+
+#define DRM_PROC_PRINT_RET(ret, fmt, arg...)                           \
+   len += sprintf(&buf[len], fmt , ##arg);                             \
+   if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }
+
+/*@}*/
+
+/***********************************************************************/
+/** \name Internal types and structures */
+/*@{*/
+
+#define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x)
+
+#define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1))
+#define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
+#define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
+
+#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
+/**
+ * Get the private SAREA mapping.
+ *
+ * \param _dev DRM device.
+ * \param _ctx context number.
+ * \param _map output mapping.
+ */
+#define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do {      \
+       (_map) = (_dev)->context_sareas[_ctx];          \
+} while(0)
+
+/**
+ * Test that the hardware lock is held by the caller, returning otherwise.
+ *
+ * \param dev DRM device.
+ * \param filp file pointer of the caller.
+ */
+#define LOCK_TEST_WITH_RETURN( dev, file_priv )                                \
+do {                                                                   \
+       if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||           \
+            dev->lock.file_priv != file_priv ) {                       \
+               DRM_ERROR( "%s called without lock held, held  %d owner %p %p\n",\
+                          __func__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\
+                          dev->lock.file_priv, file_priv );            \
+               return -EINVAL;                                         \
+       }                                                               \
+} while (0)
+
+/**
+ * Copy and IOCTL return string to user space
+ */
+#define DRM_COPY( name, value )                                                \
+       len = strlen( value );                                          \
+       if ( len > name##_len ) len = name##_len;                       \
+       name##_len = strlen( value );                                   \
+       if ( len && name ) {                                            \
+               if ( copy_to_user( name, value, len ) )                 \
+                       return -EFAULT;                                 \
+       }
+
+/**
+ * Ioctl function type.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private pointer.
+ * \param cmd command.
+ * \param arg argument.
+ */
+typedef int drm_ioctl_t(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+
+typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
+                              unsigned long arg);
+
+#define DRM_AUTH       0x1
+#define        DRM_MASTER      0x2
+#define DRM_ROOT_ONLY  0x4
+
+struct drm_ioctl_desc {
+       unsigned int cmd;
+       drm_ioctl_t *func;
+       int flags;
+};
+
+/**
+ * Creates a driver or general drm_ioctl_desc array entry for the given
+ * ioctl, for use by drm_ioctl().
+ */
+#define DRM_IOCTL_DEF(ioctl, func, flags) \
+       [DRM_IOCTL_NR(ioctl)] = {ioctl, func, flags}
+
+struct drm_magic_entry {
+       struct list_head head;
+       struct drm_hash_item hash_item;
+       struct drm_file *priv;
+};
+
+struct drm_vma_entry {
+       struct list_head head;
+       struct vm_area_struct *vma;
+       pid_t pid;
+};
+
+/**
+ * DMA buffer.
+ */
+struct drm_buf {
+       int idx;                       /**< Index into master buflist */
+       int total;                     /**< Buffer size */
+       int order;                     /**< log-base-2(total) */
+       int used;                      /**< Amount of buffer in use (for DMA) */
+       unsigned long offset;          /**< Byte offset (used internally) */
+       void *address;                 /**< Address of buffer */
+       unsigned long bus_address;     /**< Bus address of buffer */
+       struct drm_buf *next;          /**< Kernel-only: used for free list */
+       __volatile__ int waiting;      /**< On kernel DMA queue */
+       __volatile__ int pending;      /**< On hardware DMA queue */
+       wait_queue_head_t dma_wait;    /**< Processes waiting */
+       struct drm_file *file_priv;    /**< Private of holding file descr */
+       int context;                   /**< Kernel queue for this buffer */
+       int while_locked;              /**< Dispatch this buffer while locked */
+       enum {
+               DRM_LIST_NONE = 0,
+               DRM_LIST_FREE = 1,
+               DRM_LIST_WAIT = 2,
+               DRM_LIST_PEND = 3,
+               DRM_LIST_PRIO = 4,
+               DRM_LIST_RECLAIM = 5
+       } list;                        /**< Which list we're on */
+
+       int dev_priv_size;               /**< Size of buffer private storage */
+       void *dev_private;               /**< Per-buffer private storage */
+};
+
+/** bufs is one longer than it has to be */
+struct drm_waitlist {
+       int count;                      /**< Number of possible buffers */
+       struct drm_buf **bufs;          /**< List of pointers to buffers */
+       struct drm_buf **rp;                    /**< Read pointer */
+       struct drm_buf **wp;                    /**< Write pointer */
+       struct drm_buf **end;           /**< End pointer */
+       spinlock_t read_lock;
+       spinlock_t write_lock;
+};
+
+struct drm_freelist {
+       int initialized;               /**< Freelist in use */
+       atomic_t count;                /**< Number of free buffers */
+       struct drm_buf *next;          /**< End pointer */
+
+       wait_queue_head_t waiting;     /**< Processes waiting on free bufs */
+       int low_mark;                  /**< Low water mark */
+       int high_mark;                 /**< High water mark */
+       atomic_t wfh;                  /**< If waiting for high mark */
+       spinlock_t lock;
+};
+
+typedef struct drm_dma_handle {
+       dma_addr_t busaddr;
+       void *vaddr;
+       size_t size;
+} drm_dma_handle_t;
+
+/**
+ * Buffer entry.  There is one of this for each buffer size order.
+ */
+struct drm_buf_entry {
+       int buf_size;                   /**< size */
+       int buf_count;                  /**< number of buffers */
+       struct drm_buf *buflist;                /**< buffer list */
+       int seg_count;
+       int page_order;
+       struct drm_dma_handle **seglist;
+
+       struct drm_freelist freelist;
+};
+
+/** File private data */
+struct drm_file {
+       int authenticated;
+       int master;
+       pid_t pid;
+       uid_t uid;
+       drm_magic_t magic;
+       unsigned long ioctl_count;
+       struct list_head lhead;
+       struct drm_minor *minor;
+       int remove_auth_on_close;
+       unsigned long lock_count;
+       struct file *filp;
+       void *driver_priv;
+};
+
+/** Wait queue */
+struct drm_queue {
+       atomic_t use_count;             /**< Outstanding uses (+1) */
+       atomic_t finalization;          /**< Finalization in progress */
+       atomic_t block_count;           /**< Count of processes waiting */
+       atomic_t block_read;            /**< Queue blocked for reads */
+       wait_queue_head_t read_queue;   /**< Processes waiting on block_read */
+       atomic_t block_write;           /**< Queue blocked for writes */
+       wait_queue_head_t write_queue;  /**< Processes waiting on block_write */
+       atomic_t total_queued;          /**< Total queued statistic */
+       atomic_t total_flushed;         /**< Total flushes statistic */
+       atomic_t total_locks;           /**< Total locks statistics */
+       enum drm_ctx_flags flags;       /**< Context preserving and 2D-only */
+       struct drm_waitlist waitlist;   /**< Pending buffers */
+       wait_queue_head_t flush_queue;  /**< Processes waiting until flush */
+};
+
+/**
+ * Lock data.
+ */
+struct drm_lock_data {
+       struct drm_hw_lock *hw_lock;    /**< Hardware lock */
+       /** Private of lock holder's file (NULL=kernel) */
+       struct drm_file *file_priv;
+       wait_queue_head_t lock_queue;   /**< Queue of blocked processes */
+       unsigned long lock_time;        /**< Time of last lock in jiffies */
+       spinlock_t spinlock;
+       uint32_t kernel_waiters;
+       uint32_t user_waiters;
+       int idle_has_lock;
+};
+
+/**
+ * DMA data.
+ */
+struct drm_device_dma {
+
+       struct drm_buf_entry bufs[DRM_MAX_ORDER + 1];   /**< buffers, grouped by their size order */
+       int buf_count;                  /**< total number of buffers */
+       struct drm_buf **buflist;               /**< Vector of pointers into drm_device_dma::bufs */
+       int seg_count;
+       int page_count;                 /**< number of pages */
+       unsigned long *pagelist;        /**< page list */
+       unsigned long byte_count;
+       enum {
+               _DRM_DMA_USE_AGP = 0x01,
+               _DRM_DMA_USE_SG = 0x02,
+               _DRM_DMA_USE_FB = 0x04,
+               _DRM_DMA_USE_PCI_RO = 0x08
+       } flags;
+
+};
+
+/**
+ * AGP memory entry.  Stored as a doubly linked list.
+ */
+struct drm_agp_mem {
+       unsigned long handle;           /**< handle */
+       DRM_AGP_MEM *memory;
+       unsigned long bound;            /**< address */
+       int pages;
+       struct list_head head;
+};
+
+/**
+ * AGP data.
+ *
+ * \sa drm_agp_init() and drm_device::agp.
+ */
+struct drm_agp_head {
+       DRM_AGP_KERN agp_info;          /**< AGP device information */
+       struct list_head memory;
+       unsigned long mode;             /**< AGP mode */
+       struct agp_bridge_data *bridge;
+       int enabled;                    /**< whether the AGP bus as been enabled */
+       int acquired;                   /**< whether the AGP device has been acquired */
+       unsigned long base;
+       int agp_mtrr;
+       int cant_use_aperture;
+       unsigned long page_mask;
+};
+
+/**
+ * Scatter-gather memory.
+ */
+struct drm_sg_mem {
+       unsigned long handle;
+       void *virtual;
+       int pages;
+       struct page **pagelist;
+       dma_addr_t *busaddr;
+};
+
+struct drm_sigdata {
+       int context;
+       struct drm_hw_lock *lock;
+};
+
+
+/*
+ * Generic memory manager structs
+ */
+
+struct drm_mm_node {
+       struct list_head fl_entry;
+       struct list_head ml_entry;
+       int free;
+       unsigned long start;
+       unsigned long size;
+       struct drm_mm *mm;
+       void *private;
+};
+
+struct drm_mm {
+       struct list_head fl_entry;
+       struct list_head ml_entry;
+};
+
+
+/**
+ * Mappings list
+ */
+struct drm_map_list {
+       struct list_head head;          /**< list head */
+       struct drm_hash_item hash;
+       struct drm_map *map;                    /**< mapping */
+       uint64_t user_token;
+};
+
+typedef struct drm_map drm_local_map_t;
+
+/**
+ * Context handle list
+ */
+struct drm_ctx_list {
+       struct list_head head;          /**< list head */
+       drm_context_t handle;           /**< context handle */
+       struct drm_file *tag;           /**< associated fd private data */
+};
+
+struct drm_vbl_sig {
+       struct list_head head;
+       unsigned int sequence;
+       struct siginfo info;
+       struct task_struct *task;
+};
+
+/* location of GART table */
+#define DRM_ATI_GART_MAIN 1
+#define DRM_ATI_GART_FB   2
+
+#define DRM_ATI_GART_PCI 1
+#define DRM_ATI_GART_PCIE 2
+#define DRM_ATI_GART_IGP 3
+
+struct drm_ati_pcigart_info {
+       int gart_table_location;
+       int gart_reg_if;
+       void *addr;
+       dma_addr_t bus_addr;
+       dma_addr_t table_mask;
+       struct drm_dma_handle *table_handle;
+       drm_local_map_t mapping;
+       int table_size;
+};
+
+/**
+ * DRM driver structure. This structure represent the common code for
+ * a family of cards. There will one drm_device for each card present
+ * in this family
+ */
+struct drm_driver {
+       int (*load) (struct drm_device *, unsigned long flags);
+       int (*firstopen) (struct drm_device *);
+       int (*open) (struct drm_device *, struct drm_file *);
+       void (*preclose) (struct drm_device *, struct drm_file *file_priv);
+       void (*postclose) (struct drm_device *, struct drm_file *);
+       void (*lastclose) (struct drm_device *);
+       int (*unload) (struct drm_device *);
+       int (*suspend) (struct drm_device *, pm_message_t state);
+       int (*resume) (struct drm_device *);
+       int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv);
+       void (*dma_ready) (struct drm_device *);
+       int (*dma_quiescent) (struct drm_device *);
+       int (*context_ctor) (struct drm_device *dev, int context);
+       int (*context_dtor) (struct drm_device *dev, int context);
+       int (*kernel_context_switch) (struct drm_device *dev, int old,
+                                     int new);
+       void (*kernel_context_switch_unlock) (struct drm_device *dev);
+       int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
+       int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
+       int (*dri_library_name) (struct drm_device *dev, char *buf);
+
+       /**
+        * Called by \c drm_device_is_agp.  Typically used to determine if a
+        * card is really attached to AGP or not.
+        *
+        * \param dev  DRM device handle
+        *
+        * \returns
+        * One of three values is returned depending on whether or not the
+        * card is absolutely \b not AGP (return of 0), absolutely \b is AGP
+        * (return of 1), or may or may not be AGP (return of 2).
+        */
+       int (*device_is_agp) (struct drm_device *dev);
+
+       /* these have to be filled in */
+
+       irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
+       void (*irq_preinstall) (struct drm_device *dev);
+       void (*irq_postinstall) (struct drm_device *dev);
+       void (*irq_uninstall) (struct drm_device *dev);
+       void (*reclaim_buffers) (struct drm_device *dev,
+                                struct drm_file * file_priv);
+       void (*reclaim_buffers_locked) (struct drm_device *dev,
+                                       struct drm_file *file_priv);
+       void (*reclaim_buffers_idlelocked) (struct drm_device *dev,
+                                           struct drm_file *file_priv);
+       unsigned long (*get_map_ofs) (struct drm_map * map);
+       unsigned long (*get_reg_ofs) (struct drm_device *dev);
+       void (*set_version) (struct drm_device *dev,
+                            struct drm_set_version *sv);
+
+       int major;
+       int minor;
+       int patchlevel;
+       char *name;
+       char *desc;
+       char *date;
+
+       u32 driver_features;
+       int dev_priv_size;
+       struct drm_ioctl_desc *ioctls;
+       int num_ioctls;
+       struct file_operations fops;
+       struct pci_driver pci_driver;
+};
+
+#define DRM_MINOR_UNASSIGNED 0
+#define DRM_MINOR_LEGACY 1
+
+/**
+ * DRM minor structure. This structure represents a drm minor number.
+ */
+struct drm_minor {
+       int index;                      /**< Minor device number */
+       int type;                       /**< Control or render */
+       dev_t device;                   /**< Device number for mknod */
+       struct device kdev;             /**< Linux device */
+       struct drm_device *dev;
+       struct proc_dir_entry *dev_root;  /**< proc directory entry */
+};
+
+/**
+ * DRM device structure. This structure represent a complete card that
+ * may contain multiple heads.
+ */
+struct drm_device {
+       char *unique;                   /**< Unique identifier: e.g., busid */
+       int unique_len;                 /**< Length of unique field */
+       char *devname;                  /**< For /proc/interrupts */
+       int if_version;                 /**< Highest interface version set */
+
+       int blocked;                    /**< Blocked due to VC switch? */
+
+       /** \name Locks */
+       /*@{ */
+       spinlock_t count_lock;          /**< For inuse, drm_device::open_count, drm_device::buf_use */
+       struct mutex struct_mutex;      /**< For others */
+       /*@} */
+
+       /** \name Usage Counters */
+       /*@{ */
+       int open_count;                 /**< Outstanding files open */
+       atomic_t ioctl_count;           /**< Outstanding IOCTLs pending */
+       atomic_t vma_count;             /**< Outstanding vma areas open */
+       int buf_use;                    /**< Buffers in use -- cannot alloc */
+       atomic_t buf_alloc;             /**< Buffer allocation in progress */
+       /*@} */
+
+       /** \name Performance counters */
+       /*@{ */
+       unsigned long counters;
+       enum drm_stat_type types[15];
+       atomic_t counts[15];
+       /*@} */
+
+       /** \name Authentication */
+       /*@{ */
+       struct list_head filelist;
+       struct drm_open_hash magiclist; /**< magic hash table */
+       struct list_head magicfree;
+       /*@} */
+
+       /** \name Memory management */
+       /*@{ */
+       struct list_head maplist;       /**< Linked list of regions */
+       int map_count;                  /**< Number of mappable regions */
+       struct drm_open_hash map_hash;  /**< User token hash table for maps */
+
+       /** \name Context handle management */
+       /*@{ */
+       struct list_head ctxlist;       /**< Linked list of context handles */
+       int ctx_count;                  /**< Number of context handles */
+       struct mutex ctxlist_mutex;     /**< For ctxlist */
+
+       struct idr ctx_idr;
+
+       struct list_head vmalist;       /**< List of vmas (for debugging) */
+       struct drm_lock_data lock;      /**< Information on hardware lock */
+       /*@} */
+
+       /** \name DMA queues (contexts) */
+       /*@{ */
+       int queue_count;                /**< Number of active DMA queues */
+       int queue_reserved;               /**< Number of reserved DMA queues */
+       int queue_slots;                /**< Actual length of queuelist */
+       struct drm_queue **queuelist;   /**< Vector of pointers to DMA queues */
+       struct drm_device_dma *dma;             /**< Optional pointer for DMA support */
+       /*@} */
+
+       /** \name Context support */
+       /*@{ */
+       int irq;                        /**< Interrupt used by board */
+       int irq_enabled;                /**< True if irq handler is enabled */
+       __volatile__ long context_flag; /**< Context swapping flag */
+       __volatile__ long interrupt_flag; /**< Interruption handler flag */
+       __volatile__ long dma_flag;     /**< DMA dispatch flag */
+       struct timer_list timer;        /**< Timer for delaying ctx switch */
+       wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
+       int last_checked;               /**< Last context checked for DMA */
+       int last_context;               /**< Last current context */
+       unsigned long last_switch;      /**< jiffies at last context switch */
+       /*@} */
+
+       struct work_struct work;
+       /** \name VBLANK IRQ support */
+       /*@{ */
+
+       wait_queue_head_t vbl_queue;    /**< VBLANK wait queue */
+       atomic_t vbl_received;
+       atomic_t vbl_received2;         /**< number of secondary VBLANK interrupts */
+       spinlock_t vbl_lock;
+       struct list_head vbl_sigs;              /**< signal list to send on VBLANK */
+       struct list_head vbl_sigs2;     /**< signals to send on secondary VBLANK */
+       unsigned int vbl_pending;
+       spinlock_t tasklet_lock;        /**< For drm_locked_tasklet */
+       void (*locked_tasklet_func)(struct drm_device *dev);
+
+       /*@} */
+       cycles_t ctx_start;
+       cycles_t lck_start;
+
+       struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
+       wait_queue_head_t buf_readers;  /**< Processes waiting to read */
+       wait_queue_head_t buf_writers;  /**< Processes waiting to ctx switch */
+
+       struct drm_agp_head *agp;       /**< AGP data */
+
+       struct pci_dev *pdev;           /**< PCI device structure */
+       int pci_vendor;                 /**< PCI vendor id */
+       int pci_device;                 /**< PCI device id */
+#ifdef __alpha__
+       struct pci_controller *hose;
+#endif
+       struct drm_sg_mem *sg;  /**< Scatter gather memory */
+       void *dev_private;              /**< device private data */
+       struct drm_sigdata sigdata;        /**< For block_all_signals */
+       sigset_t sigmask;
+
+       struct drm_driver *driver;
+       drm_local_map_t *agp_buffer_map;
+       unsigned int agp_buffer_token;
+       struct drm_minor *primary;              /**< render type primary screen head */
+
+       /** \name Drawable information */
+       /*@{ */
+       spinlock_t drw_lock;
+       struct idr drw_idr;
+       /*@} */
+};
+
+static __inline__ int drm_core_check_feature(struct drm_device *dev,
+                                            int feature)
+{
+       return ((dev->driver->driver_features & feature) ? 1 : 0);
+}
+
+#ifdef __alpha__
+#define drm_get_pci_domain(dev) dev->hose->index
+#else
+#define drm_get_pci_domain(dev) 0
+#endif
+
+#if __OS_HAS_AGP
+static inline int drm_core_has_AGP(struct drm_device *dev)
+{
+       return drm_core_check_feature(dev, DRIVER_USE_AGP);
+}
+#else
+#define drm_core_has_AGP(dev) (0)
+#endif
+
+#if __OS_HAS_MTRR
+static inline int drm_core_has_MTRR(struct drm_device *dev)
+{
+       return drm_core_check_feature(dev, DRIVER_USE_MTRR);
+}
+
+#define DRM_MTRR_WC            MTRR_TYPE_WRCOMB
+
+static inline int drm_mtrr_add(unsigned long offset, unsigned long size,
+                              unsigned int flags)
+{
+       return mtrr_add(offset, size, flags, 1);
+}
+
+static inline int drm_mtrr_del(int handle, unsigned long offset,
+                              unsigned long size, unsigned int flags)
+{
+       return mtrr_del(handle, offset, size);
+}
+
+#else
+#define drm_core_has_MTRR(dev) (0)
+
+#define DRM_MTRR_WC            0
+
+static inline int drm_mtrr_add(unsigned long offset, unsigned long size,
+                              unsigned int flags)
+{
+       return 0;
+}
+
+static inline int drm_mtrr_del(int handle, unsigned long offset,
+                              unsigned long size, unsigned int flags)
+{
+       return 0;
+}
+#endif
+
+/******************************************************************/
+/** \name Internal function definitions */
+/*@{*/
+
+                               /* Driver support (drm_drv.h) */
+extern int drm_init(struct drm_driver *driver);
+extern void drm_exit(struct drm_driver *driver);
+extern int drm_ioctl(struct inode *inode, struct file *filp,
+                    unsigned int cmd, unsigned long arg);
+extern long drm_compat_ioctl(struct file *filp,
+                            unsigned int cmd, unsigned long arg);
+extern int drm_lastclose(struct drm_device *dev);
+
+                               /* Device support (drm_fops.h) */
+extern int drm_open(struct inode *inode, struct file *filp);
+extern int drm_stub_open(struct inode *inode, struct file *filp);
+extern int drm_fasync(int fd, struct file *filp, int on);
+extern int drm_release(struct inode *inode, struct file *filp);
+
+                               /* Mapping support (drm_vm.h) */
+extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
+extern unsigned long drm_core_get_map_ofs(struct drm_map * map);
+extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev);
+extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
+
+                               /* Memory management support (drm_memory.h) */
+#include "drm_memory.h"
+extern void drm_mem_init(void);
+extern int drm_mem_info(char *buf, char **start, off_t offset,
+                       int request, int *eof, void *data);
+extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
+
+extern DRM_AGP_MEM *drm_alloc_agp(struct drm_device *dev, int pages, u32 type);
+extern int drm_free_agp(DRM_AGP_MEM * handle, int pages);
+extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start);
+extern int drm_unbind_agp(DRM_AGP_MEM * handle);
+
+                               /* Misc. IOCTL support (drm_ioctl.h) */
+extern int drm_irq_by_busid(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv);
+extern int drm_getunique(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int drm_setunique(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int drm_getmap(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_getclient(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int drm_getstats(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_setversion(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv);
+extern int drm_noop(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv);
+
+                               /* Context IOCTL support (drm_context.h) */
+extern int drm_resctx(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_addctx(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_modctx(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_getctx(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_switchctx(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int drm_newctx(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_rmctx(struct drm_device *dev, void *data,
+                    struct drm_file *file_priv);
+
+extern int drm_ctxbitmap_init(struct drm_device *dev);
+extern void drm_ctxbitmap_cleanup(struct drm_device *dev);
+extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle);
+
+extern int drm_setsareactx(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int drm_getsareactx(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+
+                               /* Drawable IOCTL support (drm_drawable.h) */
+extern int drm_adddraw(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
+extern int drm_rmdraw(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_update_drawable_info(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
+extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev,
+                                                 drm_drawable_t id);
+extern void drm_drawable_free_all(struct drm_device *dev);
+
+                               /* Authentication IOCTL support (drm_auth.h) */
+extern int drm_getmagic(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_authmagic(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+
+                               /* Locking IOCTL support (drm_lock.h) */
+extern int drm_lock(struct drm_device *dev, void *data,
+                   struct drm_file *file_priv);
+extern int drm_unlock(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv);
+extern int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
+extern int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context);
+extern void drm_idlelock_take(struct drm_lock_data *lock_data);
+extern void drm_idlelock_release(struct drm_lock_data *lock_data);
+
+/*
+ * These are exported to drivers so that they can implement fencing using
+ * DMA quiscent + idle. DMA quiescent usually requires the hardware lock.
+ */
+
+extern int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv);
+
+                               /* Buffer management support (drm_bufs.h) */
+extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request);
+extern int drm_addmap(struct drm_device *dev, unsigned int offset,
+                     unsigned int size, enum drm_map_type type,
+                     enum drm_map_flags flags, drm_local_map_t ** map_ptr);
+extern int drm_addmap_ioctl(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv);
+extern int drm_rmmap(struct drm_device *dev, drm_local_map_t *map);
+extern int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map);
+extern int drm_rmmap_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int drm_addbufs(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
+extern int drm_infobufs(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_markbufs(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_freebufs(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_mapbufs(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
+extern int drm_order(unsigned long size);
+extern unsigned long drm_get_resource_start(struct drm_device *dev,
+                                           unsigned int resource);
+extern unsigned long drm_get_resource_len(struct drm_device *dev,
+                                         unsigned int resource);
+
+                               /* DMA support (drm_dma.h) */
+extern int drm_dma_setup(struct drm_device *dev);
+extern void drm_dma_takedown(struct drm_device *dev);
+extern void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf);
+extern void drm_core_reclaim_buffers(struct drm_device *dev,
+                                    struct drm_file *filp);
+
+                               /* IRQ support (drm_irq.h) */
+extern int drm_control(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
+extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
+extern int drm_irq_uninstall(struct drm_device *dev);
+extern void drm_driver_irq_preinstall(struct drm_device *dev);
+extern void drm_driver_irq_postinstall(struct drm_device *dev);
+extern void drm_driver_irq_uninstall(struct drm_device *dev);
+
+extern int drm_wait_vblank(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
+extern void drm_vbl_send_signals(struct drm_device *dev);
+extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
+
+                               /* AGP/GART support (drm_agpsupport.h) */
+extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
+extern int drm_agp_acquire(struct drm_device *dev);
+extern int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+extern int drm_agp_release(struct drm_device *dev);
+extern int drm_agp_release_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode);
+extern int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
+extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info);
+extern int drm_agp_info_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request);
+extern int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request);
+extern int drm_agp_free_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request);
+extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv);
+extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);
+extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type);
+extern int drm_agp_free_memory(DRM_AGP_MEM * handle);
+extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);
+extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);
+
+                               /* Stub support (drm_stub.h) */
+extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+                      struct drm_driver *driver);
+extern int drm_put_dev(struct drm_device *dev);
+extern int drm_put_minor(struct drm_minor **minor);
+extern unsigned int drm_debug;
+
+extern struct class *drm_class;
+extern struct proc_dir_entry *drm_proc_root;
+
+extern struct idr drm_minors_idr;
+
+extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
+
+                               /* Proc support (drm_proc.h) */
+extern int drm_proc_init(struct drm_minor *minor, int minor_id,
+                        struct proc_dir_entry *root);
+extern int drm_proc_cleanup(struct drm_minor *minor, struct proc_dir_entry *root);
+
+                               /* Scatter Gather Support (drm_scatter.h) */
+extern void drm_sg_cleanup(struct drm_sg_mem * entry);
+extern int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv);
+extern int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request);
+extern int drm_sg_free(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv);
+
+                              /* ATI PCIGART support (ati_pcigart.h) */
+extern int drm_ati_pcigart_init(struct drm_device *dev,
+                               struct drm_ati_pcigart_info * gart_info);
+extern int drm_ati_pcigart_cleanup(struct drm_device *dev,
+                                  struct drm_ati_pcigart_info * gart_info);
+
+extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size,
+                                      size_t align, dma_addr_t maxaddr);
+extern void __drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
+extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);
+
+                              /* sysfs support (drm_sysfs.c) */
+struct drm_sysfs_class;
+extern struct class *drm_sysfs_create(struct module *owner, char *name);
+extern void drm_sysfs_destroy(void);
+extern int drm_sysfs_device_add(struct drm_minor *minor);
+extern void drm_sysfs_device_remove(struct drm_minor *minor);
+
+/*
+ * Basic memory manager support (drm_mm.c)
+ */
+extern struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent,
+                                      unsigned long size,
+                                      unsigned alignment);
+extern void drm_mm_put_block(struct drm_mm_node * cur);
+extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, unsigned long size,
+                                        unsigned alignment, int best_match);
+extern int drm_mm_init(struct drm_mm *mm, unsigned long start, unsigned long size);
+extern void drm_mm_takedown(struct drm_mm *mm);
+extern int drm_mm_clean(struct drm_mm *mm);
+extern unsigned long drm_mm_tail_space(struct drm_mm *mm);
+extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size);
+extern int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size);
+
+extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
+extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
+
+static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev,
+                                                  unsigned int token)
+{
+       struct drm_map_list *_entry;
+       list_for_each_entry(_entry, &dev->maplist, head)
+           if (_entry->user_token == token)
+               return _entry->map;
+       return NULL;
+}
+
+static __inline__ int drm_device_is_agp(struct drm_device *dev)
+{
+       if (dev->driver->device_is_agp != NULL) {
+               int err = (*dev->driver->device_is_agp) (dev);
+
+               if (err != 2) {
+                       return err;
+               }
+       }
+
+       return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
+}
+
+static __inline__ int drm_device_is_pcie(struct drm_device *dev)
+{
+       return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
+}
+
+static __inline__ void drm_core_dropmap(struct drm_map *map)
+{
+}
+
+#ifndef DEBUG_MEMORY
+/** Wrapper around kmalloc() */
+static __inline__ void *drm_alloc(size_t size, int area)
+{
+       return kmalloc(size, GFP_KERNEL);
+}
+
+/** Wrapper around kfree() */
+static __inline__ void drm_free(void *pt, size_t size, int area)
+{
+       kfree(pt);
+}
+
+/** Wrapper around kcalloc() */
+static __inline__ void *drm_calloc(size_t nmemb, size_t size, int area)
+{
+       return kcalloc(nmemb, size, GFP_KERNEL);
+}
+#else
+extern void *drm_alloc(size_t size, int area);
+extern void drm_free(void *pt, size_t size, int area);
+extern void *drm_calloc(size_t nmemb, size_t size, int area);
+#endif
+
+/*@}*/
+
+#endif                         /* __KERNEL__ */
+#endif
diff --git a/include/drm/drm_core.h b/include/drm/drm_core.h
new file mode 100644 (file)
index 0000000..3167390
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2004 Jon Smirl <jonsmirl@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#define CORE_AUTHOR            "Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl"
+
+#define CORE_NAME              "drm"
+#define CORE_DESC              "DRM shared core routines"
+#define CORE_DATE              "20060810"
+
+#define DRM_IF_MAJOR   1
+#define DRM_IF_MINOR   3
+
+#define CORE_MAJOR     1
+#define CORE_MINOR     1
+#define CORE_PATCHLEVEL 0
diff --git a/include/drm/drm_hashtab.h b/include/drm/drm_hashtab.h
new file mode 100644 (file)
index 0000000..cd2b189
--- /dev/null
@@ -0,0 +1,67 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismack, ND. USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+/*
+ * Simple open hash tab implementation.
+ *
+ * Authors:
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef DRM_HASHTAB_H
+#define DRM_HASHTAB_H
+
+#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
+
+struct drm_hash_item {
+       struct hlist_node head;
+       unsigned long key;
+};
+
+struct drm_open_hash {
+       unsigned int size;
+       unsigned int order;
+       unsigned int fill;
+       struct hlist_head *table;
+       int use_vmalloc;
+};
+
+
+extern int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
+extern int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+extern int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
+                                    unsigned long seed, int bits, int shift,
+                                    unsigned long add);
+extern int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item);
+
+extern void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key);
+extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
+extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
+extern void drm_ht_remove(struct drm_open_hash *ht);
+
+
+#endif
diff --git a/include/drm/drm_memory.h b/include/drm/drm_memory.h
new file mode 100644 (file)
index 0000000..63e425b
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * \file drm_memory.h
+ * Memory management wrappers for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Created: Thu Feb  4 14:00:34 1999 by faith@valinux.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/highmem.h>
+#include <linux/vmalloc.h>
+#include "drmP.h"
+
+/**
+ * Cut down version of drm_memory_debug.h, which used to be called
+ * drm_memory.h.
+ */
+
+#if __OS_HAS_AGP
+
+#include <linux/vmalloc.h>
+
+#ifdef HAVE_PAGE_AGP
+#include <asm/agp.h>
+#else
+# ifdef __powerpc__
+#  define PAGE_AGP     __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
+# else
+#  define PAGE_AGP     PAGE_KERNEL
+# endif
+#endif
+
+#else                          /* __OS_HAS_AGP */
+
+#endif
diff --git a/include/drm/drm_memory_debug.h b/include/drm/drm_memory_debug.h
new file mode 100644 (file)
index 0000000..6463271
--- /dev/null
@@ -0,0 +1,309 @@
+/**
+ * \file drm_memory_debug.h
+ * Memory management wrappers for DRM.
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+
+typedef struct drm_mem_stats {
+       const char *name;
+       int succeed_count;
+       int free_count;
+       int fail_count;
+       unsigned long bytes_allocated;
+       unsigned long bytes_freed;
+} drm_mem_stats_t;
+
+static DEFINE_SPINLOCK(drm_mem_lock);
+static unsigned long drm_ram_available = 0;    /* In pages */
+static unsigned long drm_ram_used = 0;
+static drm_mem_stats_t drm_mem_stats[] =
+{
+       [DRM_MEM_DMA] = {"dmabufs"},
+       [DRM_MEM_SAREA] = {"sareas"},
+       [DRM_MEM_DRIVER] = {"driver"},
+       [DRM_MEM_MAGIC] = {"magic"},
+       [DRM_MEM_IOCTLS] = {"ioctltab"},
+       [DRM_MEM_MAPS] = {"maplist"},
+       [DRM_MEM_VMAS] = {"vmalist"},
+       [DRM_MEM_BUFS] = {"buflist"},
+       [DRM_MEM_SEGS] = {"seglist"},
+       [DRM_MEM_PAGES] = {"pagelist"},
+       [DRM_MEM_FILES] = {"files"},
+       [DRM_MEM_QUEUES] = {"queues"},
+       [DRM_MEM_CMDS] = {"commands"},
+       [DRM_MEM_MAPPINGS] = {"mappings"},
+       [DRM_MEM_BUFLISTS] = {"buflists"},
+       [DRM_MEM_AGPLISTS] = {"agplist"},
+       [DRM_MEM_SGLISTS] = {"sglist"},
+       [DRM_MEM_TOTALAGP] = {"totalagp"},
+       [DRM_MEM_BOUNDAGP] = {"boundagp"},
+       [DRM_MEM_CTXBITMAP] = {"ctxbitmap"},
+       [DRM_MEM_CTXLIST] = {"ctxlist"},
+       [DRM_MEM_STUB] = {"stub"},
+       {NULL, 0,}              /* Last entry must be null */
+};
+
+void drm_mem_init (void) {
+       drm_mem_stats_t *mem;
+       struct sysinfo si;
+
+       for (mem = drm_mem_stats; mem->name; ++mem) {
+               mem->succeed_count = 0;
+               mem->free_count = 0;
+               mem->fail_count = 0;
+               mem->bytes_allocated = 0;
+               mem->bytes_freed = 0;
+       }
+
+       si_meminfo(&si);
+       drm_ram_available = si.totalram;
+       drm_ram_used = 0;
+}
+
+/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
+
+static int drm__mem_info (char *buf, char **start, off_t offset,
+                          int request, int *eof, void *data) {
+       drm_mem_stats_t *pt;
+       int len = 0;
+
+       if (offset > DRM_PROC_LIMIT) {
+               *eof = 1;
+               return 0;
+       }
+
+       *eof = 0;
+       *start = &buf[offset];
+
+       DRM_PROC_PRINT("                  total counts                  "
+                      " |    outstanding  \n");
+       DRM_PROC_PRINT("type       alloc freed fail     bytes      freed"
+                      " | allocs      bytes\n\n");
+       DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB         |\n",
+                      "system", 0, 0, 0,
+                      drm_ram_available << (PAGE_SHIFT - 10));
+       DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB         |\n",
+                      "locked", 0, 0, 0, drm_ram_used >> 10);
+       DRM_PROC_PRINT("\n");
+       for (pt = drm_mem_stats; pt->name; pt++) {
+               DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
+                              pt->name,
+                              pt->succeed_count,
+                              pt->free_count,
+                              pt->fail_count,
+                              pt->bytes_allocated,
+                              pt->bytes_freed,
+                              pt->succeed_count - pt->free_count,
+                              (long)pt->bytes_allocated
+                              - (long)pt->bytes_freed);
+       }
+
+       if (len > request + offset)
+               return request;
+       *eof = 1;
+       return len - offset;
+}
+
+int drm_mem_info (char *buf, char **start, off_t offset,
+                  int len, int *eof, void *data) {
+       int ret;
+
+       spin_lock(&drm_mem_lock);
+       ret = drm__mem_info (buf, start, offset, len, eof, data);
+       spin_unlock(&drm_mem_lock);
+       return ret;
+}
+
+void *drm_alloc (size_t size, int area) {
+       void *pt;
+
+       if (!size) {
+               DRM_MEM_ERROR(area, "Allocating 0 bytes\n");
+               return NULL;
+       }
+
+       if (!(pt = kmalloc(size, GFP_KERNEL))) {
+               spin_lock(&drm_mem_lock);
+               ++drm_mem_stats[area].fail_count;
+               spin_unlock(&drm_mem_lock);
+               return NULL;
+       }
+       spin_lock(&drm_mem_lock);
+       ++drm_mem_stats[area].succeed_count;
+       drm_mem_stats[area].bytes_allocated += size;
+       spin_unlock(&drm_mem_lock);
+       return pt;
+}
+
+void *drm_calloc (size_t nmemb, size_t size, int area) {
+       void *addr;
+
+       addr = drm_alloc (nmemb * size, area);
+       if (addr != NULL)
+               memset((void *)addr, 0, size * nmemb);
+
+       return addr;
+}
+
+void *drm_realloc (void *oldpt, size_t oldsize, size_t size, int area) {
+       void *pt;
+
+       if (!(pt = drm_alloc (size, area)))
+               return NULL;
+       if (oldpt && oldsize) {
+               memcpy(pt, oldpt, oldsize);
+               drm_free (oldpt, oldsize, area);
+       }
+       return pt;
+}
+
+void drm_free (void *pt, size_t size, int area) {
+       int alloc_count;
+       int free_count;
+
+       if (!pt)
+               DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
+       else
+               kfree(pt);
+       spin_lock(&drm_mem_lock);
+       drm_mem_stats[area].bytes_freed += size;
+       free_count = ++drm_mem_stats[area].free_count;
+       alloc_count = drm_mem_stats[area].succeed_count;
+       spin_unlock(&drm_mem_lock);
+       if (free_count > alloc_count) {
+               DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
+                             free_count, alloc_count);
+       }
+}
+
+#if __OS_HAS_AGP
+
+DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) {
+       DRM_AGP_MEM *handle;
+
+       if (!pages) {
+               DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n");
+               return NULL;
+       }
+
+       if ((handle = drm_agp_allocate_memory (pages, type))) {
+               spin_lock(&drm_mem_lock);
+               ++drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count;
+               drm_mem_stats[DRM_MEM_TOTALAGP].bytes_allocated
+                   += pages << PAGE_SHIFT;
+               spin_unlock(&drm_mem_lock);
+               return handle;
+       }
+       spin_lock(&drm_mem_lock);
+       ++drm_mem_stats[DRM_MEM_TOTALAGP].fail_count;
+       spin_unlock(&drm_mem_lock);
+       return NULL;
+}
+
+int drm_free_agp (DRM_AGP_MEM * handle, int pages) {
+       int alloc_count;
+       int free_count;
+       int retval = -EINVAL;
+
+       if (!handle) {
+               DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
+                             "Attempt to free NULL AGP handle\n");
+               return retval;
+       }
+
+       if (drm_agp_free_memory (handle)) {
+               spin_lock(&drm_mem_lock);
+               free_count = ++drm_mem_stats[DRM_MEM_TOTALAGP].free_count;
+               alloc_count = drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count;
+               drm_mem_stats[DRM_MEM_TOTALAGP].bytes_freed
+                   += pages << PAGE_SHIFT;
+               spin_unlock(&drm_mem_lock);
+               if (free_count > alloc_count) {
+                       DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
+                                     "Excess frees: %d frees, %d allocs\n",
+                                     free_count, alloc_count);
+               }
+               return 0;
+       }
+       return retval;
+}
+
+int drm_bind_agp (DRM_AGP_MEM * handle, unsigned int start) {
+       int retcode = -EINVAL;
+
+       if (!handle) {
+               DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+                             "Attempt to bind NULL AGP handle\n");
+               return retcode;
+       }
+
+       if (!(retcode = drm_agp_bind_memory (handle, start))) {
+               spin_lock(&drm_mem_lock);
+               ++drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;
+               drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_allocated
+                   += handle->page_count << PAGE_SHIFT;
+               spin_unlock(&drm_mem_lock);
+               return retcode;
+       }
+       spin_lock(&drm_mem_lock);
+       ++drm_mem_stats[DRM_MEM_BOUNDAGP].fail_count;
+       spin_unlock(&drm_mem_lock);
+       return retcode;
+}
+
+int drm_unbind_agp (DRM_AGP_MEM * handle) {
+       int alloc_count;
+       int free_count;
+       int retcode = -EINVAL;
+
+       if (!handle) {
+               DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+                             "Attempt to unbind NULL AGP handle\n");
+               return retcode;
+       }
+
+       if ((retcode = drm_agp_unbind_memory (handle)))
+               return retcode;
+       spin_lock(&drm_mem_lock);
+       free_count = ++drm_mem_stats[DRM_MEM_BOUNDAGP].free_count;
+       alloc_count = drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;
+       drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_freed
+           += handle->page_count << PAGE_SHIFT;
+       spin_unlock(&drm_mem_lock);
+       if (free_count > alloc_count) {
+               DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
+                             "Excess frees: %d frees, %d allocs\n",
+                             free_count, alloc_count);
+       }
+       return retcode;
+}
+#endif
diff --git a/include/drm/drm_os_linux.h b/include/drm/drm_os_linux.h
new file mode 100644 (file)
index 0000000..8dbd257
--- /dev/null
@@ -0,0 +1,108 @@
+/**
+ * \file drm_os_linux.h
+ * OS abstraction macros.
+ */
+
+#include <linux/interrupt.h>   /* For task queue support */
+#include <linux/delay.h>
+
+/** Current process ID */
+#define DRM_CURRENTPID                 task_pid_nr(current)
+#define DRM_SUSER(p)                   capable(CAP_SYS_ADMIN)
+#define DRM_UDELAY(d)                  udelay(d)
+/** Read a byte from a MMIO region */
+#define DRM_READ8(map, offset)         readb(((void __iomem *)(map)->handle) + (offset))
+/** Read a word from a MMIO region */
+#define DRM_READ16(map, offset)         readw(((void __iomem *)(map)->handle) + (offset))
+/** Read a dword from a MMIO region */
+#define DRM_READ32(map, offset)                readl(((void __iomem *)(map)->handle) + (offset))
+/** Write a byte into a MMIO region */
+#define DRM_WRITE8(map, offset, val)   writeb(val, ((void __iomem *)(map)->handle) + (offset))
+/** Write a word into a MMIO region */
+#define DRM_WRITE16(map, offset, val)   writew(val, ((void __iomem *)(map)->handle) + (offset))
+/** Write a dword into a MMIO region */
+#define DRM_WRITE32(map, offset, val)  writel(val, ((void __iomem *)(map)->handle) + (offset))
+/** Read memory barrier */
+#define DRM_READMEMORYBARRIER()                rmb()
+/** Write memory barrier */
+#define DRM_WRITEMEMORYBARRIER()       wmb()
+/** Read/write memory barrier */
+#define DRM_MEMORYBARRIER()            mb()
+
+/** IRQ handler arguments and return type and values */
+#define DRM_IRQ_ARGS           int irq, void *arg
+
+/** AGP types */
+#if __OS_HAS_AGP
+#define DRM_AGP_MEM            struct agp_memory
+#define DRM_AGP_KERN           struct agp_kern_info
+#else
+/* define some dummy types for non AGP supporting kernels */
+struct no_agp_kern {
+       unsigned long aper_base;
+       unsigned long aper_size;
+};
+#define DRM_AGP_MEM             int
+#define DRM_AGP_KERN            struct no_agp_kern
+#endif
+
+#if !(__OS_HAS_MTRR)
+static __inline__ int mtrr_add(unsigned long base, unsigned long size,
+                              unsigned int type, char increment)
+{
+       return -ENODEV;
+}
+
+static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size)
+{
+       return -ENODEV;
+}
+
+#define MTRR_TYPE_WRCOMB     1
+
+#endif
+
+/** Other copying of data to kernel space */
+#define DRM_COPY_FROM_USER(arg1, arg2, arg3)           \
+       copy_from_user(arg1, arg2, arg3)
+/** Other copying of data from kernel space */
+#define DRM_COPY_TO_USER(arg1, arg2, arg3)             \
+       copy_to_user(arg1, arg2, arg3)
+/* Macros for copyfrom user, but checking readability only once */
+#define DRM_VERIFYAREA_READ( uaddr, size )             \
+       (access_ok( VERIFY_READ, uaddr, size ) ? 0 : -EFAULT)
+#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \
+       __copy_from_user(arg1, arg2, arg3)
+#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3)   \
+       __copy_to_user(arg1, arg2, arg3)
+#define DRM_GET_USER_UNCHECKED(val, uaddr)             \
+       __get_user(val, uaddr)
+
+#define DRM_HZ HZ
+
+#define DRM_WAIT_ON( ret, queue, timeout, condition )          \
+do {                                                           \
+       DECLARE_WAITQUEUE(entry, current);                      \
+       unsigned long end = jiffies + (timeout);                \
+       add_wait_queue(&(queue), &entry);                       \
+                                                               \
+       for (;;) {                                              \
+               __set_current_state(TASK_INTERRUPTIBLE);        \
+               if (condition)                                  \
+                       break;                                  \
+               if (time_after_eq(jiffies, end)) {              \
+                       ret = -EBUSY;                           \
+                       break;                                  \
+               }                                               \
+               schedule_timeout((HZ/100 > 1) ? HZ/100 : 1);    \
+               if (signal_pending(current)) {                  \
+                       ret = -EINTR;                           \
+                       break;                                  \
+               }                                               \
+       }                                                       \
+       __set_current_state(TASK_RUNNING);                      \
+       remove_wait_queue(&(queue), &entry);                    \
+} while (0)
+
+#define DRM_WAKEUP( queue ) wake_up_interruptible( queue )
+#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
new file mode 100644 (file)
index 0000000..135bd19
--- /dev/null
@@ -0,0 +1,415 @@
+/*
+   This file is auto-generated from the drm_pciids.txt in the DRM CVS
+   Please contact dri-devel@lists.sf.net to add new cards to this list
+*/
+#define radeon_PCI_IDS \
+       {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP}, \
+       {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \
+       {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+       {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+       {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+       {0x1002, 0x4147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+       {0x1002, 0x4148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+       {0x1002, 0x4149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+       {0x1002, 0x414A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+       {0x1002, 0x414B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+       {0x1002, 0x4150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+       {0x1002, 0x4151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+       {0x1002, 0x4152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+       {0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+       {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+       {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+       {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+       {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \
+       {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
+       {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
+       {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
+       {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \
+       {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+       {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+       {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+       {0x1002, 0x4E47, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
+       {0x1002, 0x4E48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+       {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+       {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+       {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+       {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
+       {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
+       {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
+       {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \
+       {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
+       {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
+       {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
+       {0x1002, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
+       {0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
+       {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
+       {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
+       {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
+       {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
+       {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5954, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+       {0x1002, 0x5955, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+       {0x1002, 0x5974, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+       {0x1002, 0x5975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+       {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+       {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+       {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+       {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+       {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+       {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
+       {0x1002, 0x5a61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+       {0x1002, 0x5a62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS480|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+       {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x710A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x710B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x710C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x710E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x710F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7140, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7141, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7142, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7143, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x714A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x714B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x714C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x714D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x714E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x714F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x715E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x715F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7183, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7186, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7187, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7188, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x718A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x718B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x718C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x718D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x718F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7193, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7196, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x719B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x719F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71C0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71C2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71C3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71C4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71C5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71C6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71C7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71CD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71CE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71D2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71D4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71D5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71D6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x71DE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV530|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7210, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV515|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7244, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7245, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7246, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7247, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7248, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x724A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x724B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x724C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x724D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x724E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x724F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7280, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7281, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7283, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7284, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R580|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7287, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7289, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x728B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x728C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV570|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7290, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7291, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7293, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7297, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x791e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
+       {0x1002, 0x791f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \
+       {0, 0, 0}
+
+#define r128_PCI_IDS \
+       {0x1002, 0x4c45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4c46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4d46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5041, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5042, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5044, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5045, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5046, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5047, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5048, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5049, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x504A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x504B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x504C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x504D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x504E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x504F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5245, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5246, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5247, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x524b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x524c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x534d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x544C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x5452, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0, 0, 0}
+
+#define mga_PCI_IDS \
+       {0x102b, 0x0520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \
+       {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \
+       {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G400}, \
+       {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G550}, \
+       {0, 0, 0}
+
+#define mach64_PCI_IDS \
+       {0x1002, 0x4749, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4742, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4744, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4c49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4c50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4c51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4c42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4c44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x474c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x474f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4752, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4753, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x474d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x474e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4c52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4c53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4c4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1002, 0x4c4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0, 0, 0}
+
+#define sisdrv_PCI_IDS \
+       {0x1039, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1039, 0x5300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1039, 0x6330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
+       {0x1039, 0x6351, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x18CA, 0x0040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
+       {0x18CA, 0x0042, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
+       {0, 0, 0}
+
+#define tdfx_PCI_IDS \
+       {0x121a, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x121a, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x121a, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x121a, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x121a, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x121a, 0x000b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0, 0, 0}
+
+#define viadrv_PCI_IDS \
+       {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \
+       {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x3343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \
+       {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \
+       {0, 0, 0}
+
+#define i810_PCI_IDS \
+       {0x8086, 0x7121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x7123, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x7125, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x1132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0, 0, 0}
+
+#define i830_PCI_IDS \
+       {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0, 0, 0}
+
+#define gamma_PCI_IDS \
+       {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0, 0, 0}
+
+#define savage_PCI_IDS \
+       {0x5333, 0x8a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
+       {0x5333, 0x8a21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
+       {0x5333, 0x8a22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE4}, \
+       {0x5333, 0x8a23, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE4}, \
+       {0x5333, 0x8c10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+       {0x5333, 0x8c11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+       {0x5333, 0x8c12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+       {0x5333, 0x8c13, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE_MX}, \
+       {0x5333, 0x8c22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c24, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c2a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c2b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c2c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8c2f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SUPERSAVAGE}, \
+       {0x5333, 0x8a25, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGE}, \
+       {0x5333, 0x8a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGE}, \
+       {0x5333, 0x8d01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_TWISTER}, \
+       {0x5333, 0x8d02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_TWISTER}, \
+       {0x5333, 0x8d03, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGEDDR}, \
+       {0x5333, 0x8d04, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGEDDR}, \
+       {0, 0, 0}
+
+#define ffb_PCI_IDS \
+       {0, 0, 0}
+
+#define i915_PCI_IDS \
+       {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x258a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x27ae, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2972, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x29b2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x29c2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x29d2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2a02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2a12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2a42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2e02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2e12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0x8086, 0x2e22, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+       {0, 0, 0}
diff --git a/include/drm/drm_sarea.h b/include/drm/drm_sarea.h
new file mode 100644 (file)
index 0000000..4800373
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+ * \file drm_sarea.h
+ * \brief SAREA definitions
+ *
+ * \author Michel Dänzer <michel@daenzer.net>
+ */
+
+/*
+ * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DRM_SAREA_H_
+#define _DRM_SAREA_H_
+
+#include "drm.h"
+
+/* SAREA area needs to be at least a page */
+#if defined(__alpha__)
+#define SAREA_MAX                       0x2000
+#elif defined(__ia64__)
+#define SAREA_MAX                       0x10000        /* 64kB */
+#else
+/* Intel 830M driver needs at least 8k SAREA */
+#define SAREA_MAX                       0x2000
+#endif
+
+/** Maximum number of drawables in the SAREA */
+#define SAREA_MAX_DRAWABLES            256
+
+#define SAREA_DRAWABLE_CLAIMED_ENTRY    0x80000000
+
+/** SAREA drawable */
+struct drm_sarea_drawable {
+       unsigned int stamp;
+       unsigned int flags;
+};
+
+/** SAREA frame */
+struct drm_sarea_frame {
+       unsigned int x;
+       unsigned int y;
+       unsigned int width;
+       unsigned int height;
+       unsigned int fullscreen;
+};
+
+/** SAREA */
+struct drm_sarea {
+    /** first thing is always the DRM locking structure */
+       struct drm_hw_lock lock;
+    /** \todo Use readers/writer lock for drm_sarea::drawable_lock */
+       struct drm_hw_lock drawable_lock;
+       struct drm_sarea_drawable drawableTable[SAREA_MAX_DRAWABLES];   /**< drawables */
+       struct drm_sarea_frame frame;   /**< frame */
+       drm_context_t dummy_context;
+};
+
+#ifndef __KERNEL__
+typedef struct drm_sarea_drawable drm_sarea_drawable_t;
+typedef struct drm_sarea_frame drm_sarea_frame_t;
+typedef struct drm_sarea drm_sarea_t;
+#endif
+
+#endif                         /* _DRM_SAREA_H_ */
diff --git a/include/drm/drm_sman.h b/include/drm/drm_sman.h
new file mode 100644 (file)
index 0000000..08ecf83
--- /dev/null
@@ -0,0 +1,176 @@
+/**************************************************************************
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+/*
+ * Simple memory MANager interface that keeps track on allocate regions on a
+ * per "owner" basis. All regions associated with an "owner" can be released
+ * with a simple call. Typically if the "owner" exists. The owner is any
+ * "unsigned long" identifier. Can typically be a pointer to a file private
+ * struct or a context identifier.
+ *
+ * Authors:
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef DRM_SMAN_H
+#define DRM_SMAN_H
+
+#include "drmP.h"
+#include "drm_hashtab.h"
+
+/*
+ * A class that is an abstration of a simple memory allocator.
+ * The sman implementation provides a default such allocator
+ * using the drm_mm.c implementation. But the user can replace it.
+ * See the SiS implementation, which may use the SiS FB kernel module
+ * for memory management.
+ */
+
+struct drm_sman_mm {
+       /* private info. If allocated, needs to be destroyed by the destroy
+          function */
+       void *private;
+
+       /* Allocate a memory block with given size and alignment.
+          Return an opaque reference to the memory block */
+
+       void *(*allocate) (void *private, unsigned long size,
+                          unsigned alignment);
+
+       /* Free a memory block. "ref" is the opaque reference that we got from
+          the "alloc" function */
+
+       void (*free) (void *private, void *ref);
+
+       /* Free all resources associated with this allocator */
+
+       void (*destroy) (void *private);
+
+       /* Return a memory offset from the opaque reference returned from the
+          "alloc" function */
+
+       unsigned long (*offset) (void *private, void *ref);
+};
+
+struct drm_memblock_item {
+       struct list_head owner_list;
+       struct drm_hash_item user_hash;
+       void *mm_info;
+       struct drm_sman_mm *mm;
+       struct drm_sman *sman;
+};
+
+struct drm_sman {
+       struct drm_sman_mm *mm;
+       int num_managers;
+       struct drm_open_hash owner_hash_tab;
+       struct drm_open_hash user_hash_tab;
+       struct list_head owner_items;
+};
+
+/*
+ * Take down a memory manager. This function should only be called after a
+ * successful init and after a call to drm_sman_cleanup.
+ */
+
+extern void drm_sman_takedown(struct drm_sman * sman);
+
+/*
+ * Allocate structures for a manager.
+ * num_managers are the number of memory pools to manage. (VRAM, AGP, ....)
+ * user_order is the log2 of the number of buckets in the user hash table.
+ *         set this to approximately log2 of the max number of memory regions
+ *         that will be allocated for _all_ pools together.
+ * owner_order is the log2 of the number of buckets in the owner hash table.
+ *         set this to approximately log2 of
+ *         the number of client file connections that will
+ *         be using the manager.
+ *
+ */
+
+extern int drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
+                        unsigned int user_order, unsigned int owner_order);
+
+/*
+ * Initialize a drm_mm.c allocator. Should be called only once for each
+ * manager unless a customized allogator is used.
+ */
+
+extern int drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
+                             unsigned long start, unsigned long size);
+
+/*
+ * Initialize a customized allocator for one of the managers.
+ * (See the SiS module). The object pointed to by "allocator" is copied,
+ * so it can be destroyed after this call.
+ */
+
+extern int drm_sman_set_manager(struct drm_sman * sman, unsigned int mananger,
+                               struct drm_sman_mm * allocator);
+
+/*
+ * Allocate a memory block. Aligment is not implemented yet.
+ */
+
+extern struct drm_memblock_item *drm_sman_alloc(struct drm_sman * sman,
+                                               unsigned int manager,
+                                               unsigned long size,
+                                               unsigned alignment,
+                                               unsigned long owner);
+/*
+ * Free a memory block identified by its user hash key.
+ */
+
+extern int drm_sman_free_key(struct drm_sman * sman, unsigned int key);
+
+/*
+ * returns 1 iff there are no stale memory blocks associated with this owner.
+ * Typically called to determine if we need to idle the hardware and call
+ * drm_sman_owner_cleanup. If there are no stale memory blocks, it removes all
+ * resources associated with owner.
+ */
+
+extern int drm_sman_owner_clean(struct drm_sman * sman, unsigned long owner);
+
+/*
+ * Frees all stale memory blocks associated with this owner. Note that this
+ * requires that the hardware is finished with all blocks, so the graphics engine
+ * should be idled before this call is made. This function also frees
+ * any resources associated with "owner" and should be called when owner
+ * is not going to be referenced anymore.
+ */
+
+extern void drm_sman_owner_cleanup(struct drm_sman * sman, unsigned long owner);
+
+/*
+ * Frees all stale memory blocks associated with the memory manager.
+ * See idling above.
+ */
+
+extern void drm_sman_cleanup(struct drm_sman * sman);
+
+#endif
diff --git a/include/drm/i810_drm.h b/include/drm/i810_drm.h
new file mode 100644 (file)
index 0000000..7a10bb6
--- /dev/null
@@ -0,0 +1,281 @@
+#ifndef _I810_DRM_H_
+#define _I810_DRM_H_
+
+/* WARNING: These defines must be the same as what the Xserver uses.
+ * if you change them, you must change the defines in the Xserver.
+ */
+
+#ifndef _I810_DEFINES_
+#define _I810_DEFINES_
+
+#define I810_DMA_BUF_ORDER             12
+#define I810_DMA_BUF_SZ                (1<<I810_DMA_BUF_ORDER)
+#define I810_DMA_BUF_NR                256
+#define I810_NR_SAREA_CLIPRECTS        8
+
+/* Each region is a minimum of 64k, and there are at most 64 of them.
+ */
+#define I810_NR_TEX_REGIONS 64
+#define I810_LOG_MIN_TEX_REGION_SIZE 16
+#endif
+
+#define I810_UPLOAD_TEX0IMAGE  0x1     /* handled clientside */
+#define I810_UPLOAD_TEX1IMAGE  0x2     /* handled clientside */
+#define I810_UPLOAD_CTX        0x4
+#define I810_UPLOAD_BUFFERS    0x8
+#define I810_UPLOAD_TEX0       0x10
+#define I810_UPLOAD_TEX1       0x20
+#define I810_UPLOAD_CLIPRECTS  0x40
+
+/* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer.  These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+/* Destbuffer state
+ *    - backbuffer linear offset and pitch -- invarient in the current dri
+ *    - zbuffer linear offset and pitch -- also invarient
+ *    - drawing origin in back and depth buffers.
+ *
+ * Keep the depth/back buffer state here to accommodate private buffers
+ * in the future.
+ */
+#define I810_DESTREG_DI0  0    /* CMD_OP_DESTBUFFER_INFO (2 dwords) */
+#define I810_DESTREG_DI1  1
+#define I810_DESTREG_DV0  2    /* GFX_OP_DESTBUFFER_VARS (2 dwords) */
+#define I810_DESTREG_DV1  3
+#define I810_DESTREG_DR0  4    /* GFX_OP_DRAWRECT_INFO (4 dwords) */
+#define I810_DESTREG_DR1  5
+#define I810_DESTREG_DR2  6
+#define I810_DESTREG_DR3  7
+#define I810_DESTREG_DR4  8
+#define I810_DEST_SETUP_SIZE 10
+
+/* Context state
+ */
+#define I810_CTXREG_CF0   0    /* GFX_OP_COLOR_FACTOR */
+#define I810_CTXREG_CF1   1
+#define I810_CTXREG_ST0   2    /* GFX_OP_STIPPLE */
+#define I810_CTXREG_ST1   3
+#define I810_CTXREG_VF    4    /* GFX_OP_VERTEX_FMT */
+#define I810_CTXREG_MT    5    /* GFX_OP_MAP_TEXELS */
+#define I810_CTXREG_MC0   6    /* GFX_OP_MAP_COLOR_STAGES - stage 0 */
+#define I810_CTXREG_MC1   7    /* GFX_OP_MAP_COLOR_STAGES - stage 1 */
+#define I810_CTXREG_MC2   8    /* GFX_OP_MAP_COLOR_STAGES - stage 2 */
+#define I810_CTXREG_MA0   9    /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */
+#define I810_CTXREG_MA1   10   /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */
+#define I810_CTXREG_MA2   11   /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */
+#define I810_CTXREG_SDM   12   /* GFX_OP_SRC_DEST_MONO */
+#define I810_CTXREG_FOG   13   /* GFX_OP_FOG_COLOR */
+#define I810_CTXREG_B1    14   /* GFX_OP_BOOL_1 */
+#define I810_CTXREG_B2    15   /* GFX_OP_BOOL_2 */
+#define I810_CTXREG_LCS   16   /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */
+#define I810_CTXREG_PV    17   /* GFX_OP_PV_RULE -- Invarient! */
+#define I810_CTXREG_ZA    18   /* GFX_OP_ZBIAS_ALPHAFUNC */
+#define I810_CTXREG_AA    19   /* GFX_OP_ANTIALIAS */
+#define I810_CTX_SETUP_SIZE 20
+
+/* Texture state (per tex unit)
+ */
+#define I810_TEXREG_MI0  0     /* GFX_OP_MAP_INFO (4 dwords) */
+#define I810_TEXREG_MI1  1
+#define I810_TEXREG_MI2  2
+#define I810_TEXREG_MI3  3
+#define I810_TEXREG_MF   4     /* GFX_OP_MAP_FILTER */
+#define I810_TEXREG_MLC  5     /* GFX_OP_MAP_LOD_CTL */
+#define I810_TEXREG_MLL  6     /* GFX_OP_MAP_LOD_LIMITS */
+#define I810_TEXREG_MCS  7     /* GFX_OP_MAP_COORD_SETS ??? */
+#define I810_TEX_SETUP_SIZE 8
+
+/* Flags for clear ioctl
+ */
+#define I810_FRONT   0x1
+#define I810_BACK    0x2
+#define I810_DEPTH   0x4
+
+typedef enum _drm_i810_init_func {
+       I810_INIT_DMA = 0x01,
+       I810_CLEANUP_DMA = 0x02,
+       I810_INIT_DMA_1_4 = 0x03
+} drm_i810_init_func_t;
+
+/* This is the init structure after v1.2 */
+typedef struct _drm_i810_init {
+       drm_i810_init_func_t func;
+       unsigned int mmio_offset;
+       unsigned int buffers_offset;
+       int sarea_priv_offset;
+       unsigned int ring_start;
+       unsigned int ring_end;
+       unsigned int ring_size;
+       unsigned int front_offset;
+       unsigned int back_offset;
+       unsigned int depth_offset;
+       unsigned int overlay_offset;
+       unsigned int overlay_physical;
+       unsigned int w;
+       unsigned int h;
+       unsigned int pitch;
+       unsigned int pitch_bits;
+} drm_i810_init_t;
+
+/* This is the init structure prior to v1.2 */
+typedef struct _drm_i810_pre12_init {
+       drm_i810_init_func_t func;
+       unsigned int mmio_offset;
+       unsigned int buffers_offset;
+       int sarea_priv_offset;
+       unsigned int ring_start;
+       unsigned int ring_end;
+       unsigned int ring_size;
+       unsigned int front_offset;
+       unsigned int back_offset;
+       unsigned int depth_offset;
+       unsigned int w;
+       unsigned int h;
+       unsigned int pitch;
+       unsigned int pitch_bits;
+} drm_i810_pre12_init_t;
+
+/* Warning: If you change the SAREA structure you must change the Xserver
+ * structure as well */
+
+typedef struct _drm_i810_tex_region {
+       unsigned char next, prev;       /* indices to form a circular LRU  */
+       unsigned char in_use;   /* owned by a client, or free? */
+       int age;                /* tracked by clients to update local LRU's */
+} drm_i810_tex_region_t;
+
+typedef struct _drm_i810_sarea {
+       unsigned int ContextState[I810_CTX_SETUP_SIZE];
+       unsigned int BufferState[I810_DEST_SETUP_SIZE];
+       unsigned int TexState[2][I810_TEX_SETUP_SIZE];
+       unsigned int dirty;
+
+       unsigned int nbox;
+       struct drm_clip_rect boxes[I810_NR_SAREA_CLIPRECTS];
+
+       /* Maintain an LRU of contiguous regions of texture space.  If
+        * you think you own a region of texture memory, and it has an
+        * age different to the one you set, then you are mistaken and
+        * it has been stolen by another client.  If global texAge
+        * hasn't changed, there is no need to walk the list.
+        *
+        * These regions can be used as a proxy for the fine-grained
+        * texture information of other clients - by maintaining them
+        * in the same lru which is used to age their own textures,
+        * clients have an approximate lru for the whole of global
+        * texture space, and can make informed decisions as to which
+        * areas to kick out.  There is no need to choose whether to
+        * kick out your own texture or someone else's - simply eject
+        * them all in LRU order.
+        */
+
+       drm_i810_tex_region_t texList[I810_NR_TEX_REGIONS + 1];
+       /* Last elt is sentinal */
+       int texAge;             /* last time texture was uploaded */
+       int last_enqueue;       /* last time a buffer was enqueued */
+       int last_dispatch;      /* age of the most recently dispatched buffer */
+       int last_quiescent;     /*  */
+       int ctxOwner;           /* last context to upload state */
+
+       int vertex_prim;
+
+       int pf_enabled;         /* is pageflipping allowed? */
+       int pf_active;
+       int pf_current_page;    /* which buffer is being displayed? */
+} drm_i810_sarea_t;
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmMga.h)
+ */
+
+/* i810 specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_I810_INIT          0x00
+#define DRM_I810_VERTEX                0x01
+#define DRM_I810_CLEAR         0x02
+#define DRM_I810_FLUSH         0x03
+#define DRM_I810_GETAGE                0x04
+#define DRM_I810_GETBUF                0x05
+#define DRM_I810_SWAP          0x06
+#define DRM_I810_COPY          0x07
+#define DRM_I810_DOCOPY                0x08
+#define DRM_I810_OV0INFO       0x09
+#define DRM_I810_FSTATUS       0x0a
+#define DRM_I810_OV0FLIP       0x0b
+#define DRM_I810_MC            0x0c
+#define DRM_I810_RSTATUS       0x0d
+#define DRM_I810_FLIP          0x0e
+
+#define DRM_IOCTL_I810_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I810_INIT, drm_i810_init_t)
+#define DRM_IOCTL_I810_VERTEX          DRM_IOW( DRM_COMMAND_BASE + DRM_I810_VERTEX, drm_i810_vertex_t)
+#define DRM_IOCTL_I810_CLEAR           DRM_IOW( DRM_COMMAND_BASE + DRM_I810_CLEAR, drm_i810_clear_t)
+#define DRM_IOCTL_I810_FLUSH           DRM_IO(  DRM_COMMAND_BASE + DRM_I810_FLUSH)
+#define DRM_IOCTL_I810_GETAGE          DRM_IO(  DRM_COMMAND_BASE + DRM_I810_GETAGE)
+#define DRM_IOCTL_I810_GETBUF          DRM_IOWR(DRM_COMMAND_BASE + DRM_I810_GETBUF, drm_i810_dma_t)
+#define DRM_IOCTL_I810_SWAP            DRM_IO(  DRM_COMMAND_BASE + DRM_I810_SWAP)
+#define DRM_IOCTL_I810_COPY            DRM_IOW( DRM_COMMAND_BASE + DRM_I810_COPY, drm_i810_copy_t)
+#define DRM_IOCTL_I810_DOCOPY          DRM_IO(  DRM_COMMAND_BASE + DRM_I810_DOCOPY)
+#define DRM_IOCTL_I810_OV0INFO         DRM_IOR( DRM_COMMAND_BASE + DRM_I810_OV0INFO, drm_i810_overlay_t)
+#define DRM_IOCTL_I810_FSTATUS         DRM_IO ( DRM_COMMAND_BASE + DRM_I810_FSTATUS)
+#define DRM_IOCTL_I810_OV0FLIP         DRM_IO ( DRM_COMMAND_BASE + DRM_I810_OV0FLIP)
+#define DRM_IOCTL_I810_MC              DRM_IOW( DRM_COMMAND_BASE + DRM_I810_MC, drm_i810_mc_t)
+#define DRM_IOCTL_I810_RSTATUS         DRM_IO ( DRM_COMMAND_BASE + DRM_I810_RSTATUS)
+#define DRM_IOCTL_I810_FLIP             DRM_IO ( DRM_COMMAND_BASE + DRM_I810_FLIP)
+
+typedef struct _drm_i810_clear {
+       int clear_color;
+       int clear_depth;
+       int flags;
+} drm_i810_clear_t;
+
+/* These may be placeholders if we have more cliprects than
+ * I810_NR_SAREA_CLIPRECTS.  In that case, the client sets discard to
+ * false, indicating that the buffer will be dispatched again with a
+ * new set of cliprects.
+ */
+typedef struct _drm_i810_vertex {
+       int idx;                /* buffer index */
+       int used;               /* nr bytes in use */
+       int discard;            /* client is finished with the buffer? */
+} drm_i810_vertex_t;
+
+typedef struct _drm_i810_copy_t {
+       int idx;                /* buffer index */
+       int used;               /* nr bytes in use */
+       void *address;          /* Address to copy from */
+} drm_i810_copy_t;
+
+#define PR_TRIANGLES         (0x0<<18)
+#define PR_TRISTRIP_0        (0x1<<18)
+#define PR_TRISTRIP_1        (0x2<<18)
+#define PR_TRIFAN            (0x3<<18)
+#define PR_POLYGON           (0x4<<18)
+#define PR_LINES             (0x5<<18)
+#define PR_LINESTRIP         (0x6<<18)
+#define PR_RECTS             (0x7<<18)
+#define PR_MASK              (0x7<<18)
+
+typedef struct drm_i810_dma {
+       void *virtual;
+       int request_idx;
+       int request_size;
+       int granted;
+} drm_i810_dma_t;
+
+typedef struct _drm_i810_overlay_t {
+       unsigned int offset;    /* Address of the Overlay Regs */
+       unsigned int physical;
+} drm_i810_overlay_t;
+
+typedef struct _drm_i810_mc {
+       int idx;                /* buffer index */
+       int used;               /* nr bytes in use */
+       int num_blocks;         /* number of GFXBlocks */
+       int *length;            /* List of lengths for GFXBlocks (FUTURE) */
+       unsigned int last_render;       /* Last Render Request */
+} drm_i810_mc_t;
+
+#endif                         /* _I810_DRM_H_ */
diff --git a/include/drm/i830_drm.h b/include/drm/i830_drm.h
new file mode 100644 (file)
index 0000000..4b00d2d
--- /dev/null
@@ -0,0 +1,342 @@
+#ifndef _I830_DRM_H_
+#define _I830_DRM_H_
+
+/* WARNING: These defines must be the same as what the Xserver uses.
+ * if you change them, you must change the defines in the Xserver.
+ *
+ * KW: Actually, you can't ever change them because doing so would
+ * break backwards compatibility.
+ */
+
+#ifndef _I830_DEFINES_
+#define _I830_DEFINES_
+
+#define I830_DMA_BUF_ORDER             12
+#define I830_DMA_BUF_SZ                        (1<<I830_DMA_BUF_ORDER)
+#define I830_DMA_BUF_NR                        256
+#define I830_NR_SAREA_CLIPRECTS                8
+
+/* Each region is a minimum of 64k, and there are at most 64 of them.
+ */
+#define I830_NR_TEX_REGIONS 64
+#define I830_LOG_MIN_TEX_REGION_SIZE 16
+
+/* KW: These aren't correct but someone set them to two and then
+ * released the module.  Now we can't change them as doing so would
+ * break backwards compatibility.
+ */
+#define I830_TEXTURE_COUNT     2
+#define I830_TEXBLEND_COUNT    I830_TEXTURE_COUNT
+
+#define I830_TEXBLEND_SIZE     12      /* (4 args + op) * 2 + COLOR_FACTOR */
+
+#define I830_UPLOAD_CTX                        0x1
+#define I830_UPLOAD_BUFFERS            0x2
+#define I830_UPLOAD_CLIPRECTS          0x4
+#define I830_UPLOAD_TEX0_IMAGE         0x100   /* handled clientside */
+#define I830_UPLOAD_TEX0_CUBE          0x200   /* handled clientside */
+#define I830_UPLOAD_TEX1_IMAGE         0x400   /* handled clientside */
+#define I830_UPLOAD_TEX1_CUBE          0x800   /* handled clientside */
+#define I830_UPLOAD_TEX2_IMAGE         0x1000  /* handled clientside */
+#define I830_UPLOAD_TEX2_CUBE          0x2000  /* handled clientside */
+#define I830_UPLOAD_TEX3_IMAGE         0x4000  /* handled clientside */
+#define I830_UPLOAD_TEX3_CUBE          0x8000  /* handled clientside */
+#define I830_UPLOAD_TEX_N_IMAGE(n)     (0x100 << (n * 2))
+#define I830_UPLOAD_TEX_N_CUBE(n)      (0x200 << (n * 2))
+#define I830_UPLOAD_TEXIMAGE_MASK      0xff00
+#define I830_UPLOAD_TEX0                       0x10000
+#define I830_UPLOAD_TEX1                       0x20000
+#define I830_UPLOAD_TEX2                       0x40000
+#define I830_UPLOAD_TEX3                       0x80000
+#define I830_UPLOAD_TEX_N(n)           (0x10000 << (n))
+#define I830_UPLOAD_TEX_MASK           0xf0000
+#define I830_UPLOAD_TEXBLEND0          0x100000
+#define I830_UPLOAD_TEXBLEND1          0x200000
+#define I830_UPLOAD_TEXBLEND2          0x400000
+#define I830_UPLOAD_TEXBLEND3          0x800000
+#define I830_UPLOAD_TEXBLEND_N(n)      (0x100000 << (n))
+#define I830_UPLOAD_TEXBLEND_MASK      0xf00000
+#define I830_UPLOAD_TEX_PALETTE_N(n)    (0x1000000 << (n))
+#define I830_UPLOAD_TEX_PALETTE_SHARED 0x4000000
+#define I830_UPLOAD_STIPPLE            0x8000000
+
+/* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer.  These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+/* Destbuffer state
+ *    - backbuffer linear offset and pitch -- invarient in the current dri
+ *    - zbuffer linear offset and pitch -- also invarient
+ *    - drawing origin in back and depth buffers.
+ *
+ * Keep the depth/back buffer state here to accommodate private buffers
+ * in the future.
+ */
+
+#define I830_DESTREG_CBUFADDR 0
+#define I830_DESTREG_DBUFADDR 1
+#define I830_DESTREG_DV0 2
+#define I830_DESTREG_DV1 3
+#define I830_DESTREG_SENABLE 4
+#define I830_DESTREG_SR0 5
+#define I830_DESTREG_SR1 6
+#define I830_DESTREG_SR2 7
+#define I830_DESTREG_DR0 8
+#define I830_DESTREG_DR1 9
+#define I830_DESTREG_DR2 10
+#define I830_DESTREG_DR3 11
+#define I830_DESTREG_DR4 12
+#define I830_DEST_SETUP_SIZE 13
+
+/* Context state
+ */
+#define I830_CTXREG_STATE1             0
+#define I830_CTXREG_STATE2             1
+#define I830_CTXREG_STATE3             2
+#define I830_CTXREG_STATE4             3
+#define I830_CTXREG_STATE5             4
+#define I830_CTXREG_IALPHAB            5
+#define I830_CTXREG_STENCILTST         6
+#define I830_CTXREG_ENABLES_1          7
+#define I830_CTXREG_ENABLES_2          8
+#define I830_CTXREG_AA                 9
+#define I830_CTXREG_FOGCOLOR           10
+#define I830_CTXREG_BLENDCOLR0         11
+#define I830_CTXREG_BLENDCOLR          12      /* Dword 1 of 2 dword command */
+#define I830_CTXREG_VF                 13
+#define I830_CTXREG_VF2                        14
+#define I830_CTXREG_MCSB0              15
+#define I830_CTXREG_MCSB1              16
+#define I830_CTX_SETUP_SIZE            17
+
+/* 1.3: Stipple state
+ */
+#define I830_STPREG_ST0 0
+#define I830_STPREG_ST1 1
+#define I830_STP_SETUP_SIZE 2
+
+/* Texture state (per tex unit)
+ */
+
+#define I830_TEXREG_MI0        0       /* GFX_OP_MAP_INFO (6 dwords) */
+#define I830_TEXREG_MI1        1
+#define I830_TEXREG_MI2        2
+#define I830_TEXREG_MI3        3
+#define I830_TEXREG_MI4        4
+#define I830_TEXREG_MI5        5
+#define I830_TEXREG_MF 6       /* GFX_OP_MAP_FILTER */
+#define I830_TEXREG_MLC        7       /* GFX_OP_MAP_LOD_CTL */
+#define I830_TEXREG_MLL        8       /* GFX_OP_MAP_LOD_LIMITS */
+#define I830_TEXREG_MCS        9       /* GFX_OP_MAP_COORD_SETS */
+#define I830_TEX_SETUP_SIZE 10
+
+#define I830_TEXREG_TM0LI      0       /* load immediate 2 texture map n */
+#define I830_TEXREG_TM0S0      1
+#define I830_TEXREG_TM0S1      2
+#define I830_TEXREG_TM0S2      3
+#define I830_TEXREG_TM0S3      4
+#define I830_TEXREG_TM0S4      5
+#define I830_TEXREG_NOP0       6       /* noop */
+#define I830_TEXREG_NOP1       7       /* noop */
+#define I830_TEXREG_NOP2       8       /* noop */
+#define __I830_TEXREG_MCS      9       /* GFX_OP_MAP_COORD_SETS -- shared */
+#define __I830_TEX_SETUP_SIZE   10
+
+#define I830_FRONT   0x1
+#define I830_BACK    0x2
+#define I830_DEPTH   0x4
+
+#endif                         /* _I830_DEFINES_ */
+
+typedef struct _drm_i830_init {
+       enum {
+               I830_INIT_DMA = 0x01,
+               I830_CLEANUP_DMA = 0x02
+       } func;
+       unsigned int mmio_offset;
+       unsigned int buffers_offset;
+       int sarea_priv_offset;
+       unsigned int ring_start;
+       unsigned int ring_end;
+       unsigned int ring_size;
+       unsigned int front_offset;
+       unsigned int back_offset;
+       unsigned int depth_offset;
+       unsigned int w;
+       unsigned int h;
+       unsigned int pitch;
+       unsigned int pitch_bits;
+       unsigned int back_pitch;
+       unsigned int depth_pitch;
+       unsigned int cpp;
+} drm_i830_init_t;
+
+/* Warning: If you change the SAREA structure you must change the Xserver
+ * structure as well */
+
+typedef struct _drm_i830_tex_region {
+       unsigned char next, prev;       /* indices to form a circular LRU  */
+       unsigned char in_use;   /* owned by a client, or free? */
+       int age;                /* tracked by clients to update local LRU's */
+} drm_i830_tex_region_t;
+
+typedef struct _drm_i830_sarea {
+       unsigned int ContextState[I830_CTX_SETUP_SIZE];
+       unsigned int BufferState[I830_DEST_SETUP_SIZE];
+       unsigned int TexState[I830_TEXTURE_COUNT][I830_TEX_SETUP_SIZE];
+       unsigned int TexBlendState[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE];
+       unsigned int TexBlendStateWordsUsed[I830_TEXBLEND_COUNT];
+       unsigned int Palette[2][256];
+       unsigned int dirty;
+
+       unsigned int nbox;
+       struct drm_clip_rect boxes[I830_NR_SAREA_CLIPRECTS];
+
+       /* Maintain an LRU of contiguous regions of texture space.  If
+        * you think you own a region of texture memory, and it has an
+        * age different to the one you set, then you are mistaken and
+        * it has been stolen by another client.  If global texAge
+        * hasn't changed, there is no need to walk the list.
+        *
+        * These regions can be used as a proxy for the fine-grained
+        * texture information of other clients - by maintaining them
+        * in the same lru which is used to age their own textures,
+        * clients have an approximate lru for the whole of global
+        * texture space, and can make informed decisions as to which
+        * areas to kick out.  There is no need to choose whether to
+        * kick out your own texture or someone else's - simply eject
+        * them all in LRU order.
+        */
+
+       drm_i830_tex_region_t texList[I830_NR_TEX_REGIONS + 1];
+       /* Last elt is sentinal */
+       int texAge;             /* last time texture was uploaded */
+       int last_enqueue;       /* last time a buffer was enqueued */
+       int last_dispatch;      /* age of the most recently dispatched buffer */
+       int last_quiescent;     /*  */
+       int ctxOwner;           /* last context to upload state */
+
+       int vertex_prim;
+
+       int pf_enabled;         /* is pageflipping allowed? */
+       int pf_active;
+       int pf_current_page;    /* which buffer is being displayed? */
+
+       int perf_boxes;         /* performance boxes to be displayed */
+
+       /* Here's the state for texunits 2,3:
+        */
+       unsigned int TexState2[I830_TEX_SETUP_SIZE];
+       unsigned int TexBlendState2[I830_TEXBLEND_SIZE];
+       unsigned int TexBlendStateWordsUsed2;
+
+       unsigned int TexState3[I830_TEX_SETUP_SIZE];
+       unsigned int TexBlendState3[I830_TEXBLEND_SIZE];
+       unsigned int TexBlendStateWordsUsed3;
+
+       unsigned int StippleState[I830_STP_SETUP_SIZE];
+} drm_i830_sarea_t;
+
+/* Flags for perf_boxes
+ */
+#define I830_BOX_RING_EMPTY    0x1     /* populated by kernel */
+#define I830_BOX_FLIP          0x2     /* populated by kernel */
+#define I830_BOX_WAIT          0x4     /* populated by kernel & client */
+#define I830_BOX_TEXTURE_LOAD  0x8     /* populated by kernel */
+#define I830_BOX_LOST_CONTEXT  0x10    /* populated by client */
+
+/* I830 specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_I830_INIT  0x00
+#define DRM_I830_VERTEX        0x01
+#define DRM_I830_CLEAR 0x02
+#define DRM_I830_FLUSH 0x03
+#define DRM_I830_GETAGE        0x04
+#define DRM_I830_GETBUF        0x05
+#define DRM_I830_SWAP  0x06
+#define DRM_I830_COPY  0x07
+#define DRM_I830_DOCOPY        0x08
+#define DRM_I830_FLIP  0x09
+#define DRM_I830_IRQ_EMIT      0x0a
+#define DRM_I830_IRQ_WAIT      0x0b
+#define DRM_I830_GETPARAM      0x0c
+#define DRM_I830_SETPARAM      0x0d
+
+#define DRM_IOCTL_I830_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_INIT, drm_i830_init_t)
+#define DRM_IOCTL_I830_VERTEX          DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_VERTEX, drm_i830_vertex_t)
+#define DRM_IOCTL_I830_CLEAR           DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_CLEAR, drm_i830_clear_t)
+#define DRM_IOCTL_I830_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_FLUSH)
+#define DRM_IOCTL_I830_GETAGE          DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_GETAGE)
+#define DRM_IOCTL_I830_GETBUF          DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_GETBUF, drm_i830_dma_t)
+#define DRM_IOCTL_I830_SWAP            DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_SWAP)
+#define DRM_IOCTL_I830_COPY            DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_COPY, drm_i830_copy_t)
+#define DRM_IOCTL_I830_DOCOPY          DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_DOCOPY)
+#define DRM_IOCTL_I830_FLIP            DRM_IO ( DRM_COMMAND_BASE + DRM_IOCTL_I830_FLIP)
+#define DRM_IOCTL_I830_IRQ_EMIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_IRQ_EMIT, drm_i830_irq_emit_t)
+#define DRM_IOCTL_I830_IRQ_WAIT         DRM_IOW( DRM_COMMAND_BASE + DRM_IOCTL_I830_IRQ_WAIT, drm_i830_irq_wait_t)
+#define DRM_IOCTL_I830_GETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_GETPARAM, drm_i830_getparam_t)
+#define DRM_IOCTL_I830_SETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_IOCTL_I830_SETPARAM, drm_i830_setparam_t)
+
+typedef struct _drm_i830_clear {
+       int clear_color;
+       int clear_depth;
+       int flags;
+       unsigned int clear_colormask;
+       unsigned int clear_depthmask;
+} drm_i830_clear_t;
+
+/* These may be placeholders if we have more cliprects than
+ * I830_NR_SAREA_CLIPRECTS.  In that case, the client sets discard to
+ * false, indicating that the buffer will be dispatched again with a
+ * new set of cliprects.
+ */
+typedef struct _drm_i830_vertex {
+       int idx;                /* buffer index */
+       int used;               /* nr bytes in use */
+       int discard;            /* client is finished with the buffer? */
+} drm_i830_vertex_t;
+
+typedef struct _drm_i830_copy_t {
+       int idx;                /* buffer index */
+       int used;               /* nr bytes in use */
+       void __user *address;   /* Address to copy from */
+} drm_i830_copy_t;
+
+typedef struct drm_i830_dma {
+       void __user *virtual;
+       int request_idx;
+       int request_size;
+       int granted;
+} drm_i830_dma_t;
+
+/* 1.3: Userspace can request & wait on irq's:
+ */
+typedef struct drm_i830_irq_emit {
+       int __user *irq_seq;
+} drm_i830_irq_emit_t;
+
+typedef struct drm_i830_irq_wait {
+       int irq_seq;
+} drm_i830_irq_wait_t;
+
+/* 1.3: New ioctl to query kernel params:
+ */
+#define I830_PARAM_IRQ_ACTIVE            1
+
+typedef struct drm_i830_getparam {
+       int param;
+       int __user *value;
+} drm_i830_getparam_t;
+
+/* 1.3: New ioctl to set kernel params:
+ */
+#define I830_SETPARAM_USE_MI_BATCHBUFFER_START            1
+
+typedef struct drm_i830_setparam {
+       int param;
+       int value;
+} drm_i830_setparam_t;
+
+#endif                         /* _I830_DRM_H_ */
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
new file mode 100644 (file)
index 0000000..05c66cf
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _I915_DRM_H_
+#define _I915_DRM_H_
+
+/* Please note that modifications to all structs defined here are
+ * subject to backwards-compatibility constraints.
+ */
+
+#include "drm.h"
+
+/* Each region is a minimum of 16k, and there are at most 255 of them.
+ */
+#define I915_NR_TEX_REGIONS 255        /* table size 2k - maximum due to use
+                                * of chars for next/prev indices */
+#define I915_LOG_MIN_TEX_REGION_SIZE 14
+
+typedef struct _drm_i915_init {
+       enum {
+               I915_INIT_DMA = 0x01,
+               I915_CLEANUP_DMA = 0x02,
+               I915_RESUME_DMA = 0x03
+       } func;
+       unsigned int mmio_offset;
+       int sarea_priv_offset;
+       unsigned int ring_start;
+       unsigned int ring_end;
+       unsigned int ring_size;
+       unsigned int front_offset;
+       unsigned int back_offset;
+       unsigned int depth_offset;
+       unsigned int w;
+       unsigned int h;
+       unsigned int pitch;
+       unsigned int pitch_bits;
+       unsigned int back_pitch;
+       unsigned int depth_pitch;
+       unsigned int cpp;
+       unsigned int chipset;
+} drm_i915_init_t;
+
+typedef struct _drm_i915_sarea {
+       struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1];
+       int last_upload;        /* last time texture was uploaded */
+       int last_enqueue;       /* last time a buffer was enqueued */
+       int last_dispatch;      /* age of the most recently dispatched buffer */
+       int ctxOwner;           /* last context to upload state */
+       int texAge;
+       int pf_enabled;         /* is pageflipping allowed? */
+       int pf_active;
+       int pf_current_page;    /* which buffer is being displayed? */
+       int perf_boxes;         /* performance boxes to be displayed */
+       int width, height;      /* screen size in pixels */
+
+       drm_handle_t front_handle;
+       int front_offset;
+       int front_size;
+
+       drm_handle_t back_handle;
+       int back_offset;
+       int back_size;
+
+       drm_handle_t depth_handle;
+       int depth_offset;
+       int depth_size;
+
+       drm_handle_t tex_handle;
+       int tex_offset;
+       int tex_size;
+       int log_tex_granularity;
+       int pitch;
+       int rotation;           /* 0, 90, 180 or 270 */
+       int rotated_offset;
+       int rotated_size;
+       int rotated_pitch;
+       int virtualX, virtualY;
+
+       unsigned int front_tiled;
+       unsigned int back_tiled;
+       unsigned int depth_tiled;
+       unsigned int rotated_tiled;
+       unsigned int rotated2_tiled;
+
+       int pipeA_x;
+       int pipeA_y;
+       int pipeA_w;
+       int pipeA_h;
+       int pipeB_x;
+       int pipeB_y;
+       int pipeB_w;
+       int pipeB_h;
+} drm_i915_sarea_t;
+
+/* Flags for perf_boxes
+ */
+#define I915_BOX_RING_EMPTY    0x1
+#define I915_BOX_FLIP          0x2
+#define I915_BOX_WAIT          0x4
+#define I915_BOX_TEXTURE_LOAD  0x8
+#define I915_BOX_LOST_CONTEXT  0x10
+
+/* I915 specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_I915_INIT          0x00
+#define DRM_I915_FLUSH         0x01
+#define DRM_I915_FLIP          0x02
+#define DRM_I915_BATCHBUFFER   0x03
+#define DRM_I915_IRQ_EMIT      0x04
+#define DRM_I915_IRQ_WAIT      0x05
+#define DRM_I915_GETPARAM      0x06
+#define DRM_I915_SETPARAM      0x07
+#define DRM_I915_ALLOC         0x08
+#define DRM_I915_FREE          0x09
+#define DRM_I915_INIT_HEAP     0x0a
+#define DRM_I915_CMDBUFFER     0x0b
+#define DRM_I915_DESTROY_HEAP  0x0c
+#define DRM_I915_SET_VBLANK_PIPE       0x0d
+#define DRM_I915_GET_VBLANK_PIPE       0x0e
+#define DRM_I915_VBLANK_SWAP   0x0f
+#define DRM_I915_HWS_ADDR      0x11
+
+#define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
+#define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
+#define DRM_IOCTL_I915_FLIP            DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
+#define DRM_IOCTL_I915_BATCHBUFFER     DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
+#define DRM_IOCTL_I915_IRQ_EMIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
+#define DRM_IOCTL_I915_IRQ_WAIT         DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
+#define DRM_IOCTL_I915_GETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t)
+#define DRM_IOCTL_I915_SETPARAM         DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t)
+#define DRM_IOCTL_I915_ALLOC            DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t)
+#define DRM_IOCTL_I915_FREE             DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t)
+#define DRM_IOCTL_I915_INIT_HEAP        DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
+#define DRM_IOCTL_I915_CMDBUFFER       DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
+#define DRM_IOCTL_I915_DESTROY_HEAP    DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
+#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
+#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
+#define DRM_IOCTL_I915_VBLANK_SWAP     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
+
+/* Allow drivers to submit batchbuffers directly to hardware, relying
+ * on the security mechanisms provided by hardware.
+ */
+typedef struct _drm_i915_batchbuffer {
+       int start;              /* agp offset */
+       int used;               /* nr bytes in use */
+       int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
+       int DR4;                /* window origin for GFX_OP_DRAWRECT_INFO */
+       int num_cliprects;      /* mulitpass with multiple cliprects? */
+       struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
+} drm_i915_batchbuffer_t;
+
+/* As above, but pass a pointer to userspace buffer which can be
+ * validated by the kernel prior to sending to hardware.
+ */
+typedef struct _drm_i915_cmdbuffer {
+       char __user *buf;       /* pointer to userspace command buffer */
+       int sz;                 /* nr bytes in buf */
+       int DR1;                /* hw flags for GFX_OP_DRAWRECT_INFO */
+       int DR4;                /* window origin for GFX_OP_DRAWRECT_INFO */
+       int num_cliprects;      /* mulitpass with multiple cliprects? */
+       struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
+} drm_i915_cmdbuffer_t;
+
+/* Userspace can request & wait on irq's:
+ */
+typedef struct drm_i915_irq_emit {
+       int __user *irq_seq;
+} drm_i915_irq_emit_t;
+
+typedef struct drm_i915_irq_wait {
+       int irq_seq;
+} drm_i915_irq_wait_t;
+
+/* Ioctl to query kernel params:
+ */
+#define I915_PARAM_IRQ_ACTIVE            1
+#define I915_PARAM_ALLOW_BATCHBUFFER     2
+#define I915_PARAM_LAST_DISPATCH         3
+
+typedef struct drm_i915_getparam {
+       int param;
+       int __user *value;
+} drm_i915_getparam_t;
+
+/* Ioctl to set kernel params:
+ */
+#define I915_SETPARAM_USE_MI_BATCHBUFFER_START            1
+#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY             2
+#define I915_SETPARAM_ALLOW_BATCHBUFFER                   3
+
+typedef struct drm_i915_setparam {
+       int param;
+       int value;
+} drm_i915_setparam_t;
+
+/* A memory manager for regions of shared memory:
+ */
+#define I915_MEM_REGION_AGP 1
+
+typedef struct drm_i915_mem_alloc {
+       int region;
+       int alignment;
+       int size;
+       int __user *region_offset;      /* offset from start of fb or agp */
+} drm_i915_mem_alloc_t;
+
+typedef struct drm_i915_mem_free {
+       int region;
+       int region_offset;
+} drm_i915_mem_free_t;
+
+typedef struct drm_i915_mem_init_heap {
+       int region;
+       int size;
+       int start;
+} drm_i915_mem_init_heap_t;
+
+/* Allow memory manager to be torn down and re-initialized (eg on
+ * rotate):
+ */
+typedef struct drm_i915_mem_destroy_heap {
+       int region;
+} drm_i915_mem_destroy_heap_t;
+
+/* Allow X server to configure which pipes to monitor for vblank signals
+ */
+#define        DRM_I915_VBLANK_PIPE_A  1
+#define        DRM_I915_VBLANK_PIPE_B  2
+
+typedef struct drm_i915_vblank_pipe {
+       int pipe;
+} drm_i915_vblank_pipe_t;
+
+/* Schedule buffer swap at given vertical blank:
+ */
+typedef struct drm_i915_vblank_swap {
+       drm_drawable_t drawable;
+       enum drm_vblank_seq_type seqtype;
+       unsigned int sequence;
+} drm_i915_vblank_swap_t;
+
+typedef struct drm_i915_hws_addr {
+       uint64_t addr;
+} drm_i915_hws_addr_t;
+
+#endif                         /* _I915_DRM_H_ */
diff --git a/include/drm/mga_drm.h b/include/drm/mga_drm.h
new file mode 100644 (file)
index 0000000..944b50a
--- /dev/null
@@ -0,0 +1,417 @@
+/* mga_drm.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*-
+ * Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Jeff Hartmann <jhartmann@valinux.com>
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * Rewritten by:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __MGA_DRM_H__
+#define __MGA_DRM_H__
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (mga_sarea.h)
+ */
+
+#ifndef __MGA_SAREA_DEFINES__
+#define __MGA_SAREA_DEFINES__
+
+/* WARP pipe flags
+ */
+#define MGA_F                  0x1     /* fog */
+#define MGA_A                  0x2     /* alpha */
+#define MGA_S                  0x4     /* specular */
+#define MGA_T2                 0x8     /* multitexture */
+
+#define MGA_WARP_TGZ           0
+#define MGA_WARP_TGZF          (MGA_F)
+#define MGA_WARP_TGZA          (MGA_A)
+#define MGA_WARP_TGZAF         (MGA_F|MGA_A)
+#define MGA_WARP_TGZS          (MGA_S)
+#define MGA_WARP_TGZSF         (MGA_S|MGA_F)
+#define MGA_WARP_TGZSA         (MGA_S|MGA_A)
+#define MGA_WARP_TGZSAF                (MGA_S|MGA_F|MGA_A)
+#define MGA_WARP_T2GZ          (MGA_T2)
+#define MGA_WARP_T2GZF         (MGA_T2|MGA_F)
+#define MGA_WARP_T2GZA         (MGA_T2|MGA_A)
+#define MGA_WARP_T2GZAF                (MGA_T2|MGA_A|MGA_F)
+#define MGA_WARP_T2GZS         (MGA_T2|MGA_S)
+#define MGA_WARP_T2GZSF                (MGA_T2|MGA_S|MGA_F)
+#define MGA_WARP_T2GZSA                (MGA_T2|MGA_S|MGA_A)
+#define MGA_WARP_T2GZSAF       (MGA_T2|MGA_S|MGA_F|MGA_A)
+
+#define MGA_MAX_G200_PIPES     8       /* no multitex */
+#define MGA_MAX_G400_PIPES     16
+#define MGA_MAX_WARP_PIPES     MGA_MAX_G400_PIPES
+#define MGA_WARP_UCODE_SIZE    32768   /* in bytes */
+
+#define MGA_CARD_TYPE_G200     1
+#define MGA_CARD_TYPE_G400     2
+#define MGA_CARD_TYPE_G450     3       /* not currently used */
+#define MGA_CARD_TYPE_G550     4
+
+#define MGA_FRONT              0x1
+#define MGA_BACK               0x2
+#define MGA_DEPTH              0x4
+
+/* What needs to be changed for the current vertex dma buffer?
+ */
+#define MGA_UPLOAD_CONTEXT     0x1
+#define MGA_UPLOAD_TEX0                0x2
+#define MGA_UPLOAD_TEX1                0x4
+#define MGA_UPLOAD_PIPE                0x8
+#define MGA_UPLOAD_TEX0IMAGE   0x10    /* handled client-side */
+#define MGA_UPLOAD_TEX1IMAGE   0x20    /* handled client-side */
+#define MGA_UPLOAD_2D          0x40
+#define MGA_WAIT_AGE           0x80    /* handled client-side */
+#define MGA_UPLOAD_CLIPRECTS   0x100   /* handled client-side */
+#if 0
+#define MGA_DMA_FLUSH          0x200   /* set when someone gets the lock
+                                          quiescent */
+#endif
+
+/* 32 buffers of 64k each, total 2 meg.
+ */
+#define MGA_BUFFER_SIZE                (1 << 16)
+#define MGA_NUM_BUFFERS                128
+
+/* Keep these small for testing.
+ */
+#define MGA_NR_SAREA_CLIPRECTS 8
+
+/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
+ * regions, subject to a minimum region size of (1<<16) == 64k.
+ *
+ * Clients may subdivide regions internally, but when sharing between
+ * clients, the region size is the minimum granularity.
+ */
+
+#define MGA_CARD_HEAP                  0
+#define MGA_AGP_HEAP                   1
+#define MGA_NR_TEX_HEAPS               2
+#define MGA_NR_TEX_REGIONS             16
+#define MGA_LOG_MIN_TEX_REGION_SIZE    16
+
+#define  DRM_MGA_IDLE_RETRY          2048
+
+#endif                         /* __MGA_SAREA_DEFINES__ */
+
+/* Setup registers for 3D context
+ */
+typedef struct {
+       unsigned int dstorg;
+       unsigned int maccess;
+       unsigned int plnwt;
+       unsigned int dwgctl;
+       unsigned int alphactrl;
+       unsigned int fogcolor;
+       unsigned int wflag;
+       unsigned int tdualstage0;
+       unsigned int tdualstage1;
+       unsigned int fcol;
+       unsigned int stencil;
+       unsigned int stencilctl;
+} drm_mga_context_regs_t;
+
+/* Setup registers for 2D, X server
+ */
+typedef struct {
+       unsigned int pitch;
+} drm_mga_server_regs_t;
+
+/* Setup registers for each texture unit
+ */
+typedef struct {
+       unsigned int texctl;
+       unsigned int texctl2;
+       unsigned int texfilter;
+       unsigned int texbordercol;
+       unsigned int texorg;
+       unsigned int texwidth;
+       unsigned int texheight;
+       unsigned int texorg1;
+       unsigned int texorg2;
+       unsigned int texorg3;
+       unsigned int texorg4;
+} drm_mga_texture_regs_t;
+
+/* General aging mechanism
+ */
+typedef struct {
+       unsigned int head;      /* Position of head pointer          */
+       unsigned int wrap;      /* Primary DMA wrap count            */
+} drm_mga_age_t;
+
+typedef struct _drm_mga_sarea {
+       /* The channel for communication of state information to the kernel
+        * on firing a vertex dma buffer.
+        */
+       drm_mga_context_regs_t context_state;
+       drm_mga_server_regs_t server_state;
+       drm_mga_texture_regs_t tex_state[2];
+       unsigned int warp_pipe;
+       unsigned int dirty;
+       unsigned int vertsize;
+
+       /* The current cliprects, or a subset thereof.
+        */
+       struct drm_clip_rect boxes[MGA_NR_SAREA_CLIPRECTS];
+       unsigned int nbox;
+
+       /* Information about the most recently used 3d drawable.  The
+        * client fills in the req_* fields, the server fills in the
+        * exported_ fields and puts the cliprects into boxes, above.
+        *
+        * The client clears the exported_drawable field before
+        * clobbering the boxes data.
+        */
+       unsigned int req_drawable;      /* the X drawable id */
+       unsigned int req_draw_buffer;   /* MGA_FRONT or MGA_BACK */
+
+       unsigned int exported_drawable;
+       unsigned int exported_index;
+       unsigned int exported_stamp;
+       unsigned int exported_buffers;
+       unsigned int exported_nfront;
+       unsigned int exported_nback;
+       int exported_back_x, exported_front_x, exported_w;
+       int exported_back_y, exported_front_y, exported_h;
+       struct drm_clip_rect exported_boxes[MGA_NR_SAREA_CLIPRECTS];
+
+       /* Counters for aging textures and for client-side throttling.
+        */
+       unsigned int status[4];
+       unsigned int last_wrap;
+
+       drm_mga_age_t last_frame;
+       unsigned int last_enqueue;      /* last time a buffer was enqueued */
+       unsigned int last_dispatch;     /* age of the most recently dispatched buffer */
+       unsigned int last_quiescent;    /*  */
+
+       /* LRU lists for texture memory in agp space and on the card.
+        */
+       struct drm_tex_region texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1];
+       unsigned int texAge[MGA_NR_TEX_HEAPS];
+
+       /* Mechanism to validate card state.
+        */
+       int ctxOwner;
+} drm_mga_sarea_t;
+
+/* MGA specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_MGA_INIT     0x00
+#define DRM_MGA_FLUSH    0x01
+#define DRM_MGA_RESET    0x02
+#define DRM_MGA_SWAP     0x03
+#define DRM_MGA_CLEAR    0x04
+#define DRM_MGA_VERTEX   0x05
+#define DRM_MGA_INDICES  0x06
+#define DRM_MGA_ILOAD    0x07
+#define DRM_MGA_BLIT     0x08
+#define DRM_MGA_GETPARAM 0x09
+
+/* 3.2:
+ * ioctls for operating on fences.
+ */
+#define DRM_MGA_SET_FENCE      0x0a
+#define DRM_MGA_WAIT_FENCE     0x0b
+#define DRM_MGA_DMA_BOOTSTRAP  0x0c
+
+#define DRM_IOCTL_MGA_INIT     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t)
+#define DRM_IOCTL_MGA_FLUSH    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, drm_lock_t)
+#define DRM_IOCTL_MGA_RESET    DRM_IO(  DRM_COMMAND_BASE + DRM_MGA_RESET)
+#define DRM_IOCTL_MGA_SWAP     DRM_IO(  DRM_COMMAND_BASE + DRM_MGA_SWAP)
+#define DRM_IOCTL_MGA_CLEAR    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t)
+#define DRM_IOCTL_MGA_VERTEX   DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t)
+#define DRM_IOCTL_MGA_INDICES  DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t)
+#define DRM_IOCTL_MGA_ILOAD    DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t)
+#define DRM_IOCTL_MGA_BLIT     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t)
+#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t)
+#define DRM_IOCTL_MGA_SET_FENCE     DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, uint32_t)
+#define DRM_IOCTL_MGA_WAIT_FENCE    DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, uint32_t)
+#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t)
+
+typedef struct _drm_mga_warp_index {
+       int installed;
+       unsigned long phys_addr;
+       int size;
+} drm_mga_warp_index_t;
+
+typedef struct drm_mga_init {
+       enum {
+               MGA_INIT_DMA = 0x01,
+               MGA_CLEANUP_DMA = 0x02
+       } func;
+
+       unsigned long sarea_priv_offset;
+
+       int chipset;
+       int sgram;
+
+       unsigned int maccess;
+
+       unsigned int fb_cpp;
+       unsigned int front_offset, front_pitch;
+       unsigned int back_offset, back_pitch;
+
+       unsigned int depth_cpp;
+       unsigned int depth_offset, depth_pitch;
+
+       unsigned int texture_offset[MGA_NR_TEX_HEAPS];
+       unsigned int texture_size[MGA_NR_TEX_HEAPS];
+
+       unsigned long fb_offset;
+       unsigned long mmio_offset;
+       unsigned long status_offset;
+       unsigned long warp_offset;
+       unsigned long primary_offset;
+       unsigned long buffers_offset;
+} drm_mga_init_t;
+
+typedef struct drm_mga_dma_bootstrap {
+       /**
+        * \name AGP texture region
+        *
+        * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will
+        * be filled in with the actual AGP texture settings.
+        *
+        * \warning
+        * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode
+        * is zero, it means that PCI memory (most likely through the use of
+        * an IOMMU) is being used for "AGP" textures.
+        */
+       /*@{ */
+       unsigned long texture_handle; /**< Handle used to map AGP textures. */
+       uint32_t texture_size;        /**< Size of the AGP texture region. */
+       /*@} */
+
+       /**
+        * Requested size of the primary DMA region.
+        *
+        * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+        * filled in with the actual AGP mode.  If AGP was not available
+        */
+       uint32_t primary_size;
+
+       /**
+        * Requested number of secondary DMA buffers.
+        *
+        * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+        * filled in with the actual number of secondary DMA buffers
+        * allocated.  Particularly when PCI DMA is used, this may be
+        * (subtantially) less than the number requested.
+        */
+       uint32_t secondary_bin_count;
+
+       /**
+        * Requested size of each secondary DMA buffer.
+        *
+        * While the kernel \b is free to reduce
+        * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed
+        * to reduce dma_mga_dma_bootstrap::secondary_bin_size.
+        */
+       uint32_t secondary_bin_size;
+
+       /**
+        * Bit-wise mask of AGPSTAT2_* values.  Currently only \c AGPSTAT2_1X,
+        * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported.  If this value is
+        * zero, it means that PCI DMA should be used, even if AGP is
+        * possible.
+        *
+        * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be
+        * filled in with the actual AGP mode.  If AGP was not available
+        * (i.e., PCI DMA was used), this value will be zero.
+        */
+       uint32_t agp_mode;
+
+       /**
+        * Desired AGP GART size, measured in megabytes.
+        */
+       uint8_t agp_size;
+} drm_mga_dma_bootstrap_t;
+
+typedef struct drm_mga_clear {
+       unsigned int flags;
+       unsigned int clear_color;
+       unsigned int clear_depth;
+       unsigned int color_mask;
+       unsigned int depth_mask;
+} drm_mga_clear_t;
+
+typedef struct drm_mga_vertex {
+       int idx;                /* buffer to queue */
+       int used;               /* bytes in use */
+       int discard;            /* client finished with buffer?  */
+} drm_mga_vertex_t;
+
+typedef struct drm_mga_indices {
+       int idx;                /* buffer to queue */
+       unsigned int start;
+       unsigned int end;
+       int discard;            /* client finished with buffer?  */
+} drm_mga_indices_t;
+
+typedef struct drm_mga_iload {
+       int idx;
+       unsigned int dstorg;
+       unsigned int length;
+} drm_mga_iload_t;
+
+typedef struct _drm_mga_blit {
+       unsigned int planemask;
+       unsigned int srcorg;
+       unsigned int dstorg;
+       int src_pitch, dst_pitch;
+       int delta_sx, delta_sy;
+       int delta_dx, delta_dy;
+       int height, ydir;       /* flip image vertically */
+       int source_pitch, dest_pitch;
+} drm_mga_blit_t;
+
+/* 3.1: An ioctl to get parameters that aren't available to the 3d
+ * client any other way.
+ */
+#define MGA_PARAM_IRQ_NR            1
+
+/* 3.2: Query the actual card type.  The DDX only distinguishes between
+ * G200 chips and non-G200 chips, which it calls G400.  It turns out that
+ * there are some very sublte differences between the G4x0 chips and the G550
+ * chips.  Using this parameter query, a client-side driver can detect the
+ * difference between a G4x0 and a G550.
+ */
+#define MGA_PARAM_CARD_TYPE         2
+
+typedef struct drm_mga_getparam {
+       int param;
+       void __user *value;
+} drm_mga_getparam_t;
+
+#endif
diff --git a/include/drm/r128_drm.h b/include/drm/r128_drm.h
new file mode 100644 (file)
index 0000000..8d8878b
--- /dev/null
@@ -0,0 +1,326 @@
+/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-
+ * Created: Wed Apr  5 19:24:19 2000 by kevin@precisioninsight.com
+ */
+/*
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Kevin E. Martin <martin@valinux.com>
+ */
+
+#ifndef __R128_DRM_H__
+#define __R128_DRM_H__
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the X server file (r128_sarea.h)
+ */
+#ifndef __R128_SAREA_DEFINES__
+#define __R128_SAREA_DEFINES__
+
+/* What needs to be changed for the current vertex buffer?
+ */
+#define R128_UPLOAD_CONTEXT            0x001
+#define R128_UPLOAD_SETUP              0x002
+#define R128_UPLOAD_TEX0               0x004
+#define R128_UPLOAD_TEX1               0x008
+#define R128_UPLOAD_TEX0IMAGES         0x010
+#define R128_UPLOAD_TEX1IMAGES         0x020
+#define R128_UPLOAD_CORE               0x040
+#define R128_UPLOAD_MASKS              0x080
+#define R128_UPLOAD_WINDOW             0x100
+#define R128_UPLOAD_CLIPRECTS          0x200   /* handled client-side */
+#define R128_REQUIRE_QUIESCENCE                0x400
+#define R128_UPLOAD_ALL                        0x7ff
+
+#define R128_FRONT                     0x1
+#define R128_BACK                      0x2
+#define R128_DEPTH                     0x4
+
+/* Primitive types
+ */
+#define R128_POINTS                    0x1
+#define R128_LINES                     0x2
+#define R128_LINE_STRIP                        0x3
+#define R128_TRIANGLES                 0x4
+#define R128_TRIANGLE_FAN              0x5
+#define R128_TRIANGLE_STRIP            0x6
+
+/* Vertex/indirect buffer size
+ */
+#define R128_BUFFER_SIZE               16384
+
+/* Byte offsets for indirect buffer data
+ */
+#define R128_INDEX_PRIM_OFFSET         20
+#define R128_HOSTDATA_BLIT_OFFSET      32
+
+/* Keep these small for testing.
+ */
+#define R128_NR_SAREA_CLIPRECTS                12
+
+/* There are 2 heaps (local/AGP).  Each region within a heap is a
+ *  minimum of 64k, and there are at most 64 of them per heap.
+ */
+#define R128_LOCAL_TEX_HEAP            0
+#define R128_AGP_TEX_HEAP              1
+#define R128_NR_TEX_HEAPS              2
+#define R128_NR_TEX_REGIONS            64
+#define R128_LOG_TEX_GRANULARITY       16
+
+#define R128_NR_CONTEXT_REGS           12
+
+#define R128_MAX_TEXTURE_LEVELS                11
+#define R128_MAX_TEXTURE_UNITS         2
+
+#endif                         /* __R128_SAREA_DEFINES__ */
+
+typedef struct {
+       /* Context state - can be written in one large chunk */
+       unsigned int dst_pitch_offset_c;
+       unsigned int dp_gui_master_cntl_c;
+       unsigned int sc_top_left_c;
+       unsigned int sc_bottom_right_c;
+       unsigned int z_offset_c;
+       unsigned int z_pitch_c;
+       unsigned int z_sten_cntl_c;
+       unsigned int tex_cntl_c;
+       unsigned int misc_3d_state_cntl_reg;
+       unsigned int texture_clr_cmp_clr_c;
+       unsigned int texture_clr_cmp_msk_c;
+       unsigned int fog_color_c;
+
+       /* Texture state */
+       unsigned int tex_size_pitch_c;
+       unsigned int constant_color_c;
+
+       /* Setup state */
+       unsigned int pm4_vc_fpu_setup;
+       unsigned int setup_cntl;
+
+       /* Mask state */
+       unsigned int dp_write_mask;
+       unsigned int sten_ref_mask_c;
+       unsigned int plane_3d_mask_c;
+
+       /* Window state */
+       unsigned int window_xy_offset;
+
+       /* Core state */
+       unsigned int scale_3d_cntl;
+} drm_r128_context_regs_t;
+
+/* Setup registers for each texture unit
+ */
+typedef struct {
+       unsigned int tex_cntl;
+       unsigned int tex_combine_cntl;
+       unsigned int tex_size_pitch;
+       unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS];
+       unsigned int tex_border_color;
+} drm_r128_texture_regs_t;
+
+typedef struct drm_r128_sarea {
+       /* The channel for communication of state information to the kernel
+        * on firing a vertex buffer.
+        */
+       drm_r128_context_regs_t context_state;
+       drm_r128_texture_regs_t tex_state[R128_MAX_TEXTURE_UNITS];
+       unsigned int dirty;
+       unsigned int vertsize;
+       unsigned int vc_format;
+
+       /* The current cliprects, or a subset thereof.
+        */
+       struct drm_clip_rect boxes[R128_NR_SAREA_CLIPRECTS];
+       unsigned int nbox;
+
+       /* Counters for client-side throttling of rendering clients.
+        */
+       unsigned int last_frame;
+       unsigned int last_dispatch;
+
+       struct drm_tex_region tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1];
+       unsigned int tex_age[R128_NR_TEX_HEAPS];
+       int ctx_owner;
+       int pfAllowPageFlip;    /* number of 3d windows (0,1,2 or more) */
+       int pfCurrentPage;      /* which buffer is being displayed? */
+} drm_r128_sarea_t;
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmR128.h)
+ */
+
+/* Rage 128 specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_R128_INIT       0x00
+#define DRM_R128_CCE_START  0x01
+#define DRM_R128_CCE_STOP   0x02
+#define DRM_R128_CCE_RESET  0x03
+#define DRM_R128_CCE_IDLE   0x04
+/* 0x05 not used */
+#define DRM_R128_RESET      0x06
+#define DRM_R128_SWAP       0x07
+#define DRM_R128_CLEAR      0x08
+#define DRM_R128_VERTEX     0x09
+#define DRM_R128_INDICES    0x0a
+#define DRM_R128_BLIT       0x0b
+#define DRM_R128_DEPTH      0x0c
+#define DRM_R128_STIPPLE    0x0d
+/* 0x0e not used */
+#define DRM_R128_INDIRECT   0x0f
+#define DRM_R128_FULLSCREEN 0x10
+#define DRM_R128_CLEAR2     0x11
+#define DRM_R128_GETPARAM   0x12
+#define DRM_R128_FLIP       0x13
+
+#define DRM_IOCTL_R128_INIT       DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INIT, drm_r128_init_t)
+#define DRM_IOCTL_R128_CCE_START  DRM_IO(  DRM_COMMAND_BASE + DRM_R128_CCE_START)
+#define DRM_IOCTL_R128_CCE_STOP   DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CCE_STOP, drm_r128_cce_stop_t)
+#define DRM_IOCTL_R128_CCE_RESET  DRM_IO(  DRM_COMMAND_BASE + DRM_R128_CCE_RESET)
+#define DRM_IOCTL_R128_CCE_IDLE   DRM_IO(  DRM_COMMAND_BASE + DRM_R128_CCE_IDLE)
+/* 0x05 not used */
+#define DRM_IOCTL_R128_RESET      DRM_IO(  DRM_COMMAND_BASE + DRM_R128_RESET)
+#define DRM_IOCTL_R128_SWAP       DRM_IO(  DRM_COMMAND_BASE + DRM_R128_SWAP)
+#define DRM_IOCTL_R128_CLEAR      DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR, drm_r128_clear_t)
+#define DRM_IOCTL_R128_VERTEX     DRM_IOW( DRM_COMMAND_BASE + DRM_R128_VERTEX, drm_r128_vertex_t)
+#define DRM_IOCTL_R128_INDICES    DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INDICES, drm_r128_indices_t)
+#define DRM_IOCTL_R128_BLIT       DRM_IOW( DRM_COMMAND_BASE + DRM_R128_BLIT, drm_r128_blit_t)
+#define DRM_IOCTL_R128_DEPTH      DRM_IOW( DRM_COMMAND_BASE + DRM_R128_DEPTH, drm_r128_depth_t)
+#define DRM_IOCTL_R128_STIPPLE    DRM_IOW( DRM_COMMAND_BASE + DRM_R128_STIPPLE, drm_r128_stipple_t)
+/* 0x0e not used */
+#define DRM_IOCTL_R128_INDIRECT   DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t)
+#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t)
+#define DRM_IOCTL_R128_CLEAR2     DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t)
+#define DRM_IOCTL_R128_GETPARAM   DRM_IOWR( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t)
+#define DRM_IOCTL_R128_FLIP       DRM_IO(  DRM_COMMAND_BASE + DRM_R128_FLIP)
+
+typedef struct drm_r128_init {
+       enum {
+               R128_INIT_CCE = 0x01,
+               R128_CLEANUP_CCE = 0x02
+       } func;
+       unsigned long sarea_priv_offset;
+       int is_pci;
+       int cce_mode;
+       int cce_secure;
+       int ring_size;
+       int usec_timeout;
+
+       unsigned int fb_bpp;
+       unsigned int front_offset, front_pitch;
+       unsigned int back_offset, back_pitch;
+       unsigned int depth_bpp;
+       unsigned int depth_offset, depth_pitch;
+       unsigned int span_offset;
+
+       unsigned long fb_offset;
+       unsigned long mmio_offset;
+       unsigned long ring_offset;
+       unsigned long ring_rptr_offset;
+       unsigned long buffers_offset;
+       unsigned long agp_textures_offset;
+} drm_r128_init_t;
+
+typedef struct drm_r128_cce_stop {
+       int flush;
+       int idle;
+} drm_r128_cce_stop_t;
+
+typedef struct drm_r128_clear {
+       unsigned int flags;
+       unsigned int clear_color;
+       unsigned int clear_depth;
+       unsigned int color_mask;
+       unsigned int depth_mask;
+} drm_r128_clear_t;
+
+typedef struct drm_r128_vertex {
+       int prim;
+       int idx;                /* Index of vertex buffer */
+       int count;              /* Number of vertices in buffer */
+       int discard;            /* Client finished with buffer? */
+} drm_r128_vertex_t;
+
+typedef struct drm_r128_indices {
+       int prim;
+       int idx;
+       int start;
+       int end;
+       int discard;            /* Client finished with buffer? */
+} drm_r128_indices_t;
+
+typedef struct drm_r128_blit {
+       int idx;
+       int pitch;
+       int offset;
+       int format;
+       unsigned short x, y;
+       unsigned short width, height;
+} drm_r128_blit_t;
+
+typedef struct drm_r128_depth {
+       enum {
+               R128_WRITE_SPAN = 0x01,
+               R128_WRITE_PIXELS = 0x02,
+               R128_READ_SPAN = 0x03,
+               R128_READ_PIXELS = 0x04
+       } func;
+       int n;
+       int __user *x;
+       int __user *y;
+       unsigned int __user *buffer;
+       unsigned char __user *mask;
+} drm_r128_depth_t;
+
+typedef struct drm_r128_stipple {
+       unsigned int __user *mask;
+} drm_r128_stipple_t;
+
+typedef struct drm_r128_indirect {
+       int idx;
+       int start;
+       int end;
+       int discard;
+} drm_r128_indirect_t;
+
+typedef struct drm_r128_fullscreen {
+       enum {
+               R128_INIT_FULLSCREEN = 0x01,
+               R128_CLEANUP_FULLSCREEN = 0x02
+       } func;
+} drm_r128_fullscreen_t;
+
+/* 2.3: An ioctl to get parameters that aren't available to the 3d
+ * client any other way.
+ */
+#define R128_PARAM_IRQ_NR            1
+
+typedef struct drm_r128_getparam {
+       int param;
+       void __user *value;
+} drm_r128_getparam_t;
+
+#endif
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h
new file mode 100644 (file)
index 0000000..73ff51f
--- /dev/null
@@ -0,0 +1,749 @@
+/* radeon_drm.h -- Public header for the radeon driver -*- linux-c -*-
+ *
+ * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Kevin E. Martin <martin@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef __RADEON_DRM_H__
+#define __RADEON_DRM_H__
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the X server file (radeon_sarea.h)
+ */
+#ifndef __RADEON_SAREA_DEFINES__
+#define __RADEON_SAREA_DEFINES__
+
+/* Old style state flags, required for sarea interface (1.1 and 1.2
+ * clears) and 1.2 drm_vertex2 ioctl.
+ */
+#define RADEON_UPLOAD_CONTEXT          0x00000001
+#define RADEON_UPLOAD_VERTFMT          0x00000002
+#define RADEON_UPLOAD_LINE             0x00000004
+#define RADEON_UPLOAD_BUMPMAP          0x00000008
+#define RADEON_UPLOAD_MASKS            0x00000010
+#define RADEON_UPLOAD_VIEWPORT         0x00000020
+#define RADEON_UPLOAD_SETUP            0x00000040
+#define RADEON_UPLOAD_TCL              0x00000080
+#define RADEON_UPLOAD_MISC             0x00000100
+#define RADEON_UPLOAD_TEX0             0x00000200
+#define RADEON_UPLOAD_TEX1             0x00000400
+#define RADEON_UPLOAD_TEX2             0x00000800
+#define RADEON_UPLOAD_TEX0IMAGES       0x00001000
+#define RADEON_UPLOAD_TEX1IMAGES       0x00002000
+#define RADEON_UPLOAD_TEX2IMAGES       0x00004000
+#define RADEON_UPLOAD_CLIPRECTS                0x00008000      /* handled client-side */
+#define RADEON_REQUIRE_QUIESCENCE      0x00010000
+#define RADEON_UPLOAD_ZBIAS            0x00020000      /* version 1.2 and newer */
+#define RADEON_UPLOAD_ALL              0x003effff
+#define RADEON_UPLOAD_CONTEXT_ALL       0x003e01ff
+
+/* New style per-packet identifiers for use in cmd_buffer ioctl with
+ * the RADEON_EMIT_PACKET command.  Comments relate new packets to old
+ * state bits and the packet size:
+ */
+#define RADEON_EMIT_PP_MISC                         0  /* context/7 */
+#define RADEON_EMIT_PP_CNTL                         1  /* context/3 */
+#define RADEON_EMIT_RB3D_COLORPITCH                 2  /* context/1 */
+#define RADEON_EMIT_RE_LINE_PATTERN                 3  /* line/2 */
+#define RADEON_EMIT_SE_LINE_WIDTH                   4  /* line/1 */
+#define RADEON_EMIT_PP_LUM_MATRIX                   5  /* bumpmap/1 */
+#define RADEON_EMIT_PP_ROT_MATRIX_0                 6  /* bumpmap/2 */
+#define RADEON_EMIT_RB3D_STENCILREFMASK             7  /* masks/3 */
+#define RADEON_EMIT_SE_VPORT_XSCALE                 8  /* viewport/6 */
+#define RADEON_EMIT_SE_CNTL                         9  /* setup/2 */
+#define RADEON_EMIT_SE_CNTL_STATUS                  10 /* setup/1 */
+#define RADEON_EMIT_RE_MISC                         11 /* misc/1 */
+#define RADEON_EMIT_PP_TXFILTER_0                   12 /* tex0/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_0               13 /* tex0/1 */
+#define RADEON_EMIT_PP_TXFILTER_1                   14 /* tex1/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_1               15 /* tex1/1 */
+#define RADEON_EMIT_PP_TXFILTER_2                   16 /* tex2/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_2               17 /* tex2/1 */
+#define RADEON_EMIT_SE_ZBIAS_FACTOR                 18 /* zbias/2 */
+#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT           19 /* tcl/11 */
+#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED   20 /* material/17 */
+#define R200_EMIT_PP_TXCBLEND_0                     21 /* tex0/4 */
+#define R200_EMIT_PP_TXCBLEND_1                     22 /* tex1/4 */
+#define R200_EMIT_PP_TXCBLEND_2                     23 /* tex2/4 */
+#define R200_EMIT_PP_TXCBLEND_3                     24 /* tex3/4 */
+#define R200_EMIT_PP_TXCBLEND_4                     25 /* tex4/4 */
+#define R200_EMIT_PP_TXCBLEND_5                     26 /* tex5/4 */
+#define R200_EMIT_PP_TXCBLEND_6                     27 /* /4 */
+#define R200_EMIT_PP_TXCBLEND_7                     28 /* /4 */
+#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0             29 /* tcl/7 */
+#define R200_EMIT_TFACTOR_0                         30 /* tf/7 */
+#define R200_EMIT_VTX_FMT_0                         31 /* vtx/5 */
+#define R200_EMIT_VAP_CTL                           32 /* vap/1 */
+#define R200_EMIT_MATRIX_SELECT_0                   33 /* msl/5 */
+#define R200_EMIT_TEX_PROC_CTL_2                    34 /* tcg/5 */
+#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL            35 /* tcl/1 */
+#define R200_EMIT_PP_TXFILTER_0                     36 /* tex0/6 */
+#define R200_EMIT_PP_TXFILTER_1                     37 /* tex1/6 */
+#define R200_EMIT_PP_TXFILTER_2                     38 /* tex2/6 */
+#define R200_EMIT_PP_TXFILTER_3                     39 /* tex3/6 */
+#define R200_EMIT_PP_TXFILTER_4                     40 /* tex4/6 */
+#define R200_EMIT_PP_TXFILTER_5                     41 /* tex5/6 */
+#define R200_EMIT_PP_TXOFFSET_0                     42 /* tex0/1 */
+#define R200_EMIT_PP_TXOFFSET_1                     43 /* tex1/1 */
+#define R200_EMIT_PP_TXOFFSET_2                     44 /* tex2/1 */
+#define R200_EMIT_PP_TXOFFSET_3                     45 /* tex3/1 */
+#define R200_EMIT_PP_TXOFFSET_4                     46 /* tex4/1 */
+#define R200_EMIT_PP_TXOFFSET_5                     47 /* tex5/1 */
+#define R200_EMIT_VTE_CNTL                          48 /* vte/1 */
+#define R200_EMIT_OUTPUT_VTX_COMP_SEL               49 /* vtx/1 */
+#define R200_EMIT_PP_TAM_DEBUG3                     50 /* tam/1 */
+#define R200_EMIT_PP_CNTL_X                         51 /* cst/1 */
+#define R200_EMIT_RB3D_DEPTHXY_OFFSET               52 /* cst/1 */
+#define R200_EMIT_RE_AUX_SCISSOR_CNTL               53 /* cst/1 */
+#define R200_EMIT_RE_SCISSOR_TL_0                   54 /* cst/2 */
+#define R200_EMIT_RE_SCISSOR_TL_1                   55 /* cst/2 */
+#define R200_EMIT_RE_SCISSOR_TL_2                   56 /* cst/2 */
+#define R200_EMIT_SE_VAP_CNTL_STATUS                57 /* cst/1 */
+#define R200_EMIT_SE_VTX_STATE_CNTL                 58 /* cst/1 */
+#define R200_EMIT_RE_POINTSIZE                      59 /* cst/1 */
+#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0       60 /* cst/4 */
+#define R200_EMIT_PP_CUBIC_FACES_0                  61
+#define R200_EMIT_PP_CUBIC_OFFSETS_0                62
+#define R200_EMIT_PP_CUBIC_FACES_1                  63
+#define R200_EMIT_PP_CUBIC_OFFSETS_1                64
+#define R200_EMIT_PP_CUBIC_FACES_2                  65
+#define R200_EMIT_PP_CUBIC_OFFSETS_2                66
+#define R200_EMIT_PP_CUBIC_FACES_3                  67
+#define R200_EMIT_PP_CUBIC_OFFSETS_3                68
+#define R200_EMIT_PP_CUBIC_FACES_4                  69
+#define R200_EMIT_PP_CUBIC_OFFSETS_4                70
+#define R200_EMIT_PP_CUBIC_FACES_5                  71
+#define R200_EMIT_PP_CUBIC_OFFSETS_5                72
+#define RADEON_EMIT_PP_TEX_SIZE_0                   73
+#define RADEON_EMIT_PP_TEX_SIZE_1                   74
+#define RADEON_EMIT_PP_TEX_SIZE_2                   75
+#define R200_EMIT_RB3D_BLENDCOLOR                   76
+#define R200_EMIT_TCL_POINT_SPRITE_CNTL             77
+#define RADEON_EMIT_PP_CUBIC_FACES_0                78
+#define RADEON_EMIT_PP_CUBIC_OFFSETS_T0             79
+#define RADEON_EMIT_PP_CUBIC_FACES_1                80
+#define RADEON_EMIT_PP_CUBIC_OFFSETS_T1             81
+#define RADEON_EMIT_PP_CUBIC_FACES_2                82
+#define RADEON_EMIT_PP_CUBIC_OFFSETS_T2             83
+#define R200_EMIT_PP_TRI_PERF_CNTL                  84
+#define R200_EMIT_PP_AFS_0                          85
+#define R200_EMIT_PP_AFS_1                          86
+#define R200_EMIT_ATF_TFACTOR                       87
+#define R200_EMIT_PP_TXCTLALL_0                     88
+#define R200_EMIT_PP_TXCTLALL_1                     89
+#define R200_EMIT_PP_TXCTLALL_2                     90
+#define R200_EMIT_PP_TXCTLALL_3                     91
+#define R200_EMIT_PP_TXCTLALL_4                     92
+#define R200_EMIT_PP_TXCTLALL_5                     93
+#define R200_EMIT_VAP_PVS_CNTL                      94
+#define RADEON_MAX_STATE_PACKETS                    95
+
+/* Commands understood by cmd_buffer ioctl.  More can be added but
+ * obviously these can't be removed or changed:
+ */
+#define RADEON_CMD_PACKET      1       /* emit one of the register packets above */
+#define RADEON_CMD_SCALARS     2       /* emit scalar data */
+#define RADEON_CMD_VECTORS     3       /* emit vector data */
+#define RADEON_CMD_DMA_DISCARD 4       /* discard current dma buf */
+#define RADEON_CMD_PACKET3     5       /* emit hw packet */
+#define RADEON_CMD_PACKET3_CLIP 6      /* emit hw packet wrapped in cliprects */
+#define RADEON_CMD_SCALARS2     7      /* r200 stopgap */
+#define RADEON_CMD_WAIT         8      /* emit hw wait commands -- note:
+                                        *  doesn't make the cpu wait, just
+                                        *  the graphics hardware */
+#define RADEON_CMD_VECLINEAR   9       /* another r200 stopgap */
+
+typedef union {
+       int i;
+       struct {
+               unsigned char cmd_type, pad0, pad1, pad2;
+       } header;
+       struct {
+               unsigned char cmd_type, packet_id, pad0, pad1;
+       } packet;
+       struct {
+               unsigned char cmd_type, offset, stride, count;
+       } scalars;
+       struct {
+               unsigned char cmd_type, offset, stride, count;
+       } vectors;
+       struct {
+               unsigned char cmd_type, addr_lo, addr_hi, count;
+       } veclinear;
+       struct {
+               unsigned char cmd_type, buf_idx, pad0, pad1;
+       } dma;
+       struct {
+               unsigned char cmd_type, flags, pad0, pad1;
+       } wait;
+} drm_radeon_cmd_header_t;
+
+#define RADEON_WAIT_2D  0x1
+#define RADEON_WAIT_3D  0x2
+
+/* Allowed parameters for R300_CMD_PACKET3
+ */
+#define R300_CMD_PACKET3_CLEAR         0
+#define R300_CMD_PACKET3_RAW           1
+
+/* Commands understood by cmd_buffer ioctl for R300.
+ * The interface has not been stabilized, so some of these may be removed
+ * and eventually reordered before stabilization.
+ */
+#define R300_CMD_PACKET0               1
+#define R300_CMD_VPU                   2       /* emit vertex program upload */
+#define R300_CMD_PACKET3               3       /* emit a packet3 */
+#define R300_CMD_END3D                 4       /* emit sequence ending 3d rendering */
+#define R300_CMD_CP_DELAY              5
+#define R300_CMD_DMA_DISCARD           6
+#define R300_CMD_WAIT                  7
+#      define R300_WAIT_2D             0x1
+#      define R300_WAIT_3D             0x2
+/* these two defines are DOING IT WRONG - however
+ * we have userspace which relies on using these.
+ * The wait interface is backwards compat new 
+ * code should use the NEW_WAIT defines below
+ * THESE ARE NOT BIT FIELDS
+ */
+#      define R300_WAIT_2D_CLEAN       0x3
+#      define R300_WAIT_3D_CLEAN       0x4
+
+#      define R300_NEW_WAIT_2D_3D      0x3
+#      define R300_NEW_WAIT_2D_2D_CLEAN        0x4
+#      define R300_NEW_WAIT_3D_3D_CLEAN        0x6
+#      define R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN    0x8
+
+#define R300_CMD_SCRATCH               8
+#define R300_CMD_R500FP                 9
+
+typedef union {
+       unsigned int u;
+       struct {
+               unsigned char cmd_type, pad0, pad1, pad2;
+       } header;
+       struct {
+               unsigned char cmd_type, count, reglo, reghi;
+       } packet0;
+       struct {
+               unsigned char cmd_type, count, adrlo, adrhi;
+       } vpu;
+       struct {
+               unsigned char cmd_type, packet, pad0, pad1;
+       } packet3;
+       struct {
+               unsigned char cmd_type, packet;
+               unsigned short count;   /* amount of packet2 to emit */
+       } delay;
+       struct {
+               unsigned char cmd_type, buf_idx, pad0, pad1;
+       } dma;
+       struct {
+               unsigned char cmd_type, flags, pad0, pad1;
+       } wait;
+       struct {
+               unsigned char cmd_type, reg, n_bufs, flags;
+       } scratch;
+       struct {
+               unsigned char cmd_type, count, adrlo, adrhi_flags;
+       } r500fp;
+} drm_r300_cmd_header_t;
+
+#define RADEON_FRONT                   0x1
+#define RADEON_BACK                    0x2
+#define RADEON_DEPTH                   0x4
+#define RADEON_STENCIL                 0x8
+#define RADEON_CLEAR_FASTZ             0x80000000
+#define RADEON_USE_HIERZ               0x40000000
+#define RADEON_USE_COMP_ZBUF           0x20000000
+
+#define R500FP_CONSTANT_TYPE  (1 << 1)
+#define R500FP_CONSTANT_CLAMP (1 << 2)
+
+/* Primitive types
+ */
+#define RADEON_POINTS                  0x1
+#define RADEON_LINES                   0x2
+#define RADEON_LINE_STRIP              0x3
+#define RADEON_TRIANGLES               0x4
+#define RADEON_TRIANGLE_FAN            0x5
+#define RADEON_TRIANGLE_STRIP          0x6
+
+/* Vertex/indirect buffer size
+ */
+#define RADEON_BUFFER_SIZE             65536
+
+/* Byte offsets for indirect buffer data
+ */
+#define RADEON_INDEX_PRIM_OFFSET       20
+
+#define RADEON_SCRATCH_REG_OFFSET      32
+
+#define RADEON_NR_SAREA_CLIPRECTS      12
+
+/* There are 2 heaps (local/GART).  Each region within a heap is a
+ * minimum of 64k, and there are at most 64 of them per heap.
+ */
+#define RADEON_LOCAL_TEX_HEAP          0
+#define RADEON_GART_TEX_HEAP           1
+#define RADEON_NR_TEX_HEAPS            2
+#define RADEON_NR_TEX_REGIONS          64
+#define RADEON_LOG_TEX_GRANULARITY     16
+
+#define RADEON_MAX_TEXTURE_LEVELS      12
+#define RADEON_MAX_TEXTURE_UNITS       3
+
+#define RADEON_MAX_SURFACES            8
+
+/* Blits have strict offset rules.  All blit offset must be aligned on
+ * a 1K-byte boundary.
+ */
+#define RADEON_OFFSET_SHIFT             10
+#define RADEON_OFFSET_ALIGN             (1 << RADEON_OFFSET_SHIFT)
+#define RADEON_OFFSET_MASK              (RADEON_OFFSET_ALIGN - 1)
+
+#endif                         /* __RADEON_SAREA_DEFINES__ */
+
+typedef struct {
+       unsigned int red;
+       unsigned int green;
+       unsigned int blue;
+       unsigned int alpha;
+} radeon_color_regs_t;
+
+typedef struct {
+       /* Context state */
+       unsigned int pp_misc;   /* 0x1c14 */
+       unsigned int pp_fog_color;
+       unsigned int re_solid_color;
+       unsigned int rb3d_blendcntl;
+       unsigned int rb3d_depthoffset;
+       unsigned int rb3d_depthpitch;
+       unsigned int rb3d_zstencilcntl;
+
+       unsigned int pp_cntl;   /* 0x1c38 */
+       unsigned int rb3d_cntl;
+       unsigned int rb3d_coloroffset;
+       unsigned int re_width_height;
+       unsigned int rb3d_colorpitch;
+       unsigned int se_cntl;
+
+       /* Vertex format state */
+       unsigned int se_coord_fmt;      /* 0x1c50 */
+
+       /* Line state */
+       unsigned int re_line_pattern;   /* 0x1cd0 */
+       unsigned int re_line_state;
+
+       unsigned int se_line_width;     /* 0x1db8 */
+
+       /* Bumpmap state */
+       unsigned int pp_lum_matrix;     /* 0x1d00 */
+
+       unsigned int pp_rot_matrix_0;   /* 0x1d58 */
+       unsigned int pp_rot_matrix_1;
+
+       /* Mask state */
+       unsigned int rb3d_stencilrefmask;       /* 0x1d7c */
+       unsigned int rb3d_ropcntl;
+       unsigned int rb3d_planemask;
+
+       /* Viewport state */
+       unsigned int se_vport_xscale;   /* 0x1d98 */
+       unsigned int se_vport_xoffset;
+       unsigned int se_vport_yscale;
+       unsigned int se_vport_yoffset;
+       unsigned int se_vport_zscale;
+       unsigned int se_vport_zoffset;
+
+       /* Setup state */
+       unsigned int se_cntl_status;    /* 0x2140 */
+
+       /* Misc state */
+       unsigned int re_top_left;       /* 0x26c0 */
+       unsigned int re_misc;
+} drm_radeon_context_regs_t;
+
+typedef struct {
+       /* Zbias state */
+       unsigned int se_zbias_factor;   /* 0x1dac */
+       unsigned int se_zbias_constant;
+} drm_radeon_context2_regs_t;
+
+/* Setup registers for each texture unit
+ */
+typedef struct {
+       unsigned int pp_txfilter;
+       unsigned int pp_txformat;
+       unsigned int pp_txoffset;
+       unsigned int pp_txcblend;
+       unsigned int pp_txablend;
+       unsigned int pp_tfactor;
+       unsigned int pp_border_color;
+} drm_radeon_texture_regs_t;
+
+typedef struct {
+       unsigned int start;
+       unsigned int finish;
+       unsigned int prim:8;
+       unsigned int stateidx:8;
+       unsigned int numverts:16;       /* overloaded as offset/64 for elt prims */
+       unsigned int vc_format; /* vertex format */
+} drm_radeon_prim_t;
+
+typedef struct {
+       drm_radeon_context_regs_t context;
+       drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS];
+       drm_radeon_context2_regs_t context2;
+       unsigned int dirty;
+} drm_radeon_state_t;
+
+typedef struct {
+       /* The channel for communication of state information to the
+        * kernel on firing a vertex buffer with either of the
+        * obsoleted vertex/index ioctls.
+        */
+       drm_radeon_context_regs_t context_state;
+       drm_radeon_texture_regs_t tex_state[RADEON_MAX_TEXTURE_UNITS];
+       unsigned int dirty;
+       unsigned int vertsize;
+       unsigned int vc_format;
+
+       /* The current cliprects, or a subset thereof.
+        */
+       struct drm_clip_rect boxes[RADEON_NR_SAREA_CLIPRECTS];
+       unsigned int nbox;
+
+       /* Counters for client-side throttling of rendering clients.
+        */
+       unsigned int last_frame;
+       unsigned int last_dispatch;
+       unsigned int last_clear;
+
+       struct drm_tex_region tex_list[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS +
+                                                      1];
+       unsigned int tex_age[RADEON_NR_TEX_HEAPS];
+       int ctx_owner;
+       int pfState;            /* number of 3d windows (0,1,2ormore) */
+       int pfCurrentPage;      /* which buffer is being displayed? */
+       int crtc2_base;         /* CRTC2 frame offset */
+       int tiling_enabled;     /* set by drm, read by 2d + 3d clients */
+} drm_radeon_sarea_t;
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the Xserver file (xf86drmRadeon.h)
+ *
+ * KW: actually it's illegal to change any of this (backwards compatibility).
+ */
+
+/* Radeon specific ioctls
+ * The device specific ioctl range is 0x40 to 0x79.
+ */
+#define DRM_RADEON_CP_INIT    0x00
+#define DRM_RADEON_CP_START   0x01
+#define DRM_RADEON_CP_STOP    0x02
+#define DRM_RADEON_CP_RESET   0x03
+#define DRM_RADEON_CP_IDLE    0x04
+#define DRM_RADEON_RESET      0x05
+#define DRM_RADEON_FULLSCREEN 0x06
+#define DRM_RADEON_SWAP       0x07
+#define DRM_RADEON_CLEAR      0x08
+#define DRM_RADEON_VERTEX     0x09
+#define DRM_RADEON_INDICES    0x0A
+#define DRM_RADEON_NOT_USED
+#define DRM_RADEON_STIPPLE    0x0C
+#define DRM_RADEON_INDIRECT   0x0D
+#define DRM_RADEON_TEXTURE    0x0E
+#define DRM_RADEON_VERTEX2    0x0F
+#define DRM_RADEON_CMDBUF     0x10
+#define DRM_RADEON_GETPARAM   0x11
+#define DRM_RADEON_FLIP       0x12
+#define DRM_RADEON_ALLOC      0x13
+#define DRM_RADEON_FREE       0x14
+#define DRM_RADEON_INIT_HEAP  0x15
+#define DRM_RADEON_IRQ_EMIT   0x16
+#define DRM_RADEON_IRQ_WAIT   0x17
+#define DRM_RADEON_CP_RESUME  0x18
+#define DRM_RADEON_SETPARAM   0x19
+#define DRM_RADEON_SURF_ALLOC 0x1a
+#define DRM_RADEON_SURF_FREE  0x1b
+
+#define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
+#define DRM_IOCTL_RADEON_CP_START   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_START)
+#define DRM_IOCTL_RADEON_CP_STOP    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t)
+#define DRM_IOCTL_RADEON_CP_RESET   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_RESET)
+#define DRM_IOCTL_RADEON_CP_IDLE    DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_IDLE)
+#define DRM_IOCTL_RADEON_RESET      DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_RESET)
+#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FULLSCREEN, drm_radeon_fullscreen_t)
+#define DRM_IOCTL_RADEON_SWAP       DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_SWAP)
+#define DRM_IOCTL_RADEON_CLEAR      DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CLEAR, drm_radeon_clear_t)
+#define DRM_IOCTL_RADEON_VERTEX     DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX, drm_radeon_vertex_t)
+#define DRM_IOCTL_RADEON_INDICES    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INDICES, drm_radeon_indices_t)
+#define DRM_IOCTL_RADEON_STIPPLE    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_STIPPLE, drm_radeon_stipple_t)
+#define DRM_IOCTL_RADEON_INDIRECT   DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INDIRECT, drm_radeon_indirect_t)
+#define DRM_IOCTL_RADEON_TEXTURE    DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_TEXTURE, drm_radeon_texture_t)
+#define DRM_IOCTL_RADEON_VERTEX2    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_VERTEX2, drm_radeon_vertex2_t)
+#define DRM_IOCTL_RADEON_CMDBUF     DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CMDBUF, drm_radeon_cmd_buffer_t)
+#define DRM_IOCTL_RADEON_GETPARAM   DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GETPARAM, drm_radeon_getparam_t)
+#define DRM_IOCTL_RADEON_FLIP       DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_FLIP)
+#define DRM_IOCTL_RADEON_ALLOC      DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_ALLOC, drm_radeon_mem_alloc_t)
+#define DRM_IOCTL_RADEON_FREE       DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_FREE, drm_radeon_mem_free_t)
+#define DRM_IOCTL_RADEON_INIT_HEAP  DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_INIT_HEAP, drm_radeon_mem_init_heap_t)
+#define DRM_IOCTL_RADEON_IRQ_EMIT   DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_IRQ_EMIT, drm_radeon_irq_emit_t)
+#define DRM_IOCTL_RADEON_IRQ_WAIT   DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_IRQ_WAIT, drm_radeon_irq_wait_t)
+#define DRM_IOCTL_RADEON_CP_RESUME  DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_RESUME)
+#define DRM_IOCTL_RADEON_SETPARAM   DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t)
+#define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t)
+#define DRM_IOCTL_RADEON_SURF_FREE  DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t)
+
+typedef struct drm_radeon_init {
+       enum {
+               RADEON_INIT_CP = 0x01,
+               RADEON_CLEANUP_CP = 0x02,
+               RADEON_INIT_R200_CP = 0x03,
+               RADEON_INIT_R300_CP = 0x04
+       } func;
+       unsigned long sarea_priv_offset;
+       int is_pci;
+       int cp_mode;
+       int gart_size;
+       int ring_size;
+       int usec_timeout;
+
+       unsigned int fb_bpp;
+       unsigned int front_offset, front_pitch;
+       unsigned int back_offset, back_pitch;
+       unsigned int depth_bpp;
+       unsigned int depth_offset, depth_pitch;
+
+       unsigned long fb_offset;
+       unsigned long mmio_offset;
+       unsigned long ring_offset;
+       unsigned long ring_rptr_offset;
+       unsigned long buffers_offset;
+       unsigned long gart_textures_offset;
+} drm_radeon_init_t;
+
+typedef struct drm_radeon_cp_stop {
+       int flush;
+       int idle;
+} drm_radeon_cp_stop_t;
+
+typedef struct drm_radeon_fullscreen {
+       enum {
+               RADEON_INIT_FULLSCREEN = 0x01,
+               RADEON_CLEANUP_FULLSCREEN = 0x02
+       } func;
+} drm_radeon_fullscreen_t;
+
+#define CLEAR_X1       0
+#define CLEAR_Y1       1
+#define CLEAR_X2       2
+#define CLEAR_Y2       3
+#define CLEAR_DEPTH    4
+
+typedef union drm_radeon_clear_rect {
+       float f[5];
+       unsigned int ui[5];
+} drm_radeon_clear_rect_t;
+
+typedef struct drm_radeon_clear {
+       unsigned int flags;
+       unsigned int clear_color;
+       unsigned int clear_depth;
+       unsigned int color_mask;
+       unsigned int depth_mask;        /* misnamed field:  should be stencil */
+       drm_radeon_clear_rect_t __user *depth_boxes;
+} drm_radeon_clear_t;
+
+typedef struct drm_radeon_vertex {
+       int prim;
+       int idx;                /* Index of vertex buffer */
+       int count;              /* Number of vertices in buffer */
+       int discard;            /* Client finished with buffer? */
+} drm_radeon_vertex_t;
+
+typedef struct drm_radeon_indices {
+       int prim;
+       int idx;
+       int start;
+       int end;
+       int discard;            /* Client finished with buffer? */
+} drm_radeon_indices_t;
+
+/* v1.2 - obsoletes drm_radeon_vertex and drm_radeon_indices
+ *      - allows multiple primitives and state changes in a single ioctl
+ *      - supports driver change to emit native primitives
+ */
+typedef struct drm_radeon_vertex2 {
+       int idx;                /* Index of vertex buffer */
+       int discard;            /* Client finished with buffer? */
+       int nr_states;
+       drm_radeon_state_t __user *state;
+       int nr_prims;
+       drm_radeon_prim_t __user *prim;
+} drm_radeon_vertex2_t;
+
+/* v1.3 - obsoletes drm_radeon_vertex2
+ *      - allows arbitarily large cliprect list
+ *      - allows updating of tcl packet, vector and scalar state
+ *      - allows memory-efficient description of state updates
+ *      - allows state to be emitted without a primitive
+ *           (for clears, ctx switches)
+ *      - allows more than one dma buffer to be referenced per ioctl
+ *      - supports tcl driver
+ *      - may be extended in future versions with new cmd types, packets
+ */
+typedef struct drm_radeon_cmd_buffer {
+       int bufsz;
+       char __user *buf;
+       int nbox;
+       struct drm_clip_rect __user *boxes;
+} drm_radeon_cmd_buffer_t;
+
+typedef struct drm_radeon_tex_image {
+       unsigned int x, y;      /* Blit coordinates */
+       unsigned int width, height;
+       const void __user *data;
+} drm_radeon_tex_image_t;
+
+typedef struct drm_radeon_texture {
+       unsigned int offset;
+       int pitch;
+       int format;
+       int width;              /* Texture image coordinates */
+       int height;
+       drm_radeon_tex_image_t __user *image;
+} drm_radeon_texture_t;
+
+typedef struct drm_radeon_stipple {
+       unsigned int __user *mask;
+} drm_radeon_stipple_t;
+
+typedef struct drm_radeon_indirect {
+       int idx;
+       int start;
+       int end;
+       int discard;
+} drm_radeon_indirect_t;
+
+/* enum for card type parameters */
+#define RADEON_CARD_PCI 0
+#define RADEON_CARD_AGP 1
+#define RADEON_CARD_PCIE 2
+
+/* 1.3: An ioctl to get parameters that aren't available to the 3d
+ * client any other way.
+ */
+#define RADEON_PARAM_GART_BUFFER_OFFSET    1   /* card offset of 1st GART buffer */
+#define RADEON_PARAM_LAST_FRAME            2
+#define RADEON_PARAM_LAST_DISPATCH         3
+#define RADEON_PARAM_LAST_CLEAR            4
+/* Added with DRM version 1.6. */
+#define RADEON_PARAM_IRQ_NR                5
+#define RADEON_PARAM_GART_BASE             6   /* card offset of GART base */
+/* Added with DRM version 1.8. */
+#define RADEON_PARAM_REGISTER_HANDLE       7   /* for drmMap() */
+#define RADEON_PARAM_STATUS_HANDLE         8
+#define RADEON_PARAM_SAREA_HANDLE          9
+#define RADEON_PARAM_GART_TEX_HANDLE       10
+#define RADEON_PARAM_SCRATCH_OFFSET        11
+#define RADEON_PARAM_CARD_TYPE             12
+#define RADEON_PARAM_VBLANK_CRTC           13   /* VBLANK CRTC */
+#define RADEON_PARAM_FB_LOCATION           14   /* FB location */
+#define RADEON_PARAM_NUM_GB_PIPES          15   /* num GB pipes */
+
+typedef struct drm_radeon_getparam {
+       int param;
+       void __user *value;
+} drm_radeon_getparam_t;
+
+/* 1.6: Set up a memory manager for regions of shared memory:
+ */
+#define RADEON_MEM_REGION_GART 1
+#define RADEON_MEM_REGION_FB   2
+
+typedef struct drm_radeon_mem_alloc {
+       int region;
+       int alignment;
+       int size;
+       int __user *region_offset;      /* offset from start of fb or GART */
+} drm_radeon_mem_alloc_t;
+
+typedef struct drm_radeon_mem_free {
+       int region;
+       int region_offset;
+} drm_radeon_mem_free_t;
+
+typedef struct drm_radeon_mem_init_heap {
+       int region;
+       int size;
+       int start;
+} drm_radeon_mem_init_heap_t;
+
+/* 1.6: Userspace can request & wait on irq's:
+ */
+typedef struct drm_radeon_irq_emit {
+       int __user *irq_seq;
+} drm_radeon_irq_emit_t;
+
+typedef struct drm_radeon_irq_wait {
+       int irq_seq;
+} drm_radeon_irq_wait_t;
+
+/* 1.10: Clients tell the DRM where they think the framebuffer is located in
+ * the card's address space, via a new generic ioctl to set parameters
+ */
+
+typedef struct drm_radeon_setparam {
+       unsigned int param;
+       int64_t value;
+} drm_radeon_setparam_t;
+
+#define RADEON_SETPARAM_FB_LOCATION    1       /* determined framebuffer location */
+#define RADEON_SETPARAM_SWITCH_TILING  2       /* enable/disable color tiling */
+#define RADEON_SETPARAM_PCIGART_LOCATION 3     /* PCI Gart Location */
+#define RADEON_SETPARAM_NEW_MEMMAP 4           /* Use new memory map */
+#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5    /* PCI GART Table Size */
+#define RADEON_SETPARAM_VBLANK_CRTC 6           /* VBLANK CRTC */
+/* 1.14: Clients can allocate/free a surface
+ */
+typedef struct drm_radeon_surface_alloc {
+       unsigned int address;
+       unsigned int size;
+       unsigned int flags;
+} drm_radeon_surface_alloc_t;
+
+typedef struct drm_radeon_surface_free {
+       unsigned int address;
+} drm_radeon_surface_free_t;
+
+#define        DRM_RADEON_VBLANK_CRTC1         1
+#define        DRM_RADEON_VBLANK_CRTC2         2
+
+#endif
diff --git a/include/drm/savage_drm.h b/include/drm/savage_drm.h
new file mode 100644 (file)
index 0000000..8a576ef
--- /dev/null
@@ -0,0 +1,210 @@
+/* savage_drm.h -- Public header for the savage driver
+ *
+ * Copyright 2004  Felix Kuehling
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __SAVAGE_DRM_H__
+#define __SAVAGE_DRM_H__
+
+#ifndef __SAVAGE_SAREA_DEFINES__
+#define __SAVAGE_SAREA_DEFINES__
+
+/* 2 heaps (1 for card, 1 for agp), each divided into upto 128
+ * regions, subject to a minimum region size of (1<<16) == 64k.
+ *
+ * Clients may subdivide regions internally, but when sharing between
+ * clients, the region size is the minimum granularity.
+ */
+
+#define SAVAGE_CARD_HEAP               0
+#define SAVAGE_AGP_HEAP                        1
+#define SAVAGE_NR_TEX_HEAPS            2
+#define SAVAGE_NR_TEX_REGIONS          16
+#define SAVAGE_LOG_MIN_TEX_REGION_SIZE 16
+
+#endif                         /* __SAVAGE_SAREA_DEFINES__ */
+
+typedef struct _drm_savage_sarea {
+       /* LRU lists for texture memory in agp space and on the card.
+        */
+       struct drm_tex_region texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS +
+                                                     1];
+       unsigned int texAge[SAVAGE_NR_TEX_HEAPS];
+
+       /* Mechanism to validate card state.
+        */
+       int ctxOwner;
+} drm_savage_sarea_t, *drm_savage_sarea_ptr;
+
+/* Savage-specific ioctls
+ */
+#define DRM_SAVAGE_BCI_INIT            0x00
+#define DRM_SAVAGE_BCI_CMDBUF           0x01
+#define DRM_SAVAGE_BCI_EVENT_EMIT      0x02
+#define DRM_SAVAGE_BCI_EVENT_WAIT      0x03
+
+#define DRM_IOCTL_SAVAGE_INIT          DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t)
+#define DRM_IOCTL_SAVAGE_CMDBUF                DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t)
+#define DRM_IOCTL_SAVAGE_EVENT_EMIT    DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t)
+#define DRM_IOCTL_SAVAGE_EVENT_WAIT    DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t)
+
+#define SAVAGE_DMA_PCI 1
+#define SAVAGE_DMA_AGP 3
+typedef struct drm_savage_init {
+       enum {
+               SAVAGE_INIT_BCI = 1,
+               SAVAGE_CLEANUP_BCI = 2
+       } func;
+       unsigned int sarea_priv_offset;
+
+       /* some parameters */
+       unsigned int cob_size;
+       unsigned int bci_threshold_lo, bci_threshold_hi;
+       unsigned int dma_type;
+
+       /* frame buffer layout */
+       unsigned int fb_bpp;
+       unsigned int front_offset, front_pitch;
+       unsigned int back_offset, back_pitch;
+       unsigned int depth_bpp;
+       unsigned int depth_offset, depth_pitch;
+
+       /* local textures */
+       unsigned int texture_offset;
+       unsigned int texture_size;
+
+       /* physical locations of non-permanent maps */
+       unsigned long status_offset;
+       unsigned long buffers_offset;
+       unsigned long agp_textures_offset;
+       unsigned long cmd_dma_offset;
+} drm_savage_init_t;
+
+typedef union drm_savage_cmd_header drm_savage_cmd_header_t;
+typedef struct drm_savage_cmdbuf {
+       /* command buffer in client's address space */
+       drm_savage_cmd_header_t __user *cmd_addr;
+       unsigned int size;      /* size of the command buffer in 64bit units */
+
+       unsigned int dma_idx;   /* DMA buffer index to use */
+       int discard;            /* discard DMA buffer when done */
+       /* vertex buffer in client's address space */
+       unsigned int __user *vb_addr;
+       unsigned int vb_size;   /* size of client vertex buffer in bytes */
+       unsigned int vb_stride; /* stride of vertices in 32bit words */
+       /* boxes in client's address space */
+       struct drm_clip_rect __user *box_addr;
+       unsigned int nbox;      /* number of clipping boxes */
+} drm_savage_cmdbuf_t;
+
+#define SAVAGE_WAIT_2D  0x1    /* wait for 2D idle before updating event tag */
+#define SAVAGE_WAIT_3D  0x2    /* wait for 3D idle before updating event tag */
+#define SAVAGE_WAIT_IRQ 0x4    /* emit or wait for IRQ, not implemented yet */
+typedef struct drm_savage_event {
+       unsigned int count;
+       unsigned int flags;
+} drm_savage_event_emit_t, drm_savage_event_wait_t;
+
+/* Commands for the cmdbuf ioctl
+ */
+#define SAVAGE_CMD_STATE       0       /* a range of state registers */
+#define SAVAGE_CMD_DMA_PRIM    1       /* vertices from DMA buffer */
+#define SAVAGE_CMD_VB_PRIM     2       /* vertices from client vertex buffer */
+#define SAVAGE_CMD_DMA_IDX     3       /* indexed vertices from DMA buffer */
+#define SAVAGE_CMD_VB_IDX      4       /* indexed vertices client vertex buffer */
+#define SAVAGE_CMD_CLEAR       5       /* clear buffers */
+#define SAVAGE_CMD_SWAP                6       /* swap buffers */
+
+/* Primitive types
+*/
+#define SAVAGE_PRIM_TRILIST    0       /* triangle list */
+#define SAVAGE_PRIM_TRISTRIP   1       /* triangle strip */
+#define SAVAGE_PRIM_TRIFAN     2       /* triangle fan */
+#define SAVAGE_PRIM_TRILIST_201        3       /* reorder verts for correct flat
+                                        * shading on s3d */
+
+/* Skip flags (vertex format)
+ */
+#define SAVAGE_SKIP_Z          0x01
+#define SAVAGE_SKIP_W          0x02
+#define SAVAGE_SKIP_C0         0x04
+#define SAVAGE_SKIP_C1         0x08
+#define SAVAGE_SKIP_S0         0x10
+#define SAVAGE_SKIP_T0         0x20
+#define SAVAGE_SKIP_ST0                0x30
+#define SAVAGE_SKIP_S1         0x40
+#define SAVAGE_SKIP_T1         0x80
+#define SAVAGE_SKIP_ST1                0xc0
+#define SAVAGE_SKIP_ALL_S3D    0x3f
+#define SAVAGE_SKIP_ALL_S4     0xff
+
+/* Buffer names for clear command
+ */
+#define SAVAGE_FRONT           0x1
+#define SAVAGE_BACK            0x2
+#define SAVAGE_DEPTH           0x4
+
+/* 64-bit command header
+ */
+union drm_savage_cmd_header {
+       struct {
+               unsigned char cmd;      /* command */
+               unsigned char pad0;
+               unsigned short pad1;
+               unsigned short pad2;
+               unsigned short pad3;
+       } cmd;                  /* generic */
+       struct {
+               unsigned char cmd;
+               unsigned char global;   /* need idle engine? */
+               unsigned short count;   /* number of consecutive registers */
+               unsigned short start;   /* first register */
+               unsigned short pad3;
+       } state;                /* SAVAGE_CMD_STATE */
+       struct {
+               unsigned char cmd;
+               unsigned char prim;     /* primitive type */
+               unsigned short skip;    /* vertex format (skip flags) */
+               unsigned short count;   /* number of vertices */
+               unsigned short start;   /* first vertex in DMA/vertex buffer */
+       } prim;                 /* SAVAGE_CMD_DMA_PRIM, SAVAGE_CMD_VB_PRIM */
+       struct {
+               unsigned char cmd;
+               unsigned char prim;
+               unsigned short skip;
+               unsigned short count;   /* number of indices that follow */
+               unsigned short pad3;
+       } idx;                  /* SAVAGE_CMD_DMA_IDX, SAVAGE_CMD_VB_IDX */
+       struct {
+               unsigned char cmd;
+               unsigned char pad0;
+               unsigned short pad1;
+               unsigned int flags;
+       } clear0;               /* SAVAGE_CMD_CLEAR */
+       struct {
+               unsigned int mask;
+               unsigned int value;
+       } clear1;               /* SAVAGE_CMD_CLEAR data */
+};
+
+#endif
diff --git a/include/drm/sis_drm.h b/include/drm/sis_drm.h
new file mode 100644 (file)
index 0000000..30f7b38
--- /dev/null
@@ -0,0 +1,67 @@
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */
+/*
+ * Copyright 2005 Eric Anholt
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __SIS_DRM_H__
+#define __SIS_DRM_H__
+
+/* SiS specific ioctls */
+#define NOT_USED_0_3
+#define DRM_SIS_FB_ALLOC       0x04
+#define DRM_SIS_FB_FREE                0x05
+#define NOT_USED_6_12
+#define DRM_SIS_AGP_INIT       0x13
+#define DRM_SIS_AGP_ALLOC      0x14
+#define DRM_SIS_AGP_FREE       0x15
+#define DRM_SIS_FB_INIT                0x16
+
+#define DRM_IOCTL_SIS_FB_ALLOC         DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_FB_ALLOC, drm_sis_mem_t)
+#define DRM_IOCTL_SIS_FB_FREE          DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_FREE, drm_sis_mem_t)
+#define DRM_IOCTL_SIS_AGP_INIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_INIT, drm_sis_agp_t)
+#define DRM_IOCTL_SIS_AGP_ALLOC                DRM_IOWR(DRM_COMMAND_BASE + DRM_SIS_AGP_ALLOC, drm_sis_mem_t)
+#define DRM_IOCTL_SIS_AGP_FREE         DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_AGP_FREE, drm_sis_mem_t)
+#define DRM_IOCTL_SIS_FB_INIT          DRM_IOW( DRM_COMMAND_BASE + DRM_SIS_FB_INIT, drm_sis_fb_t)
+/*
+#define DRM_IOCTL_SIS_FLIP             DRM_IOW( 0x48, drm_sis_flip_t)
+#define DRM_IOCTL_SIS_FLIP_INIT                DRM_IO(  0x49)
+#define DRM_IOCTL_SIS_FLIP_FINAL       DRM_IO(  0x50)
+*/
+
+typedef struct {
+       int context;
+       unsigned int offset;
+       unsigned int size;
+       unsigned long free;
+} drm_sis_mem_t;
+
+typedef struct {
+       unsigned int offset, size;
+} drm_sis_agp_t;
+
+typedef struct {
+       unsigned int offset, size;
+} drm_sis_fb_t;
+
+#endif                         /* __SIS_DRM_H__ */
diff --git a/include/drm/via_drm.h b/include/drm/via_drm.h
new file mode 100644 (file)
index 0000000..a3b5c10
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _VIA_DRM_H_
+#define _VIA_DRM_H_
+
+/* WARNING: These defines must be the same as what the Xserver uses.
+ * if you change them, you must change the defines in the Xserver.
+ */
+
+#ifndef _VIA_DEFINES_
+#define _VIA_DEFINES_
+
+#ifndef __KERNEL__
+#include "via_drmclient.h"
+#endif
+
+#define VIA_NR_SAREA_CLIPRECTS         8
+#define VIA_NR_XVMC_PORTS               10
+#define VIA_NR_XVMC_LOCKS               5
+#define VIA_MAX_CACHELINE_SIZE          64
+#define XVMCLOCKPTR(saPriv,lockNo)                                     \
+       ((volatile struct drm_hw_lock *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
+                                     (VIA_MAX_CACHELINE_SIZE - 1)) &   \
+                                    ~(VIA_MAX_CACHELINE_SIZE - 1)) +   \
+                                   VIA_MAX_CACHELINE_SIZE*(lockNo)))
+
+/* Each region is a minimum of 64k, and there are at most 64 of them.
+ */
+#define VIA_NR_TEX_REGIONS 64
+#define VIA_LOG_MIN_TEX_REGION_SIZE 16
+#endif
+
+#define VIA_UPLOAD_TEX0IMAGE  0x1      /* handled clientside */
+#define VIA_UPLOAD_TEX1IMAGE  0x2      /* handled clientside */
+#define VIA_UPLOAD_CTX        0x4
+#define VIA_UPLOAD_BUFFERS    0x8
+#define VIA_UPLOAD_TEX0       0x10
+#define VIA_UPLOAD_TEX1       0x20
+#define VIA_UPLOAD_CLIPRECTS  0x40
+#define VIA_UPLOAD_ALL        0xff
+
+/* VIA specific ioctls */
+#define DRM_VIA_ALLOCMEM       0x00
+#define DRM_VIA_FREEMEM                0x01
+#define DRM_VIA_AGP_INIT       0x02
+#define DRM_VIA_FB_INIT                0x03
+#define DRM_VIA_MAP_INIT       0x04
+#define DRM_VIA_DEC_FUTEX       0x05
+#define NOT_USED
+#define DRM_VIA_DMA_INIT       0x07
+#define DRM_VIA_CMDBUFFER      0x08
+#define DRM_VIA_FLUSH          0x09
+#define DRM_VIA_PCICMD         0x0a
+#define DRM_VIA_CMDBUF_SIZE    0x0b
+#define NOT_USED
+#define DRM_VIA_WAIT_IRQ        0x0d
+#define DRM_VIA_DMA_BLIT        0x0e
+#define DRM_VIA_BLIT_SYNC       0x0f
+
+#define DRM_IOCTL_VIA_ALLOCMEM   DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t)
+#define DRM_IOCTL_VIA_FREEMEM    DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t)
+#define DRM_IOCTL_VIA_AGP_INIT   DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_AGP_INIT, drm_via_agp_t)
+#define DRM_IOCTL_VIA_FB_INIT    DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_FB_INIT, drm_via_fb_t)
+#define DRM_IOCTL_VIA_MAP_INIT   DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_MAP_INIT, drm_via_init_t)
+#define DRM_IOCTL_VIA_DEC_FUTEX   DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_DEC_FUTEX, drm_via_futex_t)
+#define DRM_IOCTL_VIA_DMA_INIT   DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_DMA_INIT, drm_via_dma_init_t)
+#define DRM_IOCTL_VIA_CMDBUFFER          DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_CMDBUFFER, drm_via_cmdbuffer_t)
+#define DRM_IOCTL_VIA_FLUSH      DRM_IO(  DRM_COMMAND_BASE + DRM_VIA_FLUSH)
+#define DRM_IOCTL_VIA_PCICMD     DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_PCICMD, drm_via_cmdbuffer_t)
+#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \
+                                           drm_via_cmdbuf_size_t)
+#define DRM_IOCTL_VIA_WAIT_IRQ    DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t)
+#define DRM_IOCTL_VIA_DMA_BLIT    DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t)
+#define DRM_IOCTL_VIA_BLIT_SYNC   DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t)
+
+/* Indices into buf.Setup where various bits of state are mirrored per
+ * context and per buffer.  These can be fired at the card as a unit,
+ * or in a piecewise fashion as required.
+ */
+
+#define VIA_TEX_SETUP_SIZE 8
+
+/* Flags for clear ioctl
+ */
+#define VIA_FRONT   0x1
+#define VIA_BACK    0x2
+#define VIA_DEPTH   0x4
+#define VIA_STENCIL 0x8
+#define VIA_MEM_VIDEO   0      /* matches drm constant */
+#define VIA_MEM_AGP     1      /* matches drm constant */
+#define VIA_MEM_SYSTEM  2
+#define VIA_MEM_MIXED   3
+#define VIA_MEM_UNKNOWN 4
+
+typedef struct {
+       uint32_t offset;
+       uint32_t size;
+} drm_via_agp_t;
+
+typedef struct {
+       uint32_t offset;
+       uint32_t size;
+} drm_via_fb_t;
+
+typedef struct {
+       uint32_t context;
+       uint32_t type;
+       uint32_t size;
+       unsigned long index;
+       unsigned long offset;
+} drm_via_mem_t;
+
+typedef struct _drm_via_init {
+       enum {
+               VIA_INIT_MAP = 0x01,
+               VIA_CLEANUP_MAP = 0x02
+       } func;
+
+       unsigned long sarea_priv_offset;
+       unsigned long fb_offset;
+       unsigned long mmio_offset;
+       unsigned long agpAddr;
+} drm_via_init_t;
+
+typedef struct _drm_via_futex {
+       enum {
+               VIA_FUTEX_WAIT = 0x00,
+               VIA_FUTEX_WAKE = 0X01
+       } func;
+       uint32_t ms;
+       uint32_t lock;
+       uint32_t val;
+} drm_via_futex_t;
+
+typedef struct _drm_via_dma_init {
+       enum {
+               VIA_INIT_DMA = 0x01,
+               VIA_CLEANUP_DMA = 0x02,
+               VIA_DMA_INITIALIZED = 0x03
+       } func;
+
+       unsigned long offset;
+       unsigned long size;
+       unsigned long reg_pause_addr;
+} drm_via_dma_init_t;
+
+typedef struct _drm_via_cmdbuffer {
+       char __user *buf;
+       unsigned long size;
+} drm_via_cmdbuffer_t;
+
+/* Warning: If you change the SAREA structure you must change the Xserver
+ * structure as well */
+
+typedef struct _drm_via_tex_region {
+       unsigned char next, prev;       /* indices to form a circular LRU  */
+       unsigned char inUse;    /* owned by a client, or free? */
+       int age;                /* tracked by clients to update local LRU's */
+} drm_via_tex_region_t;
+
+typedef struct _drm_via_sarea {
+       unsigned int dirty;
+       unsigned int nbox;
+       struct drm_clip_rect boxes[VIA_NR_SAREA_CLIPRECTS];
+       drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1];
+       int texAge;             /* last time texture was uploaded */
+       int ctxOwner;           /* last context to upload state */
+       int vertexPrim;
+
+       /*
+        * Below is for XvMC.
+        * We want the lock integers alone on, and aligned to, a cache line.
+        * Therefore this somewhat strange construct.
+        */
+
+       char XvMCLockArea[VIA_MAX_CACHELINE_SIZE * (VIA_NR_XVMC_LOCKS + 1)];
+
+       unsigned int XvMCDisplaying[VIA_NR_XVMC_PORTS];
+       unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS];
+       unsigned int XvMCCtxNoGrabbed;  /* Last context to hold decoder */
+
+       /* Used by the 3d driver only at this point, for pageflipping:
+        */
+       unsigned int pfCurrentOffset;
+} drm_via_sarea_t;
+
+typedef struct _drm_via_cmdbuf_size {
+       enum {
+               VIA_CMDBUF_SPACE = 0x01,
+               VIA_CMDBUF_LAG = 0x02
+       } func;
+       int wait;
+       uint32_t size;
+} drm_via_cmdbuf_size_t;
+
+typedef enum {
+       VIA_IRQ_ABSOLUTE = 0x0,
+       VIA_IRQ_RELATIVE = 0x1,
+       VIA_IRQ_SIGNAL = 0x10000000,
+       VIA_IRQ_FORCE_SEQUENCE = 0x20000000
+} via_irq_seq_type_t;
+
+#define VIA_IRQ_FLAGS_MASK 0xF0000000
+
+enum drm_via_irqs {
+       drm_via_irq_hqv0 = 0,
+       drm_via_irq_hqv1,
+       drm_via_irq_dma0_dd,
+       drm_via_irq_dma0_td,
+       drm_via_irq_dma1_dd,
+       drm_via_irq_dma1_td,
+       drm_via_irq_num
+};
+
+struct drm_via_wait_irq_request {
+       unsigned irq;
+       via_irq_seq_type_t type;
+       uint32_t sequence;
+       uint32_t signal;
+};
+
+typedef union drm_via_irqwait {
+       struct drm_via_wait_irq_request request;
+       struct drm_wait_vblank_reply reply;
+} drm_via_irqwait_t;
+
+typedef struct drm_via_blitsync {
+       uint32_t sync_handle;
+       unsigned engine;
+} drm_via_blitsync_t;
+
+/* - * Below,"flags" is currently unused but will be used for possible future
+ * extensions like kernel space bounce buffers for bad alignments and
+ * blit engine busy-wait polling for better latency in the absence of
+ * interrupts.
+ */
+
+typedef struct drm_via_dmablit {
+       uint32_t num_lines;
+       uint32_t line_length;
+
+       uint32_t fb_addr;
+       uint32_t fb_stride;
+
+       unsigned char *mem_addr;
+       uint32_t mem_stride;
+
+       uint32_t flags;
+       int to_fb;
+
+       drm_via_blitsync_t sync;
+} drm_via_dmablit_t;
+
+#endif                         /* _VIA_DRM_H_ */
index b6fbb2573e8872a6496fdd1c75ee65a864a9395f..71d70d1fbce280585d575ba3f131847c0da19cd8 100644 (file)
@@ -166,7 +166,7 @@ unifdef-y += acct.h
 unifdef-y += adb.h
 unifdef-y += adfs_fs.h
 unifdef-y += agpgart.h
-ifeq ($(wildcard include/asm-$(SRCARCH)/a.out.h),include/asm-$(SRCARCH)/a.out.h)
+ifneq ($(wildcard $(srctree)/include/asm-$(SRCARCH)/a.out.h),)
 unifdef-y += a.out.h
 endif
 unifdef-y += apm_bios.h
index 63c3bb98558f6b3e2d07cd9040621273966c1eec..8b82974bdc125b561bf156a1dbfa58d3a51e3751 100644 (file)
@@ -571,7 +571,7 @@ extern void             audit_log_lost(const char *message);
 extern int                 audit_update_lsm_rules(void);
 
                                /* Private API (for audit.c only) */
-extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
+extern int audit_filter_user(struct netlink_skb_parms *cb);
 extern int audit_filter_type(int type);
 extern int  audit_receive_filter(int type, int pid, int uid, int seq,
                                void *data, size_t datasz, uid_t loginuid,
index 61c15eaf3fb3d8f309cd604380f0574f9547749f..0933a14e641423f523d8ed7a56ef7f2a6b849e5c 100644 (file)
@@ -64,6 +64,7 @@ struct bio_vec {
 
 struct bio_set;
 struct bio;
+struct bio_integrity_payload;
 typedef void (bio_end_io_t) (struct bio *, int);
 typedef void (bio_destructor_t) (struct bio *);
 
@@ -112,6 +113,9 @@ struct bio {
        atomic_t                bi_cnt;         /* pin count */
 
        void                    *bi_private;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+       struct bio_integrity_payload *bi_integrity;  /* data integrity */
+#endif
 
        bio_destructor_t        *bi_destructor; /* destructor */
 };
@@ -271,6 +275,29 @@ static inline void *bio_data(struct bio *bio)
  */
 #define bio_get(bio)   atomic_inc(&(bio)->bi_cnt)
 
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+/*
+ * bio integrity payload
+ */
+struct bio_integrity_payload {
+       struct bio              *bip_bio;       /* parent bio */
+       struct bio_vec          *bip_vec;       /* integrity data vector */
+
+       sector_t                bip_sector;     /* virtual start sector */
+
+       void                    *bip_buf;       /* generated integrity data */
+       bio_end_io_t            *bip_end_io;    /* saved I/O completion fn */
+
+       int                     bip_error;      /* saved I/O error */
+       unsigned int            bip_size;
+
+       unsigned short          bip_pool;       /* pool the ivec came from */
+       unsigned short          bip_vcnt;       /* # of integrity bio_vecs */
+       unsigned short          bip_idx;        /* current bip_vec index */
+
+       struct work_struct      bip_work;       /* I/O completion */
+};
+#endif /* CONFIG_BLK_DEV_INTEGRITY */
 
 /*
  * A bio_pair is used when we need to split a bio.
@@ -283,10 +310,14 @@ static inline void *bio_data(struct bio *bio)
  *   in bio2.bi_private
  */
 struct bio_pair {
-       struct bio      bio1, bio2;
-       struct bio_vec  bv1, bv2;
-       atomic_t        cnt;
-       int             error;
+       struct bio                      bio1, bio2;
+       struct bio_vec                  bv1, bv2;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+       struct bio_integrity_payload    bip1, bip2;
+       struct bio_vec                  iv1, iv2;
+#endif
+       atomic_t                        cnt;
+       int                             error;
 };
 extern struct bio_pair *bio_split(struct bio *bi, mempool_t *pool,
                                  int first_sectors);
@@ -333,6 +364,39 @@ extern struct bio *bio_copy_user_iov(struct request_queue *, struct sg_iovec *,
                                     int, int);
 extern int bio_uncopy_user(struct bio *);
 void zero_fill_bio(struct bio *bio);
+extern struct bio_vec *bvec_alloc_bs(gfp_t, int, unsigned long *, struct bio_set *);
+extern unsigned int bvec_nr_vecs(unsigned short idx);
+
+/*
+ * bio_set is used to allow other portions of the IO system to
+ * allocate their own private memory pools for bio and iovec structures.
+ * These memory pools in turn all allocate from the bio_slab
+ * and the bvec_slabs[].
+ */
+#define BIO_POOL_SIZE 2
+#define BIOVEC_NR_POOLS 6
+
+struct bio_set {
+       mempool_t *bio_pool;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+       mempool_t *bio_integrity_pool;
+#endif
+       mempool_t *bvec_pools[BIOVEC_NR_POOLS];
+};
+
+struct biovec_slab {
+       int nr_vecs;
+       char *name;
+       struct kmem_cache *slab;
+};
+
+extern struct bio_set *fs_bio_set;
+
+/*
+ * a small number of entries is fine, not going to be performance critical.
+ * basically we just need to survive
+ */
+#define BIO_SPLIT_ENTRIES 2
 
 #ifdef CONFIG_HIGHMEM
 /*
@@ -381,5 +445,63 @@ static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
        __bio_kmap_irq((bio), (bio)->bi_idx, (flags))
 #define bio_kunmap_irq(buf,flags)      __bio_kunmap_irq(buf, flags)
 
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+
+#define bip_vec_idx(bip, idx)  (&(bip->bip_vec[(idx)]))
+#define bip_vec(bip)           bip_vec_idx(bip, 0)
+
+#define __bip_for_each_vec(bvl, bip, i, start_idx)                     \
+       for (bvl = bip_vec_idx((bip), (start_idx)), i = (start_idx);    \
+            i < (bip)->bip_vcnt;                                       \
+            bvl++, i++)
+
+#define bip_for_each_vec(bvl, bip, i)                                  \
+       __bip_for_each_vec(bvl, bip, i, (bip)->bip_idx)
+
+static inline int bio_integrity(struct bio *bio)
+{
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+       return bio->bi_integrity != NULL;
+#else
+       return 0;
+#endif
+}
+
+extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *);
+extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int);
+extern void bio_integrity_free(struct bio *, struct bio_set *);
+extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int);
+extern int bio_integrity_enabled(struct bio *bio);
+extern int bio_integrity_set_tag(struct bio *, void *, unsigned int);
+extern int bio_integrity_get_tag(struct bio *, void *, unsigned int);
+extern int bio_integrity_prep(struct bio *);
+extern void bio_integrity_endio(struct bio *, int);
+extern void bio_integrity_advance(struct bio *, unsigned int);
+extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int);
+extern void bio_integrity_split(struct bio *, struct bio_pair *, int);
+extern int bio_integrity_clone(struct bio *, struct bio *, struct bio_set *);
+extern int bioset_integrity_create(struct bio_set *, int);
+extern void bioset_integrity_free(struct bio_set *);
+extern void bio_integrity_init_slab(void);
+
+#else /* CONFIG_BLK_DEV_INTEGRITY */
+
+#define bio_integrity(a)               (0)
+#define bioset_integrity_create(a, b)  (0)
+#define bio_integrity_prep(a)          (0)
+#define bio_integrity_enabled(a)       (0)
+#define bio_integrity_clone(a, b, c)   (0)
+#define bioset_integrity_free(a)       do { } while (0)
+#define bio_integrity_free(a, b)       do { } while (0)
+#define bio_integrity_endio(a, b)      do { } while (0)
+#define bio_integrity_advance(a, b)    do { } while (0)
+#define bio_integrity_trim(a, b, c)    do { } while (0)
+#define bio_integrity_split(a, b, c)   do { } while (0)
+#define bio_integrity_set_tag(a, b, c) do { } while (0)
+#define bio_integrity_get_tag(a, b, c) do { } while (0)
+#define bio_integrity_init_slab(a)     do { } while (0)
+
+#endif /* CONFIG_BLK_DEV_INTEGRITY */
+
 #endif /* CONFIG_BLOCK */
 #endif /* __LINUX_BIO_H */
index d2a1b71e93c3eee9570e86513bdb2786d260699c..1ffd8bfdc4c94956fa14bb8e6c880d79e0953918 100644 (file)
@@ -23,7 +23,6 @@
 struct scsi_ioctl_command;
 
 struct request_queue;
-typedef struct request_queue request_queue_t __deprecated;
 struct elevator_queue;
 typedef struct elevator_queue elevator_t;
 struct request_pm_state;
@@ -34,12 +33,6 @@ struct sg_io_hdr;
 #define BLKDEV_MIN_RQ  4
 #define BLKDEV_MAX_RQ  128     /* Default maximum */
 
-int put_io_context(struct io_context *ioc);
-void exit_io_context(void);
-struct io_context *get_io_context(gfp_t gfp_flags, int node);
-struct io_context *alloc_io_context(gfp_t gfp_flags, int node);
-void copy_io_context(struct io_context **pdst, struct io_context **psrc);
-
 struct request;
 typedef void (rq_end_io_fn)(struct request *, int);
 
@@ -113,6 +106,7 @@ enum rq_flag_bits {
        __REQ_ALLOCED,          /* request came from our alloc pool */
        __REQ_RW_META,          /* metadata io request */
        __REQ_COPY_USER,        /* contains copies of user pages */
+       __REQ_INTEGRITY,        /* integrity metadata has been remapped */
        __REQ_NR_BITS,          /* stops here */
 };
 
@@ -135,6 +129,7 @@ enum rq_flag_bits {
 #define REQ_ALLOCED    (1 << __REQ_ALLOCED)
 #define REQ_RW_META    (1 << __REQ_RW_META)
 #define REQ_COPY_USER  (1 << __REQ_COPY_USER)
+#define REQ_INTEGRITY  (1 << __REQ_INTEGRITY)
 
 #define BLK_MAX_CDB    16
 
@@ -259,7 +254,14 @@ typedef int (prep_rq_fn) (struct request_queue *, struct request *);
 typedef void (unplug_fn) (struct request_queue *);
 
 struct bio_vec;
-typedef int (merge_bvec_fn) (struct request_queue *, struct bio *, struct bio_vec *);
+struct bvec_merge_data {
+       struct block_device *bi_bdev;
+       sector_t bi_sector;
+       unsigned bi_size;
+       unsigned long bi_rw;
+};
+typedef int (merge_bvec_fn) (struct request_queue *, struct bvec_merge_data *,
+                            struct bio_vec *);
 typedef void (prepare_flush_fn) (struct request_queue *, struct request *);
 typedef void (softirq_done_fn)(struct request *);
 typedef int (dma_drain_needed_fn)(struct request *);
@@ -426,6 +428,32 @@ static inline void queue_flag_set_unlocked(unsigned int flag,
        __set_bit(flag, &q->queue_flags);
 }
 
+static inline int queue_flag_test_and_clear(unsigned int flag,
+                                           struct request_queue *q)
+{
+       WARN_ON_ONCE(!queue_is_locked(q));
+
+       if (test_bit(flag, &q->queue_flags)) {
+               __clear_bit(flag, &q->queue_flags);
+               return 1;
+       }
+
+       return 0;
+}
+
+static inline int queue_flag_test_and_set(unsigned int flag,
+                                         struct request_queue *q)
+{
+       WARN_ON_ONCE(!queue_is_locked(q));
+
+       if (!test_bit(flag, &q->queue_flags)) {
+               __set_bit(flag, &q->queue_flags);
+               return 0;
+       }
+
+       return 1;
+}
+
 static inline void queue_flag_set(unsigned int flag, struct request_queue *q)
 {
        WARN_ON_ONCE(!queue_is_locked(q));
@@ -676,7 +704,6 @@ extern int blk_execute_rq(struct request_queue *, struct gendisk *,
                          struct request *, int);
 extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *,
                                  struct request *, int, rq_end_io_fn *);
-extern int blk_verify_command(unsigned char *, int);
 extern void blk_unplug(struct request_queue *q);
 
 static inline struct request_queue *bdev_get_queue(struct block_device *bdev)
@@ -749,6 +776,7 @@ extern void blk_queue_max_segment_size(struct request_queue *, unsigned int);
 extern void blk_queue_hardsect_size(struct request_queue *, unsigned short);
 extern void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b);
 extern void blk_queue_dma_pad(struct request_queue *, unsigned int);
+extern void blk_queue_update_dma_pad(struct request_queue *, unsigned int);
 extern int blk_queue_dma_drain(struct request_queue *q,
                               dma_drain_needed_fn *dma_drain_needed,
                               void *buf, unsigned int size);
@@ -802,6 +830,15 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt,
 
 extern int blkdev_issue_flush(struct block_device *, sector_t *);
 
+/*
+* command filter functions
+*/
+extern int blk_verify_command(struct file *file, unsigned char *cmd);
+extern int blk_cmd_filter_verify_command(struct blk_scsi_cmd_filter *filter,
+                                        unsigned char *cmd, mode_t *f_mode);
+extern int blk_register_filter(struct gendisk *disk);
+extern void blk_unregister_filter(struct gendisk *disk);
+
 #define MAX_PHYS_SEGMENTS 128
 #define MAX_HW_SEGMENTS 128
 #define SAFE_MAX_SECTORS 255
@@ -865,28 +902,116 @@ void kblockd_flush_work(struct work_struct *work);
 #define MODULE_ALIAS_BLOCKDEV_MAJOR(major) \
        MODULE_ALIAS("block-major-" __stringify(major) "-*")
 
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
 
-#else /* CONFIG_BLOCK */
-/*
- * stubs for when the block layer is configured out
- */
-#define buffer_heads_over_limit 0
+#define INTEGRITY_FLAG_READ    2       /* verify data integrity on read */
+#define INTEGRITY_FLAG_WRITE   4       /* generate data integrity on write */
 
-static inline long nr_blockdev_pages(void)
+struct blk_integrity_exchg {
+       void                    *prot_buf;
+       void                    *data_buf;
+       sector_t                sector;
+       unsigned int            data_size;
+       unsigned short          sector_size;
+       const char              *disk_name;
+};
+
+typedef void (integrity_gen_fn) (struct blk_integrity_exchg *);
+typedef int (integrity_vrfy_fn) (struct blk_integrity_exchg *);
+typedef void (integrity_set_tag_fn) (void *, void *, unsigned int);
+typedef void (integrity_get_tag_fn) (void *, void *, unsigned int);
+
+struct blk_integrity {
+       integrity_gen_fn        *generate_fn;
+       integrity_vrfy_fn       *verify_fn;
+       integrity_set_tag_fn    *set_tag_fn;
+       integrity_get_tag_fn    *get_tag_fn;
+
+       unsigned short          flags;
+       unsigned short          tuple_size;
+       unsigned short          sector_size;
+       unsigned short          tag_size;
+
+       const char              *name;
+
+       struct kobject          kobj;
+};
+
+extern int blk_integrity_register(struct gendisk *, struct blk_integrity *);
+extern void blk_integrity_unregister(struct gendisk *);
+extern int blk_integrity_compare(struct block_device *, struct block_device *);
+extern int blk_rq_map_integrity_sg(struct request *, struct scatterlist *);
+extern int blk_rq_count_integrity_sg(struct request *);
+
+static inline unsigned short blk_integrity_tuple_size(struct blk_integrity *bi)
 {
+       if (bi)
+               return bi->tuple_size;
+
        return 0;
 }
 
-static inline void exit_io_context(void)
+static inline struct blk_integrity *bdev_get_integrity(struct block_device *bdev)
 {
+       return bdev->bd_disk->integrity;
 }
 
-struct io_context;
-static inline int put_io_context(struct io_context *ioc)
+static inline unsigned int bdev_get_tag_size(struct block_device *bdev)
 {
-       return 1;
+       struct blk_integrity *bi = bdev_get_integrity(bdev);
+
+       if (bi)
+               return bi->tag_size;
+
+       return 0;
+}
+
+static inline int bdev_integrity_enabled(struct block_device *bdev, int rw)
+{
+       struct blk_integrity *bi = bdev_get_integrity(bdev);
+
+       if (bi == NULL)
+               return 0;
+
+       if (rw == READ && bi->verify_fn != NULL &&
+           (bi->flags & INTEGRITY_FLAG_READ))
+               return 1;
+
+       if (rw == WRITE && bi->generate_fn != NULL &&
+           (bi->flags & INTEGRITY_FLAG_WRITE))
+               return 1;
+
+       return 0;
 }
 
+static inline int blk_integrity_rq(struct request *rq)
+{
+       return bio_integrity(rq->bio);
+}
+
+#else /* CONFIG_BLK_DEV_INTEGRITY */
+
+#define blk_integrity_rq(rq)                   (0)
+#define blk_rq_count_integrity_sg(a)           (0)
+#define blk_rq_map_integrity_sg(a, b)          (0)
+#define bdev_get_integrity(a)                  (0)
+#define bdev_get_tag_size(a)                   (0)
+#define blk_integrity_compare(a, b)            (0)
+#define blk_integrity_register(a, b)           (0)
+#define blk_integrity_unregister(a)            do { } while (0);
+
+#endif /* CONFIG_BLK_DEV_INTEGRITY */
+
+#else /* CONFIG_BLOCK */
+/*
+ * stubs for when the block layer is configured out
+ */
+#define buffer_heads_over_limit 0
+
+static inline long nr_blockdev_pages(void)
+{
+       return 0;
+}
 
 #endif /* CONFIG_BLOCK */
 
index e3ef903aae88224fef2f43fa96b0e0f199baa09b..d084b8d227a52fb978c02a4f07d98e08b653502b 100644 (file)
@@ -129,6 +129,7 @@ struct blk_trace {
        u32 dev;
        struct dentry *dir;
        struct dentry *dropped_file;
+       struct dentry *msg_file;
        atomic_t dropped;
 };
 
index fa830f8de0328d6cea2e73c7f66352e9ab6f8871..02673846d20539b25949c3e10356ae09e9be762b 100644 (file)
@@ -501,6 +501,8 @@ extern const kernel_cap_t __cap_empty_set;
 extern const kernel_cap_t __cap_full_set;
 extern const kernel_cap_t __cap_init_eff_set;
 
+kernel_cap_t cap_set_effective(const kernel_cap_t pE_new);
+
 int capable(int cap);
 int __capable(struct task_struct *t, int cap);
 
index 1605dd8aa6463a3edef46cc6bb1ff7216bdb825c..6f9f19d665910e86a4732e2c581fee53b016cc96 100644 (file)
@@ -4,7 +4,7 @@
  * Description: cfag12864b LCD driver header
  *     License: GPLv2
  *
- *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
+ *      Author: Copyright (C) Miguel Ojeda Sandonis
  *        Date: 2006-10-12
  *
  *  This program is free software; you can redistribute it and/or modify
index 5df3db58fcc65620fe5daf05752252c59048a21c..c24875bd9c5b0ef1b6347f61a87716c5e8673914 100644 (file)
@@ -353,6 +353,10 @@ static inline void __cpus_fold(cpumask_t *dstp, const cpumask_t *origp,
        for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)
 #endif /* NR_CPUS */
 
+#define next_cpu_nr(n, src)            next_cpu(n, src)
+#define cpus_weight_nr(cpumask)                cpus_weight(cpumask)
+#define for_each_cpu_mask_nr(cpu, mask)        for_each_cpu_mask(cpu, mask)
+
 /*
  * The following particular system cpumasks and operations manage
  * possible, present and online cpus.  Each of them is a fixed size
index 2a6639407c8037581ce7baa58e95c8c936a26245..d982eb89c77d324a7875c1486ac421d7ecdfdae7 100644 (file)
@@ -300,7 +300,7 @@ extern int d_validate(struct dentry *, struct dentry *);
 extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
 
 extern char *__d_path(const struct path *path, struct path *root, char *, int);
-extern char *d_path(struct path *, char *, int);
+extern char *d_path(const struct path *, char *, int);
 extern char *dentry_path(struct dentry *, char *, int);
 
 /* Allocation counts.. */
index f4a5871767f534ef6b8a2a950c70372ef7c27ca7..4aaa4afb1cb99f849bb345a8189153e65e94cbcd 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __LINUX_DEBUG_LOCKING_H
 #define __LINUX_DEBUG_LOCKING_H
 
+#include <linux/kernel.h>
+
 struct task_struct;
 
 extern int debug_locks;
@@ -11,14 +13,6 @@ extern int debug_locks_silent;
  */
 extern int debug_locks_off(void);
 
-/*
- * In the debug case we carry the caller's instruction pointer into
- * other functions, but we dont want the function argument overhead
- * in the nondebug case - hence these macros:
- */
-#define _RET_IP_               (unsigned long)__builtin_return_address(0)
-#define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
-
 #define DEBUG_LOCKS_WARN_ON(c)                                         \
 ({                                                                     \
        int __ret = 0;                                                  \
index 4d10c7328d2dabafcee9cf285bf263ba6988b3cd..6c7eff2ebada88cf3bb5e543a5bd36da0f7237cd 100644 (file)
@@ -13,7 +13,7 @@ struct firmware {
 
 struct device;
 
-#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
+#if defined(CONFIG_FW_LOADER) || (defined(CONFIG_FW_LOADER_MODULE) && defined(MODULE))
 int request_firmware(const struct firmware **fw, const char *name,
                     struct device *device);
 int request_firmware_nowait(
index d490779f18d946e52d443148cb8501649aad9030..d8e2762ed14df21bb05c50fde55158d6ec42bd5e 100644 (file)
@@ -83,6 +83,7 @@ extern int dir_notify_enable;
 #define READ_SYNC      (READ | (1 << BIO_RW_SYNC))
 #define READ_META      (READ | (1 << BIO_RW_META))
 #define WRITE_SYNC     (WRITE | (1 << BIO_RW_SYNC))
+#define SWRITE_SYNC    (SWRITE | (1 << BIO_RW_SYNC))
 #define WRITE_BARRIER  ((1 << BIO_RW) | (1 << BIO_RW_BARRIER))
 
 #define SEL_IN         1
@@ -894,8 +895,6 @@ static inline int file_check_writeable(struct file *filp)
 typedef struct files_struct *fl_owner_t;
 
 struct file_lock_operations {
-       void (*fl_insert)(struct file_lock *);  /* lock insertion callback */
-       void (*fl_remove)(struct file_lock *);  /* lock removal callback */
        void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
        void (*fl_release_private)(struct file_lock *);
 };
index ae7aec3cabee67ef4fb9c6440b8ec14dd76c5207..e8787417f65a1175cb4e1542f7271c0d3dbfd87b 100644 (file)
@@ -110,6 +110,14 @@ struct hd_struct {
 #define GENHD_FL_SUPPRESS_PARTITION_INFO       32
 #define GENHD_FL_FAIL                          64
 
+#define BLK_SCSI_MAX_CMDS      (256)
+#define BLK_SCSI_CMD_PER_LONG  (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))
+
+struct blk_scsi_cmd_filter {
+       unsigned long read_ok[BLK_SCSI_CMD_PER_LONG];
+       unsigned long write_ok[BLK_SCSI_CMD_PER_LONG];
+       struct kobject kobj;
+};
 
 struct gendisk {
        int major;                      /* major number of driver */
@@ -120,6 +128,7 @@ struct gendisk {
        struct hd_struct **part;        /* [indexed by minor] */
        struct block_device_operations *fops;
        struct request_queue *queue;
+       struct blk_scsi_cmd_filter cmd_filter;
        void *private_data;
        sector_t capacity;
 
@@ -141,6 +150,9 @@ struct gendisk {
        struct disk_stats dkstats;
 #endif
        struct work_struct async_notify;
+#ifdef  CONFIG_BLK_DEV_INTEGRITY
+       struct blk_integrity *integrity;
+#endif
 };
 
 /* 
index fb9af6a0fe9cb0bf275c706129c4589d4ee8fb30..8dc7301321926f6f4a6e9454dcd50d9aa9d1722f 100644 (file)
@@ -171,7 +171,7 @@ struct i2c_client {
        struct i2c_adapter *adapter;    /* the adapter we sit on        */
        struct i2c_driver *driver;      /* and our access routines      */
        struct device dev;              /* the device structure         */
-       int irq;                        /* irq issued by device (or -1) */
+       int irq;                        /* irq issued by device         */
        struct list_head list;          /* DEPRECATED */
        struct completion released;
 };
index 9918772bf274c82e2dcf1b9d9ec1c82c1d5660d5..eddb6daadf4abceaffec3f9a0b36603e2e97f4cb 100644 (file)
@@ -189,6 +189,21 @@ static inline void ide_std_init_ports(hw_regs_t *hw,
        hw->io_ports.ctl_addr = ctl_addr;
 }
 
+/* for IDE PCI controllers in legacy mode, temporary */
+static inline int __ide_default_irq(unsigned long base)
+{
+       switch (base) {
+#ifdef CONFIG_IA64
+       case 0x1f0: return isa_irq_to_vector(14);
+       case 0x170: return isa_irq_to_vector(15);
+#else
+       case 0x1f0: return 14;
+       case 0x170: return 15;
+#endif
+       }
+       return 0;
+}
+
 #include <asm/ide.h>
 
 #if !defined(MAX_HWIFS) || defined(CONFIG_EMBEDDED)
index 80335b7d77c5bea2d9f64320c46fb19dfcb60cc2..c4335faebb63eba7eb9771dc8f937b1fa82103ac 100644 (file)
@@ -84,7 +84,11 @@ struct net_lro_mgr {
                                    from received packets and eth protocol
                                    is still ETH_P_8021Q */
 
-       u32 ip_summed;      /* Set in non generated SKBs in page mode */
+       /*
+        * Set for generated SKBs that are not added to
+        * the frag list in fragmented mode
+        */
+       u32 ip_summed;
        u32 ip_summed_aggr; /* Set in aggregated SKBs: CHECKSUM_UNNECESSARY
                             * or CHECKSUM_NONE */
 
index e075c4b762fb367e0a3ad07227c440cb7500629e..d150c57e5f0af8653fc2ab96d3b1e3c3a17ec5b5 100644 (file)
@@ -534,8 +534,8 @@ struct input_absinfo {
 
 #define KEY_FRAMEBACK          0x1b4   /* Consumer - transport controls */
 #define KEY_FRAMEFORWARD       0x1b5
-
 #define KEY_CONTEXT_MENU       0x1b6   /* GenDesc - system context menu */
+#define KEY_MEDIA_REPEAT       0x1b7   /* Consumer - transport control */
 
 #define KEY_DEL_EOL            0x1c0
 #define KEY_DEL_EOS            0x1c1
index 2b7a1187cb29a804988d686be4c8a8d088d6356f..08b987bccf89aff533268c0718770583ba204026 100644 (file)
@@ -99,4 +99,22 @@ static inline struct io_context *ioc_task_link(struct io_context *ioc)
        return NULL;
 }
 
+#ifdef CONFIG_BLOCK
+int put_io_context(struct io_context *ioc);
+void exit_io_context(void);
+struct io_context *get_io_context(gfp_t gfp_flags, int node);
+struct io_context *alloc_io_context(gfp_t gfp_flags, int node);
+void copy_io_context(struct io_context **pdst, struct io_context **psrc);
+#else
+static inline void exit_io_context(void)
+{
+}
+
+struct io_context;
+static inline int put_io_context(struct io_context *ioc)
+{
+       return 1;
+}
+#endif
+
 #endif
index 792bf0aa779b50d3e6aee9edaff9efe69569848f..2e70006c7fa8876d84e4d7f7c3a3803a721914e4 100644 (file)
@@ -46,6 +46,9 @@ extern const char linux_proc_banner[];
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
 
+#define _RET_IP_               (unsigned long)__builtin_return_address(0)
+#define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
+
 #ifdef CONFIG_LBD
 # include <asm/div64.h>
 # define sector_div(a, b) do_div(a, b)
index a2c54acceb4e9da1b21ab6e5dea9dc8c7e5fd362..cb311798e0bc642dc01eba7ebf9e73e997723b74 100644 (file)
@@ -4,7 +4,7 @@
  * Description: ks0108 LCD Controller driver header
  *     License: GPLv2
  *
- *      Author: Copyright (C) Miguel Ojeda Sandonis <maxextreme@gmail.com>
+ *      Author: Copyright (C) Miguel Ojeda Sandonis
  *        Date: 2006-10-31
  *
  *  This program is free software; you can redistribute it and/or modify
index 69b2342d5ebb81954ad9bcf3df568aa7d6585ada..c4db5827963d98a5624ec1c8fb637ad959903a75 100644 (file)
@@ -159,6 +159,15 @@ struct ap_device_id {
 
 #define AP_DEVICE_ID_MATCH_DEVICE_TYPE         0x01
 
+/* s390 css bus devices (subchannels) */
+struct css_device_id {
+       __u8 match_flags;
+       __u8 type; /* subchannel type */
+       __u16 pad2;
+       __u32 pad3;
+       kernel_ulong_t driver_data;
+};
+
 #define ACPI_ID_LEN    16 /* only 9 bytes needed here, 16 bytes are used */
                           /* to workaround crosscompile issues */
 
index f27fd2009334922325866c69d2abe42bb45bfd67..25f87102ab663e149e10043c9c399a8d8ca3bd96 100644 (file)
@@ -88,6 +88,8 @@ struct wireless_dev;
 #define NETDEV_TX_BUSY 1       /* driver tx path was busy*/
 #define NETDEV_TX_LOCKED -1    /* driver tx lock was already taken */
 
+#ifdef  __KERNEL__
+
 /*
  *     Compute the worst case header length according to the protocols
  *     used.
@@ -114,6 +116,8 @@ struct wireless_dev;
 #define MAX_HEADER (LL_MAX_HEADER + 48)
 #endif
 
+#endif  /*  __KERNEL__  */
+
 struct net_device_subqueue
 {
        /* Give a control state for each queue.  This struct may contain
index eafc9d6d2b35183dab63c8293ad8eba9b2c2111b..65953822c9cb752fb94d3fd0daa26f2c162544ae 100644 (file)
 #define PCI_DEVICE_ID_MARVELL_GT64260  0x6430
 #define PCI_DEVICE_ID_MARVELL_MV64360  0x6460
 #define PCI_DEVICE_ID_MARVELL_MV64460  0x6480
+#define PCI_DEVICE_ID_MARVELL_CAFE_SD  0x4101
 
 #define PCI_VENDOR_ID_V3               0x11b0
 #define PCI_DEVICE_ID_V3_V960          0x0001
index f98501ba557eea676a827aed770d57b0b4b12c56..c6f5f9dd0cee41636f282237e0ccfacf07586f96 100644 (file)
@@ -95,8 +95,12 @@ extern void __ptrace_link(struct task_struct *child,
                          struct task_struct *new_parent);
 extern void __ptrace_unlink(struct task_struct *child);
 extern void ptrace_untrace(struct task_struct *child);
-extern int ptrace_may_attach(struct task_struct *task);
-extern int __ptrace_may_attach(struct task_struct *task);
+#define PTRACE_MODE_READ   1
+#define PTRACE_MODE_ATTACH 2
+/* Returns 0 on success, -errno on denial. */
+extern int __ptrace_may_access(struct task_struct *task, unsigned int mode);
+/* Returns true on success, false on denial. */
+extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
 
 static inline int ptrace_reparented(struct task_struct *child)
 {
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
new file mode 100644 (file)
index 0000000..bde4586
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _LINUX_RCULIST_H
+#define _LINUX_RCULIST_H
+
+#include <linux/list.h>
+
+#endif /* _LINUX_RCULIST_H */
index c1f19dbceb0566f8a4e1342e4f4c1291d0f29349..92f09bdf11752dcbbe579f1e9f239dfb70036266 100644 (file)
@@ -7,14 +7,15 @@
    inheritance of root-permissions and suid-root executable under
    compatibility mode. We raise the effective and inheritable bitmasks
    *of the executable file* if the effective uid of the new process is
-   0. If the real uid is 0, we raise the inheritable bitmask of the
+   0. If the real uid is 0, we raise the effective (legacy) bit of the
    executable file. */
 #define SECURE_NOROOT                  0
 #define SECURE_NOROOT_LOCKED           1  /* make bit-0 immutable */
 
-/* When set, setuid to/from uid 0 does not trigger capability-"fixes"
-   to be compatible with old programs relying on set*uid to loose
-   privileges. When unset, setuid doesn't change privileges. */
+/* When set, setuid to/from uid 0 does not trigger capability-"fixup".
+   When unset, to provide compatiblility with old programs relying on
+   set*uid to gain/lose privilege, transitions to/from uid 0 cause
+   capabilities to be gained/lost. */
 #define SECURE_NO_SETUID_FIXUP         2
 #define SECURE_NO_SETUID_FIXUP_LOCKED  3  /* make bit-2 immutable */
 
 #define SECURE_KEEP_CAPS               4
 #define SECURE_KEEP_CAPS_LOCKED                5  /* make bit-4 immutable */
 
-/* Each securesetting is implemented using two bits. One bit specify
+/* Each securesetting is implemented using two bits. One bit specifies
    whether the setting is on or off. The other bit specify whether the
-   setting is fixed or not. A setting which is fixed cannot be changed
-   from user-level. */
+   setting is locked or not. A setting which is locked cannot be
+   changed from user-level. */
 #define issecure_mask(X)       (1 << (X))
 #define issecure(X)            (issecure_mask(X) & current->securebits)
 
index 50737c70e78ea41e2a2e4551b6044df86f8a1de3..31c8851ec5d0fba51ceab47da8d76f424f7e0345 100644 (file)
@@ -46,7 +46,8 @@ struct audit_krule;
  */
 extern int cap_capable(struct task_struct *tsk, int cap);
 extern int cap_settime(struct timespec *ts, struct timezone *tz);
-extern int cap_ptrace(struct task_struct *parent, struct task_struct *child);
+extern int cap_ptrace(struct task_struct *parent, struct task_struct *child,
+                     unsigned int mode);
 extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
 extern int cap_capset_check(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
 extern void cap_capset_set(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
@@ -79,6 +80,7 @@ struct xfrm_selector;
 struct xfrm_policy;
 struct xfrm_state;
 struct xfrm_user_sec_ctx;
+struct seq_file;
 
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
@@ -289,10 +291,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     Update module state after a successful pivot.
  *     @old_path contains the path for the old root.
  *     @new_path contains the path for the new root.
- * @sb_get_mnt_opts:
- *     Get the security relevant mount options used for a superblock
- *     @sb the superblock to get security mount options from
- *     @opts binary data structure containing all lsm mount data
  * @sb_set_mnt_opts:
  *     Set the security relevant mount options used for a superblock
  *     @sb the superblock to set security mount options for
@@ -1170,6 +1168,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     attributes would be changed by the execve.
  *     @parent contains the task_struct structure for parent process.
  *     @child contains the task_struct structure for child process.
+ *     @mode contains the PTRACE_MODE flags indicating the form of access.
  *     Return 0 if permission is granted.
  * @capget:
  *     Get the @effective, @inheritable, and @permitted capability sets for
@@ -1240,11 +1239,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     @pages contains the number of pages.
  *     Return 0 if permission is granted.
  *
- * @register_security:
- *     allow module stacking.
- *     @name contains the name of the security module being stacked.
- *     @ops contains a pointer to the struct security_operations of the module to stack.
- *
  * @secid_to_secctx:
  *     Convert secid to security context.
  *     @secid contains the security ID.
@@ -1295,7 +1289,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
 struct security_operations {
        char name[SECURITY_NAME_MAX + 1];
 
-       int (*ptrace) (struct task_struct *parent, struct task_struct *child);
+       int (*ptrace) (struct task_struct *parent, struct task_struct *child,
+                      unsigned int mode);
        int (*capget) (struct task_struct *target,
                       kernel_cap_t *effective,
                       kernel_cap_t *inheritable, kernel_cap_t *permitted);
@@ -1328,6 +1323,7 @@ struct security_operations {
        void (*sb_free_security) (struct super_block *sb);
        int (*sb_copy_data) (char *orig, char *copy);
        int (*sb_kern_mount) (struct super_block *sb, void *data);
+       int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
        int (*sb_statfs) (struct dentry *dentry);
        int (*sb_mount) (char *dev_name, struct path *path,
                         char *type, unsigned long flags, void *data);
@@ -1343,8 +1339,6 @@ struct security_operations {
                             struct path *new_path);
        void (*sb_post_pivotroot) (struct path *old_path,
                                   struct path *new_path);
-       int (*sb_get_mnt_opts) (const struct super_block *sb,
-                               struct security_mnt_opts *opts);
        int (*sb_set_mnt_opts) (struct super_block *sb,
                                struct security_mnt_opts *opts);
        void (*sb_clone_mnt_opts) (const struct super_block *oldsb,
@@ -1472,10 +1466,6 @@ struct security_operations {
        int (*netlink_send) (struct sock *sk, struct sk_buff *skb);
        int (*netlink_recv) (struct sk_buff *skb, int cap);
 
-       /* allow module stacking */
-       int (*register_security) (const char *name,
-                                 struct security_operations *ops);
-
        void (*d_instantiate) (struct dentry *dentry, struct inode *inode);
 
        int (*getprocattr) (struct task_struct *p, char *name, char **value);
@@ -1565,7 +1555,6 @@ struct security_operations {
 extern int security_init(void);
 extern int security_module_enable(struct security_operations *ops);
 extern int register_security(struct security_operations *ops);
-extern int mod_reg_security(const char *name, struct security_operations *ops);
 extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
                                             struct dentry *parent, void *data,
                                             const struct file_operations *fops);
@@ -1573,7 +1562,8 @@ extern struct dentry *securityfs_create_dir(const char *name, struct dentry *par
 extern void securityfs_remove(struct dentry *dentry);
 
 /* Security operations */
-int security_ptrace(struct task_struct *parent, struct task_struct *child);
+int security_ptrace(struct task_struct *parent, struct task_struct *child,
+                   unsigned int mode);
 int security_capget(struct task_struct *target,
                    kernel_cap_t *effective,
                    kernel_cap_t *inheritable,
@@ -1606,6 +1596,7 @@ int security_sb_alloc(struct super_block *sb);
 void security_sb_free(struct super_block *sb);
 int security_sb_copy_data(char *orig, char *copy);
 int security_sb_kern_mount(struct super_block *sb, void *data);
+int security_sb_show_options(struct seq_file *m, struct super_block *sb);
 int security_sb_statfs(struct dentry *dentry);
 int security_sb_mount(char *dev_name, struct path *path,
                      char *type, unsigned long flags, void *data);
@@ -1617,8 +1608,6 @@ void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *d
 void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint);
 int security_sb_pivotroot(struct path *old_path, struct path *new_path);
 void security_sb_post_pivotroot(struct path *old_path, struct path *new_path);
-int security_sb_get_mnt_opts(const struct super_block *sb,
-                               struct security_mnt_opts *opts);
 int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts);
 void security_sb_clone_mnt_opts(const struct super_block *oldsb,
                                struct super_block *newsb);
@@ -1755,9 +1744,11 @@ static inline int security_init(void)
        return 0;
 }
 
-static inline int security_ptrace(struct task_struct *parent, struct task_struct *child)
+static inline int security_ptrace(struct task_struct *parent,
+                                 struct task_struct *child,
+                                 unsigned int mode)
 {
-       return cap_ptrace(parent, child);
+       return cap_ptrace(parent, child, mode);
 }
 
 static inline int security_capget(struct task_struct *target,
@@ -1881,6 +1872,12 @@ static inline int security_sb_kern_mount(struct super_block *sb, void *data)
        return 0;
 }
 
+static inline int security_sb_show_options(struct seq_file *m,
+                                          struct super_block *sb)
+{
+       return 0;
+}
+
 static inline int security_sb_statfs(struct dentry *dentry)
 {
        return 0;
@@ -1927,12 +1924,6 @@ static inline int security_sb_pivotroot(struct path *old_path,
 static inline void security_sb_post_pivotroot(struct path *old_path,
                                              struct path *new_path)
 { }
-static inline int security_sb_get_mnt_opts(const struct super_block *sb,
-                                          struct security_mnt_opts *opts)
-{
-       security_init_mnt_opts(opts);
-       return 0;
-}
 
 static inline int security_sb_set_mnt_opts(struct super_block *sb,
                                           struct security_mnt_opts *opts)
index c2ad35016599ba11b6ce9b947963bc4975c23a21..9aa90a6f20e02e920e883f17e7393aa0e0046400 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Written by Mark Hemment, 1996 (markhe@nextd.demon.co.uk).
  *
- * (C) SGI 2006, Christoph Lameter <clameter@sgi.com>
+ * (C) SGI 2006, Christoph Lameter
  *     Cleaned up and restructured to ease the addition of alternative
  *     implementations of SLAB allocators.
  */
index 71e43a12ebbbc62521498155d6bace9b2b0e0585..d117ea2825a9187b44e37a12602b5538ec175839 100644 (file)
@@ -4,7 +4,7 @@
 /*
  * SLUB : A Slab allocator without object queues.
  *
- * (C) 2007 SGI, Christoph Lameter <clameter@sgi.com>
+ * (C) 2007 SGI, Christoph Lameter
  */
 #include <linux/types.h>
 #include <linux/gfp.h>
@@ -137,10 +137,12 @@ static __always_inline int kmalloc_index(size_t size)
        if (size <= KMALLOC_MIN_SIZE)
                return KMALLOC_SHIFT_LOW;
 
+#if KMALLOC_MIN_SIZE <= 64
        if (size > 64 && size <= 96)
                return 1;
        if (size > 128 && size <= 192)
                return 2;
+#endif
        if (size <=          8) return 3;
        if (size <=         16) return 4;
        if (size <=         32) return 5;
index 06d3e6eb9ca84ddb19b85e862ab51bafbaf0ce4b..917707e6151d7d2c5e4e5c3e6bd2b4310f86d971 100644 (file)
@@ -66,8 +66,7 @@ struct thermal_cooling_device {
                                ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
 #define CELSIUS_TO_KELVIN(t)   ((t)*10+2732)
 
-#if defined(CONFIG_HWMON) ||   \
-       (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE))
+#if defined(CONFIG_THERMAL_HWMON)
 /* thermal zone devices with the same type share one hwmon device */
 struct thermal_hwmon_device {
        char type[THERMAL_NAME_LENGTH];
@@ -94,8 +93,7 @@ struct thermal_zone_device {
        struct idr idr;
        struct mutex lock;      /* protect cooling devices list */
        struct list_head node;
-#if defined(CONFIG_HWMON) ||   \
-       (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE))
+#if defined(CONFIG_THERMAL_HWMON)
        struct list_head hwmon_node;
        struct thermal_hwmon_device *hwmon;
        struct thermal_hwmon_attr temp_input;   /* hwmon sys attr */
index 2ca6bae88721920215a649bc437393733452aae9..fb0c215a3051a0e697d305c98067f39c25a2c790 100644 (file)
@@ -339,6 +339,7 @@ struct xfrm_usersa_info {
 #define XFRM_STATE_NOPMTUDISC  4
 #define XFRM_STATE_WILDRECV    8
 #define XFRM_STATE_ICMP                16
+#define XFRM_STATE_AF_UNSPEC   32
 };
 
 struct xfrm_usersa_id {
index cd599ad29fb2114b2b7e26ab46e613c8ea5ccff5..db431d513f2f01ce27cb9d150ed85f62f61d7195 100644 (file)
@@ -32,12 +32,16 @@ enum cx25840_video_input {
        CX25840_COMPOSITE7,
        CX25840_COMPOSITE8,
 
-       /* S-Video inputs consist of one luma input (In1-In4) ORed with one
+       /* S-Video inputs consist of one luma input (In1-In8) ORed with one
           chroma input (In5-In8) */
        CX25840_SVIDEO_LUMA1 = 0x10,
        CX25840_SVIDEO_LUMA2 = 0x20,
        CX25840_SVIDEO_LUMA3 = 0x30,
        CX25840_SVIDEO_LUMA4 = 0x40,
+       CX25840_SVIDEO_LUMA5 = 0x50,
+       CX25840_SVIDEO_LUMA6 = 0x60,
+       CX25840_SVIDEO_LUMA7 = 0x70,
+       CX25840_SVIDEO_LUMA8 = 0x80,
        CX25840_SVIDEO_CHROMA4 = 0x400,
        CX25840_SVIDEO_CHROMA5 = 0x500,
        CX25840_SVIDEO_CHROMA6 = 0x600,
index bfee8be5d63fb6b69765535a8384e928017b8b40..b8e8aa91905a4450bf3ff9c431e2ba7168092f1a 100644 (file)
@@ -146,6 +146,7 @@ extern IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE];
 
 #endif
 
index 33f01ae08f767da78c532c257332391bfb48b88c..859f7a6f6f67ab0c5073deb703c928de9f614d2f 100644 (file)
@@ -40,9 +40,9 @@
 #define VFL_TYPE_VTX           3
 
 /*  Video standard functions  */
-extern char *v4l2_norm_to_name(v4l2_std_id id);
+extern const char *v4l2_norm_to_name(v4l2_std_id id);
 extern int v4l2_video_std_construct(struct v4l2_standard *vs,
-                                   int id, char *name);
+                                   int id, const char *name);
 /* Prints the ioctl in a human-readable format */
 extern void v4l_printk_ioctl(unsigned int cmd);
 
index dae3f9ec11549b240ae07be19dc4f58a2389ce62..bcd1623245cbfc09e879776beceeafeeee229fdc 100644 (file)
@@ -595,6 +595,15 @@ enum ieee80211_key_alg {
        ALG_CCMP,
 };
 
+/**
+ * enum ieee80211_key_len - key length
+ * @WEP40: WEP 5 byte long key
+ * @WEP104: WEP 13 byte long key
+ */
+enum ieee80211_key_len {
+       LEN_WEP40 = 5,
+       LEN_WEP104 = 13,
+};
 
 /**
  * enum ieee80211_key_flags - key flags
index ab502ec1c61c3752b022b24ce49f833235b8621c..a87fc0312edc1a724560771980b06ac1a497daf3 100644 (file)
@@ -178,7 +178,7 @@ extern struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops);
 extern struct Qdisc *qdisc_create_dflt(struct net_device *dev,
                                       struct Qdisc_ops *ops, u32 parentid);
 extern void tcf_destroy(struct tcf_proto *tp);
-extern void tcf_destroy_chain(struct tcf_proto *fl);
+extern void tcf_destroy_chain(struct tcf_proto **fl);
 
 static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch,
                                       struct sk_buff_head *list)
diff --git a/include/pcmcia/bulkmem.h b/include/pcmcia/bulkmem.h
deleted file mode 100644 (file)
index 6bc7472..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * bulkmem.h -- Definitions for bulk memory services
- *
- * 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.
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
- *
- * (C) 1999            David A. Hinds
- */
-
-#ifndef _LINUX_BULKMEM_H
-#define _LINUX_BULKMEM_H
-
-/* For GetFirstRegion and GetNextRegion */
-typedef struct region_info_t {
-    u_int              Attributes;
-    u_int              CardOffset;
-    u_int              RegionSize;
-    u_int              AccessSpeed;
-    u_int              BlockSize;
-    u_int              PartMultiple;
-    u_char             JedecMfr, JedecInfo;
-    memory_handle_t    next;
-} region_info_t;
-
-#define REGION_TYPE            0x0001
-#define REGION_TYPE_CM         0x0000
-#define REGION_TYPE_AM         0x0001
-#define REGION_PREFETCH                0x0008
-#define REGION_CACHEABLE       0x0010
-#define REGION_BAR_MASK                0xe000
-#define REGION_BAR_SHIFT       13
-
-int pcmcia_get_first_region(struct pcmcia_device *handle, region_info_t *rgn);
-int pcmcia_get_next_region(struct pcmcia_device *handle, region_info_t *rgn);
-
-#endif /* _LINUX_BULKMEM_H */
index d3bbb19caf8183def6fa7e6e22dce4753ae7a40a..e2e10c1e9a0615fc9844419ed9995f40f2d9f732 100644 (file)
@@ -595,7 +595,7 @@ int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple
 int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple);
 int pccard_parse_tuple(tuple_t *tuple, cisparse_t *parse);
 
-int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, cisinfo_t *info);
+int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned int *count);
 
 /* ... but use these wrappers instead */
 #define pcmcia_get_first_tuple(p_dev, tuple) \
index 87a260e3699efd3dd138216e84038ed916064060..45d84b275789e3e138536bcac9ffff52e81a0df9 100644 (file)
@@ -373,9 +373,6 @@ struct pcmcia_socket;
 
 int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, conf_reg_t *reg);
 int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, config_info_t *config);
-int pcmcia_get_first_window(window_handle_t *win, win_req_t *req);
-int pcmcia_get_next_window(window_handle_t *win, win_req_t *req);
-int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status);
 int pcmcia_get_mem_page(window_handle_t win, memreq_t *req);
 int pcmcia_map_mem_page(window_handle_t win, memreq_t *req);
 int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
index 9a6bcc4952f0653fbc8dafad010b3c87b9be11bf..f402a0f435b451ce6843a4e9fa7faaf4620ede61 100644 (file)
@@ -21,7 +21,8 @@
 #include <sys/types.h>
 #endif
 
-#if defined(__arm__) || defined(__mips__) || defined(__avr32__)
+#if defined(__arm__) || defined(__mips__) || defined(__avr32__) || \
+       defined(__bfin__)
 /* This (ioaddr_t) is exposed to userspace & hence cannot be changed. */
 typedef u_int   ioaddr_t;
 #else
@@ -33,9 +34,6 @@ typedef u_int event_t;
 typedef u_char cisdata_t;
 typedef u_short        page_t;
 
-struct pcmcia_device;
-typedef struct pcmcia_device *client_handle_t;
-
 struct window_t;
 typedef struct window_t *window_handle_t;
 
index f047a1fd64f803a887ce40430a7e14a86d0e4627..b316027c853d7845dc374591b5a3f4c155f8f03d 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/mod_devicetable.h>
 #endif
 
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/device_id.h>
 
@@ -51,6 +50,24 @@ typedef struct mtd_info_t {
     u_int              CardOffset;
 } mtd_info_t;
 
+typedef struct region_info_t {
+    u_int              Attributes;
+    u_int              CardOffset;
+    u_int              RegionSize;
+    u_int              AccessSpeed;
+    u_int              BlockSize;
+    u_int              PartMultiple;
+    u_char             JedecMfr, JedecInfo;
+    memory_handle_t    next;
+} region_info_t;
+#define REGION_TYPE            0x0001
+#define REGION_TYPE_CM         0x0000
+#define REGION_TYPE_AM         0x0001
+#define REGION_PREFETCH                0x0008
+#define REGION_CACHEABLE       0x0010
+#define REGION_BAR_MASK                0xe000
+#define REGION_BAR_SHIFT       13
+
 typedef union ds_ioctl_arg_t {
     adjust_t           adjust;
     config_info_t      config;
index f95dca077c1c2fdc8cc5c59562185fadc2c65ddd..ed919dd9bb5c29debac61ce496baa06ae6408c4f 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
 #ifdef CONFIG_CARDBUS
 #include <linux/pci.h>
 #endif
@@ -136,8 +135,14 @@ struct pccard_resource_ops {
        struct resource* (*find_mem)    (unsigned long base, unsigned long num,
                                         unsigned long align, int low,
                                         struct pcmcia_socket *s);
-       int     (*adjust_resource)      (struct pcmcia_socket *s,
-                                        adjust_t *adj);
+       int     (*add_io)               (struct pcmcia_socket *s,
+                                        unsigned int action,
+                                        unsigned long r_start,
+                                        unsigned long r_end);
+       int     (*add_mem)              (struct pcmcia_socket *s,
+                                        unsigned int action,
+                                        unsigned long r_start,
+                                        unsigned long r_end);
        int     (*init)                 (struct pcmcia_socket *s);
        void    (*exit)                 (struct pcmcia_socket *s);
 };
@@ -245,7 +250,6 @@ struct pcmcia_socket {
 
        struct task_struct              *thread;
        struct completion               thread_done;
-       wait_queue_head_t               thread_wait;
        spinlock_t                      thread_lock;    /* protects thread_events */
        unsigned int                    thread_events;
 
diff --git a/include/pcmcia/version.h b/include/pcmcia/version.h
deleted file mode 100644 (file)
index 5ad9c5e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-/* version.h 1.94 2000/10/03 17:55:48 (David Hinds) */
-
-/* This file will be removed, please don't include it */
diff --git a/include/sound/ad1843.h b/include/sound/ad1843.h
new file mode 100644 (file)
index 0000000..b236a9d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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 2003 Vivien Chappelier <vivien.chappelier@linux-mips.org>
+ * Copyright 2008 Thomas Bogendoerfer <tsbogend@franken.de>
+ */
+
+#ifndef __SOUND_AD1843_H
+#define __SOUND_AD1843_H
+
+struct snd_ad1843 {
+       void *chip;
+       int (*read)(void *chip, int reg);
+       int (*write)(void *chip, int reg, int val);
+};
+
+#define AD1843_GAIN_RECLEV 0
+#define AD1843_GAIN_LINE   1
+#define AD1843_GAIN_LINE_2 2
+#define AD1843_GAIN_MIC    3
+#define AD1843_GAIN_PCM_0  4
+#define AD1843_GAIN_PCM_1  5
+#define AD1843_GAIN_SIZE   (AD1843_GAIN_PCM_1+1)
+
+int ad1843_get_gain_max(struct snd_ad1843 *ad1843, int id);
+int ad1843_get_gain(struct snd_ad1843 *ad1843, int id);
+int ad1843_set_gain(struct snd_ad1843 *ad1843, int id, int newval);
+int ad1843_get_recsrc(struct snd_ad1843 *ad1843);
+int ad1843_set_recsrc(struct snd_ad1843 *ad1843, int newsrc);
+void ad1843_setup_dac(struct snd_ad1843 *ad1843,
+                     unsigned int id,
+                     unsigned int framerate,
+                     snd_pcm_format_t fmt,
+                     unsigned int channels);
+void ad1843_shutdown_dac(struct snd_ad1843 *ad1843,
+                        unsigned int id);
+void ad1843_setup_adc(struct snd_ad1843 *ad1843,
+                     unsigned int framerate,
+                     snd_pcm_format_t fmt,
+                     unsigned int channels);
+void ad1843_shutdown_adc(struct snd_ad1843 *ad1843);
+int ad1843_init(struct snd_ad1843 *ad1843);
+
+#endif /* __SOUND_AD1843_H */
index 3dc1291f52db78e8f525801f1b79204180e91dbf..4721b4bba0538360cd808db6c6cc0f13db9a3c7a 100644 (file)
@@ -129,9 +129,6 @@ int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
 #define snd_ctl_unregister_ioctl_compat(fcn)
 #endif
 
-int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control);
-int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, struct snd_ctl_elem_value *control);
-
 static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
 {
        return id->numid - kctl->id.numid;
index 695ee53488a382ab85d90f1deb5e3b83a5fe82e6..558b96284bd22eba399ff2e8f28147a5c46b2eb0 100644 (file)
@@ -412,13 +412,13 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
 
 #endif /* CONFIG_SND_DEBUG */
 
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
 /**
  * snd_printdd - debug printk
  * @format: format string
  *
  * Works like snd_printk() for debugging purposes.
- * Ignored when CONFIG_SND_DEBUG_DETECT is not set.
+ * Ignored when CONFIG_SND_DEBUG_VERBOSE is not set.
  */
 #define snd_printdd(format, args...) snd_printk(format, ##args)
 #else
@@ -442,7 +442,7 @@ struct snd_pci_quirk {
        unsigned short subvendor;       /* PCI subvendor ID */
        unsigned short subdevice;       /* PCI subdevice ID */
        int value;                      /* value */
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
        const char *name;               /* name of the device (optional) */
 #endif
 };
@@ -450,7 +450,7 @@ struct snd_pci_quirk {
 #define _SND_PCI_QUIRK_ID(vend,dev) \
        .subvendor = (vend), .subdevice = (dev)
 #define SND_PCI_QUIRK_ID(vend,dev) {_SND_PCI_QUIRK_ID(vend, dev)}
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
 #define SND_PCI_QUIRK(vend,dev,xname,val) \
        {_SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname)}
 #else
index e8d1f3e31f9e5c1eebc42ab6be4cdb9a1d8b3ebf..92647532c454aff379a627492211fcfac96d7abc 100644 (file)
 #define CS4236_RIGHT_WAVE      0x1c    /* right wavetable serial port volume */
 #define CS4236_VERSION         0x9c    /* chip version and ID */
 
+/* definitions for extended registers - OPTI93X */
+#define OPTi931_AUX_LEFT_INPUT 0x10
+#define OPTi931_AUX_RIGHT_INPUT        0x11
+#define OPTi93X_MIC_LEFT_INPUT 0x14
+#define OPTi93X_MIC_RIGHT_INPUT        0x15
+#define OPTi93X_OUT_LEFT       0x16
+#define OPTi93X_OUT_RIGHT      0x17
+
 #endif /* __SOUND_CS4231_REGS_H */
index 66055d702aa3cadf6c77544a31df05ff248960f9..f0785f9f4ae4939fc6289f53d1572e9f7802f4b1 100644 (file)
@@ -58,6 +58,7 @@
 /* compatible, but clones */
 #define CS4231_HW_INTERWAVE     0x1000 /* InterWave chip */
 #define CS4231_HW_OPL3SA2       0x1101 /* OPL3-SA2 chip, similar to cs4231 */
+#define CS4231_HW_OPTI93X      0x1102  /* Opti 930/931/933 */
 
 /* defines for codec.hwshare */
 #define CS4231_HWSHARE_IRQ     (1<<0)
@@ -120,6 +121,8 @@ unsigned char snd_cs4236_ext_in(struct snd_cs4231 *chip, unsigned char reg);
 void snd_cs4231_mce_up(struct snd_cs4231 *chip);
 void snd_cs4231_mce_down(struct snd_cs4231 *chip);
 
+void snd_cs4231_overrange(struct snd_cs4231 *chip);
+
 irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id);
 
 const char *snd_cs4231_chip_id(struct snd_cs4231 *chip);
index 7b7b9b13b4ddd8d04c1cf6392d15c95d58972de0..10ee28eac018535da6f1e706b9c6189f90d46230 100644 (file)
@@ -1670,6 +1670,7 @@ struct snd_emu_chip_details {
        unsigned char spi_dac;      /* SPI interface for DAC */
        unsigned char i2c_adc;      /* I2C interface for ADC */
        unsigned char adc_1361t;    /* Use Philips 1361T ADC */
+       unsigned char invert_shared_spdif; /* analog/digital switch inverted */
        const char *driver;
        const char *name;
        const char *id;         /* for backward compatibility - can be NULL if not needed */
index f023c1b97f8caa93cee30e8ed91f27a270c3b7a1..3d9afb6a8c9cd86b5ead0d9ccccaa49614f47fd8 100644 (file)
@@ -105,7 +105,7 @@ int snd_seq_event_port_attach(int client, struct snd_seq_port_callback *pcbp,
                              int cap, int type, int midi_channels, int midi_voices, char *portname);
 int snd_seq_event_port_detach(int client, int port);
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 void snd_seq_autoload_lock(void);
 void snd_seq_autoload_unlock(void);
 #else
index a105b01e06d50dc3ccb8b8bcb527d64ea9b7cbe8..3030fdc6981d05b804ccb5e31d5d7d3fafd7565e 100644 (file)
 {      .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
        .shift = wshift, .invert = winvert}
 
+/* generic register modifier widget */
+#define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \
+{      .id = wid, .name = wname, .kcontrols = NULL, .num_kcontrols = 0, \
+       .reg = -((wreg) + 1), .shift = wshift, .mask = wmask, \
+       .on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \
+       .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
+
 /* dapm kcontrol types */
 #define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -193,6 +200,7 @@ struct snd_soc_dapm_widget;
 enum snd_soc_dapm_type;
 struct snd_soc_dapm_path;
 struct snd_soc_dapm_pin;
+struct snd_soc_dapm_route;
 
 /* dapm controls */
 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
@@ -205,25 +213,32 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
 int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
        const struct snd_soc_dapm_widget *widget);
+int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
+       const struct snd_soc_dapm_widget *widget,
+       int num);
 
 /* dapm path setup */
-int snd_soc_dapm_connect_input(struct snd_soc_codec *codec,
+int  __deprecated snd_soc_dapm_connect_input(struct snd_soc_codec *codec,
        const char *sink_name, const char *control_name, const char *src_name);
 int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
 void snd_soc_dapm_free(struct snd_soc_device *socdev);
+int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
+                           const struct snd_soc_dapm_route *route, int num);
 
 /* dapm events */
 int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream,
        int event);
-int snd_soc_dapm_device_event(struct snd_soc_device *socdev, int event);
+int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
+       enum snd_soc_bias_level level);
 
 /* dapm sys fs - used by the core */
 int snd_soc_dapm_sys_add(struct device *dev);
 
-/* dapm audio endpoint control */
-int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
-       char *pin, int status);
-int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec);
+/* dapm audio pin control and status */
+int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin);
+int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin);
+int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin);
+int snd_soc_dapm_sync(struct snd_soc_codec *codec);
 
 /* dapm widget types */
 enum snd_soc_dapm_type {
@@ -245,6 +260,18 @@ enum snd_soc_dapm_type {
        snd_soc_dapm_post,                      /* machine specific post widget - exec last */
 };
 
+/*
+ * DAPM audio route definition.
+ *
+ * Defines an audio route originating at source via control and finishing
+ * at sink.
+ */
+struct snd_soc_dapm_route {
+       const char *sink;
+       const char *control;
+       const char *source;
+};
+
 /* dapm audio path between two widgets */
 struct snd_soc_dapm_path {
        char *name;
@@ -277,6 +304,9 @@ struct snd_soc_dapm_widget {
        unsigned char shift;                    /* bits to shift */
        unsigned int saved_value;               /* widget saved value */
        unsigned int value;                             /* widget current value */
+       unsigned int mask;                      /* non-shifted mask */
+       unsigned int on_val;                    /* on state value */
+       unsigned int off_val;                   /* off state value */
        unsigned char power:1;                  /* block power status */
        unsigned char invert:1;                 /* invert the power bit */
        unsigned char active:1;                 /* active stream on DAC, ADC's */
index d3c8c033dff83b06d772e4dab9178f35413e17ff..1890d87c52042adc4d375953195a350d20e198ea 100644 (file)
        .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
        .private_value = (reg_left) | ((shift) << 8)  | \
                ((max) << 12) | ((invert) << 20) | ((reg_right) << 24) }
+#define SOC_DOUBLE_S8_TLV(xname, reg, min, max, tlv_array) \
+{      .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+                 SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+       .tlv.p  = (tlv_array), \
+       .info   = snd_soc_info_volsw_s8, .get = snd_soc_get_volsw_s8, \
+       .put    = snd_soc_put_volsw_s8, \
+       .private_value = (reg) | (((signed char)max) << 16) | \
+                        (((signed char)min) << 24) }
 #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
 {      .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
        .mask = xmask, .texts = xtexts }
        .info = snd_soc_info_volsw, \
        .get = xhandler_get, .put = xhandler_put, \
        .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmask, xinvert) }
+#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmask, xinvert,\
+        xhandler_get, xhandler_put, tlv_array) \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+                SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+       .tlv.p = (tlv_array), \
+       .info = snd_soc_info_volsw, \
+       .get = xhandler_get, .put = xhandler_put, \
+       .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmask, xinvert) }
 #define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
        .info = snd_soc_info_bool_ext, \
        .get = xhandler_get, .put = xhandler_put, \
        .private_value = (unsigned long)&xenum }
 
+/*
+ * Bias levels
+ *
+ * @ON:      Bias is fully on for audio playback and capture operations.
+ * @PREPARE: Prepare for audio operations. Called before DAPM switching for
+ *           stream start and stop operations.
+ * @STANDBY: Low power standby state when no playback/capture operations are
+ *           in progress. NOTE: The transition time between STANDBY and ON
+ *           should be as fast as possible and no longer than 10ms.
+ * @OFF:     Power Off. No restrictions on transition times.
+ */
+enum snd_soc_bias_level {
+       SND_SOC_BIAS_ON,
+       SND_SOC_BIAS_PREPARE,
+       SND_SOC_BIAS_STANDBY,
+       SND_SOC_BIAS_OFF,
+};
+
 /*
  * Digital Audio Interface (DAI) types
  */
@@ -185,8 +221,7 @@ struct snd_soc_pcm_stream;
 struct snd_soc_ops;
 struct snd_soc_dai_mode;
 struct snd_soc_pcm_runtime;
-struct snd_soc_codec_dai;
-struct snd_soc_cpu_dai;
+struct snd_soc_dai;
 struct snd_soc_codec;
 struct snd_soc_machine_config;
 struct soc_enum;
@@ -221,6 +256,27 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
        struct snd_ac97_bus_ops *ops, int num);
 void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
 
+/* Digital Audio Interface clocking API.*/
+int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+       unsigned int freq, int dir);
+
+int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
+       int div_id, int div);
+
+int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
+       int pll_id, unsigned int freq_in, unsigned int freq_out);
+
+/* Digital Audio interface formatting */
+int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
+
+int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
+       unsigned int mask, int slots);
+
+int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
+
+/* Digital Audio Interface mute */
+int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
+
 /*
  *Controls
  */
@@ -249,6 +305,12 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
 int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
+int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo);
+int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol);
+int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol);
 
 /* SoC PCM stream information */
 struct snd_soc_pcm_stream {
@@ -272,87 +334,45 @@ struct snd_soc_ops {
        int (*trigger)(struct snd_pcm_substream *, int);
 };
 
-/* ASoC codec DAI ops */
-struct snd_soc_codec_ops {
-       /* codec DAI clocking configuration */
-       int (*set_sysclk)(struct snd_soc_codec_dai *codec_dai,
+/* ASoC DAI ops */
+struct snd_soc_dai_ops {
+       /* DAI clocking configuration */
+       int (*set_sysclk)(struct snd_soc_dai *dai,
                int clk_id, unsigned int freq, int dir);
-       int (*set_pll)(struct snd_soc_codec_dai *codec_dai,
+       int (*set_pll)(struct snd_soc_dai *dai,
                int pll_id, unsigned int freq_in, unsigned int freq_out);
-       int (*set_clkdiv)(struct snd_soc_codec_dai *codec_dai,
-               int div_id, int div);
+       int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
 
-       /* CPU DAI format configuration */
-       int (*set_fmt)(struct snd_soc_codec_dai *codec_dai,
-               unsigned int fmt);
-       int (*set_tdm_slot)(struct snd_soc_codec_dai *codec_dai,
+       /* DAI format configuration */
+       int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
+       int (*set_tdm_slot)(struct snd_soc_dai *dai,
                unsigned int mask, int slots);
-       int (*set_tristate)(struct snd_soc_codec_dai *, int tristate);
+       int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
 
        /* digital mute */
-       int (*digital_mute)(struct snd_soc_codec_dai *, int mute);
-};
-
-/* ASoC cpu DAI ops */
-struct snd_soc_cpu_ops {
-       /* CPU DAI clocking configuration */
-       int (*set_sysclk)(struct snd_soc_cpu_dai *cpu_dai,
-               int clk_id, unsigned int freq, int dir);
-       int (*set_clkdiv)(struct snd_soc_cpu_dai *cpu_dai,
-               int div_id, int div);
-       int (*set_pll)(struct snd_soc_cpu_dai *cpu_dai,
-               int pll_id, unsigned int freq_in, unsigned int freq_out);
-
-       /* CPU DAI format configuration */
-       int (*set_fmt)(struct snd_soc_cpu_dai *cpu_dai,
-               unsigned int fmt);
-       int (*set_tdm_slot)(struct snd_soc_cpu_dai *cpu_dai,
-               unsigned int mask, int slots);
-       int (*set_tristate)(struct snd_soc_cpu_dai *, int tristate);
-};
-
-/* SoC Codec DAI */
-struct snd_soc_codec_dai {
-       char *name;
-       int id;
-       unsigned char type;
-
-       /* DAI capabilities */
-       struct snd_soc_pcm_stream playback;
-       struct snd_soc_pcm_stream capture;
-
-       /* DAI runtime info */
-       struct snd_soc_codec *codec;
-       unsigned int active;
-       unsigned char pop_wait:1;
-
-       /* ops */
-       struct snd_soc_ops ops;
-       struct snd_soc_codec_ops dai_ops;
-
-       /* DAI private data */
-       void *private_data;
+       int (*digital_mute)(struct snd_soc_dai *dai, int mute);
 };
 
-/* SoC CPU DAI */
-struct snd_soc_cpu_dai {
-
+/* SoC  DAI (Digital Audio Interface) */
+struct snd_soc_dai {
        /* DAI description */
        char *name;
        unsigned int id;
        unsigned char type;
 
        /* DAI callbacks */
-       int (*probe)(struct platform_device *pdev);
-       void (*remove)(struct platform_device *pdev);
+       int (*probe)(struct platform_device *pdev,
+                    struct snd_soc_dai *dai);
+       void (*remove)(struct platform_device *pdev,
+                      struct snd_soc_dai *dai);
        int (*suspend)(struct platform_device *pdev,
-               struct snd_soc_cpu_dai *cpu_dai);
+               struct snd_soc_dai *dai);
        int (*resume)(struct platform_device *pdev,
-               struct snd_soc_cpu_dai *cpu_dai);
+               struct snd_soc_dai *dai);
 
        /* ops */
        struct snd_soc_ops ops;
-       struct snd_soc_cpu_ops dai_ops;
+       struct snd_soc_dai_ops dai_ops;
 
        /* DAI capabilities */
        struct snd_soc_pcm_stream capture;
@@ -360,7 +380,9 @@ struct snd_soc_cpu_dai {
 
        /* DAI runtime info */
        struct snd_pcm_runtime *runtime;
-       unsigned char active:1;
+       struct snd_soc_codec *codec;
+       unsigned int active;
+       unsigned char pop_wait:1;
        void *dma_data;
 
        /* DAI private data */
@@ -374,7 +396,8 @@ struct snd_soc_codec {
        struct mutex mutex;
 
        /* callbacks */
-       int (*dapm_event)(struct snd_soc_codec *codec, int event);
+       int (*set_bias_level)(struct snd_soc_codec *,
+                             enum snd_soc_bias_level level);
 
        /* runtime */
        struct snd_card *card;
@@ -396,12 +419,12 @@ struct snd_soc_codec {
        /* dapm */
        struct list_head dapm_widgets;
        struct list_head dapm_paths;
-       unsigned int dapm_state;
-       unsigned int suspend_dapm_state;
+       enum snd_soc_bias_level bias_level;
+       enum snd_soc_bias_level suspend_bias_level;
        struct delayed_work delayed_work;
 
        /* codec DAI's */
-       struct snd_soc_codec_dai *dai;
+       struct snd_soc_dai *dai;
        unsigned int num_dai;
 };
 
@@ -420,12 +443,12 @@ struct snd_soc_platform {
        int (*probe)(struct platform_device *pdev);
        int (*remove)(struct platform_device *pdev);
        int (*suspend)(struct platform_device *pdev,
-               struct snd_soc_cpu_dai *cpu_dai);
+               struct snd_soc_dai *dai);
        int (*resume)(struct platform_device *pdev,
-               struct snd_soc_cpu_dai *cpu_dai);
+               struct snd_soc_dai *dai);
 
        /* pcm creation and destruction */
-       int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *,
+       int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
                struct snd_pcm *);
        void (*pcm_free)(struct snd_pcm *);
 
@@ -439,8 +462,8 @@ struct snd_soc_dai_link  {
        char *stream_name;              /* Stream name */
 
        /* DAI */
-       struct snd_soc_codec_dai *codec_dai;
-       struct snd_soc_cpu_dai *cpu_dai;
+       struct snd_soc_dai *codec_dai;
+       struct snd_soc_dai *cpu_dai;
 
        /* machine stream operations */
        struct snd_soc_ops *ops;
@@ -467,7 +490,8 @@ struct snd_soc_machine {
        int (*resume_post)(struct platform_device *pdev);
 
        /* callbacks */
-       int (*dapm_event)(struct snd_soc_machine *, int event);
+       int (*set_bias_level)(struct snd_soc_machine *,
+                             enum snd_soc_bias_level level);
 
        /* CPU <--> Codec DAI links  */
        struct snd_soc_dai_link *dai_link;
@@ -482,6 +506,7 @@ struct snd_soc_device {
        struct snd_soc_codec *codec;
        struct snd_soc_codec_device *codec_dev;
        struct delayed_work delayed_work;
+       struct work_struct deferred_resume_work;
        void *codec_data;
 };
 
index 2e564bfb37fea135053d7993991b0d53e31597bd..110d5dc3a2bed878815abc5abf3c03a17a31e43e 100644 (file)
@@ -15,8 +15,6 @@
  *                           features support
  */
 
-/* $Id: uda1341.h,v 1.8 2005/11/17 14:17:21 tiwai Exp $ */
-
 #define UDA1341_ALSA_NAME "snd-uda1341"
 
 /*
index ed6fb2eb1eac210d8812bfe26016ff9dd2bbeab0..6b78aff273a8a812fd303baa7b2f7f2bae1ca969 100644 (file)
@@ -1,3 +1,3 @@
-/* include/version.h.  Generated by alsa/ksync script.  */
-#define CONFIG_SND_VERSION "1.0.16"
+/* include/version.h */
+#define CONFIG_SND_VERSION "1.0.17"
 #define CONFIG_SND_DATE ""
index e8692a5748c24d2bd841ea7a81eaa09ae992bb04..e092f1c0ce3030916d9ad4c3af2b90fd64082f15 100644 (file)
@@ -738,7 +738,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                if (!audit_enabled && msg_type != AUDIT_USER_AVC)
                        return 0;
 
-               err = audit_filter_user(&NETLINK_CB(skb), msg_type);
+               err = audit_filter_user(&NETLINK_CB(skb));
                if (err == 1) {
                        err = 0;
                        if (msg_type == AUDIT_USER_TTY) {
@@ -779,7 +779,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                }
                /* fallthrough */
        case AUDIT_LIST:
-               err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
+               err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid,
                                           uid, seq, data, nlmsg_len(nlh),
                                           loginuid, sessionid, sid);
                break;
@@ -798,7 +798,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                }
                /* fallthrough */
        case AUDIT_LIST_RULES:
-               err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
+               err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid,
                                           uid, seq, data, nlmsg_len(nlh),
                                           loginuid, sessionid, sid);
                break;
index 0e0bd27e65129ec94e087753ba398c42f92acc7e..98c50cc671bb85525f8534cc422bc692dbef5dc9 100644 (file)
@@ -1544,6 +1544,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sessionid, u32 sid,
  * @data: payload data
  * @datasz: size of payload data
  * @loginuid: loginuid of sender
+ * @sessionid: sessionid for netlink audit message
  * @sid: SE Linux Security ID of sender
  */
 int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
@@ -1720,7 +1721,7 @@ static int audit_filter_user_rules(struct netlink_skb_parms *cb,
        return 1;
 }
 
-int audit_filter_user(struct netlink_skb_parms *cb, int type)
+int audit_filter_user(struct netlink_skb_parms *cb)
 {
        enum audit_state state = AUDIT_DISABLED;
        struct audit_entry *e;
index cfbe44299488c18187d80acbe06d9e03c5dc8a83..901e0fdc3fffa3b32fca26e0aa4e1985b244bd10 100644 (file)
@@ -121,6 +121,27 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy)
  * uninteresting and/or not to be changed.
  */
 
+/*
+ * Atomically modify the effective capabilities returning the original
+ * value. No permission check is performed here - it is assumed that the
+ * caller is permitted to set the desired effective capabilities.
+ */
+kernel_cap_t cap_set_effective(const kernel_cap_t pE_new)
+{
+       kernel_cap_t pE_old;
+
+       spin_lock(&task_capability_lock);
+
+       pE_old = current->cap_effective;
+       current->cap_effective = pE_new;
+
+       spin_unlock(&task_capability_lock);
+
+       return pE_old;
+}
+
+EXPORT_SYMBOL(cap_set_effective);
+
 /**
  * sys_capget - get the capabilities of a given process.
  * @header: pointer to struct that contains capability version and
index 9fceb97e989c25c82e438010437804774b892025..798b3ab054ebda48f9dd758ba7d080b3ab51bd28 100644 (file)
@@ -1882,7 +1882,7 @@ static void scan_for_empty_cpusets(const struct cpuset *root)
  * in order to minimize text size.
  */
 
-static void common_cpu_mem_hotplug_unplug(void)
+static void common_cpu_mem_hotplug_unplug(int rebuild_sd)
 {
        cgroup_lock();
 
@@ -1894,7 +1894,8 @@ static void common_cpu_mem_hotplug_unplug(void)
         * Scheduler destroys domains on hotplug events.
         * Rebuild them based on the current settings.
         */
-       rebuild_sched_domains();
+       if (rebuild_sd)
+               rebuild_sched_domains();
 
        cgroup_unlock();
 }
@@ -1912,11 +1913,22 @@ static void common_cpu_mem_hotplug_unplug(void)
 static int cpuset_handle_cpuhp(struct notifier_block *unused_nb,
                                unsigned long phase, void *unused_cpu)
 {
-       if (phase == CPU_DYING || phase == CPU_DYING_FROZEN)
+       switch (phase) {
+       case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
+       case CPU_DOWN_FAILED:
+       case CPU_DOWN_FAILED_FROZEN:
+       case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
+       case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
+               common_cpu_mem_hotplug_unplug(1);
+               break;
+       default:
                return NOTIFY_DONE;
+       }
 
-       common_cpu_mem_hotplug_unplug();
-       return 0;
+       return NOTIFY_OK;
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
@@ -1929,7 +1941,7 @@ static int cpuset_handle_cpuhp(struct notifier_block *unused_nb,
 
 void cpuset_track_online_nodes(void)
 {
-       common_cpu_mem_hotplug_unplug();
+       common_cpu_mem_hotplug_unplug(0);
 }
 #endif
 
index 8f6185e69b691265746f81a1ca4ce9de9fd8a640..ceb258782835a1073774e0337e0bc4d85f7a160f 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/personality.h>
 #include <linux/tty.h>
 #include <linux/mnt_namespace.h>
+#include <linux/iocontext.h>
 #include <linux/key.h>
 #include <linux/security.h>
 #include <linux/cpu.h>
index 19908b26cf80494a0db8f3410384521081293a32..b71ccd09fc8def0bb524d536b9faf3fee8e50451 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/sem.h>
 #include <linux/file.h>
 #include <linux/fdtable.h>
+#include <linux/iocontext.h>
 #include <linux/key.h>
 #include <linux/binfmts.h>
 #include <linux/mman.h>
index 421be5fe5cc78f5d2be0eabd3ba2367fe1b15b3e..ab80515008f4740fd980b1089d922811978ccff4 100644 (file)
@@ -1003,10 +1003,18 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
         */
        raise = timer->state == HRTIMER_STATE_PENDING;
 
+       /*
+        * We use preempt_disable to prevent this task from migrating after
+        * setting up the softirq and raising it. Otherwise, if me migrate
+        * we will raise the softirq on the wrong CPU.
+        */
+       preempt_disable();
+
        unlock_hrtimer_base(timer, &flags);
 
        if (raise)
                hrtimer_raise_softirq();
+       preempt_enable();
 
        return ret;
 }
index d4998f81e229efdc83d7135ecc61fa0cc70ecd91..1485ca8d0e00503104e81248a7c5e30b58edfb79 100644 (file)
@@ -79,7 +79,7 @@ static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
  *
  * For such cases, we now have a blacklist
  */
-struct kprobe_blackpoint kprobe_blacklist[] = {
+static struct kprobe_blackpoint kprobe_blacklist[] = {
        {"preempt_schedule",},
        {NULL}    /* Terminator */
 };
index 8fb01c32aa3bb7eaf44f5b9e63e316628dd935c1..e2129e83fd75b8d0c708a7c410005015e0cba564 100644 (file)
@@ -666,7 +666,7 @@ static int acquire_console_semaphore_for_printk(unsigned int cpu)
        return retval;
 }
 
-const char printk_recursion_bug_msg [] =
+static const char printk_recursion_bug_msg [] =
                        KERN_CRIT "BUG: recent printk recursion!\n";
 static int printk_recursion_bug;
 
index 6c19e94fd0a5482786e432599a0fb4840a5c66cb..e337390fce011dc0ea1d5eba1cf678553fb93b71 100644 (file)
@@ -121,7 +121,7 @@ int ptrace_check_attach(struct task_struct *child, int kill)
        return ret;
 }
 
-int __ptrace_may_attach(struct task_struct *task)
+int __ptrace_may_access(struct task_struct *task, unsigned int mode)
 {
        /* May we inspect the given task?
         * This check is used both for attaching with ptrace
@@ -148,16 +148,16 @@ int __ptrace_may_attach(struct task_struct *task)
        if (!dumpable && !capable(CAP_SYS_PTRACE))
                return -EPERM;
 
-       return security_ptrace(current, task);
+       return security_ptrace(current, task, mode);
 }
 
-int ptrace_may_attach(struct task_struct *task)
+bool ptrace_may_access(struct task_struct *task, unsigned int mode)
 {
        int err;
        task_lock(task);
-       err = __ptrace_may_attach(task);
+       err = __ptrace_may_access(task, mode);
        task_unlock(task);
-       return !err;
+       return (!err ? true : false);
 }
 
 int ptrace_attach(struct task_struct *task)
@@ -195,7 +195,7 @@ repeat:
        /* the same process cannot be attached many times */
        if (task->ptrace & PT_PTRACED)
                goto bad;
-       retval = __ptrace_may_attach(task);
+       retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
        if (retval)
                goto bad;
 
@@ -494,7 +494,8 @@ int ptrace_traceme(void)
         */
        task_lock(current);
        if (!(current->ptrace & PT_PTRACED)) {
-               ret = security_ptrace(current->parent, current);
+               ret = security_ptrace(current->parent, current,
+                                     PTRACE_MODE_ATTACH);
                /*
                 * Set the ptrace bit in the process ptrace flags.
                 */
index f4ffbd0f306f57c63afbe502c235df1b5e8548ed..a38895a5b8e2eeb1da28a829bebfe4a963c97561 100644 (file)
@@ -89,8 +89,22 @@ static void force_quiescent_state(struct rcu_data *rdp,
                /*
                 * Don't send IPI to itself. With irqs disabled,
                 * rdp->cpu is the current cpu.
+                *
+                * cpu_online_map is updated by the _cpu_down()
+                * using stop_machine_run(). Since we're in irqs disabled
+                * section, stop_machine_run() is not exectuting, hence
+                * the cpu_online_map is stable.
+                *
+                * However,  a cpu might have been offlined _just_ before
+                * we disabled irqs while entering here.
+                * And rcu subsystem might not yet have handled the CPU_DEAD
+                * notification, leading to the offlined cpu's bit
+                * being set in the rcp->cpumask.
+                *
+                * Hence cpumask = (rcp->cpumask & cpu_online_map) to prevent
+                * sending smp_reschedule() to an offlined CPU.
                 */
-               cpumask = rcp->cpumask;
+               cpus_and(cpumask, rcp->cpumask, cpu_online_map);
                cpu_clear(rdp->cpu, cpumask);
                for_each_cpu_mask(cpu, cpumask)
                        smp_send_reschedule(cpu);
index 5e02b7740702fa928d188d7afd9855689d1b7b41..41d275a81df512229c424c317ed78d246a01ae3a 100644 (file)
@@ -925,26 +925,22 @@ void rcu_offline_cpu(int cpu)
        spin_unlock_irqrestore(&rdp->lock, flags);
 }
 
-void __devinit rcu_online_cpu(int cpu)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&rcu_ctrlblk.fliplock, flags);
-       cpu_set(cpu, rcu_cpu_online_map);
-       spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags);
-}
-
 #else /* #ifdef CONFIG_HOTPLUG_CPU */
 
 void rcu_offline_cpu(int cpu)
 {
 }
 
-void __devinit rcu_online_cpu(int cpu)
+#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
+
+void __cpuinit rcu_online_cpu(int cpu)
 {
-}
+       unsigned long flags;
 
-#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
+       spin_lock_irqsave(&rcu_ctrlblk.fliplock, flags);
+       cpu_set(cpu, rcu_cpu_online_map);
+       spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags);
+}
 
 static void rcu_process_callbacks(struct softirq_action *unused)
 {
index 3aaa5c8cb4214586bd283eedc2375baa3dc739c0..4e2f6033565687f648cbd27e8976ea6c647217fa 100644 (file)
@@ -5622,10 +5622,10 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
        double_rq_lock(rq_src, rq_dest);
        /* Already moved. */
        if (task_cpu(p) != src_cpu)
-               goto out;
+               goto done;
        /* Affinity changed (again). */
        if (!cpu_isset(dest_cpu, p->cpus_allowed))
-               goto out;
+               goto fail;
 
        on_rq = p->se.on_rq;
        if (on_rq)
@@ -5636,8 +5636,9 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
                activate_task(rq_dest, p, 0);
                check_preempt_curr(rq_dest, p);
        }
+done:
        ret = 1;
-out:
+fail:
        double_rq_unlock(rq_src, rq_dest);
        return ret;
 }
@@ -5887,6 +5888,7 @@ static void migrate_dead_tasks(unsigned int dead_cpu)
                next = pick_next_task(rq, rq->curr);
                if (!next)
                        break;
+               next->sched_class->put_prev_task(rq, next);
                migrate_dead(dead_cpu, next);
 
        }
@@ -8501,6 +8503,9 @@ int sched_group_set_rt_period(struct task_group *tg, long rt_period_us)
        rt_period = (u64)rt_period_us * NSEC_PER_USEC;
        rt_runtime = tg->rt_bandwidth.rt_runtime;
 
+       if (rt_period == 0)
+               return -EINVAL;
+
        return tg_set_bandwidth(tg, rt_period, rt_runtime);
 }
 
index c828c2339cc9e8a8992df52f31756f8894c7f6b1..a272d78185eb5901449b0e8765f33a3f5723df28 100644 (file)
@@ -120,6 +120,7 @@ void softlockup_tick(void)
        printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %lus! [%s:%d]\n",
                        this_cpu, now - touch_timestamp,
                        current->comm, task_pid_nr(current));
+       print_modules();
        if (regs)
                show_regs(regs);
        else
index 29fc39f1029cec92528b0cb66380028670b9eee1..ce7799540c91d28d3109e0e31fc53e623859ed1e 100644 (file)
@@ -13,7 +13,7 @@
  *   Kai Petzke <wpp@marie.physik.tu-berlin.de>
  *   Theodore Ts'o <tytso@mit.edu>
  *
- * Made to use alloc_percpu by Christoph Lameter <clameter@sgi.com>.
+ * Made to use alloc_percpu by Christoph Lameter.
  */
 
 #include <linux/module.h>
index 530f38f55787ec8703375c7706ae49fc7f529f7b..bfeafd60ee9fce4ba8e643c2beb5d8e66cff74e3 100644 (file)
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -37,6 +37,7 @@
  */
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/bug.h>
 #include <linux/sched.h>
 
@@ -149,6 +150,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
                               (void *)bugaddr);
 
                show_regs(regs);
+               add_taint(TAINT_WARN);
                return BUG_TRAP_TYPE_WARN;
        }
 
index a76a5e122ae134dabd283073c6404aac51501243..85b18d79be89acee07e25004eac991df799f0b8a 100644 (file)
@@ -68,6 +68,7 @@ static int fill_pool(void)
 {
        gfp_t gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
        struct debug_obj *new;
+       unsigned long flags;
 
        if (likely(obj_pool_free >= ODEBUG_POOL_MIN_LEVEL))
                return obj_pool_free;
@@ -81,10 +82,10 @@ static int fill_pool(void)
                if (!new)
                        return obj_pool_free;
 
-               spin_lock(&pool_lock);
+               spin_lock_irqsave(&pool_lock, flags);
                hlist_add_head(&new->node, &obj_pool);
                obj_pool_free++;
-               spin_unlock(&pool_lock);
+               spin_unlock_irqrestore(&pool_lock, flags);
        }
        return obj_pool_free;
 }
@@ -110,16 +111,13 @@ static struct debug_obj *lookup_object(void *addr, struct debug_bucket *b)
 }
 
 /*
- * Allocate a new object. If the pool is empty and no refill possible,
- * switch off the debugger.
+ * Allocate a new object. If the pool is empty, switch off the debugger.
  */
 static struct debug_obj *
 alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
 {
        struct debug_obj *obj = NULL;
-       int retry = 0;
 
-repeat:
        spin_lock(&pool_lock);
        if (obj_pool.first) {
                obj         = hlist_entry(obj_pool.first, typeof(*obj), node);
@@ -141,9 +139,6 @@ repeat:
        }
        spin_unlock(&pool_lock);
 
-       if (fill_pool() && !obj && !retry++)
-               goto repeat;
-
        return obj;
 }
 
@@ -261,6 +256,8 @@ __debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack)
        struct debug_obj *obj;
        unsigned long flags;
 
+       fill_pool();
+
        db = get_bucket((unsigned long) addr);
 
        spin_lock_irqsave(&db->lock, flags);
index 169a2f8dabcc901f185faec5ff26da0d7194cdff..56ec21a7f73dc09fb64dc395ee4297b04907d649 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2001 Momchil Velikov
  * Portions Copyright (C) 2001 Christoph Hellwig
- * Copyright (C) 2005 SGI, Christoph Lameter <clameter@sgi.com>
+ * Copyright (C) 2005 SGI, Christoph Lameter
  * Copyright (C) 2006 Nick Piggin
  *
  * This program is free software; you can redistribute it and/or
index d90822c378a48af52878f41e5db18858496fddb9..4a7fce72898ed40f13d58bca7cc1d97293d8bba0 100644 (file)
@@ -63,7 +63,7 @@ static unsigned int bm_find(struct ts_config *conf, struct ts_state *state)
        struct ts_bm *bm = ts_config_priv(conf);
        unsigned int i, text_len, consumed = state->offset;
        const u8 *text;
-       int shift = bm->patlen, bs;
+       int shift = bm->patlen - 1, bs;
 
        for (;;) {
                text_len = conf->get_next_block(consumed, &text, conf, state);
index 6021757a449663074cded737138d31acd83da325..1dc2d1d18fa8fddb9887dad750461d9f63faeb6f 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/kernel.h>
+#include <linux/kallsyms.h>
+#include <linux/uaccess.h>
 
 #include <asm/page.h>          /* for PAGE_SIZE */
 #include <asm/div64.h>
@@ -482,6 +484,89 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
        return buf;
 }
 
+static char *string(char *buf, char *end, char *s, int field_width, int precision, int flags)
+{
+       int len, i;
+
+       if ((unsigned long)s < PAGE_SIZE)
+               s = "<NULL>";
+
+       len = strnlen(s, precision);
+
+       if (!(flags & LEFT)) {
+               while (len < field_width--) {
+                       if (buf < end)
+                               *buf = ' ';
+                       ++buf;
+               }
+       }
+       for (i = 0; i < len; ++i) {
+               if (buf < end)
+                       *buf = *s;
+               ++buf; ++s;
+       }
+       while (len < field_width--) {
+               if (buf < end)
+                       *buf = ' ';
+               ++buf;
+       }
+       return buf;
+}
+
+static inline void *dereference_function_descriptor(void *ptr)
+{
+#if defined(CONFIG_IA64) || defined(CONFIG_PPC64)
+       void *p;
+       if (!probe_kernel_address(ptr, p))
+               ptr = p;
+#endif
+       return ptr;
+}
+
+static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags)
+{
+       unsigned long value = (unsigned long) ptr;
+#ifdef CONFIG_KALLSYMS
+       char sym[KSYM_SYMBOL_LEN];
+       sprint_symbol(sym, value);
+       return string(buf, end, sym, field_width, precision, flags);
+#else
+       field_width = 2*sizeof(void *);
+       flags |= SPECIAL | SMALL | ZEROPAD;
+       return number(buf, end, value, 16, field_width, precision, flags);
+#endif
+}
+
+/*
+ * Show a '%p' thing.  A kernel extension is that the '%p' is followed
+ * by an extra set of alphanumeric characters that are extended format
+ * specifiers.
+ *
+ * Right now we just handle 'F' (for symbolic Function descriptor pointers)
+ * and 'S' (for Symbolic direct pointers), but this can easily be
+ * extended in the future (network address types etc).
+ *
+ * The difference between 'S' and 'F' is that on ia64 and ppc64 function
+ * pointers are really function descriptors, which contain a pointer the
+ * real address. 
+ */
+static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags)
+{
+       switch (*fmt) {
+       case 'F':
+               ptr = dereference_function_descriptor(ptr);
+               /* Fallthrough */
+       case 'S':
+               return symbol_string(buf, end, ptr, field_width, precision, flags);
+       }
+       flags |= SMALL;
+       if (field_width == -1) {
+               field_width = 2*sizeof(void *);
+               flags |= ZEROPAD;
+       }
+       return number(buf, end, (unsigned long) ptr, 16, field_width, precision, flags);
+}
+
 /**
  * vsnprintf - Format a string and place it in a buffer
  * @buf: The buffer to place the result into
@@ -502,11 +587,9 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
  */
 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
 {
-       int len;
        unsigned long long num;
-       int i, base;
+       int base;
        char *str, *end, c;
-       const char *s;
 
        int flags;              /* flags to number() */
 
@@ -622,43 +705,18 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
                                continue;
 
                        case 's':
-                               s = va_arg(args, char *);
-                               if ((unsigned long)s < PAGE_SIZE)
-                                       s = "<NULL>";
-
-                               len = strnlen(s, precision);
-
-                               if (!(flags & LEFT)) {
-                                       while (len < field_width--) {
-                                               if (str < end)
-                                                       *str = ' ';
-                                               ++str;
-                                       }
-                               }
-                               for (i = 0; i < len; ++i) {
-                                       if (str < end)
-                                               *str = *s;
-                                       ++str; ++s;
-                               }
-                               while (len < field_width--) {
-                                       if (str < end)
-                                               *str = ' ';
-                                       ++str;
-                               }
+                               str = string(str, end, va_arg(args, char *), field_width, precision, flags);
                                continue;
 
                        case 'p':
-                               flags |= SMALL;
-                               if (field_width == -1) {
-                                       field_width = 2*sizeof(void *);
-                                       flags |= ZEROPAD;
-                               }
-                               str = number(str, end,
-                                               (unsigned long) va_arg(args, void *),
-                                               16, field_width, precision, flags);
+                               str = pointer(fmt+1, str, end,
+                                               va_arg(args, void *),
+                                               field_width, precision, flags);
+                               /* Skip all alphanumeric pointer suffixes */
+                               while (isalnum(fmt[1]))
+                                       fmt++;
                                continue;
 
-
                        case 'n':
                                /* FIXME:
                                * What does C99 say about the overflow case here? */
index 60b2619527834fac95d98f018f074423aa811526..c4de85285bb43cd2ab9810d42c67c8001d9adb1b 100644 (file)
@@ -129,7 +129,7 @@ config MEMORY_HOTPLUG
        bool "Allow for memory hot-add"
        depends on SPARSEMEM || X86_64_ACPI_NUMA
        depends on HOTPLUG && !HIBERNATION && ARCH_ENABLE_MEMORY_HOTPLUG
-       depends on (IA64 || X86 || PPC64 || SUPERH)
+       depends on (IA64 || X86 || PPC64 || SUPERH || S390)
 
 comment "Memory hotplug is currently incompatible with Software Suspend"
        depends on SPARSEMEM && HOTPLUG && HIBERNATION
index f4026bae6eedadb9e077e3500480fc47feb25624..05f2b4009cccd4c249ccfbd50aa8bc3237d4cb59 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/mm/allocpercpu.c
  *
- * Separated from slab.c August 11, 2006 Christoph Lameter <clameter@sgi.com>
+ * Separated from slab.c August 11, 2006 Christoph Lameter
  */
 #include <linux/mm.h>
 #include <linux/module.h>
index d14b251a25a638dec1b5327a6261a67660ba67d5..2302d228fe04f3926f8c52bf65965623f1caff05 100644 (file)
@@ -1151,7 +1151,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                         * be processed until returning to user space.
                         */
                        if (unlikely(test_tsk_thread_flag(tsk, TIF_MEMDIE)))
-                               return -ENOMEM;
+                               return i ? i : -ENOMEM;
 
                        if (write)
                                foll_flags |= FOLL_WRITE;
@@ -1697,8 +1697,19 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
        struct page *dirty_page = NULL;
 
        old_page = vm_normal_page(vma, address, orig_pte);
-       if (!old_page)
+       if (!old_page) {
+               /*
+                * VM_MIXEDMAP !pfn_valid() case
+                *
+                * We should not cow pages in a shared writeable mapping.
+                * Just mark the pages writable as we can't do any dirty
+                * accounting on raw pfn maps.
+                */
+               if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
+                                    (VM_WRITE|VM_SHARED))
+                       goto reuse;
                goto gotten;
+       }
 
        /*
         * Take out anonymous pages first, anonymous shared vmas are
@@ -1751,6 +1762,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
        }
 
        if (reuse) {
+reuse:
                flush_cache_page(vma, address, pte_pfn(orig_pte));
                entry = pte_mkyoung(orig_pte);
                entry = maybe_mkwrite(pte_mkdirty(entry), vma);
index a37a5034f63dda824f15b5ffb89156fea43fb4a3..c94e58b192c3c9913f4f4ab57860b6ac9469f839 100644 (file)
@@ -729,7 +729,11 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask,
        } else {
                *policy = pol == &default_policy ? MPOL_DEFAULT :
                                                pol->mode;
-               *policy |= pol->flags;
+               /*
+                * Internal mempolicy flags must be masked off before exposing
+                * the policy to userspace.
+                */
+               *policy |= (pol->flags & MPOL_MODE_FLAGS);
        }
 
        if (vma) {
index 112bcaeaa1046076af8618b7f06b2cfbc32faf8a..55bd355d170d055907c407f0c93d98dcb6e9e555 100644 (file)
@@ -9,7 +9,7 @@
  * IWAMOTO Toshihiro <iwamoto@valinux.co.jp>
  * Hirokazu Takahashi <taka@valinux.co.jp>
  * Dave Hansen <haveblue@us.ibm.com>
- * Christoph Lameter <clameter@sgi.com>
+ * Christoph Lameter
  */
 
 #include <linux/migrate.h>
index 2f552955a02fbade92fb28c7e7338df46e8244e0..f32fae3121f07461f846911ee6963ce679828780 100644 (file)
@@ -2328,7 +2328,6 @@ static void build_zonelists(pg_data_t *pgdat)
 static void build_zonelist_cache(pg_data_t *pgdat)
 {
        pgdat->node_zonelists[0].zlcache_ptr = NULL;
-       pgdat->node_zonelists[1].zlcache_ptr = NULL;
 }
 
 #endif /* CONFIG_NUMA */
index 0987d1cd943cc88d626a7d1b1097ba1f83243591..5f6e2c4a2ba7cbf51e85961eaa56b9d3f82981f0 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -5,7 +5,7 @@
  * The allocator synchronizes using per slab locks and only
  * uses a centralized lock to manage a pool of partial slabs.
  *
- * (C) 2007 SGI, Christoph Lameter <clameter@sgi.com>
+ * (C) 2007 SGI, Christoph Lameter
  */
 
 #include <linux/mm.h>
@@ -431,9 +431,8 @@ static void print_track(const char *s, struct track *t)
        if (!t->addr)
                return;
 
-       printk(KERN_ERR "INFO: %s in ", s);
-       __print_symbol("%s", (unsigned long)t->addr);
-       printk(" age=%lu cpu=%u pid=%d\n", jiffies - t->when, t->cpu, t->pid);
+       printk(KERN_ERR "INFO: %s in %pS age=%lu cpu=%u pid=%d\n",
+               s, t->addr, jiffies - t->when, t->cpu, t->pid);
 }
 
 static void print_tracking(struct kmem_cache *s, void *object)
@@ -1628,9 +1627,11 @@ static __always_inline void *slab_alloc(struct kmem_cache *s,
        void **object;
        struct kmem_cache_cpu *c;
        unsigned long flags;
+       unsigned int objsize;
 
        local_irq_save(flags);
        c = get_cpu_slab(s, smp_processor_id());
+       objsize = c->objsize;
        if (unlikely(!c->freelist || !node_match(c, node)))
 
                object = __slab_alloc(s, gfpflags, node, addr, c);
@@ -1643,7 +1644,7 @@ static __always_inline void *slab_alloc(struct kmem_cache *s,
        local_irq_restore(flags);
 
        if (unlikely((gfpflags & __GFP_ZERO) && object))
-               memset(object, 0, c->objsize);
+               memset(object, 0, objsize);
 
        return object;
 }
@@ -2995,8 +2996,6 @@ void __init kmem_cache_init(void)
                create_kmalloc_cache(&kmalloc_caches[1],
                                "kmalloc-96", 96, GFP_KERNEL);
                caches++;
-       }
-       if (KMALLOC_MIN_SIZE <= 128) {
                create_kmalloc_cache(&kmalloc_caches[2],
                                "kmalloc-192", 192, GFP_KERNEL);
                caches++;
@@ -3026,6 +3025,16 @@ void __init kmem_cache_init(void)
        for (i = 8; i < KMALLOC_MIN_SIZE; i += 8)
                size_index[(i - 1) / 8] = KMALLOC_SHIFT_LOW;
 
+       if (KMALLOC_MIN_SIZE == 128) {
+               /*
+                * The 192 byte sized cache is not used if the alignment
+                * is 128 byte. Redirect kmalloc to use the 256 byte cache
+                * instead.
+                */
+               for (i = 128 + 8; i <= 192; i += 8)
+                       size_index[(i - 1) / 8] = 8;
+       }
+
        slab_state = UP;
 
        /* Provide the correct kmalloc names now that the caches are up */
index 99c4f36eb8a33def3c713937cecb9cc51256359a..a91b5f8fcaf61e6dc50bfe0526e5b488c3c967c7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Virtual Memory Map support
  *
- * (C) 2007 sgi. Christoph Lameter <clameter@sgi.com>.
+ * (C) 2007 sgi. Christoph Lameter.
  *
  * Virtual memory maps allow VM primitives pfn_to_page, page_to_pfn,
  * virt_to_page, page_address() to be implemented as a base offset
index c2397f503b0f94e850d7da40b68e53fb16b9f9ae..f38cc5317b888bd45f271ed7db5a0f065ada9803 100644 (file)
@@ -442,12 +442,16 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
 
 void __exit br_cleanup_bridges(void)
 {
-       struct net_device *dev, *nxt;
+       struct net_device *dev;
 
        rtnl_lock();
-       for_each_netdev_safe(&init_net, dev, nxt)
-               if (dev->priv_flags & IFF_EBRIDGE)
+restart:
+       for_each_netdev(&init_net, dev) {
+               if (dev->priv_flags & IFF_EBRIDGE) {
                        del_br(dev->priv);
+                       goto restart;
+               }
+       }
        rtnl_unlock();
 
 }
index 7e8ca2836452a5053c4695691ceba78a9d4605d1..484bbf6dd0322790f6f42cee71c3e1f86f6ace41 100644 (file)
@@ -205,12 +205,19 @@ static int can_create(struct net *net, struct socket *sock, int protocol)
  *  -ENOBUFS on full driver queue (see net_xmit_errno())
  *  -ENOMEM when local loopback failed at calling skb_clone()
  *  -EPERM when trying to send on a non-CAN interface
+ *  -EINVAL when the skb->data does not contain a valid CAN frame
  */
 int can_send(struct sk_buff *skb, int loop)
 {
        struct sk_buff *newskb = NULL;
+       struct can_frame *cf = (struct can_frame *)skb->data;
        int err;
 
+       if (skb->len != sizeof(struct can_frame) || cf->can_dlc > 8) {
+               kfree_skb(skb);
+               return -EINVAL;
+       }
+
        if (skb->dev->type != ARPHRD_CAN) {
                kfree_skb(skb);
                return -EPERM;
@@ -605,6 +612,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
                   struct packet_type *pt, struct net_device *orig_dev)
 {
        struct dev_rcv_lists *d;
+       struct can_frame *cf = (struct can_frame *)skb->data;
        int matches;
 
        if (dev->type != ARPHRD_CAN || dev_net(dev) != &init_net) {
@@ -612,6 +620,8 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
                return 0;
        }
 
+       BUG_ON(skb->len != sizeof(struct can_frame) || cf->can_dlc > 8);
+
        /* update statistics */
        can_stats.rx_frames++;
        can_stats.rx_frames_delta++;
index d9a3a9d13bedbb5b11cc1850aa604adccf47ad1c..72c2ce904f83ab9f92109e33c6ed34f947a80a73 100644 (file)
@@ -298,7 +298,7 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
 
        if (head->nframes) {
                /* can_frames starting here */
-               firstframe = (struct can_frame *) skb_tail_pointer(skb);
+               firstframe = (struct can_frame *)skb_tail_pointer(skb);
 
                memcpy(skb_put(skb, datalen), frames, datalen);
 
@@ -826,6 +826,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                for (i = 0; i < msg_head->nframes; i++) {
                        err = memcpy_fromiovec((u8 *)&op->frames[i],
                                               msg->msg_iov, CFSIZ);
+
+                       if (op->frames[i].can_dlc > 8)
+                               err = -EINVAL;
+
                        if (err < 0)
                                return err;
 
@@ -858,6 +862,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                for (i = 0; i < msg_head->nframes; i++) {
                        err = memcpy_fromiovec((u8 *)&op->frames[i],
                                               msg->msg_iov, CFSIZ);
+
+                       if (op->frames[i].can_dlc > 8)
+                               err = -EINVAL;
+
                        if (err < 0) {
                                if (op->frames != &op->sframe)
                                        kfree(op->frames);
@@ -1164,9 +1172,12 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk)
 
        skb->dev = dev;
        skb->sk  = sk;
-       can_send(skb, 1); /* send with loopback */
+       err = can_send(skb, 1); /* send with loopback */
        dev_put(dev);
 
+       if (err)
+               return err;
+
        return CFSIZ + MHSIZ;
 }
 
@@ -1185,6 +1196,10 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock,
        if (!bo->bound)
                return -ENOTCONN;
 
+       /* check for valid message length from userspace */
+       if (size < MHSIZ || (size - MHSIZ) % CFSIZ)
+               return -EINVAL;
+
        /* check for alternative ifindex for this bcm_op */
 
        if (!ifindex && msg->msg_name) {
@@ -1259,8 +1274,8 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock,
                break;
 
        case TX_SEND:
-               /* we need at least one can_frame */
-               if (msg_head.nframes < 1)
+               /* we need exactly one can_frame behind the msg head */
+               if ((msg_head.nframes != 1) || (size != CFSIZ + MHSIZ))
                        ret = -EINVAL;
                else
                        ret = bcm_tx_send(msg, ifindex, sk);
index 69877b8e7e9c772be9479bced40b6b8273662322..3e46ee36a1aaf819b8ed4a8d7c6afcb7b8614948 100644 (file)
@@ -632,6 +632,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
        } else
                ifindex = ro->ifindex;
 
+       if (size != sizeof(struct can_frame))
+               return -EINVAL;
+
        dev = dev_get_by_index(&init_net, ifindex);
        if (!dev)
                return -ENXIO;
index c421a1f8f0b94cc23d8193d254fcf97d06ed6a1b..fca23a3bf12c1b5b14d6430ff07abbecbd749cc4 100644 (file)
@@ -454,7 +454,7 @@ static int netdev_boot_setup_add(char *name, struct ifmap *map)
        for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) {
                if (s[i].name[0] == '\0' || s[i].name[0] == ' ') {
                        memset(s[i].name, 0, sizeof(s[i].name));
-                       strcpy(s[i].name, name);
+                       strlcpy(s[i].name, name, IFNAMSIZ);
                        memcpy(&s[i].map, map, sizeof(s[i].map));
                        break;
                }
@@ -479,7 +479,7 @@ int netdev_boot_setup_check(struct net_device *dev)
 
        for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) {
                if (s[i].name[0] != '\0' && s[i].name[0] != ' ' &&
-                   !strncmp(dev->name, s[i].name, strlen(s[i].name))) {
+                   !strcmp(dev->name, s[i].name)) {
                        dev->irq        = s[i].map.irq;
                        dev->base_addr  = s[i].map.base_addr;
                        dev->mem_start  = s[i].map.mem_start;
@@ -2973,7 +2973,7 @@ EXPORT_SYMBOL(dev_unicast_delete);
 /**
  *     dev_unicast_add         - add a secondary unicast address
  *     @dev: device
- *     @addr: address to delete
+ *     @addr: address to add
  *     @alen: length of @addr
  *
  *     Add a secondary unicast address to the device or increase
index e3e9ab0f74e33caf9e0df3a8d0829359f86eefe7..277a2302eb3abb666574a5b3b7dc2714f45ef7c4 100644 (file)
@@ -226,7 +226,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 
        ops = lookup_rules_ops(net, frh->family);
        if (ops == NULL) {
-               err = EAFNOSUPPORT;
+               err = -EAFNOSUPPORT;
                goto errout;
        }
 
@@ -365,7 +365,7 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 
        ops = lookup_rules_ops(net, frh->family);
        if (ops == NULL) {
-               err = EAFNOSUPPORT;
+               err = -EAFNOSUPPORT;
                goto errout;
        }
 
index 4f8369729a4e8d15347a00cfeac2b56aea40b112..df37443558395a01780f725e744a920fb1664872 100644 (file)
@@ -68,7 +68,6 @@ static inline void *load_pointer(struct sk_buff *skb, int k,
  *     sk_filter - run a packet through a socket filter
  *     @sk: sock associated with &sk_buff
  *     @skb: buffer to filter
- *     @needlock: set to 1 if the sock is not locked by caller.
  *
  * Run the filter code and then cut skb->data to correct size returned by
  * sk_run_filter. If pkt_len is 0 we toss packet. If skb->len is smaller
index 1e556d31211742d41acb39cbc2c1cd8460e2d3b0..366621610e76d5a91ae72522d38d0b60e3df45d9 100644 (file)
@@ -1292,12 +1292,14 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
 {
        unsigned int nr_pages = spd->nr_pages;
        unsigned int poff, plen, len, toff, tlen;
-       int headlen, seg;
+       int headlen, seg, error = 0;
 
        toff = *offset;
        tlen = *total_len;
-       if (!tlen)
+       if (!tlen) {
+               error = 1;
                goto err;
+       }
 
        /*
         * if the offset is greater than the linear part, go directly to
@@ -1339,7 +1341,8 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
                 * just jump directly to update and return, no point
                 * in going over fragments when the output is full.
                 */
-               if (spd_fill_page(spd, virt_to_page(p), plen, poff, skb))
+               error = spd_fill_page(spd, virt_to_page(p), plen, poff, skb);
+               if (error)
                        goto done;
 
                tlen -= plen;
@@ -1369,7 +1372,8 @@ map_frag:
                if (!plen)
                        break;
 
-               if (spd_fill_page(spd, f->page, plen, poff, skb))
+               error = spd_fill_page(spd, f->page, plen, poff, skb);
+               if (error)
                        break;
 
                tlen -= plen;
@@ -1382,7 +1386,10 @@ done:
                return 0;
        }
 err:
-       return 1;
+       /* update the offset to reflect the linear part skip, if any */
+       if (!error)
+               *offset = toff;
+       return error;
 }
 
 /*
index 4b02d14e7ab9685cece9fa1565e528132313eb26..e1600ad8fb0e44fbd33657589ba84040b0ac8333 100644 (file)
@@ -1359,17 +1359,17 @@ static int check_leaf(struct trie *t, struct leaf *l,
                        t->stats.semantic_match_miss++;
 #endif
                if (err <= 0)
-                       return plen;
+                       return err;
        }
 
-       return -1;
+       return 1;
 }
 
 static int fn_trie_lookup(struct fib_table *tb, const struct flowi *flp,
                          struct fib_result *res)
 {
        struct trie *t = (struct trie *) tb->tb_data;
-       int plen, ret = 0;
+       int ret;
        struct node *n;
        struct tnode *pn;
        int pos, bits;
@@ -1393,10 +1393,7 @@ static int fn_trie_lookup(struct fib_table *tb, const struct flowi *flp,
 
        /* Just a leaf? */
        if (IS_LEAF(n)) {
-               plen = check_leaf(t, (struct leaf *)n, key, flp, res);
-               if (plen < 0)
-                       goto failed;
-               ret = 0;
+               ret = check_leaf(t, (struct leaf *)n, key, flp, res);
                goto found;
        }
 
@@ -1421,11 +1418,9 @@ static int fn_trie_lookup(struct fib_table *tb, const struct flowi *flp,
                }
 
                if (IS_LEAF(n)) {
-                       plen = check_leaf(t, (struct leaf *)n, key, flp, res);
-                       if (plen < 0)
+                       ret = check_leaf(t, (struct leaf *)n, key, flp, res);
+                       if (ret > 0)
                                goto backtrace;
-
-                       ret = 0;
                        goto found;
                }
 
index 4ed429bd5951542401130f16e3a4f0341ded3920..0546a0bc97ea37bdc1b9bef0c22d6b82ec190abf 100644 (file)
@@ -192,14 +192,21 @@ EXPORT_SYMBOL(inet_frag_evictor);
 
 static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
                struct inet_frag_queue *qp_in, struct inet_frags *f,
-               unsigned int hash, void *arg)
+               void *arg)
 {
        struct inet_frag_queue *qp;
 #ifdef CONFIG_SMP
        struct hlist_node *n;
 #endif
+       unsigned int hash;
 
        write_lock(&f->lock);
+       /*
+        * While we stayed w/o the lock other CPU could update
+        * the rnd seed, so we need to re-calculate the hash
+        * chain. Fortunatelly the qp_in can be used to get one.
+        */
+       hash = f->hashfn(qp_in);
 #ifdef CONFIG_SMP
        /* With SMP race we have to recheck hash table, because
         * such entry could be created on other cpu, while we
@@ -247,7 +254,7 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf,
 }
 
 static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf,
-               struct inet_frags *f, void *arg, unsigned int hash)
+               struct inet_frags *f, void *arg)
 {
        struct inet_frag_queue *q;
 
@@ -255,7 +262,7 @@ static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf,
        if (q == NULL)
                return NULL;
 
-       return inet_frag_intern(nf, q, f, hash, arg);
+       return inet_frag_intern(nf, q, f, arg);
 }
 
 struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
@@ -264,7 +271,6 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
        struct inet_frag_queue *q;
        struct hlist_node *n;
 
-       read_lock(&f->lock);
        hlist_for_each_entry(q, n, &f->hash[hash], list) {
                if (q->net == nf && f->match(q, key)) {
                        atomic_inc(&q->refcnt);
@@ -274,6 +280,6 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
        }
        read_unlock(&f->lock);
 
-       return inet_frag_create(nf, f, key, hash);
+       return inet_frag_create(nf, f, key);
 }
 EXPORT_SYMBOL(inet_frag_find);
index 4a4d49fca1f2518a12eebbfbae02211eace06a19..cfd034a2b96ed7926f5139aeb161a58ba1820b2f 100644 (file)
@@ -383,8 +383,7 @@ static int __lro_proc_skb(struct net_lro_mgr *lro_mgr, struct sk_buff *skb,
 out2: /* send aggregated SKBs to stack */
        lro_flush(lro_mgr, lro_desc);
 
-out:  /* Original SKB has to be posted to stack */
-       skb->ip_summed = lro_mgr->ip_summed;
+out:
        return 1;
 }
 
index cd6ce6ac635843e4598e5332c32256bb0ff93926..37221f65915960a8a5173b4862fcace1591fdec9 100644 (file)
@@ -229,6 +229,8 @@ static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user)
 
        arg.iph = iph;
        arg.user = user;
+
+       read_lock(&ip4_frags.lock);
        hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
 
        q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash);
index 7750c97fde7bb6bdc6ae05061b2528d3d3e31310..ffeaffc3fffe6c31c78e858b9a1fa61fe71ba03e 100644 (file)
@@ -439,8 +439,8 @@ static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,
                                     unsigned int *len)
 {
        unsigned long subid;
-       unsigned int  size;
        unsigned long *optr;
+       size_t size;
 
        size = eoc - ctx->pointer + 1;
 
index fc54a48fde1e6a6b07a157b1cc551427d226099b..1d723de18686a9ff80bb82876fac7a1ee7fb013e 100644 (file)
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/skbuff.h>
+#include <linux/scatterlist.h>
 #include <linux/splice.h>
 #include <linux/net.h>
 #include <linux/socket.h>
 #include <linux/random.h>
 #include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/swap.h>
 #include <linux/cache.h>
 #include <linux/err.h>
 #include <linux/crypto.h>
@@ -1206,7 +1209,8 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
                return -ENOTCONN;
        while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) {
                if (offset < skb->len) {
-                       size_t used, len;
+                       int used;
+                       size_t len;
 
                        len = skb->len - offset;
                        /* Stop reading if we hit a patch of urgent data */
@@ -2620,7 +2624,7 @@ __setup("thash_entries=", set_thash_entries);
 void __init tcp_init(void)
 {
        struct sk_buff *skb = NULL;
-       unsigned long limit;
+       unsigned long nr_pages, limit;
        int order, i, max_share;
 
        BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
@@ -2689,8 +2693,9 @@ void __init tcp_init(void)
         * is up to 1/2 at 256 MB, decreasing toward zero with the amount of
         * memory, with a floor of 128 pages.
         */
-       limit = min(nr_all_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
-       limit = (limit * (nr_all_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
+       nr_pages = totalram_pages - totalhigh_pages;
+       limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT);
+       limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11);
        limit = max(limit, 128UL);
        sysctl_tcp_mem[0] = limit / 4 * 3;
        sysctl_tcp_mem[1] = limit;
index 12695be2c255a2ac4baeb5aa049dd16f41fb7bf9..ffe869ac1bcf15b51abd801b3b3b4533da0b530e 100644 (file)
@@ -2291,7 +2291,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
        }
 
        seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
-                       "%08X %5d %8d %lu %d %p %u %u %u %u %d%n",
+                       "%08X %5d %8d %lu %d %p %lu %lu %u %u %d%n",
                i, src, srcp, dest, destp, sk->sk_state,
                tp->write_seq - tp->snd_una,
                sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog :
@@ -2303,8 +2303,8 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
                icsk->icsk_probes_out,
                sock_i_ino(sk),
                atomic_read(&sk->sk_refcnt), sk,
-               icsk->icsk_rto,
-               icsk->icsk_ack.ato,
+               jiffies_to_clock_t(icsk->icsk_rto),
+               jiffies_to_clock_t(icsk->icsk_ack.ato),
                (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
                tp->snd_cwnd,
                tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh,
index 5ff0ce6e9d39d25538f5c98dff986231fbaebcc9..7ddc30f0744ff13afe250c37f000fe46d144efcc 100644 (file)
@@ -224,7 +224,7 @@ static __init int tcpprobe_init(void)
        if (bufsize < 0)
                return -EINVAL;
 
-       tcp_probe.log = kcalloc(sizeof(struct tcp_log), bufsize, GFP_KERNEL);
+       tcp_probe.log = kcalloc(bufsize, sizeof(struct tcp_log), GFP_KERNEL);
        if (!tcp_probe.log)
                goto err0;
 
index 147588f4c7c05e1ef5cafb776931840912d8adba..ff61a5cdb0b3c9a927205f34ef355a0b8812ff72 100644 (file)
@@ -749,12 +749,12 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
        }
        write_unlock_bh(&idev->lock);
 
+       addrconf_del_timer(ifp);
+
        ipv6_ifa_notify(RTM_DELADDR, ifp);
 
        atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp);
 
-       addrconf_del_timer(ifp);
-
        /*
         * Purge or update corresponding prefix
         *
index 3cd1c993d52b8fa6988c84140ca9fc387e55f312..dcf94fdfb863889bf1a9729010f4ffa3a6c3696a 100644 (file)
@@ -445,7 +445,7 @@ looped_back:
                        kfree_skb(skb);
                        return -1;
                }
-               if (!ipv6_chk_home_addr(&init_net, addr)) {
+               if (!ipv6_chk_home_addr(dev_net(skb->dst->dev), addr)) {
                        IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
                                         IPSTATS_MIB_INADDRERRORS);
                        kfree_skb(skb);
index 27a5e8b48d93a27fababd4d79fb998903d039422..f405cea21a8b89687558c83deb094d7c1940631e 100644 (file)
@@ -129,7 +129,7 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = {
                .priority       = NF_IP6_PRI_MANGLE,
        },
        {
-               .hook           = ip6t_local_hook,
+               .hook           = ip6t_route_hook,
                .owner          = THIS_MODULE,
                .pf             = PF_INET6,
                .hooknum        = NF_INET_LOCAL_IN,
index e65e26e210ee3a66873f6d472fdca708559fb0a2..cf20bc4fd60db346eab94b35ec3b84ee255dd265 100644 (file)
@@ -207,9 +207,10 @@ fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst)
        arg.id = id;
        arg.src = src;
        arg.dst = dst;
+
+       read_lock_bh(&nf_frags.lock);
        hash = ip6qhashfn(id, src, dst);
 
-       local_bh_disable();
        q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash);
        local_bh_enable();
        if (q == NULL)
index 798cabc7535b747d9193ce20e1dce1907e18eb8f..a60d7d1297137880de4294999966f3cb487ec16c 100644 (file)
@@ -247,6 +247,8 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst,
        arg.id = id;
        arg.src = src;
        arg.dst = dst;
+
+       read_lock(&ip6_frags.lock);
        hash = ip6qhashfn(id, src, dst);
 
        q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash);
index d1f3e19b06c79ade99a6b34eb385ee15753c6c77..7ff687020fa9ee780042ddeeb080e3ebb20f8199 100644 (file)
@@ -240,7 +240,7 @@ static inline int rt6_need_strict(struct in6_addr *daddr)
 static inline struct rt6_info *rt6_device_match(struct net *net,
                                                    struct rt6_info *rt,
                                                    int oif,
-                                                   int strict)
+                                                   int flags)
 {
        struct rt6_info *local = NULL;
        struct rt6_info *sprt;
@@ -253,7 +253,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
                        if (dev->flags & IFF_LOOPBACK) {
                                if (sprt->rt6i_idev == NULL ||
                                    sprt->rt6i_idev->dev->ifindex != oif) {
-                                       if (strict && oif)
+                                       if (flags & RT6_LOOKUP_F_IFACE && oif)
                                                continue;
                                        if (local && (!oif ||
                                                      local->rt6i_idev->dev->ifindex == oif))
@@ -266,7 +266,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
                if (local)
                        return local;
 
-               if (strict)
+               if (flags & RT6_LOOKUP_F_IFACE)
                        return net->ipv6.ip6_null_entry;
        }
        return rt;
index cb46749d4c326a3e7133537b70ed3cccce82eb9d..40ea9c36d24bff0426a807a9f200b0de08362c39 100644 (file)
@@ -2036,7 +2036,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
 
        seq_printf(seq,
                   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-                  "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d\n",
+                  "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %lu %lu %u %u %d\n",
                   i,
                   src->s6_addr32[0], src->s6_addr32[1],
                   src->s6_addr32[2], src->s6_addr32[3], srcp,
@@ -2052,8 +2052,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
                   icsk->icsk_probes_out,
                   sock_i_ino(sp),
                   atomic_read(&sp->sk_refcnt), sp,
-                  icsk->icsk_rto,
-                  icsk->icsk_ack.ato,
+                  jiffies_to_clock_t(icsk->icsk_rto),
+                  jiffies_to_clock_t(icsk->icsk_ack.ato),
                   (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong,
                   tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
                   );
index 9e1fb82e322005a3749d4213c91612eadb73d1c3..2f05ec1037ab32322838dfd2cf851e66050ceb0c 100644 (file)
@@ -101,8 +101,8 @@ static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info)
 
        hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
                          &irda_nl_family, 0,  IRDA_NL_CMD_GET_MODE);
-       if (IS_ERR(hdr)) {
-               ret = PTR_ERR(hdr);
+       if (hdr == NULL) {
+               ret = -EMSGSIZE;
                goto err_out;
        }
 
index 7b0038f45b168c3aab1e2f236dd62584542c0331..bda71015885cd2fdbfb4a0135eb82445854d9e08 100644 (file)
@@ -1135,8 +1135,7 @@ static void iucv_callback_txdone(struct iucv_path *path,
                if (this)
                        kfree_skb(this);
        }
-       if (!this)
-               printk(KERN_ERR "AF_IUCV msg tag %u not found\n", msg->tag);
+       BUG_ON(!this);
 
        if (sk->sk_state == IUCV_CLOSING) {
                if (skb_queue_empty(&iucv_sk(sk)->send_skb_q)) {
@@ -1196,7 +1195,7 @@ static int __init afiucv_init(void)
        }
        cpcmd("QUERY USERID", iucv_userid, sizeof(iucv_userid), &err);
        if (unlikely(err)) {
-               printk(KERN_ERR "AF_IUCV needs the VM userid\n");
+               WARN_ON(err);
                err = -EPROTONOSUPPORT;
                goto out;
        }
@@ -1210,7 +1209,6 @@ static int __init afiucv_init(void)
        err = sock_register(&iucv_sock_family_ops);
        if (err)
                goto out_proto;
-       printk(KERN_INFO "AF_IUCV lowlevel driver initialized\n");
        return 0;
 
 out_proto:
@@ -1226,8 +1224,6 @@ static void __exit afiucv_exit(void)
        sock_unregister(PF_IUCV);
        proto_unregister(&iucv_proto);
        iucv_unregister(&af_iucv_handler, 0);
-
-       printk(KERN_INFO "AF_IUCV lowlevel driver unloaded\n");
 }
 
 module_init(afiucv_init);
index 91897076213158bbad89db5f8cacc1b2b49acc74..7f82b7616212eeaa6ab04fab033510ba9b39fb8f 100644 (file)
@@ -1559,16 +1559,11 @@ static void iucv_external_interrupt(u16 code)
 
        p = iucv_irq_data[smp_processor_id()];
        if (p->ippathid >= iucv_max_pathid) {
-               printk(KERN_WARNING "iucv_do_int: Got interrupt with "
-                      "pathid %d > max_connections (%ld)\n",
-                      p->ippathid, iucv_max_pathid - 1);
+               WARN_ON(p->ippathid >= iucv_max_pathid);
                iucv_sever_pathid(p->ippathid, iucv_error_no_listener);
                return;
        }
-       if (p->iptype  < 0x01 || p->iptype > 0x09) {
-               printk(KERN_ERR "iucv_do_int: unknown iucv interrupt\n");
-               return;
-       }
+       BUG_ON(p->iptype  < 0x01 || p->iptype > 0x09);
        work = kmalloc(sizeof(struct iucv_irq_list), GFP_ATOMIC);
        if (!work) {
                printk(KERN_WARNING "iucv_external_interrupt: out of memory\n");
index 150d66dbda9d22de6ca0b94c48eab7e70c3f733f..220e83be3ef4a3dad7331f451bb95021d7c04701 100644 (file)
@@ -380,6 +380,15 @@ void ieee80211_key_free(struct ieee80211_key *key)
        if (!key)
                return;
 
+       if (!key->sdata) {
+               /* The key has not been linked yet, simply free it
+                * and don't Oops */
+               if (key->conf.alg == ALG_CCMP)
+                       ieee80211_aes_key_free(key->u.ccmp.tfm);
+               kfree(key);
+               return;
+       }
+
        spin_lock_irqsave(&key->sdata->local->key_lock, flags);
        __ieee80211_key_free(key);
        spin_unlock_irqrestore(&key->sdata->local->key_lock, flags);
index 98c0b5e56ecc02e50a754dd0b77303dac9b6160c..df0836ff1a206c4cfaf25d5ba602ed5496a95b89 100644 (file)
@@ -530,8 +530,6 @@ static int ieee80211_stop(struct net_device *dev)
                                local->sta_hw_scanning = 0;
                }
 
-               flush_workqueue(local->hw.workqueue);
-
                sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
                kfree(sdata->u.sta.extra_ie);
                sdata->u.sta.extra_ie = NULL;
@@ -555,6 +553,8 @@ static int ieee80211_stop(struct net_device *dev)
 
                ieee80211_led_radio(local, 0);
 
+               flush_workqueue(local->hw.workqueue);
+
                tasklet_disable(&local->tx_pending_tasklet);
                tasklet_disable(&local->tasklet);
        }
index 4d2b582dd05587ed46ec7b8dc7d45e708e22e1a6..b404537c0bcd1a470f4f7e305ab18c1e263c0b34 100644 (file)
@@ -547,15 +547,14 @@ static void ieee80211_set_associated(struct net_device *dev,
                        sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf;
                }
 
-               netif_carrier_on(dev);
                ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
                memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
                memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
                ieee80211_sta_send_associnfo(dev, ifsta);
        } else {
+               netif_carrier_off(dev);
                ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid);
                ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
-               netif_carrier_off(dev);
                ieee80211_reset_erp_info(dev);
 
                sdata->bss_conf.assoc_ht = 0;
@@ -569,6 +568,10 @@ static void ieee80211_set_associated(struct net_device *dev,
 
        sdata->bss_conf.assoc = assoc;
        ieee80211_bss_info_change_notify(sdata, changed);
+
+       if (assoc)
+               netif_carrier_on(dev);
+
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
        wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
 }
@@ -3611,8 +3614,10 @@ static int ieee80211_sta_find_ibss(struct net_device *dev,
        spin_unlock_bh(&local->sta_bss_lock);
 
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
-       printk(KERN_DEBUG "   sta_find_ibss: selected %s current "
-              "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid));
+       if (found)
+               printk(KERN_DEBUG "   sta_find_ibss: selected %s current "
+                      "%s\n", print_mac(mac, bssid),
+                      print_mac(mac2, ifsta->bssid));
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
        if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
            (bss = ieee80211_rx_bss_get(dev, bssid,
index 04afc13ed82551c87c2e2aa292cc00012da7520d..4ea7b97d1af1406737e94f22b85c7c2de0679d99 100644 (file)
@@ -141,7 +141,6 @@ struct rc_pid_events_file_info {
  *     rate behaviour values (lower means we should trust more what we learnt
  *     about behaviour of rates, higher means we should trust more the natural
  *     ordering of rates)
- * @fast_start: if Y, push high rates right after initialization
  */
 struct rc_pid_debugfs_entries {
        struct dentry *dir;
@@ -154,7 +153,6 @@ struct rc_pid_debugfs_entries {
        struct dentry *sharpen_factor;
        struct dentry *sharpen_duration;
        struct dentry *norm_offset;
-       struct dentry *fast_start;
 };
 
 void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf,
@@ -267,9 +265,6 @@ struct rc_pid_info {
        /* Normalization offset. */
        unsigned int norm_offset;
 
-       /* Fast starst parameter. */
-       unsigned int fast_start;
-
        /* Rates information. */
        struct rc_pid_rateinfo *rinfo;
 
index a849b745bdb56b6f83b19a98e73f069f42341621..bcd27c1d75941d8b56d1802d99d1d0209c5c1187 100644 (file)
@@ -398,13 +398,25 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local)
                return NULL;
        }
 
+       pinfo->target = RC_PID_TARGET_PF;
+       pinfo->sampling_period = RC_PID_INTERVAL;
+       pinfo->coeff_p = RC_PID_COEFF_P;
+       pinfo->coeff_i = RC_PID_COEFF_I;
+       pinfo->coeff_d = RC_PID_COEFF_D;
+       pinfo->smoothing_shift = RC_PID_SMOOTHING_SHIFT;
+       pinfo->sharpen_factor = RC_PID_SHARPENING_FACTOR;
+       pinfo->sharpen_duration = RC_PID_SHARPENING_DURATION;
+       pinfo->norm_offset = RC_PID_NORM_OFFSET;
+       pinfo->rinfo = rinfo;
+       pinfo->oldrate = 0;
+
        /* Sort the rates. This is optimized for the most common case (i.e.
         * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed
         * mapping too. */
        for (i = 0; i < sband->n_bitrates; i++) {
                rinfo[i].index = i;
                rinfo[i].rev_index = i;
-               if (pinfo->fast_start)
+               if (RC_PID_FAST_START)
                        rinfo[i].diff = 0;
                else
                        rinfo[i].diff = i * pinfo->norm_offset;
@@ -425,19 +437,6 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local)
                        break;
        }
 
-       pinfo->target = RC_PID_TARGET_PF;
-       pinfo->sampling_period = RC_PID_INTERVAL;
-       pinfo->coeff_p = RC_PID_COEFF_P;
-       pinfo->coeff_i = RC_PID_COEFF_I;
-       pinfo->coeff_d = RC_PID_COEFF_D;
-       pinfo->smoothing_shift = RC_PID_SMOOTHING_SHIFT;
-       pinfo->sharpen_factor = RC_PID_SHARPENING_FACTOR;
-       pinfo->sharpen_duration = RC_PID_SHARPENING_DURATION;
-       pinfo->norm_offset = RC_PID_NORM_OFFSET;
-       pinfo->fast_start = RC_PID_FAST_START;
-       pinfo->rinfo = rinfo;
-       pinfo->oldrate = 0;
-
 #ifdef CONFIG_MAC80211_DEBUGFS
        de = &pinfo->dentries;
        de->dir = debugfs_create_dir("rc80211_pid",
@@ -465,9 +464,6 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local)
        de->norm_offset = debugfs_create_u32("norm_offset",
                                             S_IRUSR | S_IWUSR, de->dir,
                                             &pinfo->norm_offset);
-       de->fast_start = debugfs_create_bool("fast_start",
-                                            S_IRUSR | S_IWUSR, de->dir,
-                                            &pinfo->fast_start);
 #endif
 
        return pinfo;
@@ -479,7 +475,6 @@ static void rate_control_pid_free(void *priv)
 #ifdef CONFIG_MAC80211_DEBUGFS
        struct rc_pid_debugfs_entries *de = &pinfo->dentries;
 
-       debugfs_remove(de->fast_start);
        debugfs_remove(de->norm_offset);
        debugfs_remove(de->sharpen_duration);
        debugfs_remove(de->sharpen_factor);
index 6106cb79060c928f65e7d5a5d2154f280b55bf5f..e8404212ad57ecdfda2df597a9725c73278627b4 100644 (file)
@@ -95,6 +95,13 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
                        }
                }
 
+               if (alg == ALG_WEP &&
+                       key_len != LEN_WEP40 && key_len != LEN_WEP104) {
+                       ieee80211_key_free(key);
+                       err = -EINVAL;
+                       goto out_unlock;
+               }
+
                ieee80211_key_link(key, sdata, sta);
 
                if (set_tx_key || (!sta && !sdata->default_key && key))
index 635b996c8c350c52c5f9cef6747c3408e3e40711..5d09e8698b57584cb66bbc83e96295955c68c360 100644 (file)
@@ -323,8 +323,7 @@ static void wme_qdiscop_destroy(struct Qdisc* qd)
        struct ieee80211_hw *hw = &local->hw;
        int queue;
 
-       tcf_destroy_chain(q->filter_list);
-       q->filter_list = NULL;
+       tcf_destroy_chain(&q->filter_list);
 
        for (queue=0; queue < hw->queues; queue++) {
                skb_queue_purge(&q->requeued[queue]);
index ba94004fe323182b6a527507548a1e54e1099321..dd28fb239a60438b28ed3c90b9f5d979c8c6b700 100644 (file)
@@ -331,12 +331,13 @@ static unsigned int get_conntrack_index(const struct tcphdr *tcph)
 
    I.   Upper bound for valid data:    seq <= sender.td_maxend
    II.  Lower bound for valid data:    seq + len >= sender.td_end - receiver.td_maxwin
-   III.        Upper bound for valid ack:      sack <= receiver.td_end
-   IV. Lower bound for valid ack:      ack >= receiver.td_end - MAXACKWINDOW
+   III.        Upper bound for valid (s)ack:   sack <= receiver.td_end
+   IV. Lower bound for valid (s)ack:   sack >= receiver.td_end - MAXACKWINDOW
 
-   where sack is the highest right edge of sack block found in the packet.
+   where sack is the highest right edge of sack block found in the packet
+   or ack in the case of packet without SACK option.
 
-   The upper bound limit for a valid ack is not ignored -
+   The upper bound limit for a valid (s)ack is not ignored -
    we doesn't have to deal with fragments.
 */
 
@@ -606,12 +607,12 @@ static bool tcp_in_window(const struct nf_conn *ct,
                 before(seq, sender->td_maxend + 1),
                 after(end, sender->td_end - receiver->td_maxwin - 1),
                 before(sack, receiver->td_end + 1),
-                after(ack, receiver->td_end - MAXACKWINDOW(sender)));
+                after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1));
 
        if (before(seq, sender->td_maxend + 1) &&
            after(end, sender->td_end - receiver->td_maxwin - 1) &&
            before(sack, receiver->td_end + 1) &&
-           after(ack, receiver->td_end - MAXACKWINDOW(sender))) {
+           after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1)) {
                /*
                 * Take into account window scaling (RFC 1323).
                 */
@@ -843,9 +844,15 @@ static int tcp_packet(struct nf_conn *ct,
                        /* Attempt to reopen a closed/aborted connection.
                         * Delete this connection and look up again. */
                        write_unlock_bh(&tcp_lock);
-                       if (del_timer(&ct->timeout))
+                       /* Only repeat if we can actually remove the timer.
+                        * Destruction may already be in progress in process
+                        * context and we must give it a chance to terminate.
+                        */
+                       if (del_timer(&ct->timeout)) {
                                ct->timeout.function((unsigned long)ct);
-                       return -NF_REPEAT;
+                               return -NF_REPEAT;
+                       }
+                       return -NF_DROP;
                }
                /* Fall through */
        case TCP_CONNTRACK_IGNORE:
index fdc14a0d21af8fce47ced5d63fc8af46453851a5..9080c61b71a5633a7b4b49199db9b83a4c26559e 100644 (file)
@@ -584,12 +584,7 @@ list_start:
        rcu_read_unlock();
 
        genlmsg_end(ans_skb, data);
-
-       ret_val = genlmsg_reply(ans_skb, info);
-       if (ret_val != 0)
-               goto list_failure;
-
-       return 0;
+       return genlmsg_reply(ans_skb, info);
 
 list_retry:
        /* XXX - this limit is a guesstimate */
index 22c19126780899b464b70f3f4e545b29f1e51f65..44be5d5261f4670005f44276f5fb5a257fe97538 100644 (file)
@@ -386,11 +386,7 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
        rcu_read_unlock();
 
        genlmsg_end(ans_skb, data);
-
-       ret_val = genlmsg_reply(ans_skb, info);
-       if (ret_val != 0)
-               goto listdef_failure;
-       return 0;
+       return genlmsg_reply(ans_skb, info);
 
 listdef_failure_lock:
        rcu_read_unlock();
@@ -501,11 +497,7 @@ static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info)
                goto version_failure;
 
        genlmsg_end(ans_skb, data);
-
-       ret_val = genlmsg_reply(ans_skb, info);
-       if (ret_val != 0)
-               goto version_failure;
-       return 0;
+       return genlmsg_reply(ans_skb, info);
 
 version_failure:
        kfree_skb(ans_skb);
index 0099da5b2591e5295429b7578688fa6949db3db1..56f80872924e88e5b007b004db93572382c94cd1 100644 (file)
@@ -1107,11 +1107,7 @@ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
                goto list_failure;
 
        genlmsg_end(ans_skb, data);
-
-       ret_val = genlmsg_reply(ans_skb, info);
-       if (ret_val != 0)
-               goto list_failure;
-       return 0;
+       return genlmsg_reply(ans_skb, info);
 
 list_failure:
        kfree_skb(ans_skb);
@@ -1534,7 +1530,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
                }
        }
        list_for_each_entry_rcu(addr6, &iface->addr6_list, list) {
-               if (addr6->valid || iter_addr6++ < skip_addr6)
+               if (!addr6->valid || iter_addr6++ < skip_addr6)
                        continue;
                if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
                                           iface,
index 9b97f8006c9c6edfd0dea0dde522b6a7e64c171f..349aba189558669c9ddd8ac82ad585d1fb23d557 100644 (file)
@@ -886,7 +886,7 @@ retry:
                return netlink_unicast_kernel(sk, skb);
 
        if (sk_filter(sk, skb)) {
-               int err = skb->len;
+               err = skb->len;
                kfree_skb(skb);
                sock_put(sk);
                return err;
index 47bbf45ae5d7905e05487955d77832e03915f215..2d106cfe1d276bf5e234195753eb091cba7b7f1e 100644 (file)
@@ -132,6 +132,7 @@ errout:
  * @maxtype: maximum attribute type to be expected
  * @head: head of attribute stream
  * @len: length of attribute stream
+ * @policy: validation policy
  *
  * Parses a stream of attributes and stores a pointer to each attribute in
  * the tb array accessable via the attribute type. Attributes with a type
@@ -194,7 +195,7 @@ struct nlattr *nla_find(struct nlattr *head, int len, int attrtype)
 /**
  * nla_strlcpy - Copy string attribute payload into a sized buffer
  * @dst: where to copy the string to
- * @src: attribute to copy the string from
+ * @nla: attribute to copy the string from
  * @dstsize: size of destination buffer
  *
  * Copies at most dstsize - 1 bytes into the destination buffer.
@@ -340,9 +341,9 @@ struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
 }
 
 /**
- * nla_reserve - reserve room for attribute without header
+ * nla_reserve_nohdr - reserve room for attribute without header
  * @skb: socket buffer to reserve room on
- * @len: length of attribute payload
+ * @attrlen: length of attribute payload
  *
  * Reserves room for attribute payload without a header.
  *
index 82adfe6447d7db004c7108731e0ad4c7b87f8657..9437b27ff84de101b88b3cbe08675f002e562238 100644 (file)
@@ -106,17 +106,6 @@ config NET_SCH_PRIO
          To compile this code as a module, choose M here: the
          module will be called sch_prio.
 
-config NET_SCH_RR
-       tristate "Multi Band Round Robin Queuing (RR)"
-       select NET_SCH_PRIO
-       ---help---
-         Say Y here if you want to use an n-band round robin packet
-         scheduler.
-
-         The module uses sch_prio for its framework and is aliased as
-         sch_rr, so it will load sch_prio, although it is referred
-         to using sch_rr.
-
 config NET_SCH_RED
        tristate "Random Early Detection (RED)"
        ---help---
index c40773cdbe45466c8bead7bfd58c0fde73fc6c76..10f01ad043800589f9d2eebd994c7f8de86ce19b 100644 (file)
@@ -1252,12 +1252,12 @@ void tcf_destroy(struct tcf_proto *tp)
        kfree(tp);
 }
 
-void tcf_destroy_chain(struct tcf_proto *fl)
+void tcf_destroy_chain(struct tcf_proto **fl)
 {
        struct tcf_proto *tp;
 
-       while ((tp = fl) != NULL) {
-               fl = tp->next;
+       while ((tp = *fl) != NULL) {
+               *fl = tp->next;
                tcf_destroy(tp);
        }
 }
index 33527341638427c3bf9e97385a7f7d5ba37f07d8..db0e23ae85f8fb048c81e654ecbe8524fbf08f43 100644 (file)
@@ -160,7 +160,7 @@ static void atm_tc_put(struct Qdisc *sch, unsigned long cl)
        *prev = flow->next;
        pr_debug("atm_tc_put: qdisc %p\n", flow->q);
        qdisc_destroy(flow->q);
-       tcf_destroy_chain(flow->filter_list);
+       tcf_destroy_chain(&flow->filter_list);
        if (flow->sock) {
                pr_debug("atm_tc_put: f_count %d\n",
                        file_count(flow->sock->file));
@@ -586,10 +586,11 @@ static void atm_tc_destroy(struct Qdisc *sch)
        struct atm_flow_data *flow;
 
        pr_debug("atm_tc_destroy(sch %p,[qdisc %p])\n", sch, p);
+       for (flow = p->flows; flow; flow = flow->next)
+               tcf_destroy_chain(&flow->filter_list);
+
        /* races ? */
        while ((flow = p->flows)) {
-               tcf_destroy_chain(flow->filter_list);
-               flow->filter_list = NULL;
                if (flow->ref > 1)
                        printk(KERN_ERR "atm_destroy: %p->ref = %d\n", flow,
                               flow->ref);
index 09969c1fbc08f287cb8b6bbc749e8a360fb9ea26..2a3c97f7dc630a7a44864f3af7b0c15d0186791b 100644 (file)
@@ -1704,7 +1704,7 @@ static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl)
 
        BUG_TRAP(!cl->filters);
 
-       tcf_destroy_chain(cl->filter_list);
+       tcf_destroy_chain(&cl->filter_list);
        qdisc_destroy(cl->q);
        qdisc_put_rtab(cl->R_tab);
        gen_kill_estimator(&cl->bstats, &cl->rate_est);
@@ -1728,10 +1728,8 @@ cbq_destroy(struct Qdisc* sch)
         * be bound to classes which have been destroyed already. --TGR '04
         */
        for (h = 0; h < 16; h++) {
-               for (cl = q->classes[h]; cl; cl = cl->next) {
-                       tcf_destroy_chain(cl->filter_list);
-                       cl->filter_list = NULL;
-               }
+               for (cl = q->classes[h]; cl; cl = cl->next)
+                       tcf_destroy_chain(&cl->filter_list);
        }
        for (h = 0; h < 16; h++) {
                struct cbq_class *next;
index 64465bacbe79e62c9515150b4baa44fa2d6bcff3..c4c1317cd47db91c56310db02bf933f3b521e722 100644 (file)
@@ -416,7 +416,7 @@ static void dsmark_destroy(struct Qdisc *sch)
 
        pr_debug("dsmark_destroy(sch %p,[qdisc %p])\n", sch, p);
 
-       tcf_destroy_chain(p->filter_list);
+       tcf_destroy_chain(&p->filter_list);
        qdisc_destroy(p->q);
        kfree(p->mask);
 }
index d355e5e47fe3a71aca1d151db1ce72429a069297..13afa7214392a74998ebbad3576ae4bb7a6d4638 100644 (file)
@@ -468,7 +468,7 @@ struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops)
 
        return sch;
 errout:
-       return ERR_PTR(-err);
+       return ERR_PTR(err);
 }
 
 struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops,
index fdfaa3fcc16d861ed2b14dc3511bea66cf206611..e817aa00441d4a7b5a647450405e202f485bdc88 100644 (file)
@@ -1123,7 +1123,7 @@ hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl)
 {
        struct hfsc_sched *q = qdisc_priv(sch);
 
-       tcf_destroy_chain(cl->filter_list);
+       tcf_destroy_chain(&cl->filter_list);
        qdisc_destroy(cl->qdisc);
        gen_kill_estimator(&cl->bstats, &cl->rate_est);
        if (cl != &q->root)
@@ -1540,6 +1540,10 @@ hfsc_destroy_qdisc(struct Qdisc *sch)
        struct hfsc_class *cl, *next;
        unsigned int i;
 
+       for (i = 0; i < HFSC_HSIZE; i++) {
+               list_for_each_entry(cl, &q->clhash[i], hlist)
+                       tcf_destroy_chain(&cl->filter_list);
+       }
        for (i = 0; i < HFSC_HSIZE; i++) {
                list_for_each_entry_safe(cl, next, &q->clhash[i], hlist)
                        hfsc_destroy_class(sch, cl);
index 6807c97985a54adac52ceb42d4b3847e0beebdd2..3fb58f428f724ca9a8fd8c6cd9a41450df567c4d 100644 (file)
@@ -1238,7 +1238,7 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
        qdisc_put_rtab(cl->rate);
        qdisc_put_rtab(cl->ceil);
 
-       tcf_destroy_chain(cl->filter_list);
+       tcf_destroy_chain(&cl->filter_list);
 
        while (!list_empty(&cl->children))
                htb_destroy_class(sch, list_entry(cl->children.next,
@@ -1267,7 +1267,7 @@ static void htb_destroy(struct Qdisc *sch)
           and surprisingly it worked in 2.4. But it must precede it
           because filter need its target class alive to be able to call
           unbind_filter on it (without Oops). */
-       tcf_destroy_chain(q->filter_list);
+       tcf_destroy_chain(&q->filter_list);
 
        while (!list_empty(&q->root))
                htb_destroy_class(sch, list_entry(q->root.next,
index 274b1ddb160c3956da169dd1bbc7da5e5f482637..956c80ad59654caa20fe7a805418f02992209465 100644 (file)
@@ -104,7 +104,7 @@ static void ingress_destroy(struct Qdisc *sch)
 {
        struct ingress_qdisc_data *p = qdisc_priv(sch);
 
-       tcf_destroy_chain(p->filter_list);
+       tcf_destroy_chain(&p->filter_list);
 }
 
 static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
index 4aa2b45dad0a80232ed1d1d1c2fbabf33b19ec8f..5532f1031ab52fd3276f37b383967986de070ea9 100644 (file)
@@ -219,7 +219,7 @@ prio_destroy(struct Qdisc* sch)
        int prio;
        struct prio_sched_data *q = qdisc_priv(sch);
 
-       tcf_destroy_chain(q->filter_list);
+       tcf_destroy_chain(&q->filter_list);
        for (prio=0; prio<q->bands; prio++)
                qdisc_destroy(q->queues[prio]);
 }
index f0463d757a98489f5b12138c0026d1b91742fd9d..6a97afbfb95245cc019f371606f36884e4e63b25 100644 (file)
@@ -520,7 +520,7 @@ static void sfq_destroy(struct Qdisc *sch)
 {
        struct sfq_sched_data *q = qdisc_priv(sch);
 
-       tcf_destroy_chain(q->filter_list);
+       tcf_destroy_chain(&q->filter_list);
        q->perturb_period = 0;
        del_timer_sync(&q->perturb_timer);
 }
index 0c9d5a6950fe0c5842076fba62f54b58b497f105..fcdb45d1071bb9c0ca90c7b680145b5521c87f1d 100644 (file)
@@ -5899,12 +5899,6 @@ static int sctp_eat_data(const struct sctp_association *asoc,
                return SCTP_IERROR_NO_DATA;
        }
 
-       /* If definately accepting the DATA chunk, record its TSN, otherwise
-        * wait for renege processing.
-        */
-       if (SCTP_CMD_CHUNK_ULP == deliver)
-               sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
-
        chunk->data_accepted = 1;
 
        /* Note: Some chunks may get overcounted (if we drop) or overcounted
@@ -5924,6 +5918,9 @@ static int sctp_eat_data(const struct sctp_association *asoc,
         * and discard the DATA chunk.
         */
        if (ntohs(data_hdr->stream) >= asoc->c.sinit_max_instreams) {
+               /* Mark tsn as received even though we drop it */
+               sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
+
                err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
                                         &data_hdr->stream,
                                         sizeof(data_hdr->stream));
index ce6cda6b6994daaf5e1a64c09fdb31c126e07b5b..a1f654aea2687ea740a48596a927486869bb7f65 100644 (file)
@@ -710,6 +710,11 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
        if (!skb)
                goto fail;
 
+       /* Now that all memory allocations for this chunk succeeded, we
+        * can mark it as received so the tsn_map is updated correctly.
+        */
+       sctp_tsnmap_mark(&asoc->peer.tsn_map, ntohl(chunk->subh.data_hdr->tsn));
+
        /* First calculate the padding, so we don't inadvertently
         * pass up the wrong length to the user.
         *
index 5905d56737d6052a6ea10afbe975e9349a8530d0..81ae3d62a0cc9010d4cc1b6e5de130ae64ca2a57 100644 (file)
@@ -1144,20 +1144,20 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
                case RPC_GSS_SVC_NONE:
                        break;
                case RPC_GSS_SVC_INTEGRITY:
+                       /* placeholders for length and seq. number: */
+                       svc_putnl(resv, 0);
+                       svc_putnl(resv, 0);
                        if (unwrap_integ_data(&rqstp->rq_arg,
                                        gc->gc_seq, rsci->mechctx))
                                goto garbage_args;
+                       break;
+               case RPC_GSS_SVC_PRIVACY:
                        /* placeholders for length and seq. number: */
                        svc_putnl(resv, 0);
                        svc_putnl(resv, 0);
-                       break;
-               case RPC_GSS_SVC_PRIVACY:
                        if (unwrap_priv_data(rqstp, &rqstp->rq_arg,
                                        gc->gc_seq, rsci->mechctx))
                                goto garbage_args;
-                       /* placeholders for length and seq. number: */
-                       svc_putnl(resv, 0);
-                       svc_putnl(resv, 0);
                        break;
                default:
                        goto auth_err;
@@ -1170,8 +1170,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
                goto out;
        }
 garbage_args:
-       /* Restore write pointer to its original value: */
-       xdr_ressize_check(rqstp, reject_stat);
        ret = SVC_GARBAGE;
        goto out;
 auth_err:
index 0517967a68bf85571919923e9935658d4c63e6f3..e6fb21b19b86b6421011f76400e74e5d2a919acc 100644 (file)
@@ -243,10 +243,10 @@ int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
 }
 EXPORT_SYMBOL_GPL(rpcb_getport_sync);
 
-static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, int version)
+static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, struct rpc_procinfo *proc)
 {
        struct rpc_message msg = {
-               .rpc_proc = rpcb_next_version[version].rpc_proc,
+               .rpc_proc = proc,
                .rpc_argp = map,
                .rpc_resp = &map->r_port,
        };
@@ -271,6 +271,7 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
 void rpcb_getport_async(struct rpc_task *task)
 {
        struct rpc_clnt *clnt = task->tk_client;
+       struct rpc_procinfo *proc;
        u32 bind_version;
        struct rpc_xprt *xprt = task->tk_xprt;
        struct rpc_clnt *rpcb_clnt;
@@ -280,7 +281,6 @@ void rpcb_getport_async(struct rpc_task *task)
        struct sockaddr *sap = (struct sockaddr *)&addr;
        size_t salen;
        int status;
-       struct rpcb_info *info;
 
        dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
                task->tk_pid, __func__,
@@ -313,10 +313,12 @@ void rpcb_getport_async(struct rpc_task *task)
        /* Don't ever use rpcbind v2 for AF_INET6 requests */
        switch (sap->sa_family) {
        case AF_INET:
-               info = rpcb_next_version;
+               proc = rpcb_next_version[xprt->bind_index].rpc_proc;
+               bind_version = rpcb_next_version[xprt->bind_index].rpc_vers;
                break;
        case AF_INET6:
-               info = rpcb_next_version6;
+               proc = rpcb_next_version6[xprt->bind_index].rpc_proc;
+               bind_version = rpcb_next_version6[xprt->bind_index].rpc_vers;
                break;
        default:
                status = -EAFNOSUPPORT;
@@ -324,14 +326,13 @@ void rpcb_getport_async(struct rpc_task *task)
                                task->tk_pid, __func__);
                goto bailout_nofree;
        }
-       if (info[xprt->bind_index].rpc_proc == NULL) {
+       if (proc == NULL) {
                xprt->bind_index = 0;
                status = -EPFNOSUPPORT;
                dprintk("RPC: %5u %s: no more getport versions available\n",
                        task->tk_pid, __func__);
                goto bailout_nofree;
        }
-       bind_version = info[xprt->bind_index].rpc_vers;
 
        dprintk("RPC: %5u %s: trying rpcbind version %u\n",
                task->tk_pid, __func__, bind_version);
@@ -361,22 +362,20 @@ void rpcb_getport_async(struct rpc_task *task)
        map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR);
        map->r_owner = RPCB_OWNER_STRING;       /* ignored for GETADDR */
 
-       child = rpcb_call_async(rpcb_clnt, map, xprt->bind_index);
+       child = rpcb_call_async(rpcb_clnt, map, proc);
        rpc_release_client(rpcb_clnt);
        if (IS_ERR(child)) {
                status = -EIO;
+               /* rpcb_map_release() has freed the arguments */
                dprintk("RPC: %5u %s: rpc_run_task failed\n",
                        task->tk_pid, __func__);
-               goto bailout;
+               goto bailout_nofree;
        }
        rpc_put_task(child);
 
        task->tk_xprt->stat.bind_count++;
        return;
 
-bailout:
-       kfree(map);
-       xprt_put(xprt);
 bailout_nofree:
        rpcb_wake_rpcbind_waiters(xprt, status);
 bailout_nowake:
index 657835f227d342a2eadc4498c6076b7c435839ac..783317dacd3090f7d602b3c56e82859f3cc22a46 100644 (file)
@@ -487,8 +487,8 @@ static int unix_socketpair(struct socket *, struct socket *);
 static int unix_accept(struct socket *, struct socket *, int);
 static int unix_getname(struct socket *, struct sockaddr *, int *, int);
 static unsigned int unix_poll(struct file *, struct socket *, poll_table *);
-static unsigned int unix_datagram_poll(struct file *, struct socket *,
-                                      poll_table *);
+static unsigned int unix_dgram_poll(struct file *, struct socket *,
+                                   poll_table *);
 static int unix_ioctl(struct socket *, unsigned int, unsigned long);
 static int unix_shutdown(struct socket *, int);
 static int unix_stream_sendmsg(struct kiocb *, struct socket *,
@@ -534,7 +534,7 @@ static const struct proto_ops unix_dgram_ops = {
        .socketpair =   unix_socketpair,
        .accept =       sock_no_accept,
        .getname =      unix_getname,
-       .poll =         unix_datagram_poll,
+       .poll =         unix_dgram_poll,
        .ioctl =        unix_ioctl,
        .listen =       sock_no_listen,
        .shutdown =     unix_shutdown,
@@ -555,7 +555,7 @@ static const struct proto_ops unix_seqpacket_ops = {
        .socketpair =   unix_socketpair,
        .accept =       unix_accept,
        .getname =      unix_getname,
-       .poll =         unix_datagram_poll,
+       .poll =         unix_dgram_poll,
        .ioctl =        unix_ioctl,
        .listen =       unix_listen,
        .shutdown =     unix_shutdown,
@@ -1994,29 +1994,13 @@ static unsigned int unix_poll(struct file * file, struct socket *sock, poll_tabl
        return mask;
 }
 
-static unsigned int unix_datagram_poll(struct file *file, struct socket *sock,
-                                      poll_table *wait)
+static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
+                                   poll_table *wait)
 {
-       struct sock *sk = sock->sk, *peer;
-       unsigned int mask;
+       struct sock *sk = sock->sk, *other;
+       unsigned int mask, writable;
 
        poll_wait(file, sk->sk_sleep, wait);
-
-       peer = unix_peer_get(sk);
-       if (peer) {
-               if (peer != sk) {
-                       /*
-                        * Writability of a connected socket additionally
-                        * depends on the state of the receive queue of the
-                        * peer.
-                        */
-                       poll_wait(file, &unix_sk(peer)->peer_wait, wait);
-               } else {
-                       sock_put(peer);
-                       peer = NULL;
-               }
-       }
-
        mask = 0;
 
        /* exceptional events? */
@@ -2042,14 +2026,26 @@ static unsigned int unix_datagram_poll(struct file *file, struct socket *sock,
        }
 
        /* writable? */
-       if (unix_writable(sk) && !(peer && unix_recvq_full(peer)))
+       writable = unix_writable(sk);
+       if (writable) {
+               other = unix_peer_get(sk);
+               if (other) {
+                       if (unix_peer(other) != sk) {
+                               poll_wait(file, &unix_sk(other)->peer_wait,
+                                         wait);
+                               if (unix_recvq_full(other))
+                                       writable = 0;
+                       }
+
+                       sock_put(other);
+               }
+       }
+
+       if (writable)
                mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
        else
                set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
 
-       if (peer)
-               sock_put(peer);
-
        return mask;
 }
 
index 185488da246647c06bd85261f856a71fed182c34..855bff4b3250a0eb04b094b5fca6c5512ecb35b1 100644 (file)
@@ -80,6 +80,23 @@ static const struct ieee80211_channel_range ieee80211_JP_channels[] = {
                                     IEEE80211_CHAN_RADAR),
 };
 
+static const struct ieee80211_channel_range ieee80211_EU_channels[] = {
+       /* IEEE 802.11b/g, channels 1..13 */
+       RANGE_PWR(2412, 2472, 20, 6, 0),
+       /* IEEE 802.11a, channel 36*/
+       RANGE_PWR(5180, 5180, 23, 6, IEEE80211_CHAN_PASSIVE_SCAN),
+       /* IEEE 802.11a, channel 40*/
+       RANGE_PWR(5200, 5200, 23, 6, IEEE80211_CHAN_PASSIVE_SCAN),
+       /* IEEE 802.11a, channel 44*/
+       RANGE_PWR(5220, 5220, 23, 6, IEEE80211_CHAN_PASSIVE_SCAN),
+       /* IEEE 802.11a, channels 48..64 */
+       RANGE_PWR(5240, 5320, 23, 6, IEEE80211_CHAN_NO_IBSS |
+                                    IEEE80211_CHAN_RADAR),
+       /* IEEE 802.11a, channels 100..140 */
+       RANGE_PWR(5500, 5700, 30, 6, IEEE80211_CHAN_NO_IBSS |
+                                    IEEE80211_CHAN_RADAR),
+};
+
 #define REGDOM(_code)                                                  \
        {                                                               \
                .code = __stringify(_code),                             \
@@ -90,6 +107,7 @@ static const struct ieee80211_channel_range ieee80211_JP_channels[] = {
 static const struct ieee80211_regdomain ieee80211_regdoms[] = {
        REGDOM(US),
        REGDOM(JP),
+       REGDOM(EU),
 };
 
 
index b976d9ed10e45a3a2e410a6b873f9128a18f6021..04c41504f84c44b8b84d8be9b6cc602d568d3ce1 100644 (file)
@@ -277,9 +277,8 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
        memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr));
        x->props.flags = p->flags;
 
-       if (!x->sel.family)
+       if (!x->sel.family && !(p->flags & XFRM_STATE_AF_UNSPEC))
                x->sel.family = p->family;
-
 }
 
 /*
index cea4a790e1e97170459576b8b68c94daf3e95cc9..37d5c363fbcd8f0008044a08414721f9710c7442 100644 (file)
@@ -304,6 +304,14 @@ static int do_ap_entry(const char *filename,
        return 1;
 }
 
+/* looks like: "css:tN" */
+static int do_css_entry(const char *filename,
+                       struct css_device_id *id, char *alias)
+{
+       sprintf(alias, "css:t%01X", id->type);
+       return 1;
+}
+
 /* Looks like: "serio:tyNprNidNexN" */
 static int do_serio_entry(const char *filename,
                          struct serio_device_id *id, char *alias)
@@ -680,6 +688,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
                do_table(symval, sym->st_size,
                         sizeof(struct ap_device_id), "ap",
                         do_ap_entry, mod);
+       else if (sym_is(symname, "__mod_css_device_table"))
+               do_table(symval, sym->st_size,
+                        sizeof(struct css_device_id), "css",
+                        do_css_entry, mod);
        else if (sym_is(symname, "__mod_serio_device_table"))
                do_table(symval, sym->st_size,
                         sizeof(struct serio_device_id), "serio",
index 49b51f964897dcb7133be9b58f1b936462bb6309..62ed4717d334f3f10de514aa4b9e088f4b2ca827 100644 (file)
@@ -73,17 +73,9 @@ config SECURITY_NETWORK_XFRM
          IPSec.
          If you are unsure how to answer this question, answer N.
 
-config SECURITY_CAPABILITIES
-       bool "Default Linux Capabilities"
-       depends on SECURITY
-       default y
-       help
-         This enables the "default" Linux capabilities functionality.
-         If you are unsure how to answer this question, answer Y.
-
 config SECURITY_FILE_CAPABILITIES
        bool "File POSIX Capabilities (EXPERIMENTAL)"
-       depends on (SECURITY=n || SECURITY_CAPABILITIES!=n) && EXPERIMENTAL
+       depends on EXPERIMENTAL
        default n
        help
          This enables filesystem capabilities, allowing you to give
index 7ef1107a72875412e3cdc52f48fe609f7dfbc764..f65426099aa625be9aac60a1a009ea860956dbb7 100644 (file)
@@ -6,16 +6,13 @@ obj-$(CONFIG_KEYS)                    += keys/
 subdir-$(CONFIG_SECURITY_SELINUX)      += selinux
 subdir-$(CONFIG_SECURITY_SMACK)                += smack
 
-# if we don't select a security model, use the default capabilities
-ifneq ($(CONFIG_SECURITY),y)
+# always enable default capabilities
 obj-y          += commoncap.o
-endif
 
 # Object file lists
-obj-$(CONFIG_SECURITY)                 += security.o dummy.o inode.o
+obj-$(CONFIG_SECURITY)                 += security.o capability.o inode.o
 # Must precede capability.o in order to stack properly.
 obj-$(CONFIG_SECURITY_SELINUX)         += selinux/built-in.o
-obj-$(CONFIG_SECURITY_SMACK)           += commoncap.o smack/built-in.o
-obj-$(CONFIG_SECURITY_CAPABILITIES)    += commoncap.o capability.o
-obj-$(CONFIG_SECURITY_ROOTPLUG)                += commoncap.o root_plug.o
+obj-$(CONFIG_SECURITY_SMACK)           += smack/built-in.o
+obj-$(CONFIG_SECURITY_ROOTPLUG)                += root_plug.o
 obj-$(CONFIG_CGROUP_DEVICE)            += device_cgroup.o
index 38ac54e3aed14aebfe84f0b8e11ce4802dae845c..5b01c0b02422b28a1809ba7be383e1b93e76159f 100644 (file)
@@ -1,6 +1,8 @@
 /*
  *  Capabilities Linux Security Module
  *
+ *  This is the default security module in case no other module is loaded.
+ *
  *     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
  *
  */
 
-#include <linux/init.h>
-#include <linux/kernel.h>
 #include <linux/security.h>
-#include <linux/file.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/pagemap.h>
-#include <linux/swap.h>
-#include <linux/skbuff.h>
-#include <linux/netlink.h>
-#include <linux/ptrace.h>
-#include <linux/moduleparam.h>
-
-static struct security_operations capability_ops = {
-       .ptrace =                       cap_ptrace,
-       .capget =                       cap_capget,
-       .capset_check =                 cap_capset_check,
-       .capset_set =                   cap_capset_set,
-       .capable =                      cap_capable,
-       .settime =                      cap_settime,
-       .netlink_send =                 cap_netlink_send,
-       .netlink_recv =                 cap_netlink_recv,
-
-       .bprm_apply_creds =             cap_bprm_apply_creds,
-       .bprm_set_security =            cap_bprm_set_security,
-       .bprm_secureexec =              cap_bprm_secureexec,
-
-       .inode_setxattr =               cap_inode_setxattr,
-       .inode_removexattr =            cap_inode_removexattr,
-       .inode_need_killpriv =          cap_inode_need_killpriv,
-       .inode_killpriv =               cap_inode_killpriv,
-
-       .task_setscheduler =            cap_task_setscheduler,
-       .task_setioprio =               cap_task_setioprio,
-       .task_setnice =                 cap_task_setnice,
-       .task_post_setuid =             cap_task_post_setuid,
-       .task_prctl =                   cap_task_prctl,
-       .task_reparent_to_init =        cap_task_reparent_to_init,
-
-       .syslog =                       cap_syslog,
-
-       .vm_enough_memory =             cap_vm_enough_memory,
-};
 
-/* flag to keep track of how we were registered */
-static int secondary;
+static int cap_acct(struct file *file)
+{
+       return 0;
+}
+
+static int cap_sysctl(ctl_table *table, int op)
+{
+       return 0;
+}
+
+static int cap_quotactl(int cmds, int type, int id, struct super_block *sb)
+{
+       return 0;
+}
+
+static int cap_quota_on(struct dentry *dentry)
+{
+       return 0;
+}
+
+static int cap_bprm_alloc_security(struct linux_binprm *bprm)
+{
+       return 0;
+}
+
+static void cap_bprm_free_security(struct linux_binprm *bprm)
+{
+}
+
+static void cap_bprm_post_apply_creds(struct linux_binprm *bprm)
+{
+}
+
+static int cap_bprm_check_security(struct linux_binprm *bprm)
+{
+       return 0;
+}
+
+static int cap_sb_alloc_security(struct super_block *sb)
+{
+       return 0;
+}
+
+static void cap_sb_free_security(struct super_block *sb)
+{
+}
+
+static int cap_sb_copy_data(char *orig, char *copy)
+{
+       return 0;
+}
+
+static int cap_sb_kern_mount(struct super_block *sb, void *data)
+{
+       return 0;
+}
+
+static int cap_sb_show_options(struct seq_file *m, struct super_block *sb)
+{
+       return 0;
+}
+
+static int cap_sb_statfs(struct dentry *dentry)
+{
+       return 0;
+}
+
+static int cap_sb_mount(char *dev_name, struct path *path, char *type,
+                       unsigned long flags, void *data)
+{
+       return 0;
+}
+
+static int cap_sb_check_sb(struct vfsmount *mnt, struct path *path)
+{
+       return 0;
+}
+
+static int cap_sb_umount(struct vfsmount *mnt, int flags)
+{
+       return 0;
+}
+
+static void cap_sb_umount_close(struct vfsmount *mnt)
+{
+}
+
+static void cap_sb_umount_busy(struct vfsmount *mnt)
+{
+}
+
+static void cap_sb_post_remount(struct vfsmount *mnt, unsigned long flags,
+                               void *data)
+{
+}
+
+static void cap_sb_post_addmount(struct vfsmount *mnt, struct path *path)
+{
+}
+
+static int cap_sb_pivotroot(struct path *old_path, struct path *new_path)
+{
+       return 0;
+}
+
+static void cap_sb_post_pivotroot(struct path *old_path, struct path *new_path)
+{
+}
+
+static int cap_sb_set_mnt_opts(struct super_block *sb,
+                              struct security_mnt_opts *opts)
+{
+       if (unlikely(opts->num_mnt_opts))
+               return -EOPNOTSUPP;
+       return 0;
+}
+
+static void cap_sb_clone_mnt_opts(const struct super_block *oldsb,
+                                 struct super_block *newsb)
+{
+}
+
+static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
+{
+       return 0;
+}
+
+static int cap_inode_alloc_security(struct inode *inode)
+{
+       return 0;
+}
+
+static void cap_inode_free_security(struct inode *inode)
+{
+}
+
+static int cap_inode_init_security(struct inode *inode, struct inode *dir,
+                                  char **name, void **value, size_t *len)
+{
+       return -EOPNOTSUPP;
+}
+
+static int cap_inode_create(struct inode *inode, struct dentry *dentry,
+                           int mask)
+{
+       return 0;
+}
+
+static int cap_inode_link(struct dentry *old_dentry, struct inode *inode,
+                         struct dentry *new_dentry)
+{
+       return 0;
+}
+
+static int cap_inode_unlink(struct inode *inode, struct dentry *dentry)
+{
+       return 0;
+}
+
+static int cap_inode_symlink(struct inode *inode, struct dentry *dentry,
+                            const char *name)
+{
+       return 0;
+}
+
+static int cap_inode_mkdir(struct inode *inode, struct dentry *dentry,
+                          int mask)
+{
+       return 0;
+}
+
+static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry)
+{
+       return 0;
+}
+
+static int cap_inode_mknod(struct inode *inode, struct dentry *dentry,
+                          int mode, dev_t dev)
+{
+       return 0;
+}
+
+static int cap_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
+                           struct inode *new_inode, struct dentry *new_dentry)
+{
+       return 0;
+}
+
+static int cap_inode_readlink(struct dentry *dentry)
+{
+       return 0;
+}
+
+static int cap_inode_follow_link(struct dentry *dentry,
+                                struct nameidata *nameidata)
+{
+       return 0;
+}
+
+static int cap_inode_permission(struct inode *inode, int mask,
+                               struct nameidata *nd)
+{
+       return 0;
+}
+
+static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+       return 0;
+}
+
+static int cap_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
+{
+       return 0;
+}
+
+static void cap_inode_delete(struct inode *ino)
+{
+}
+
+static void cap_inode_post_setxattr(struct dentry *dentry, const char *name,
+                                   const void *value, size_t size, int flags)
+{
+}
+
+static int cap_inode_getxattr(struct dentry *dentry, const char *name)
+{
+       return 0;
+}
+
+static int cap_inode_listxattr(struct dentry *dentry)
+{
+       return 0;
+}
+
+static int cap_inode_getsecurity(const struct inode *inode, const char *name,
+                                void **buffer, bool alloc)
+{
+       return -EOPNOTSUPP;
+}
+
+static int cap_inode_setsecurity(struct inode *inode, const char *name,
+                                const void *value, size_t size, int flags)
+{
+       return -EOPNOTSUPP;
+}
+
+static int cap_inode_listsecurity(struct inode *inode, char *buffer,
+                                 size_t buffer_size)
+{
+       return 0;
+}
+
+static void cap_inode_getsecid(const struct inode *inode, u32 *secid)
+{
+       *secid = 0;
+}
+
+static int cap_file_permission(struct file *file, int mask)
+{
+       return 0;
+}
+
+static int cap_file_alloc_security(struct file *file)
+{
+       return 0;
+}
+
+static void cap_file_free_security(struct file *file)
+{
+}
+
+static int cap_file_ioctl(struct file *file, unsigned int command,
+                         unsigned long arg)
+{
+       return 0;
+}
+
+static int cap_file_mmap(struct file *file, unsigned long reqprot,
+                        unsigned long prot, unsigned long flags,
+                        unsigned long addr, unsigned long addr_only)
+{
+       if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO))
+               return -EACCES;
+       return 0;
+}
+
+static int cap_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
+                            unsigned long prot)
+{
+       return 0;
+}
+
+static int cap_file_lock(struct file *file, unsigned int cmd)
+{
+       return 0;
+}
+
+static int cap_file_fcntl(struct file *file, unsigned int cmd,
+                         unsigned long arg)
+{
+       return 0;
+}
+
+static int cap_file_set_fowner(struct file *file)
+{
+       return 0;
+}
+
+static int cap_file_send_sigiotask(struct task_struct *tsk,
+                                  struct fown_struct *fown, int sig)
+{
+       return 0;
+}
+
+static int cap_file_receive(struct file *file)
+{
+       return 0;
+}
+
+static int cap_dentry_open(struct file *file)
+{
+       return 0;
+}
+
+static int cap_task_create(unsigned long clone_flags)
+{
+       return 0;
+}
+
+static int cap_task_alloc_security(struct task_struct *p)
+{
+       return 0;
+}
+
+static void cap_task_free_security(struct task_struct *p)
+{
+}
+
+static int cap_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
+{
+       return 0;
+}
+
+static int cap_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
+{
+       return 0;
+}
 
-static int capability_disable;
-module_param_named(disable, capability_disable, int, 0);
+static int cap_task_setpgid(struct task_struct *p, pid_t pgid)
+{
+       return 0;
+}
 
-static int __init capability_init (void)
+static int cap_task_getpgid(struct task_struct *p)
 {
-       if (capability_disable) {
-               printk(KERN_INFO "Capabilities disabled at initialization\n");
-               return 0;
-       }
-       /* register ourselves with the security framework */
-       if (register_security (&capability_ops)) {
-               /* try registering with primary module */
-               if (mod_reg_security (KBUILD_MODNAME, &capability_ops)) {
-                       printk (KERN_INFO "Failure registering capabilities "
-                               "with primary security module.\n");
-                       return -EINVAL;
-               }
-               secondary = 1;
-       }
-       printk (KERN_INFO "Capability LSM initialized%s\n",
-               secondary ? " as secondary" : "");
        return 0;
 }
 
-security_initcall (capability_init);
+static int cap_task_getsid(struct task_struct *p)
+{
+       return 0;
+}
+
+static void cap_task_getsecid(struct task_struct *p, u32 *secid)
+{
+       *secid = 0;
+}
+
+static int cap_task_setgroups(struct group_info *group_info)
+{
+       return 0;
+}
+
+static int cap_task_getioprio(struct task_struct *p)
+{
+       return 0;
+}
+
+static int cap_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
+{
+       return 0;
+}
+
+static int cap_task_getscheduler(struct task_struct *p)
+{
+       return 0;
+}
+
+static int cap_task_movememory(struct task_struct *p)
+{
+       return 0;
+}
+
+static int cap_task_wait(struct task_struct *p)
+{
+       return 0;
+}
+
+static int cap_task_kill(struct task_struct *p, struct siginfo *info,
+                        int sig, u32 secid)
+{
+       return 0;
+}
+
+static void cap_task_to_inode(struct task_struct *p, struct inode *inode)
+{
+}
+
+static int cap_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
+{
+       return 0;
+}
+
+static void cap_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
+{
+       *secid = 0;
+}
+
+static int cap_msg_msg_alloc_security(struct msg_msg *msg)
+{
+       return 0;
+}
+
+static void cap_msg_msg_free_security(struct msg_msg *msg)
+{
+}
+
+static int cap_msg_queue_alloc_security(struct msg_queue *msq)
+{
+       return 0;
+}
+
+static void cap_msg_queue_free_security(struct msg_queue *msq)
+{
+}
+
+static int cap_msg_queue_associate(struct msg_queue *msq, int msqflg)
+{
+       return 0;
+}
+
+static int cap_msg_queue_msgctl(struct msg_queue *msq, int cmd)
+{
+       return 0;
+}
+
+static int cap_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
+                               int msgflg)
+{
+       return 0;
+}
+
+static int cap_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
+                               struct task_struct *target, long type, int mode)
+{
+       return 0;
+}
+
+static int cap_shm_alloc_security(struct shmid_kernel *shp)
+{
+       return 0;
+}
+
+static void cap_shm_free_security(struct shmid_kernel *shp)
+{
+}
+
+static int cap_shm_associate(struct shmid_kernel *shp, int shmflg)
+{
+       return 0;
+}
+
+static int cap_shm_shmctl(struct shmid_kernel *shp, int cmd)
+{
+       return 0;
+}
+
+static int cap_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
+                        int shmflg)
+{
+       return 0;
+}
+
+static int cap_sem_alloc_security(struct sem_array *sma)
+{
+       return 0;
+}
+
+static void cap_sem_free_security(struct sem_array *sma)
+{
+}
+
+static int cap_sem_associate(struct sem_array *sma, int semflg)
+{
+       return 0;
+}
+
+static int cap_sem_semctl(struct sem_array *sma, int cmd)
+{
+       return 0;
+}
+
+static int cap_sem_semop(struct sem_array *sma, struct sembuf *sops,
+                        unsigned nsops, int alter)
+{
+       return 0;
+}
+
+#ifdef CONFIG_SECURITY_NETWORK
+static int cap_unix_stream_connect(struct socket *sock, struct socket *other,
+                                  struct sock *newsk)
+{
+       return 0;
+}
+
+static int cap_unix_may_send(struct socket *sock, struct socket *other)
+{
+       return 0;
+}
+
+static int cap_socket_create(int family, int type, int protocol, int kern)
+{
+       return 0;
+}
+
+static int cap_socket_post_create(struct socket *sock, int family, int type,
+                                 int protocol, int kern)
+{
+       return 0;
+}
+
+static int cap_socket_bind(struct socket *sock, struct sockaddr *address,
+                          int addrlen)
+{
+       return 0;
+}
+
+static int cap_socket_connect(struct socket *sock, struct sockaddr *address,
+                             int addrlen)
+{
+       return 0;
+}
+
+static int cap_socket_listen(struct socket *sock, int backlog)
+{
+       return 0;
+}
+
+static int cap_socket_accept(struct socket *sock, struct socket *newsock)
+{
+       return 0;
+}
+
+static void cap_socket_post_accept(struct socket *sock, struct socket *newsock)
+{
+}
+
+static int cap_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
+{
+       return 0;
+}
+
+static int cap_socket_recvmsg(struct socket *sock, struct msghdr *msg,
+                             int size, int flags)
+{
+       return 0;
+}
+
+static int cap_socket_getsockname(struct socket *sock)
+{
+       return 0;
+}
+
+static int cap_socket_getpeername(struct socket *sock)
+{
+       return 0;
+}
+
+static int cap_socket_setsockopt(struct socket *sock, int level, int optname)
+{
+       return 0;
+}
+
+static int cap_socket_getsockopt(struct socket *sock, int level, int optname)
+{
+       return 0;
+}
+
+static int cap_socket_shutdown(struct socket *sock, int how)
+{
+       return 0;
+}
+
+static int cap_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+       return 0;
+}
+
+static int cap_socket_getpeersec_stream(struct socket *sock,
+                                       char __user *optval,
+                                       int __user *optlen, unsigned len)
+{
+       return -ENOPROTOOPT;
+}
+
+static int cap_socket_getpeersec_dgram(struct socket *sock,
+                                      struct sk_buff *skb, u32 *secid)
+{
+       return -ENOPROTOOPT;
+}
+
+static int cap_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
+{
+       return 0;
+}
+
+static void cap_sk_free_security(struct sock *sk)
+{
+}
+
+static void cap_sk_clone_security(const struct sock *sk, struct sock *newsk)
+{
+}
+
+static void cap_sk_getsecid(struct sock *sk, u32 *secid)
+{
+}
+
+static void cap_sock_graft(struct sock *sk, struct socket *parent)
+{
+}
+
+static int cap_inet_conn_request(struct sock *sk, struct sk_buff *skb,
+                                struct request_sock *req)
+{
+       return 0;
+}
+
+static void cap_inet_csk_clone(struct sock *newsk,
+                              const struct request_sock *req)
+{
+}
+
+static void cap_inet_conn_established(struct sock *sk, struct sk_buff *skb)
+{
+}
+
+static void cap_req_classify_flow(const struct request_sock *req,
+                                 struct flowi *fl)
+{
+}
+#endif /* CONFIG_SECURITY_NETWORK */
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static int cap_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp,
+                                         struct xfrm_user_sec_ctx *sec_ctx)
+{
+       return 0;
+}
+
+static int cap_xfrm_policy_clone_security(struct xfrm_sec_ctx *old_ctx,
+                                         struct xfrm_sec_ctx **new_ctxp)
+{
+       return 0;
+}
+
+static void cap_xfrm_policy_free_security(struct xfrm_sec_ctx *ctx)
+{
+}
+
+static int cap_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx)
+{
+       return 0;
+}
+
+static int cap_xfrm_state_alloc_security(struct xfrm_state *x,
+                                        struct xfrm_user_sec_ctx *sec_ctx,
+                                        u32 secid)
+{
+       return 0;
+}
+
+static void cap_xfrm_state_free_security(struct xfrm_state *x)
+{
+}
+
+static int cap_xfrm_state_delete_security(struct xfrm_state *x)
+{
+       return 0;
+}
+
+static int cap_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 sk_sid, u8 dir)
+{
+       return 0;
+}
+
+static int cap_xfrm_state_pol_flow_match(struct xfrm_state *x,
+                                        struct xfrm_policy *xp,
+                                        struct flowi *fl)
+{
+       return 1;
+}
+
+static int cap_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall)
+{
+       return 0;
+}
+
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+static void cap_d_instantiate(struct dentry *dentry, struct inode *inode)
+{
+}
+
+static int cap_getprocattr(struct task_struct *p, char *name, char **value)
+{
+       return -EINVAL;
+}
+
+static int cap_setprocattr(struct task_struct *p, char *name, void *value,
+                          size_t size)
+{
+       return -EINVAL;
+}
+
+static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+{
+       return -EOPNOTSUPP;
+}
+
+static int cap_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
+{
+       return -EOPNOTSUPP;
+}
+
+static void cap_release_secctx(char *secdata, u32 seclen)
+{
+}
+
+#ifdef CONFIG_KEYS
+static int cap_key_alloc(struct key *key, struct task_struct *ctx,
+                        unsigned long flags)
+{
+       return 0;
+}
+
+static void cap_key_free(struct key *key)
+{
+}
+
+static int cap_key_permission(key_ref_t key_ref, struct task_struct *context,
+                             key_perm_t perm)
+{
+       return 0;
+}
+
+static int cap_key_getsecurity(struct key *key, char **_buffer)
+{
+       *_buffer = NULL;
+       return 0;
+}
+
+#endif /* CONFIG_KEYS */
+
+#ifdef CONFIG_AUDIT
+static int cap_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
+{
+       return 0;
+}
+
+static int cap_audit_rule_known(struct audit_krule *krule)
+{
+       return 0;
+}
+
+static int cap_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
+                               struct audit_context *actx)
+{
+       return 0;
+}
+
+static void cap_audit_rule_free(void *lsmrule)
+{
+}
+#endif /* CONFIG_AUDIT */
+
+struct security_operations default_security_ops = {
+       .name   = "default",
+};
+
+#define set_to_cap_if_null(ops, function)                              \
+       do {                                                            \
+               if (!ops->function) {                                   \
+                       ops->function = cap_##function;                 \
+                       pr_debug("Had to override the " #function       \
+                                " security operation with the default.\n");\
+                       }                                               \
+       } while (0)
+
+void security_fixup_ops(struct security_operations *ops)
+{
+       set_to_cap_if_null(ops, ptrace);
+       set_to_cap_if_null(ops, capget);
+       set_to_cap_if_null(ops, capset_check);
+       set_to_cap_if_null(ops, capset_set);
+       set_to_cap_if_null(ops, acct);
+       set_to_cap_if_null(ops, capable);
+       set_to_cap_if_null(ops, quotactl);
+       set_to_cap_if_null(ops, quota_on);
+       set_to_cap_if_null(ops, sysctl);
+       set_to_cap_if_null(ops, syslog);
+       set_to_cap_if_null(ops, settime);
+       set_to_cap_if_null(ops, vm_enough_memory);
+       set_to_cap_if_null(ops, bprm_alloc_security);
+       set_to_cap_if_null(ops, bprm_free_security);
+       set_to_cap_if_null(ops, bprm_apply_creds);
+       set_to_cap_if_null(ops, bprm_post_apply_creds);
+       set_to_cap_if_null(ops, bprm_set_security);
+       set_to_cap_if_null(ops, bprm_check_security);
+       set_to_cap_if_null(ops, bprm_secureexec);
+       set_to_cap_if_null(ops, sb_alloc_security);
+       set_to_cap_if_null(ops, sb_free_security);
+       set_to_cap_if_null(ops, sb_copy_data);
+       set_to_cap_if_null(ops, sb_kern_mount);
+       set_to_cap_if_null(ops, sb_show_options);
+       set_to_cap_if_null(ops, sb_statfs);
+       set_to_cap_if_null(ops, sb_mount);
+       set_to_cap_if_null(ops, sb_check_sb);
+       set_to_cap_if_null(ops, sb_umount);
+       set_to_cap_if_null(ops, sb_umount_close);
+       set_to_cap_if_null(ops, sb_umount_busy);
+       set_to_cap_if_null(ops, sb_post_remount);
+       set_to_cap_if_null(ops, sb_post_addmount);
+       set_to_cap_if_null(ops, sb_pivotroot);
+       set_to_cap_if_null(ops, sb_post_pivotroot);
+       set_to_cap_if_null(ops, sb_set_mnt_opts);
+       set_to_cap_if_null(ops, sb_clone_mnt_opts);
+       set_to_cap_if_null(ops, sb_parse_opts_str);
+       set_to_cap_if_null(ops, inode_alloc_security);
+       set_to_cap_if_null(ops, inode_free_security);
+       set_to_cap_if_null(ops, inode_init_security);
+       set_to_cap_if_null(ops, inode_create);
+       set_to_cap_if_null(ops, inode_link);
+       set_to_cap_if_null(ops, inode_unlink);
+       set_to_cap_if_null(ops, inode_symlink);
+       set_to_cap_if_null(ops, inode_mkdir);
+       set_to_cap_if_null(ops, inode_rmdir);
+       set_to_cap_if_null(ops, inode_mknod);
+       set_to_cap_if_null(ops, inode_rename);
+       set_to_cap_if_null(ops, inode_readlink);
+       set_to_cap_if_null(ops, inode_follow_link);
+       set_to_cap_if_null(ops, inode_permission);
+       set_to_cap_if_null(ops, inode_setattr);
+       set_to_cap_if_null(ops, inode_getattr);
+       set_to_cap_if_null(ops, inode_delete);
+       set_to_cap_if_null(ops, inode_setxattr);
+       set_to_cap_if_null(ops, inode_post_setxattr);
+       set_to_cap_if_null(ops, inode_getxattr);
+       set_to_cap_if_null(ops, inode_listxattr);
+       set_to_cap_if_null(ops, inode_removexattr);
+       set_to_cap_if_null(ops, inode_need_killpriv);
+       set_to_cap_if_null(ops, inode_killpriv);
+       set_to_cap_if_null(ops, inode_getsecurity);
+       set_to_cap_if_null(ops, inode_setsecurity);
+       set_to_cap_if_null(ops, inode_listsecurity);
+       set_to_cap_if_null(ops, inode_getsecid);
+       set_to_cap_if_null(ops, file_permission);
+       set_to_cap_if_null(ops, file_alloc_security);
+       set_to_cap_if_null(ops, file_free_security);
+       set_to_cap_if_null(ops, file_ioctl);
+       set_to_cap_if_null(ops, file_mmap);
+       set_to_cap_if_null(ops, file_mprotect);
+       set_to_cap_if_null(ops, file_lock);
+       set_to_cap_if_null(ops, file_fcntl);
+       set_to_cap_if_null(ops, file_set_fowner);
+       set_to_cap_if_null(ops, file_send_sigiotask);
+       set_to_cap_if_null(ops, file_receive);
+       set_to_cap_if_null(ops, dentry_open);
+       set_to_cap_if_null(ops, task_create);
+       set_to_cap_if_null(ops, task_alloc_security);
+       set_to_cap_if_null(ops, task_free_security);
+       set_to_cap_if_null(ops, task_setuid);
+       set_to_cap_if_null(ops, task_post_setuid);
+       set_to_cap_if_null(ops, task_setgid);
+       set_to_cap_if_null(ops, task_setpgid);
+       set_to_cap_if_null(ops, task_getpgid);
+       set_to_cap_if_null(ops, task_getsid);
+       set_to_cap_if_null(ops, task_getsecid);
+       set_to_cap_if_null(ops, task_setgroups);
+       set_to_cap_if_null(ops, task_setnice);
+       set_to_cap_if_null(ops, task_setioprio);
+       set_to_cap_if_null(ops, task_getioprio);
+       set_to_cap_if_null(ops, task_setrlimit);
+       set_to_cap_if_null(ops, task_setscheduler);
+       set_to_cap_if_null(ops, task_getscheduler);
+       set_to_cap_if_null(ops, task_movememory);
+       set_to_cap_if_null(ops, task_wait);
+       set_to_cap_if_null(ops, task_kill);
+       set_to_cap_if_null(ops, task_prctl);
+       set_to_cap_if_null(ops, task_reparent_to_init);
+       set_to_cap_if_null(ops, task_to_inode);
+       set_to_cap_if_null(ops, ipc_permission);
+       set_to_cap_if_null(ops, ipc_getsecid);
+       set_to_cap_if_null(ops, msg_msg_alloc_security);
+       set_to_cap_if_null(ops, msg_msg_free_security);
+       set_to_cap_if_null(ops, msg_queue_alloc_security);
+       set_to_cap_if_null(ops, msg_queue_free_security);
+       set_to_cap_if_null(ops, msg_queue_associate);
+       set_to_cap_if_null(ops, msg_queue_msgctl);
+       set_to_cap_if_null(ops, msg_queue_msgsnd);
+       set_to_cap_if_null(ops, msg_queue_msgrcv);
+       set_to_cap_if_null(ops, shm_alloc_security);
+       set_to_cap_if_null(ops, shm_free_security);
+       set_to_cap_if_null(ops, shm_associate);
+       set_to_cap_if_null(ops, shm_shmctl);
+       set_to_cap_if_null(ops, shm_shmat);
+       set_to_cap_if_null(ops, sem_alloc_security);
+       set_to_cap_if_null(ops, sem_free_security);
+       set_to_cap_if_null(ops, sem_associate);
+       set_to_cap_if_null(ops, sem_semctl);
+       set_to_cap_if_null(ops, sem_semop);
+       set_to_cap_if_null(ops, netlink_send);
+       set_to_cap_if_null(ops, netlink_recv);
+       set_to_cap_if_null(ops, d_instantiate);
+       set_to_cap_if_null(ops, getprocattr);
+       set_to_cap_if_null(ops, setprocattr);
+       set_to_cap_if_null(ops, secid_to_secctx);
+       set_to_cap_if_null(ops, secctx_to_secid);
+       set_to_cap_if_null(ops, release_secctx);
+#ifdef CONFIG_SECURITY_NETWORK
+       set_to_cap_if_null(ops, unix_stream_connect);
+       set_to_cap_if_null(ops, unix_may_send);
+       set_to_cap_if_null(ops, socket_create);
+       set_to_cap_if_null(ops, socket_post_create);
+       set_to_cap_if_null(ops, socket_bind);
+       set_to_cap_if_null(ops, socket_connect);
+       set_to_cap_if_null(ops, socket_listen);
+       set_to_cap_if_null(ops, socket_accept);
+       set_to_cap_if_null(ops, socket_post_accept);
+       set_to_cap_if_null(ops, socket_sendmsg);
+       set_to_cap_if_null(ops, socket_recvmsg);
+       set_to_cap_if_null(ops, socket_getsockname);
+       set_to_cap_if_null(ops, socket_getpeername);
+       set_to_cap_if_null(ops, socket_setsockopt);
+       set_to_cap_if_null(ops, socket_getsockopt);
+       set_to_cap_if_null(ops, socket_shutdown);
+       set_to_cap_if_null(ops, socket_sock_rcv_skb);
+       set_to_cap_if_null(ops, socket_getpeersec_stream);
+       set_to_cap_if_null(ops, socket_getpeersec_dgram);
+       set_to_cap_if_null(ops, sk_alloc_security);
+       set_to_cap_if_null(ops, sk_free_security);
+       set_to_cap_if_null(ops, sk_clone_security);
+       set_to_cap_if_null(ops, sk_getsecid);
+       set_to_cap_if_null(ops, sock_graft);
+       set_to_cap_if_null(ops, inet_conn_request);
+       set_to_cap_if_null(ops, inet_csk_clone);
+       set_to_cap_if_null(ops, inet_conn_established);
+       set_to_cap_if_null(ops, req_classify_flow);
+#endif /* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+       set_to_cap_if_null(ops, xfrm_policy_alloc_security);
+       set_to_cap_if_null(ops, xfrm_policy_clone_security);
+       set_to_cap_if_null(ops, xfrm_policy_free_security);
+       set_to_cap_if_null(ops, xfrm_policy_delete_security);
+       set_to_cap_if_null(ops, xfrm_state_alloc_security);
+       set_to_cap_if_null(ops, xfrm_state_free_security);
+       set_to_cap_if_null(ops, xfrm_state_delete_security);
+       set_to_cap_if_null(ops, xfrm_policy_lookup);
+       set_to_cap_if_null(ops, xfrm_state_pol_flow_match);
+       set_to_cap_if_null(ops, xfrm_decode_session);
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+#ifdef CONFIG_KEYS
+       set_to_cap_if_null(ops, key_alloc);
+       set_to_cap_if_null(ops, key_free);
+       set_to_cap_if_null(ops, key_permission);
+       set_to_cap_if_null(ops, key_getsecurity);
+#endif /* CONFIG_KEYS */
+#ifdef CONFIG_AUDIT
+       set_to_cap_if_null(ops, audit_rule_init);
+       set_to_cap_if_null(ops, audit_rule_known);
+       set_to_cap_if_null(ops, audit_rule_match);
+       set_to_cap_if_null(ops, audit_rule_free);
+#endif
+}
index 5edabc7542ae00c46e568456285f9bf5f369f2e6..0b6537a3672d8822baf4b10627f142e9afc1102b 100644 (file)
@@ -63,7 +63,8 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
        return 0;
 }
 
-int cap_ptrace (struct task_struct *parent, struct task_struct *child)
+int cap_ptrace (struct task_struct *parent, struct task_struct *child,
+               unsigned int mode)
 {
        /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
        if (!cap_issubset(child->cap_permitted, parent->cap_permitted) &&
@@ -103,10 +104,16 @@ static inline int cap_inh_is_capped(void)
        return (cap_capable(current, CAP_SETPCAP) != 0);
 }
 
+static inline int cap_limit_ptraced_target(void) { return 1; }
+
 #else /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */
 
 static inline int cap_block_setpcap(struct task_struct *t) { return 0; }
 static inline int cap_inh_is_capped(void) { return 1; }
+static inline int cap_limit_ptraced_target(void)
+{
+       return !capable(CAP_SETPCAP);
+}
 
 #endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
 
@@ -342,9 +349,10 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
                                bprm->e_uid = current->uid;
                                bprm->e_gid = current->gid;
                        }
-                       if (!capable (CAP_SETPCAP)) {
-                               new_permitted = cap_intersect (new_permitted,
-                                                       current->cap_permitted);
+                       if (cap_limit_ptraced_target()) {
+                               new_permitted =
+                                       cap_intersect(new_permitted,
+                                                     current->cap_permitted);
                        }
                }
        }
index baf348834b66c003758246427a98907d38f78c14..ddd92cec78ed81c44bcfc4d9c530662a179381f2 100644 (file)
@@ -222,7 +222,7 @@ static void devcgroup_destroy(struct cgroup_subsys *ss,
 #define DEVCG_DENY 2
 #define DEVCG_LIST 3
 
-#define MAJMINLEN 10
+#define MAJMINLEN 13
 #define ACCLEN 4
 
 static void set_access(char *acc, short access)
@@ -254,7 +254,7 @@ static void set_majmin(char *str, unsigned m)
        if (m == ~0)
                sprintf(str, "*");
        else
-               snprintf(str, MAJMINLEN, "%d", m);
+               snprintf(str, MAJMINLEN, "%u", m);
 }
 
 static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
@@ -300,7 +300,7 @@ static int may_access_whitelist(struct dev_cgroup *c,
                        continue;
                if (whitem->minor != ~0 && whitem->minor != refwh->minor)
                        continue;
-               if (refwh->access & (~(whitem->access | ACC_MASK)))
+               if (refwh->access & (~whitem->access))
                        continue;
                return 1;
        }
@@ -382,6 +382,8 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
        case 'a':
                wh.type = DEV_ALL;
                wh.access = ACC_MASK;
+               wh.major = ~0;
+               wh.minor = ~0;
                goto handle;
        case 'b':
                wh.type = DEV_BLOCK;
diff --git a/security/dummy.c b/security/dummy.c
deleted file mode 100644 (file)
index b891688..0000000
+++ /dev/null
@@ -1,1251 +0,0 @@
-/*
- * Stub functions for the default security function pointers in case no
- * security model is loaded.
- *
- * Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com>
- * Copyright (C) 2001-2002  Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.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.
- */
-
-#undef DEBUG
-
-#include <linux/capability.h>
-#include <linux/kernel.h>
-#include <linux/mman.h>
-#include <linux/pagemap.h>
-#include <linux/swap.h>
-#include <linux/security.h>
-#include <linux/skbuff.h>
-#include <linux/netlink.h>
-#include <net/sock.h>
-#include <linux/xattr.h>
-#include <linux/hugetlb.h>
-#include <linux/ptrace.h>
-#include <linux/file.h>
-#include <linux/prctl.h>
-#include <linux/securebits.h>
-
-static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
-{
-       return 0;
-}
-
-static int dummy_capget (struct task_struct *target, kernel_cap_t * effective,
-                        kernel_cap_t * inheritable, kernel_cap_t * permitted)
-{
-       if (target->euid == 0) {
-               cap_set_full(*permitted);
-               cap_set_init_eff(*effective);
-       } else {
-               cap_clear(*permitted);
-               cap_clear(*effective);
-       }
-
-       cap_clear(*inheritable);
-
-       if (target->fsuid != 0) {
-               *permitted = cap_drop_fs_set(*permitted);
-               *effective = cap_drop_fs_set(*effective);
-       }
-       return 0;
-}
-
-static int dummy_capset_check (struct task_struct *target,
-                              kernel_cap_t * effective,
-                              kernel_cap_t * inheritable,
-                              kernel_cap_t * permitted)
-{
-       return -EPERM;
-}
-
-static void dummy_capset_set (struct task_struct *target,
-                             kernel_cap_t * effective,
-                             kernel_cap_t * inheritable,
-                             kernel_cap_t * permitted)
-{
-       return;
-}
-
-static int dummy_acct (struct file *file)
-{
-       return 0;
-}
-
-static int dummy_capable (struct task_struct *tsk, int cap)
-{
-       if (cap_raised (tsk->cap_effective, cap))
-               return 0;
-       return -EPERM;
-}
-
-static int dummy_sysctl (ctl_table * table, int op)
-{
-       return 0;
-}
-
-static int dummy_quotactl (int cmds, int type, int id, struct super_block *sb)
-{
-       return 0;
-}
-
-static int dummy_quota_on (struct dentry *dentry)
-{
-       return 0;
-}
-
-static int dummy_syslog (int type)
-{
-       if ((type != 3 && type != 10) && current->euid)
-               return -EPERM;
-       return 0;
-}
-
-static int dummy_settime(struct timespec *ts, struct timezone *tz)
-{
-       if (!capable(CAP_SYS_TIME))
-               return -EPERM;
-       return 0;
-}
-
-static int dummy_vm_enough_memory(struct mm_struct *mm, long pages)
-{
-       int cap_sys_admin = 0;
-
-       if (dummy_capable(current, CAP_SYS_ADMIN) == 0)
-               cap_sys_admin = 1;
-       return __vm_enough_memory(mm, pages, cap_sys_admin);
-}
-
-static int dummy_bprm_alloc_security (struct linux_binprm *bprm)
-{
-       return 0;
-}
-
-static void dummy_bprm_free_security (struct linux_binprm *bprm)
-{
-       return;
-}
-
-static void dummy_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
-{
-       if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
-               set_dumpable(current->mm, suid_dumpable);
-
-               if ((unsafe & ~LSM_UNSAFE_PTRACE_CAP) && !capable(CAP_SETUID)) {
-                       bprm->e_uid = current->uid;
-                       bprm->e_gid = current->gid;
-               }
-       }
-
-       current->suid = current->euid = current->fsuid = bprm->e_uid;
-       current->sgid = current->egid = current->fsgid = bprm->e_gid;
-
-       dummy_capget(current, &current->cap_effective, &current->cap_inheritable, &current->cap_permitted);
-}
-
-static void dummy_bprm_post_apply_creds (struct linux_binprm *bprm)
-{
-       return;
-}
-
-static int dummy_bprm_set_security (struct linux_binprm *bprm)
-{
-       return 0;
-}
-
-static int dummy_bprm_check_security (struct linux_binprm *bprm)
-{
-       return 0;
-}
-
-static int dummy_bprm_secureexec (struct linux_binprm *bprm)
-{
-       /* The new userland will simply use the value provided
-          in the AT_SECURE field to decide whether secure mode
-          is required.  Hence, this logic is required to preserve
-          the legacy decision algorithm used by the old userland. */
-       return (current->euid != current->uid ||
-               current->egid != current->gid);
-}
-
-static int dummy_sb_alloc_security (struct super_block *sb)
-{
-       return 0;
-}
-
-static void dummy_sb_free_security (struct super_block *sb)
-{
-       return;
-}
-
-static int dummy_sb_copy_data (char *orig, char *copy)
-{
-       return 0;
-}
-
-static int dummy_sb_kern_mount (struct super_block *sb, void *data)
-{
-       return 0;
-}
-
-static int dummy_sb_statfs (struct dentry *dentry)
-{
-       return 0;
-}
-
-static int dummy_sb_mount (char *dev_name, struct path *path, char *type,
-                          unsigned long flags, void *data)
-{
-       return 0;
-}
-
-static int dummy_sb_check_sb (struct vfsmount *mnt, struct path *path)
-{
-       return 0;
-}
-
-static int dummy_sb_umount (struct vfsmount *mnt, int flags)
-{
-       return 0;
-}
-
-static void dummy_sb_umount_close (struct vfsmount *mnt)
-{
-       return;
-}
-
-static void dummy_sb_umount_busy (struct vfsmount *mnt)
-{
-       return;
-}
-
-static void dummy_sb_post_remount (struct vfsmount *mnt, unsigned long flags,
-                                  void *data)
-{
-       return;
-}
-
-
-static void dummy_sb_post_addmount (struct vfsmount *mnt, struct path *path)
-{
-       return;
-}
-
-static int dummy_sb_pivotroot (struct path *old_path, struct path *new_path)
-{
-       return 0;
-}
-
-static void dummy_sb_post_pivotroot (struct path *old_path, struct path *new_path)
-{
-       return;
-}
-
-static int dummy_sb_get_mnt_opts(const struct super_block *sb,
-                                struct security_mnt_opts *opts)
-{
-       security_init_mnt_opts(opts);
-       return 0;
-}
-
-static int dummy_sb_set_mnt_opts(struct super_block *sb,
-                                struct security_mnt_opts *opts)
-{
-       if (unlikely(opts->num_mnt_opts))
-               return -EOPNOTSUPP;
-       return 0;
-}
-
-static void dummy_sb_clone_mnt_opts(const struct super_block *oldsb,
-                                   struct super_block *newsb)
-{
-       return;
-}
-
-static int dummy_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
-{
-       return 0;
-}
-
-static int dummy_inode_alloc_security (struct inode *inode)
-{
-       return 0;
-}
-
-static void dummy_inode_free_security (struct inode *inode)
-{
-       return;
-}
-
-static int dummy_inode_init_security (struct inode *inode, struct inode *dir,
-                                     char **name, void **value, size_t *len)
-{
-       return -EOPNOTSUPP;
-}
-
-static int dummy_inode_create (struct inode *inode, struct dentry *dentry,
-                              int mask)
-{
-       return 0;
-}
-
-static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode,
-                            struct dentry *new_dentry)
-{
-       return 0;
-}
-
-static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry)
-{
-       return 0;
-}
-
-static int dummy_inode_symlink (struct inode *inode, struct dentry *dentry,
-                               const char *name)
-{
-       return 0;
-}
-
-static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry,
-                             int mask)
-{
-       return 0;
-}
-
-static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry)
-{
-       return 0;
-}
-
-static int dummy_inode_mknod (struct inode *inode, struct dentry *dentry,
-                             int mode, dev_t dev)
-{
-       return 0;
-}
-
-static int dummy_inode_rename (struct inode *old_inode,
-                              struct dentry *old_dentry,
-                              struct inode *new_inode,
-                              struct dentry *new_dentry)
-{
-       return 0;
-}
-
-static int dummy_inode_readlink (struct dentry *dentry)
-{
-       return 0;
-}
-
-static int dummy_inode_follow_link (struct dentry *dentry,
-                                   struct nameidata *nameidata)
-{
-       return 0;
-}
-
-static int dummy_inode_permission (struct inode *inode, int mask, struct nameidata *nd)
-{
-       return 0;
-}
-
-static int dummy_inode_setattr (struct dentry *dentry, struct iattr *iattr)
-{
-       return 0;
-}
-
-static int dummy_inode_getattr (struct vfsmount *mnt, struct dentry *dentry)
-{
-       return 0;
-}
-
-static void dummy_inode_delete (struct inode *ino)
-{
-       return;
-}
-
-static int dummy_inode_setxattr (struct dentry *dentry, const char *name,
-                                const void *value, size_t size, int flags)
-{
-       if (!strncmp(name, XATTR_SECURITY_PREFIX,
-                    sizeof(XATTR_SECURITY_PREFIX) - 1) &&
-           !capable(CAP_SYS_ADMIN))
-               return -EPERM;
-       return 0;
-}
-
-static void dummy_inode_post_setxattr (struct dentry *dentry, const char *name,
-                                      const void *value, size_t size,
-                                      int flags)
-{
-}
-
-static int dummy_inode_getxattr (struct dentry *dentry, const char *name)
-{
-       return 0;
-}
-
-static int dummy_inode_listxattr (struct dentry *dentry)
-{
-       return 0;
-}
-
-static int dummy_inode_removexattr (struct dentry *dentry, const char *name)
-{
-       if (!strncmp(name, XATTR_SECURITY_PREFIX,
-                    sizeof(XATTR_SECURITY_PREFIX) - 1) &&
-           !capable(CAP_SYS_ADMIN))
-               return -EPERM;
-       return 0;
-}
-
-static int dummy_inode_need_killpriv(struct dentry *dentry)
-{
-       return 0;
-}
-
-static int dummy_inode_killpriv(struct dentry *dentry)
-{
-       return 0;
-}
-
-static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
-{
-       return -EOPNOTSUPP;
-}
-
-static int dummy_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
-{
-       return -EOPNOTSUPP;
-}
-
-static int dummy_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
-{
-       return 0;
-}
-
-static void dummy_inode_getsecid(const struct inode *inode, u32 *secid)
-{
-       *secid = 0;
-}
-
-static int dummy_file_permission (struct file *file, int mask)
-{
-       return 0;
-}
-
-static int dummy_file_alloc_security (struct file *file)
-{
-       return 0;
-}
-
-static void dummy_file_free_security (struct file *file)
-{
-       return;
-}
-
-static int dummy_file_ioctl (struct file *file, unsigned int command,
-                            unsigned long arg)
-{
-       return 0;
-}
-
-static int dummy_file_mmap (struct file *file, unsigned long reqprot,
-                           unsigned long prot,
-                           unsigned long flags,
-                           unsigned long addr,
-                           unsigned long addr_only)
-{
-       if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO))
-               return -EACCES;
-       return 0;
-}
-
-static int dummy_file_mprotect (struct vm_area_struct *vma,
-                               unsigned long reqprot,
-                               unsigned long prot)
-{
-       return 0;
-}
-
-static int dummy_file_lock (struct file *file, unsigned int cmd)
-{
-       return 0;
-}
-
-static int dummy_file_fcntl (struct file *file, unsigned int cmd,
-                            unsigned long arg)
-{
-       return 0;
-}
-
-static int dummy_file_set_fowner (struct file *file)
-{
-       return 0;
-}
-
-static int dummy_file_send_sigiotask (struct task_struct *tsk,
-                                     struct fown_struct *fown, int sig)
-{
-       return 0;
-}
-
-static int dummy_file_receive (struct file *file)
-{
-       return 0;
-}
-
-static int dummy_dentry_open (struct file *file)
-{
-       return 0;
-}
-
-static int dummy_task_create (unsigned long clone_flags)
-{
-       return 0;
-}
-
-static int dummy_task_alloc_security (struct task_struct *p)
-{
-       return 0;
-}
-
-static void dummy_task_free_security (struct task_struct *p)
-{
-       return;
-}
-
-static int dummy_task_setuid (uid_t id0, uid_t id1, uid_t id2, int flags)
-{
-       return 0;
-}
-
-static int dummy_task_post_setuid (uid_t id0, uid_t id1, uid_t id2, int flags)
-{
-       dummy_capget(current, &current->cap_effective, &current->cap_inheritable, &current->cap_permitted);
-       return 0;
-}
-
-static int dummy_task_setgid (gid_t id0, gid_t id1, gid_t id2, int flags)
-{
-       return 0;
-}
-
-static int dummy_task_setpgid (struct task_struct *p, pid_t pgid)
-{
-       return 0;
-}
-
-static int dummy_task_getpgid (struct task_struct *p)
-{
-       return 0;
-}
-
-static int dummy_task_getsid (struct task_struct *p)
-{
-       return 0;
-}
-
-static void dummy_task_getsecid (struct task_struct *p, u32 *secid)
-{
-       *secid = 0;
-}
-
-static int dummy_task_setgroups (struct group_info *group_info)
-{
-       return 0;
-}
-
-static int dummy_task_setnice (struct task_struct *p, int nice)
-{
-       return 0;
-}
-
-static int dummy_task_setioprio (struct task_struct *p, int ioprio)
-{
-       return 0;
-}
-
-static int dummy_task_getioprio (struct task_struct *p)
-{
-       return 0;
-}
-
-static int dummy_task_setrlimit (unsigned int resource, struct rlimit *new_rlim)
-{
-       return 0;
-}
-
-static int dummy_task_setscheduler (struct task_struct *p, int policy,
-                                   struct sched_param *lp)
-{
-       return 0;
-}
-
-static int dummy_task_getscheduler (struct task_struct *p)
-{
-       return 0;
-}
-
-static int dummy_task_movememory (struct task_struct *p)
-{
-       return 0;
-}
-
-static int dummy_task_wait (struct task_struct *p)
-{
-       return 0;
-}
-
-static int dummy_task_kill (struct task_struct *p, struct siginfo *info,
-                           int sig, u32 secid)
-{
-       return 0;
-}
-
-static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3,
-                            unsigned long arg4, unsigned long arg5, long *rc_p)
-{
-       switch (option) {
-       case PR_CAPBSET_READ:
-               *rc_p = (cap_valid(arg2) ? 1 : -EINVAL);
-               break;
-       case PR_GET_KEEPCAPS:
-               *rc_p = issecure(SECURE_KEEP_CAPS);
-               break;
-       case PR_SET_KEEPCAPS:
-               if (arg2 > 1)
-                       *rc_p = -EINVAL;
-               else if (arg2)
-                       current->securebits |= issecure_mask(SECURE_KEEP_CAPS);
-               else
-                       current->securebits &=
-                               ~issecure_mask(SECURE_KEEP_CAPS);
-               break;
-       default:
-               return 0;
-       }
-
-       return 1;
-}
-
-static void dummy_task_reparent_to_init (struct task_struct *p)
-{
-       p->euid = p->fsuid = 0;
-       return;
-}
-
-static void dummy_task_to_inode(struct task_struct *p, struct inode *inode)
-{ }
-
-static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
-{
-       return 0;
-}
-
-static void dummy_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
-{
-       *secid = 0;
-}
-
-static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
-{
-       return 0;
-}
-
-static void dummy_msg_msg_free_security (struct msg_msg *msg)
-{
-       return;
-}
-
-static int dummy_msg_queue_alloc_security (struct msg_queue *msq)
-{
-       return 0;
-}
-
-static void dummy_msg_queue_free_security (struct msg_queue *msq)
-{
-       return;
-}
-
-static int dummy_msg_queue_associate (struct msg_queue *msq, 
-                                     int msqflg)
-{
-       return 0;
-}
-
-static int dummy_msg_queue_msgctl (struct msg_queue *msq, int cmd)
-{
-       return 0;
-}
-
-static int dummy_msg_queue_msgsnd (struct msg_queue *msq, struct msg_msg *msg,
-                                  int msgflg)
-{
-       return 0;
-}
-
-static int dummy_msg_queue_msgrcv (struct msg_queue *msq, struct msg_msg *msg,
-                                  struct task_struct *target, long type,
-                                  int mode)
-{
-       return 0;
-}
-
-static int dummy_shm_alloc_security (struct shmid_kernel *shp)
-{
-       return 0;
-}
-
-static void dummy_shm_free_security (struct shmid_kernel *shp)
-{
-       return;
-}
-
-static int dummy_shm_associate (struct shmid_kernel *shp, int shmflg)
-{
-       return 0;
-}
-
-static int dummy_shm_shmctl (struct shmid_kernel *shp, int cmd)
-{
-       return 0;
-}
-
-static int dummy_shm_shmat (struct shmid_kernel *shp, char __user *shmaddr,
-                           int shmflg)
-{
-       return 0;
-}
-
-static int dummy_sem_alloc_security (struct sem_array *sma)
-{
-       return 0;
-}
-
-static void dummy_sem_free_security (struct sem_array *sma)
-{
-       return;
-}
-
-static int dummy_sem_associate (struct sem_array *sma, int semflg)
-{
-       return 0;
-}
-
-static int dummy_sem_semctl (struct sem_array *sma, int cmd)
-{
-       return 0;
-}
-
-static int dummy_sem_semop (struct sem_array *sma, 
-                           struct sembuf *sops, unsigned nsops, int alter)
-{
-       return 0;
-}
-
-static int dummy_netlink_send (struct sock *sk, struct sk_buff *skb)
-{
-       NETLINK_CB(skb).eff_cap = current->cap_effective;
-       return 0;
-}
-
-static int dummy_netlink_recv (struct sk_buff *skb, int cap)
-{
-       if (!cap_raised (NETLINK_CB (skb).eff_cap, cap))
-               return -EPERM;
-       return 0;
-}
-
-#ifdef CONFIG_SECURITY_NETWORK
-static int dummy_unix_stream_connect (struct socket *sock,
-                                     struct socket *other,
-                                     struct sock *newsk)
-{
-       return 0;
-}
-
-static int dummy_unix_may_send (struct socket *sock,
-                               struct socket *other)
-{
-       return 0;
-}
-
-static int dummy_socket_create (int family, int type,
-                               int protocol, int kern)
-{
-       return 0;
-}
-
-static int dummy_socket_post_create (struct socket *sock, int family, int type,
-                                    int protocol, int kern)
-{
-       return 0;
-}
-
-static int dummy_socket_bind (struct socket *sock, struct sockaddr *address,
-                             int addrlen)
-{
-       return 0;
-}
-
-static int dummy_socket_connect (struct socket *sock, struct sockaddr *address,
-                                int addrlen)
-{
-       return 0;
-}
-
-static int dummy_socket_listen (struct socket *sock, int backlog)
-{
-       return 0;
-}
-
-static int dummy_socket_accept (struct socket *sock, struct socket *newsock)
-{
-       return 0;
-}
-
-static void dummy_socket_post_accept (struct socket *sock, 
-                                     struct socket *newsock)
-{
-       return;
-}
-
-static int dummy_socket_sendmsg (struct socket *sock, struct msghdr *msg,
-                                int size)
-{
-       return 0;
-}
-
-static int dummy_socket_recvmsg (struct socket *sock, struct msghdr *msg,
-                                int size, int flags)
-{
-       return 0;
-}
-
-static int dummy_socket_getsockname (struct socket *sock)
-{
-       return 0;
-}
-
-static int dummy_socket_getpeername (struct socket *sock)
-{
-       return 0;
-}
-
-static int dummy_socket_setsockopt (struct socket *sock, int level, int optname)
-{
-       return 0;
-}
-
-static int dummy_socket_getsockopt (struct socket *sock, int level, int optname)
-{
-       return 0;
-}
-
-static int dummy_socket_shutdown (struct socket *sock, int how)
-{
-       return 0;
-}
-
-static int dummy_socket_sock_rcv_skb (struct sock *sk, struct sk_buff *skb)
-{
-       return 0;
-}
-
-static int dummy_socket_getpeersec_stream(struct socket *sock, char __user *optval,
-                                         int __user *optlen, unsigned len)
-{
-       return -ENOPROTOOPT;
-}
-
-static int dummy_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
-{
-       return -ENOPROTOOPT;
-}
-
-static inline int dummy_sk_alloc_security (struct sock *sk, int family, gfp_t priority)
-{
-       return 0;
-}
-
-static inline void dummy_sk_free_security (struct sock *sk)
-{
-}
-
-static inline void dummy_sk_clone_security (const struct sock *sk, struct sock *newsk)
-{
-}
-
-static inline void dummy_sk_getsecid(struct sock *sk, u32 *secid)
-{
-}
-
-static inline void dummy_sock_graft(struct sock* sk, struct socket *parent)
-{
-}
-
-static inline int dummy_inet_conn_request(struct sock *sk,
-                       struct sk_buff *skb, struct request_sock *req)
-{
-       return 0;
-}
-
-static inline void dummy_inet_csk_clone(struct sock *newsk,
-                       const struct request_sock *req)
-{
-}
-
-static inline void dummy_inet_conn_established(struct sock *sk,
-                       struct sk_buff *skb)
-{
-}
-
-static inline void dummy_req_classify_flow(const struct request_sock *req,
-                       struct flowi *fl)
-{
-}
-#endif /* CONFIG_SECURITY_NETWORK */
-
-#ifdef CONFIG_SECURITY_NETWORK_XFRM
-static int dummy_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp,
-                                           struct xfrm_user_sec_ctx *sec_ctx)
-{
-       return 0;
-}
-
-static inline int dummy_xfrm_policy_clone_security(struct xfrm_sec_ctx *old_ctx,
-                                          struct xfrm_sec_ctx **new_ctxp)
-{
-       return 0;
-}
-
-static void dummy_xfrm_policy_free_security(struct xfrm_sec_ctx *ctx)
-{
-}
-
-static int dummy_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx)
-{
-       return 0;
-}
-
-static int dummy_xfrm_state_alloc_security(struct xfrm_state *x,
-       struct xfrm_user_sec_ctx *sec_ctx, u32 secid)
-{
-       return 0;
-}
-
-static void dummy_xfrm_state_free_security(struct xfrm_state *x)
-{
-}
-
-static int dummy_xfrm_state_delete_security(struct xfrm_state *x)
-{
-       return 0;
-}
-
-static int dummy_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx,
-                                   u32 sk_sid, u8 dir)
-{
-       return 0;
-}
-
-static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x,
-                               struct xfrm_policy *xp, struct flowi *fl)
-{
-       return 1;
-}
-
-static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall)
-{
-       return 0;
-}
-
-#endif /* CONFIG_SECURITY_NETWORK_XFRM */
-static int dummy_register_security (const char *name, struct security_operations *ops)
-{
-       return -EINVAL;
-}
-
-static void dummy_d_instantiate (struct dentry *dentry, struct inode *inode)
-{
-       return;
-}
-
-static int dummy_getprocattr(struct task_struct *p, char *name, char **value)
-{
-       return -EINVAL;
-}
-
-static int dummy_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
-{
-       return -EINVAL;
-}
-
-static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
-{
-       return -EOPNOTSUPP;
-}
-
-static int dummy_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
-{
-       return -EOPNOTSUPP;
-}
-
-static void dummy_release_secctx(char *secdata, u32 seclen)
-{
-}
-
-#ifdef CONFIG_KEYS
-static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx,
-                                 unsigned long flags)
-{
-       return 0;
-}
-
-static inline void dummy_key_free(struct key *key)
-{
-}
-
-static inline int dummy_key_permission(key_ref_t key_ref,
-                                      struct task_struct *context,
-                                      key_perm_t perm)
-{
-       return 0;
-}
-
-static int dummy_key_getsecurity(struct key *key, char **_buffer)
-{
-       *_buffer = NULL;
-       return 0;
-}
-
-#endif /* CONFIG_KEYS */
-
-#ifdef CONFIG_AUDIT
-static inline int dummy_audit_rule_init(u32 field, u32 op, char *rulestr,
-                                       void **lsmrule)
-{
-       return 0;
-}
-
-static inline int dummy_audit_rule_known(struct audit_krule *krule)
-{
-       return 0;
-}
-
-static inline int dummy_audit_rule_match(u32 secid, u32 field, u32 op,
-                                        void *lsmrule,
-                                        struct audit_context *actx)
-{
-       return 0;
-}
-
-static inline void dummy_audit_rule_free(void *lsmrule)
-{ }
-
-#endif /* CONFIG_AUDIT */
-
-struct security_operations dummy_security_ops = {
-       .name = "dummy",
-};
-
-#define set_to_dummy_if_null(ops, function)                            \
-       do {                                                            \
-               if (!ops->function) {                                   \
-                       ops->function = dummy_##function;               \
-                       pr_debug("Had to override the " #function       \
-                                " security operation with the dummy one.\n");\
-                       }                                               \
-       } while (0)
-
-void security_fixup_ops (struct security_operations *ops)
-{
-       set_to_dummy_if_null(ops, ptrace);
-       set_to_dummy_if_null(ops, capget);
-       set_to_dummy_if_null(ops, capset_check);
-       set_to_dummy_if_null(ops, capset_set);
-       set_to_dummy_if_null(ops, acct);
-       set_to_dummy_if_null(ops, capable);
-       set_to_dummy_if_null(ops, quotactl);
-       set_to_dummy_if_null(ops, quota_on);
-       set_to_dummy_if_null(ops, sysctl);
-       set_to_dummy_if_null(ops, syslog);
-       set_to_dummy_if_null(ops, settime);
-       set_to_dummy_if_null(ops, vm_enough_memory);
-       set_to_dummy_if_null(ops, bprm_alloc_security);
-       set_to_dummy_if_null(ops, bprm_free_security);
-       set_to_dummy_if_null(ops, bprm_apply_creds);
-       set_to_dummy_if_null(ops, bprm_post_apply_creds);
-       set_to_dummy_if_null(ops, bprm_set_security);
-       set_to_dummy_if_null(ops, bprm_check_security);
-       set_to_dummy_if_null(ops, bprm_secureexec);
-       set_to_dummy_if_null(ops, sb_alloc_security);
-       set_to_dummy_if_null(ops, sb_free_security);
-       set_to_dummy_if_null(ops, sb_copy_data);
-       set_to_dummy_if_null(ops, sb_kern_mount);
-       set_to_dummy_if_null(ops, sb_statfs);
-       set_to_dummy_if_null(ops, sb_mount);
-       set_to_dummy_if_null(ops, sb_check_sb);
-       set_to_dummy_if_null(ops, sb_umount);
-       set_to_dummy_if_null(ops, sb_umount_close);
-       set_to_dummy_if_null(ops, sb_umount_busy);
-       set_to_dummy_if_null(ops, sb_post_remount);
-       set_to_dummy_if_null(ops, sb_post_addmount);
-       set_to_dummy_if_null(ops, sb_pivotroot);
-       set_to_dummy_if_null(ops, sb_post_pivotroot);
-       set_to_dummy_if_null(ops, sb_get_mnt_opts);
-       set_to_dummy_if_null(ops, sb_set_mnt_opts);
-       set_to_dummy_if_null(ops, sb_clone_mnt_opts);
-       set_to_dummy_if_null(ops, sb_parse_opts_str);
-       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_link);
-       set_to_dummy_if_null(ops, inode_unlink);
-       set_to_dummy_if_null(ops, inode_symlink);
-       set_to_dummy_if_null(ops, inode_mkdir);
-       set_to_dummy_if_null(ops, inode_rmdir);
-       set_to_dummy_if_null(ops, inode_mknod);
-       set_to_dummy_if_null(ops, inode_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);
-       set_to_dummy_if_null(ops, inode_setattr);
-       set_to_dummy_if_null(ops, inode_getattr);
-       set_to_dummy_if_null(ops, inode_delete);
-       set_to_dummy_if_null(ops, inode_setxattr);
-       set_to_dummy_if_null(ops, inode_post_setxattr);
-       set_to_dummy_if_null(ops, inode_getxattr);
-       set_to_dummy_if_null(ops, inode_listxattr);
-       set_to_dummy_if_null(ops, inode_removexattr);
-       set_to_dummy_if_null(ops, inode_need_killpriv);
-       set_to_dummy_if_null(ops, inode_killpriv);
-       set_to_dummy_if_null(ops, inode_getsecurity);
-       set_to_dummy_if_null(ops, inode_setsecurity);
-       set_to_dummy_if_null(ops, inode_listsecurity);
-       set_to_dummy_if_null(ops, inode_getsecid);
-       set_to_dummy_if_null(ops, file_permission);
-       set_to_dummy_if_null(ops, file_alloc_security);
-       set_to_dummy_if_null(ops, file_free_security);
-       set_to_dummy_if_null(ops, file_ioctl);
-       set_to_dummy_if_null(ops, file_mmap);
-       set_to_dummy_if_null(ops, file_mprotect);
-       set_to_dummy_if_null(ops, file_lock);
-       set_to_dummy_if_null(ops, file_fcntl);
-       set_to_dummy_if_null(ops, file_set_fowner);
-       set_to_dummy_if_null(ops, file_send_sigiotask);
-       set_to_dummy_if_null(ops, file_receive);
-       set_to_dummy_if_null(ops, dentry_open);
-       set_to_dummy_if_null(ops, task_create);
-       set_to_dummy_if_null(ops, task_alloc_security);
-       set_to_dummy_if_null(ops, task_free_security);
-       set_to_dummy_if_null(ops, task_setuid);
-       set_to_dummy_if_null(ops, task_post_setuid);
-       set_to_dummy_if_null(ops, task_setgid);
-       set_to_dummy_if_null(ops, task_setpgid);
-       set_to_dummy_if_null(ops, task_getpgid);
-       set_to_dummy_if_null(ops, task_getsid);
-       set_to_dummy_if_null(ops, task_getsecid);
-       set_to_dummy_if_null(ops, task_setgroups);
-       set_to_dummy_if_null(ops, task_setnice);
-       set_to_dummy_if_null(ops, task_setioprio);
-       set_to_dummy_if_null(ops, task_getioprio);
-       set_to_dummy_if_null(ops, task_setrlimit);
-       set_to_dummy_if_null(ops, task_setscheduler);
-       set_to_dummy_if_null(ops, task_getscheduler);
-       set_to_dummy_if_null(ops, task_movememory);
-       set_to_dummy_if_null(ops, task_wait);
-       set_to_dummy_if_null(ops, task_kill);
-       set_to_dummy_if_null(ops, task_prctl);
-       set_to_dummy_if_null(ops, task_reparent_to_init);
-       set_to_dummy_if_null(ops, task_to_inode);
-       set_to_dummy_if_null(ops, ipc_permission);
-       set_to_dummy_if_null(ops, ipc_getsecid);
-       set_to_dummy_if_null(ops, msg_msg_alloc_security);
-       set_to_dummy_if_null(ops, msg_msg_free_security);
-       set_to_dummy_if_null(ops, msg_queue_alloc_security);
-       set_to_dummy_if_null(ops, msg_queue_free_security);
-       set_to_dummy_if_null(ops, msg_queue_associate);
-       set_to_dummy_if_null(ops, msg_queue_msgctl);
-       set_to_dummy_if_null(ops, msg_queue_msgsnd);
-       set_to_dummy_if_null(ops, msg_queue_msgrcv);
-       set_to_dummy_if_null(ops, shm_alloc_security);
-       set_to_dummy_if_null(ops, shm_free_security);
-       set_to_dummy_if_null(ops, shm_associate);
-       set_to_dummy_if_null(ops, shm_shmctl);
-       set_to_dummy_if_null(ops, shm_shmat);
-       set_to_dummy_if_null(ops, sem_alloc_security);
-       set_to_dummy_if_null(ops, sem_free_security);
-       set_to_dummy_if_null(ops, sem_associate);
-       set_to_dummy_if_null(ops, sem_semctl);
-       set_to_dummy_if_null(ops, sem_semop);
-       set_to_dummy_if_null(ops, netlink_send);
-       set_to_dummy_if_null(ops, netlink_recv);
-       set_to_dummy_if_null(ops, register_security);
-       set_to_dummy_if_null(ops, d_instantiate);
-       set_to_dummy_if_null(ops, getprocattr);
-       set_to_dummy_if_null(ops, setprocattr);
-       set_to_dummy_if_null(ops, secid_to_secctx);
-       set_to_dummy_if_null(ops, secctx_to_secid);
-       set_to_dummy_if_null(ops, release_secctx);
-#ifdef CONFIG_SECURITY_NETWORK
-       set_to_dummy_if_null(ops, unix_stream_connect);
-       set_to_dummy_if_null(ops, unix_may_send);
-       set_to_dummy_if_null(ops, socket_create);
-       set_to_dummy_if_null(ops, socket_post_create);
-       set_to_dummy_if_null(ops, socket_bind);
-       set_to_dummy_if_null(ops, socket_connect);
-       set_to_dummy_if_null(ops, socket_listen);
-       set_to_dummy_if_null(ops, socket_accept);
-       set_to_dummy_if_null(ops, socket_post_accept);
-       set_to_dummy_if_null(ops, socket_sendmsg);
-       set_to_dummy_if_null(ops, socket_recvmsg);
-       set_to_dummy_if_null(ops, socket_getsockname);
-       set_to_dummy_if_null(ops, socket_getpeername);
-       set_to_dummy_if_null(ops, socket_setsockopt);
-       set_to_dummy_if_null(ops, socket_getsockopt);
-       set_to_dummy_if_null(ops, socket_shutdown);
-       set_to_dummy_if_null(ops, socket_sock_rcv_skb);
-       set_to_dummy_if_null(ops, socket_getpeersec_stream);
-       set_to_dummy_if_null(ops, socket_getpeersec_dgram);
-       set_to_dummy_if_null(ops, sk_alloc_security);
-       set_to_dummy_if_null(ops, sk_free_security);
-       set_to_dummy_if_null(ops, sk_clone_security);
-       set_to_dummy_if_null(ops, sk_getsecid);
-       set_to_dummy_if_null(ops, sock_graft);
-       set_to_dummy_if_null(ops, inet_conn_request);
-       set_to_dummy_if_null(ops, inet_csk_clone);
-       set_to_dummy_if_null(ops, inet_conn_established);
-       set_to_dummy_if_null(ops, req_classify_flow);
- #endif        /* CONFIG_SECURITY_NETWORK */
-#ifdef  CONFIG_SECURITY_NETWORK_XFRM
-       set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
-       set_to_dummy_if_null(ops, xfrm_policy_clone_security);
-       set_to_dummy_if_null(ops, xfrm_policy_free_security);
-       set_to_dummy_if_null(ops, xfrm_policy_delete_security);
-       set_to_dummy_if_null(ops, xfrm_state_alloc_security);
-       set_to_dummy_if_null(ops, xfrm_state_free_security);
-       set_to_dummy_if_null(ops, xfrm_state_delete_security);
-       set_to_dummy_if_null(ops, xfrm_policy_lookup);
-       set_to_dummy_if_null(ops, xfrm_state_pol_flow_match);
-       set_to_dummy_if_null(ops, xfrm_decode_session);
-#endif /* CONFIG_SECURITY_NETWORK_XFRM */
-#ifdef CONFIG_KEYS
-       set_to_dummy_if_null(ops, key_alloc);
-       set_to_dummy_if_null(ops, key_free);
-       set_to_dummy_if_null(ops, key_permission);
-       set_to_dummy_if_null(ops, key_getsecurity);
-#endif /* CONFIG_KEYS */
-#ifdef CONFIG_AUDIT
-       set_to_dummy_if_null(ops, audit_rule_init);
-       set_to_dummy_if_null(ops, audit_rule_known);
-       set_to_dummy_if_null(ops, audit_rule_match);
-       set_to_dummy_if_null(ops, audit_rule_free);
-#endif
-}
-
index a41cf42a4fa0b5d68921f632d329dbf5cb9d7d76..be0ebec2580b14165f24f9cbc9fac3778b73b15b 100644 (file)
@@ -28,9 +28,6 @@
 #include <linux/usb.h>
 #include <linux/moduleparam.h>
 
-/* flag to keep track of how we were registered */
-static int secondary;
-
 /* default is a generic type of usb to serial converter */
 static int vendor_id = 0x0557;
 static int product_id = 0x2008;
@@ -97,13 +94,7 @@ static int __init rootplug_init (void)
        if (register_security (&rootplug_security_ops)) {
                printk (KERN_INFO 
                        "Failure registering Root Plug module with the kernel\n");
-               /* try registering with primary module */
-               if (mod_reg_security (MY_NAME, &rootplug_security_ops)) {
-                       printk (KERN_INFO "Failure registering Root Plug "
-                               " module with primary security module.\n");
                        return -EINVAL;
-               }
-               secondary = 1;
        }
        printk (KERN_INFO "Root Plug module initialized, "
                "vendor_id = %4.4x, product id = %4.4x\n", vendor_id, product_id);
index 59838a99b80e981d27ae892e7d3aa0204bb484c1..59f23b5918b38c01028263798cebd1ca304b171d 100644 (file)
@@ -20,8 +20,8 @@
 /* Boot-time LSM user choice */
 static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1];
 
-/* things that live in dummy.c */
-extern struct security_operations dummy_security_ops;
+/* things that live in capability.c */
+extern struct security_operations default_security_ops;
 extern void security_fixup_ops(struct security_operations *ops);
 
 struct security_operations *security_ops;      /* Initialized to NULL */
@@ -57,13 +57,8 @@ int __init security_init(void)
 {
        printk(KERN_INFO "Security Framework initialized\n");
 
-       if (verify(&dummy_security_ops)) {
-               printk(KERN_ERR "%s could not verify "
-                      "dummy_security_ops structure.\n", __func__);
-               return -EIO;
-       }
-
-       security_ops = &dummy_security_ops;
+       security_fixup_ops(&default_security_ops);
+       security_ops = &default_security_ops;
        do_security_initcalls();
 
        return 0;
@@ -122,7 +117,7 @@ int register_security(struct security_operations *ops)
                return -EINVAL;
        }
 
-       if (security_ops != &dummy_security_ops)
+       if (security_ops != &default_security_ops)
                return -EAGAIN;
 
        security_ops = ops;
@@ -130,40 +125,12 @@ int register_security(struct security_operations *ops)
        return 0;
 }
 
-/**
- * mod_reg_security - allows security modules to be "stacked"
- * @name: a pointer to a string with the name of the security_options to be registered
- * @ops: a pointer to the struct security_options that is to be registered
- *
- * This function allows security modules to be stacked if the currently loaded
- * security module allows this to happen.  It passes the @name and @ops to the
- * register_security function of the currently loaded security module.
- *
- * The return value depends on the currently loaded security module, with 0 as
- * success.
- */
-int mod_reg_security(const char *name, struct security_operations *ops)
-{
-       if (verify(ops)) {
-               printk(KERN_INFO "%s could not verify "
-                      "security operations.\n", __func__);
-               return -EINVAL;
-       }
-
-       if (ops == security_ops) {
-               printk(KERN_INFO "%s security operations "
-                      "already registered.\n", __func__);
-               return -EINVAL;
-       }
-
-       return security_ops->register_security(name, ops);
-}
-
 /* Security operations */
 
-int security_ptrace(struct task_struct *parent, struct task_struct *child)
+int security_ptrace(struct task_struct *parent, struct task_struct *child,
+                   unsigned int mode)
 {
-       return security_ops->ptrace(parent, child);
+       return security_ops->ptrace(parent, child, mode);
 }
 
 int security_capget(struct task_struct *target,
@@ -291,6 +258,11 @@ int security_sb_kern_mount(struct super_block *sb, void *data)
        return security_ops->sb_kern_mount(sb, data);
 }
 
+int security_sb_show_options(struct seq_file *m, struct super_block *sb)
+{
+       return security_ops->sb_show_options(m, sb);
+}
+
 int security_sb_statfs(struct dentry *dentry)
 {
        return security_ops->sb_statfs(dentry);
@@ -342,12 +314,6 @@ void security_sb_post_pivotroot(struct path *old_path, struct path *new_path)
        security_ops->sb_post_pivotroot(old_path, new_path);
 }
 
-int security_sb_get_mnt_opts(const struct super_block *sb,
-                               struct security_mnt_opts *opts)
-{
-       return security_ops->sb_get_mnt_opts(sb, opts);
-}
-
 int security_sb_set_mnt_opts(struct super_block *sb,
                                struct security_mnt_opts *opts)
 {
@@ -894,7 +860,7 @@ EXPORT_SYMBOL(security_secctx_to_secid);
 
 void security_release_secctx(char *secdata, u32 seclen)
 {
-       return security_ops->release_secctx(secdata, seclen);
+       security_ops->release_secctx(secdata, seclen);
 }
 EXPORT_SYMBOL(security_release_secctx);
 
@@ -1011,12 +977,12 @@ int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
 
 void security_sk_free(struct sock *sk)
 {
-       return security_ops->sk_free_security(sk);
+       security_ops->sk_free_security(sk);
 }
 
 void security_sk_clone(const struct sock *sk, struct sock *newsk)
 {
-       return security_ops->sk_clone_security(sk, newsk);
+       security_ops->sk_clone_security(sk, newsk);
 }
 
 void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
index 1c864c0efe2b90592d0e86a49e7347ff8ad02829..91200feb3f9c3792c2b06218a6ff44c667e168b2 100644 (file)
@@ -9,7 +9,8 @@
  *           James Morris <jmorris@redhat.com>
  *
  *  Copyright (C) 2001,2002 Networks Associates Technology, Inc.
- *  Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *  Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *                                        Eric Paris <eparis@redhat.com>
  *  Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  *                         <dgoeddel@trustedcs.com>
  *  Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
@@ -42,9 +43,7 @@
 #include <linux/fdtable.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
-#include <linux/ext2_fs.h>
 #include <linux/proc_fs.h>
-#include <linux/kd.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
 #include <linux/tty.h>
@@ -53,7 +52,7 @@
 #include <net/tcp.h>           /* struct or_callable used in sock_rcv_skb */
 #include <net/net_namespace.h>
 #include <net/netlabel.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ioctls.h>
 #include <asm/atomic.h>
 #include <linux/bitops.h>
@@ -104,7 +103,9 @@ int selinux_enforcing;
 
 static int __init enforcing_setup(char *str)
 {
-       selinux_enforcing = simple_strtol(str, NULL, 0);
+       unsigned long enforcing;
+       if (!strict_strtoul(str, 0, &enforcing))
+               selinux_enforcing = enforcing ? 1 : 0;
        return 1;
 }
 __setup("enforcing=", enforcing_setup);
@@ -115,7 +116,9 @@ int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
 
 static int __init selinux_enabled_setup(char *str)
 {
-       selinux_enabled = simple_strtol(str, NULL, 0);
+       unsigned long enabled;
+       if (!strict_strtoul(str, 0, &enabled))
+               selinux_enabled = enabled ? 1 : 0;
        return 1;
 }
 __setup("selinux=", selinux_enabled_setup);
@@ -123,13 +126,11 @@ __setup("selinux=", selinux_enabled_setup);
 int selinux_enabled = 1;
 #endif
 
-/* Original (dummy) security module. */
-static struct security_operations *original_ops;
 
-/* Minimal support for a secondary security module,
-   just to allow the use of the dummy or capability modules.
-   The owlsm module can alternatively be used as a secondary
  module as long as CONFIG_OWLSM_FD is not enabled. */
+/*
+ * Minimal support for a secondary security module,
+ * just to allow the use of the capability module.
+ */
 static struct security_operations *secondary_ops;
 
 /* Lists of inode and superblock security structures initialized
@@ -554,13 +555,15 @@ static int selinux_set_mnt_opts(struct super_block *sb,
        struct task_security_struct *tsec = current->security;
        struct superblock_security_struct *sbsec = sb->s_security;
        const char *name = sb->s_type->name;
-       struct inode *inode = sbsec->sb->s_root->d_inode;
-       struct inode_security_struct *root_isec = inode->i_security;
+       struct dentry *root = sb->s_root;
+       struct inode *root_inode = root->d_inode;
+       struct inode_security_struct *root_isec = root_inode->i_security;
        u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
        u32 defcontext_sid = 0;
        char **mount_options = opts->mnt_opts;
        int *flags = opts->mnt_opts_flags;
        int num_opts = opts->num_mnt_opts;
+       bool can_xattr = false;
 
        mutex_lock(&sbsec->lock);
 
@@ -594,7 +597,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
         */
        if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
            && (num_opts == 0))
-               goto out;
+               goto out;
 
        /*
         * parse the mount options, check if they are valid sids.
@@ -664,14 +667,24 @@ static int selinux_set_mnt_opts(struct super_block *sb,
                goto out;
        }
 
-       if (strcmp(sb->s_type->name, "proc") == 0)
+       if (strcmp(name, "proc") == 0)
                sbsec->proc = 1;
 
+       /*
+        * test if the fs supports xattrs, fs_use might make use of this if the
+        * fs has no definition in policy.
+        */
+       if (root_inode->i_op->getxattr) {
+               rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
+               if (rc >= 0 || rc == -ENODATA)
+                       can_xattr = true;
+       }
+
        /* Determine the labeling behavior to use for this filesystem type. */
-       rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
+       rc = security_fs_use(name, &sbsec->behavior, &sbsec->sid, can_xattr);
        if (rc) {
                printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
-                      __func__, sb->s_type->name, rc);
+                      __func__, name, rc);
                goto out;
        }
 
@@ -956,6 +969,57 @@ out_err:
        return rc;
 }
 
+void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts)
+{
+       int i;
+       char *prefix;
+
+       for (i = 0; i < opts->num_mnt_opts; i++) {
+               char *has_comma = strchr(opts->mnt_opts[i], ',');
+
+               switch (opts->mnt_opts_flags[i]) {
+               case CONTEXT_MNT:
+                       prefix = CONTEXT_STR;
+                       break;
+               case FSCONTEXT_MNT:
+                       prefix = FSCONTEXT_STR;
+                       break;
+               case ROOTCONTEXT_MNT:
+                       prefix = ROOTCONTEXT_STR;
+                       break;
+               case DEFCONTEXT_MNT:
+                       prefix = DEFCONTEXT_STR;
+                       break;
+               default:
+                       BUG();
+               };
+               /* we need a comma before each option */
+               seq_putc(m, ',');
+               seq_puts(m, prefix);
+               if (has_comma)
+                       seq_putc(m, '\"');
+               seq_puts(m, opts->mnt_opts[i]);
+               if (has_comma)
+                       seq_putc(m, '\"');
+       }
+}
+
+static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
+{
+       struct security_mnt_opts opts;
+       int rc;
+
+       rc = selinux_get_mnt_opts(sb, &opts);
+       if (rc)
+               return rc;
+
+       selinux_write_opts(m, &opts);
+
+       security_free_mnt_opts(&opts);
+
+       return rc;
+}
+
 static inline u16 inode_mode_to_security_class(umode_t mode)
 {
        switch (mode & S_IFMT) {
@@ -1682,14 +1746,23 @@ static inline u32 file_to_av(struct file *file)
 
 /* Hook functions begin here. */
 
-static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
+static int selinux_ptrace(struct task_struct *parent,
+                         struct task_struct *child,
+                         unsigned int mode)
 {
        int rc;
 
-       rc = secondary_ops->ptrace(parent, child);
+       rc = secondary_ops->ptrace(parent, child, mode);
        if (rc)
                return rc;
 
+       if (mode == PTRACE_MODE_READ) {
+               struct task_security_struct *tsec = parent->security;
+               struct task_security_struct *csec = child->security;
+               return avc_has_perm(tsec->sid, csec->sid,
+                                   SECCLASS_FILE, FILE__READ, NULL);
+       }
+
        return task_has_perm(parent, child, PROCESS__PTRACE);
 }
 
@@ -2495,7 +2568,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
        }
 
        if (value && len) {
-               rc = security_sid_to_context(newsid, &context, &clen);
+               rc = security_sid_to_context_force(newsid, &context, &clen);
                if (rc) {
                        kfree(namep);
                        return rc;
@@ -2669,6 +2742,11 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
                return rc;
 
        rc = security_context_to_sid(value, size, &newsid);
+       if (rc == -EINVAL) {
+               if (!capable(CAP_MAC_ADMIN))
+                       return rc;
+               rc = security_context_to_sid_force(value, size, &newsid);
+       }
        if (rc)
                return rc;
 
@@ -2690,7 +2768,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
 }
 
 static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
-                                        const void *value, size_t size,
+                                       const void *value, size_t size,
                                        int flags)
 {
        struct inode *inode = dentry->d_inode;
@@ -2703,10 +2781,11 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
                return;
        }
 
-       rc = security_context_to_sid(value, size, &newsid);
+       rc = security_context_to_sid_force(value, size, &newsid);
        if (rc) {
-               printk(KERN_WARNING "%s:  unable to obtain SID for context "
-                      "%s, rc=%d\n", __func__, (char *)value, -rc);
+               printk(KERN_ERR "SELinux:  unable to map context to SID"
+                      "for (%s, %lu), rc=%d\n",
+                      inode->i_sb->s_id, inode->i_ino, -rc);
                return;
        }
 
@@ -2735,9 +2814,7 @@ static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
 }
 
 /*
- * Copy the in-core inode security context value to the user.  If the
- * getxattr() prior to this succeeded, check to see if we need to
- * canonicalize the value to be finally returned to the user.
+ * Copy the inode security context value to the user.
  *
  * Permission check is handled by selinux_inode_getxattr hook.
  */
@@ -2746,12 +2823,33 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
        u32 size;
        int error;
        char *context = NULL;
+       struct task_security_struct *tsec = current->security;
        struct inode_security_struct *isec = inode->i_security;
 
        if (strcmp(name, XATTR_SELINUX_SUFFIX))
                return -EOPNOTSUPP;
 
-       error = security_sid_to_context(isec->sid, &context, &size);
+       /*
+        * If the caller has CAP_MAC_ADMIN, then get the raw context
+        * value even if it is not defined by current policy; otherwise,
+        * use the in-core value under current policy.
+        * Use the non-auditing forms of the permission checks since
+        * getxattr may be called by unprivileged processes commonly
+        * and lack of permission just means that we fall back to the
+        * in-core context value, not a denial.
+        */
+       error = secondary_ops->capable(current, CAP_MAC_ADMIN);
+       if (!error)
+               error = avc_has_perm_noaudit(tsec->sid, tsec->sid,
+                                            SECCLASS_CAPABILITY2,
+                                            CAPABILITY2__MAC_ADMIN,
+                                            0,
+                                            NULL);
+       if (!error)
+               error = security_sid_to_context_force(isec->sid, &context,
+                                                     &size);
+       else
+               error = security_sid_to_context(isec->sid, &context, &size);
        if (error)
                return error;
        error = size;
@@ -2865,46 +2963,16 @@ static void selinux_file_free_security(struct file *file)
 static int selinux_file_ioctl(struct file *file, unsigned int cmd,
                              unsigned long arg)
 {
-       int error = 0;
-
-       switch (cmd) {
-       case FIONREAD:
-       /* fall through */
-       case FIBMAP:
-       /* fall through */
-       case FIGETBSZ:
-       /* fall through */
-       case EXT2_IOC_GETFLAGS:
-       /* fall through */
-       case EXT2_IOC_GETVERSION:
-               error = file_has_perm(current, file, FILE__GETATTR);
-               break;
-
-       case EXT2_IOC_SETFLAGS:
-       /* fall through */
-       case EXT2_IOC_SETVERSION:
-               error = file_has_perm(current, file, FILE__SETATTR);
-               break;
-
-       /* sys_ioctl() checks */
-       case FIONBIO:
-       /* fall through */
-       case FIOASYNC:
-               error = file_has_perm(current, file, 0);
-               break;
+       u32 av = 0;
 
-       case KDSKBENT:
-       case KDSKBSENT:
-               error = task_has_capability(current, CAP_SYS_TTY_CONFIG);
-               break;
+       if (_IOC_DIR(cmd) & _IOC_WRITE)
+               av |= FILE__WRITE;
+       if (_IOC_DIR(cmd) & _IOC_READ)
+               av |= FILE__READ;
+       if (!av)
+               av = FILE__IOCTL;
 
-       /* default case assumes that the command will go
-        * to the file's ioctl() function.
-        */
-       default:
-               error = file_has_perm(current, file, FILE__IOCTL);
-       }
-       return error;
+       return file_has_perm(current, file, av);
 }
 
 static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
@@ -3663,7 +3731,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                struct sockaddr_in6 *addr6 = NULL;
                unsigned short snum;
                struct sock *sk = sock->sk;
-               u32 sid, node_perm, addrlen;
+               u32 sid, node_perm;
 
                tsec = current->security;
                isec = SOCK_INODE(sock)->i_security;
@@ -3671,12 +3739,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                if (family == PF_INET) {
                        addr4 = (struct sockaddr_in *)address;
                        snum = ntohs(addr4->sin_port);
-                       addrlen = sizeof(addr4->sin_addr.s_addr);
                        addrp = (char *)&addr4->sin_addr.s_addr;
                } else {
                        addr6 = (struct sockaddr_in6 *)address;
                        snum = ntohs(addr6->sin6_port);
-                       addrlen = sizeof(addr6->sin6_addr.s6_addr);
                        addrp = (char *)&addr6->sin6_addr.s6_addr;
                }
 
@@ -5047,24 +5113,6 @@ static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
        *secid = isec->sid;
 }
 
-/* module stacking operations */
-static int selinux_register_security(const char *name, struct security_operations *ops)
-{
-       if (secondary_ops != original_ops) {
-               printk(KERN_ERR "%s:  There is already a secondary security "
-                      "module registered.\n", __func__);
-               return -EINVAL;
-       }
-
-       secondary_ops = ops;
-
-       printk(KERN_INFO "%s:  Registering secondary module %s\n",
-              __func__,
-              name);
-
-       return 0;
-}
-
 static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
 {
        if (inode)
@@ -5153,6 +5201,12 @@ static int selinux_setprocattr(struct task_struct *p,
                        size--;
                }
                error = security_context_to_sid(value, size, &sid);
+               if (error == -EINVAL && !strcmp(name, "fscreate")) {
+                       if (!capable(CAP_MAC_ADMIN))
+                               return error;
+                       error = security_context_to_sid_force(value, size,
+                                                             &sid);
+               }
                if (error)
                        return error;
        }
@@ -5186,12 +5240,12 @@ static int selinux_setprocattr(struct task_struct *p,
                        struct task_struct *g, *t;
                        struct mm_struct *mm = p->mm;
                        read_lock(&tasklist_lock);
-                       do_each_thread(g, t)
+                       do_each_thread(g, t) {
                                if (t->mm == mm && t != p) {
                                        read_unlock(&tasklist_lock);
                                        return -EPERM;
                                }
-                       while_each_thread(g, t);
+                       while_each_thread(g, t);
                        read_unlock(&tasklist_lock);
                }
 
@@ -5343,10 +5397,10 @@ static struct security_operations selinux_ops = {
        .sb_free_security =             selinux_sb_free_security,
        .sb_copy_data =                 selinux_sb_copy_data,
        .sb_kern_mount =                selinux_sb_kern_mount,
+       .sb_show_options =              selinux_sb_show_options,
        .sb_statfs =                    selinux_sb_statfs,
        .sb_mount =                     selinux_mount,
        .sb_umount =                    selinux_umount,
-       .sb_get_mnt_opts =              selinux_get_mnt_opts,
        .sb_set_mnt_opts =              selinux_set_mnt_opts,
        .sb_clone_mnt_opts =            selinux_sb_clone_mnt_opts,
        .sb_parse_opts_str =            selinux_parse_opts_str,
@@ -5378,7 +5432,7 @@ static struct security_operations selinux_ops = {
        .inode_listsecurity =           selinux_inode_listsecurity,
        .inode_need_killpriv =          selinux_inode_need_killpriv,
        .inode_killpriv =               selinux_inode_killpriv,
-       .inode_getsecid =               selinux_inode_getsecid,
+       .inode_getsecid =               selinux_inode_getsecid,
 
        .file_permission =              selinux_file_permission,
        .file_alloc_security =          selinux_file_alloc_security,
@@ -5419,7 +5473,7 @@ static struct security_operations selinux_ops = {
        .task_to_inode =                selinux_task_to_inode,
 
        .ipc_permission =               selinux_ipc_permission,
-       .ipc_getsecid =                 selinux_ipc_getsecid,
+       .ipc_getsecid =                 selinux_ipc_getsecid,
 
        .msg_msg_alloc_security =       selinux_msg_msg_alloc_security,
        .msg_msg_free_security =        selinux_msg_msg_free_security,
@@ -5443,8 +5497,6 @@ static struct security_operations selinux_ops = {
        .sem_semctl =                   selinux_sem_semctl,
        .sem_semop =                    selinux_sem_semop,
 
-       .register_security =            selinux_register_security,
-
        .d_instantiate =                selinux_d_instantiate,
 
        .getprocattr =                  selinux_getprocattr,
@@ -5538,7 +5590,7 @@ static __init int selinux_init(void)
                                            0, SLAB_PANIC, NULL);
        avc_init();
 
-       original_ops = secondary_ops = security_ops;
+       secondary_ops = security_ops;
        if (!secondary_ops)
                panic("SELinux: No initial security operations\n");
        if (register_security(&selinux_ops))
index 6c8b9ef15579095764c4592377128a0db5f350db..1bdf973433cc20c7d5dc74fe8172047ce965d48a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SELinux support for the Audit LSM hooks
  *
- * Most of below header was moved from include/linux/selinux.h which 
+ * Most of below header was moved from include/linux/selinux.h which
  * is released under below copyrights:
  *
  * Author: James Morris <jmorris@redhat.com>
@@ -52,7 +52,7 @@ void selinux_audit_rule_free(void *rule);
  *     -errno on failure.
  */
 int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule,
-                             struct audit_context *actx);
+                            struct audit_context *actx);
 
 /**
  *     selinux_audit_rule_known - check to see if rule contains selinux fields.
index 8e23d7a873a4a3453d77bb87b235a2ebcd137649..7b9769f5e775e1dcacd24292aa2ba43d60e38691 100644 (file)
@@ -75,13 +75,12 @@ struct avc_audit_data {
 
 /* Initialize an AVC audit data structure. */
 #define AVC_AUDIT_DATA_INIT(_d,_t) \
-        { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; }
+       { memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; }
 
 /*
  * AVC statistics
  */
-struct avc_cache_stats
-{
+struct avc_cache_stats {
        unsigned int lookups;
        unsigned int hits;
        unsigned int misses;
@@ -97,8 +96,8 @@ struct avc_cache_stats
 void __init avc_init(void);
 
 void avc_audit(u32 ssid, u32 tsid,
-               u16 tclass, u32 requested,
-               struct av_decision *avd, int result, struct avc_audit_data *auditdata);
+              u16 tclass, u32 requested,
+              struct av_decision *avd, int result, struct avc_audit_data *auditdata);
 
 #define AVC_STRICT 1 /* Ignore permissive mode. */
 int avc_has_perm_noaudit(u32 ssid, u32 tsid,
@@ -107,8 +106,8 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
                         struct av_decision *avd);
 
 int avc_has_perm(u32 ssid, u32 tsid,
-                 u16 tclass, u32 requested,
-                 struct avc_audit_data *auditdata);
+                u16 tclass, u32 requested,
+                struct avc_audit_data *auditdata);
 
 u32 avc_policy_seqno(void);
 
@@ -122,7 +121,7 @@ u32 avc_policy_seqno(void);
 #define AVC_CALLBACK_AUDITDENY_DISABLE 128
 
 int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
-                                     u16 tclass, u32 perms,
+                                    u16 tclass, u32 perms,
                                     u32 *out_retained),
                     u32 events, u32 ssid, u32 tsid,
                     u16 tclass, u32 perms);
index 032c2357dad1d4cef675bfc05a5e2ebb567cee7e..91070ab874ce8b1255fadfff9f99aac0ce5bcc60 100644 (file)
@@ -44,7 +44,6 @@ struct inode_security_struct {
        u16 sclass;             /* security class of this object */
        unsigned char initialized;      /* initialization flag */
        struct mutex lock;
-       unsigned char inherit;  /* inherit SID from parent entry */
 };
 
 struct file_security_struct {
index ad30ac4273d629b37e9f93ae2cbf143db36fc4f0..44cba2e21dcf2a9e65f273be89ae970d01d78f5a 100644 (file)
@@ -93,12 +93,17 @@ int security_change_sid(u32 ssid, u32 tsid,
 int security_sid_to_context(u32 sid, char **scontext,
        u32 *scontext_len);
 
+int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len);
+
 int security_context_to_sid(const char *scontext, u32 scontext_len,
        u32 *out_sid);
 
 int security_context_to_sid_default(const char *scontext, u32 scontext_len,
                                    u32 *out_sid, u32 def_sid, gfp_t gfp_flags);
 
+int security_context_to_sid_force(const char *scontext, u32 scontext_len,
+                                 u32 *sid);
+
 int security_get_user_sids(u32 callsid, char *username,
                           u32 **sids, u32 *nel);
 
@@ -131,7 +136,7 @@ int security_get_allow_unknown(void);
 #define SECURITY_FS_USE_MNTPOINT       6 /* use mountpoint labeling */
 
 int security_fs_use(const char *fstype, unsigned int *behavior,
-       u32 *sid);
+       u32 *sid, bool can_xattr);
 
 int security_genfs_sid(const char *fstype, char *name, u16 sclass,
        u32 *sid);
index b6ccd09379f15456c04e32c89dca4c5119baf128..7100072bb1b0c88f56f4b9e50a48fa675338e297 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/ipv6.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
-#include <asm/bug.h>
 
 #include "netnode.h"
 #include "objsec.h"
index 90b4cff7c350280e151d8ba6fd65fc09775c92fd..fe7fba67f19f0dd2c0b2c96c5a736ecb15bd362d 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/ipv6.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
-#include <asm/bug.h>
 
 #include "netport.h"
 #include "objsec.h"
@@ -272,7 +271,7 @@ static __init int sel_netport_init(void)
        }
 
        ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET,
-                              SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+                              SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
        if (ret != 0)
                panic("avc_add_callback() failed, error %d\n", ret);
 
index ac1ccc13a704cfaffc87a334a03388bf7f0a2d45..69c9dccc8cf0a116beecd3b093950f5c9a33b791 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/seq_file.h>
 #include <linux/percpu.h>
 #include <linux/audit.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* selinuxfs pseudo filesystem for exporting the security policy API.
    Based on the proc code and the fs/nfsd/nfsctl.c code. */
@@ -57,14 +57,18 @@ int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
 
 static int __init checkreqprot_setup(char *str)
 {
-       selinux_checkreqprot = simple_strtoul(str, NULL, 0) ? 1 : 0;
+       unsigned long checkreqprot;
+       if (!strict_strtoul(str, 0, &checkreqprot))
+               selinux_checkreqprot = checkreqprot ? 1 : 0;
        return 1;
 }
 __setup("checkreqprot=", checkreqprot_setup);
 
 static int __init selinux_compat_net_setup(char *str)
 {
-       selinux_compat_net = simple_strtoul(str, NULL, 0) ? 1 : 0;
+       unsigned long compat_net;
+       if (!strict_strtoul(str, 0, &compat_net))
+               selinux_compat_net = compat_net ? 1 : 0;
        return 1;
 }
 __setup("selinux_compat_net=", selinux_compat_net_setup);
@@ -352,11 +356,6 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
                length = count;
 
 out1:
-
-       printk(KERN_INFO "SELinux: policy loaded with handle_unknown=%s\n",
-              (security_get_reject_unknown() ? "reject" :
-               (security_get_allow_unknown() ? "allow" : "deny")));
-
        audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
                "policy loaded auid=%u ses=%u",
                audit_get_loginuid(current),
index 9e6626362bfd3504af65120b5d1090a064fcd620..a1be97f8beea0ac0aa0fa7519801128b6eb54b62 100644 (file)
@@ -311,7 +311,7 @@ void avtab_hash_eval(struct avtab *h, char *tag)
        }
 
        printk(KERN_DEBUG "SELinux: %s:  %d entries and %d/%d buckets used, "
-              "longest chain length %d sum of chain length^2 %Lu\n",
+              "longest chain length %d sum of chain length^2 %llu\n",
               tag, h->nel, slots_used, h->nslot, max_chain_len,
               chain2_len_sum);
 }
index b9a6f7fc62fca2b0b251ccb2843f60655426c944..658c2bd17da8eb4437f306a87d37ff0195b4b731 100644 (file)
@@ -28,6 +28,8 @@ struct context {
        u32 role;
        u32 type;
        struct mls_range range;
+       char *str;      /* string representation if context cannot be mapped. */
+       u32 len;        /* length of string in bytes */
 };
 
 static inline void mls_context_init(struct context *c)
@@ -106,20 +108,43 @@ static inline void context_init(struct context *c)
 
 static inline int context_cpy(struct context *dst, struct context *src)
 {
+       int rc;
+
        dst->user = src->user;
        dst->role = src->role;
        dst->type = src->type;
-       return mls_context_cpy(dst, src);
+       if (src->str) {
+               dst->str = kstrdup(src->str, GFP_ATOMIC);
+               if (!dst->str)
+                       return -ENOMEM;
+               dst->len = src->len;
+       } else {
+               dst->str = NULL;
+               dst->len = 0;
+       }
+       rc = mls_context_cpy(dst, src);
+       if (rc) {
+               kfree(dst->str);
+               return rc;
+       }
+       return 0;
 }
 
 static inline void context_destroy(struct context *c)
 {
        c->user = c->role = c->type = 0;
+       kfree(c->str);
+       c->str = NULL;
+       c->len = 0;
        mls_context_destroy(c);
 }
 
 static inline int context_cmp(struct context *c1, struct context *c2)
 {
+       if (c1->len && c2->len)
+               return (c1->len == c2->len && !strcmp(c1->str, c2->str));
+       if (c1->len || c2->len)
+               return 0;
        return ((c1->user == c2->user) &&
                (c1->role == c2->role) &&
                (c1->type == c2->type) &&
index 8b1706b7b3ccc72dc6c373423a66f0b012fc1a39..77d745da48bb6e4c2153fc3a64852b9c08f80e51 100644 (file)
@@ -239,7 +239,8 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
  * Policy read-lock must be held for sidtab lookup.
  *
  */
-int mls_context_to_sid(char oldc,
+int mls_context_to_sid(struct policydb *pol,
+                      char oldc,
                       char **scontext,
                       struct context *context,
                       struct sidtab *s,
@@ -286,7 +287,7 @@ int mls_context_to_sid(char oldc,
                *p++ = 0;
 
        for (l = 0; l < 2; l++) {
-               levdatum = hashtab_search(policydb.p_levels.table, scontextp);
+               levdatum = hashtab_search(pol->p_levels.table, scontextp);
                if (!levdatum) {
                        rc = -EINVAL;
                        goto out;
@@ -311,7 +312,7 @@ int mls_context_to_sid(char oldc,
                                        *rngptr++ = 0;
                                }
 
-                               catdatum = hashtab_search(policydb.p_cats.table,
+                               catdatum = hashtab_search(pol->p_cats.table,
                                                          scontextp);
                                if (!catdatum) {
                                        rc = -EINVAL;
@@ -327,7 +328,7 @@ int mls_context_to_sid(char oldc,
                                if (rngptr) {
                                        int i;
 
-                                       rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
+                                       rngdatum = hashtab_search(pol->p_cats.table, rngptr);
                                        if (!rngdatum) {
                                                rc = -EINVAL;
                                                goto out;
@@ -395,7 +396,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
        if (!tmpstr) {
                rc = -ENOMEM;
        } else {
-               rc = mls_context_to_sid(':', &tmpstr, context,
+               rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
                                        NULL, SECSID_NULL);
                kfree(freestr);
        }
@@ -436,13 +437,13 @@ int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
                struct mls_level *usercon_clr = &(usercon->range.level[1]);
 
                /* Honor the user's default level if we can */
-               if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) {
+               if (mls_level_between(user_def, fromcon_sen, fromcon_clr))
                        *usercon_sen = *user_def;
-               } else if (mls_level_between(fromcon_sen, user_def, user_clr)) {
+               else if (mls_level_between(fromcon_sen, user_def, user_clr))
                        *usercon_sen = *fromcon_sen;
-               } else if (mls_level_between(fromcon_clr, user_low, user_def)) {
+               else if (mls_level_between(fromcon_clr, user_low, user_def))
                        *usercon_sen = *user_low;
-               else
+               else
                        return -EINVAL;
 
                /* Lower the clearance of available contexts
index 0fdf6257ef6429928eed044d33d9b025ecda7b49..1276715aaa8bf3f0aac5973022f38e98388b0605 100644 (file)
@@ -30,7 +30,8 @@ int mls_context_isvalid(struct policydb *p, struct context *c);
 int mls_range_isvalid(struct policydb *p, struct mls_range *r);
 int mls_level_isvalid(struct policydb *p, struct mls_level *l);
 
-int mls_context_to_sid(char oldc,
+int mls_context_to_sid(struct policydb *p,
+                      char oldc,
                       char **scontext,
                       struct context *context,
                       struct sidtab *s,
index 84f8cc73c7db64c9b358784a5f85e4185b6ac2e4..2391761ae42248806d92b2d2e220f5b1dd7ae6ea 100644 (file)
@@ -1478,7 +1478,8 @@ int policydb_read(struct policydb *p, void *fp)
        struct ocontext *l, *c, *newc;
        struct genfs *genfs_p, *genfs, *newgenfs;
        int i, j, rc;
-       __le32 buf[8];
+       __le32 buf[4];
+       u32 nodebuf[8];
        u32 len, len2, config, nprim, nel, nel2;
        char *policydb_str;
        struct policydb_compat_info *info;
@@ -1749,11 +1750,11 @@ int policydb_read(struct policydb *p, void *fp)
                                        goto bad;
                                break;
                        case OCON_NODE:
-                               rc = next_entry(buf, fp, sizeof(u32) * 2);
+                               rc = next_entry(nodebuf, fp, sizeof(u32) * 2);
                                if (rc < 0)
                                        goto bad;
-                               c->u.node.addr = le32_to_cpu(buf[0]);
-                               c->u.node.mask = le32_to_cpu(buf[1]);
+                               c->u.node.addr = nodebuf[0]; /* network order */
+                               c->u.node.mask = nodebuf[1]; /* network order */
                                rc = context_read_and_validate(&c->context[0], p, fp);
                                if (rc)
                                        goto bad;
@@ -1782,13 +1783,13 @@ int policydb_read(struct policydb *p, void *fp)
                        case OCON_NODE6: {
                                int k;
 
-                               rc = next_entry(buf, fp, sizeof(u32) * 8);
+                               rc = next_entry(nodebuf, fp, sizeof(u32) * 8);
                                if (rc < 0)
                                        goto bad;
                                for (k = 0; k < 4; k++)
-                                       c->u.node6.addr[k] = le32_to_cpu(buf[k]);
+                                       c->u.node6.addr[k] = nodebuf[k];
                                for (k = 0; k < 4; k++)
-                                       c->u.node6.mask[k] = le32_to_cpu(buf[k+4]);
+                                       c->u.node6.mask[k] = nodebuf[k+4];
                                if (context_read_and_validate(&c->context[0], p, fp))
                                        goto bad;
                                break;
index dcc2e1c4fd83df58438bfd8592da112bfaa4b28d..8e42da120101432885fa63ac1b867c6f8c227d0e 100644 (file)
@@ -71,14 +71,6 @@ int selinux_policycap_openperm;
 extern const struct selinux_class_perm selinux_class_perm;
 
 static DEFINE_RWLOCK(policy_rwlock);
-#define POLICY_RDLOCK read_lock(&policy_rwlock)
-#define POLICY_WRLOCK write_lock_irq(&policy_rwlock)
-#define POLICY_RDUNLOCK read_unlock(&policy_rwlock)
-#define POLICY_WRUNLOCK write_unlock_irq(&policy_rwlock)
-
-static DEFINE_MUTEX(load_mutex);
-#define LOAD_LOCK mutex_lock(&load_mutex)
-#define LOAD_UNLOCK mutex_unlock(&load_mutex)
 
 static struct sidtab sidtab;
 struct policydb policydb;
@@ -332,7 +324,7 @@ static int context_struct_compute_av(struct context *scontext,
                goto inval_class;
        if (unlikely(tclass > policydb.p_classes.nprim))
                if (tclass > kdefs->cts_len ||
-                   !kdefs->class_to_string[tclass - 1] ||
+                   !kdefs->class_to_string[tclass] ||
                    !policydb.allow_unknown)
                        goto inval_class;
 
@@ -415,9 +407,19 @@ static int context_struct_compute_av(struct context *scontext,
        return 0;
 
 inval_class:
-       printk(KERN_ERR "SELinux: %s:  unrecognized class %d\n", __func__,
-               tclass);
-       return -EINVAL;
+       if (!tclass || tclass > kdefs->cts_len ||
+           !kdefs->class_to_string[tclass]) {
+               if (printk_ratelimit())
+                       printk(KERN_ERR "SELinux: %s:  unrecognized class %d\n",
+                              __func__, tclass);
+               return -EINVAL;
+       }
+
+       /*
+        * Known to the kernel, but not to the policy.
+        * Handle as a denial (allowed is 0).
+        */
+       return 0;
 }
 
 /*
@@ -429,7 +431,7 @@ int security_permissive_sid(u32 sid)
        u32 type;
        int rc;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        context = sidtab_search(&sidtab, sid);
        BUG_ON(!context);
@@ -441,7 +443,7 @@ int security_permissive_sid(u32 sid)
         */
        rc = ebitmap_get_bit(&policydb.permissive_map, type);
 
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 }
 
@@ -486,7 +488,7 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
        if (!ss_initialized)
                return 0;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        /*
         * Remap extended Netlink classes for old policy versions.
@@ -543,7 +545,7 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
        }
 
 out:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 }
 
@@ -578,7 +580,7 @@ int security_compute_av(u32 ssid,
                return 0;
        }
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        scontext = sidtab_search(&sidtab, ssid);
        if (!scontext) {
@@ -598,7 +600,7 @@ int security_compute_av(u32 ssid,
        rc = context_struct_compute_av(scontext, tcontext, tclass,
                                       requested, avd);
 out:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 }
 
@@ -616,6 +618,14 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
        *scontext = NULL;
        *scontext_len = 0;
 
+       if (context->len) {
+               *scontext_len = context->len;
+               *scontext = kstrdup(context->str, GFP_ATOMIC);
+               if (!(*scontext))
+                       return -ENOMEM;
+               return 0;
+       }
+
        /* Compute the size of the context. */
        *scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1;
        *scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1;
@@ -655,17 +665,8 @@ const char *security_get_initial_sid_context(u32 sid)
        return initial_sid_to_string[sid];
 }
 
-/**
- * security_sid_to_context - Obtain a context for a given SID.
- * @sid: security identifier, SID
- * @scontext: security context
- * @scontext_len: length in bytes
- *
- * Write the string representation of the context associated with @sid
- * into a dynamically allocated string of the correct size.  Set @scontext
- * to point to this string and set @scontext_len to the length of the string.
- */
-int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
+static int security_sid_to_context_core(u32 sid, char **scontext,
+                                       u32 *scontext_len, int force)
 {
        struct context *context;
        int rc = 0;
@@ -692,8 +693,11 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
                rc = -EINVAL;
                goto out;
        }
-       POLICY_RDLOCK;
-       context = sidtab_search(&sidtab, sid);
+       read_lock(&policy_rwlock);
+       if (force)
+               context = sidtab_search_force(&sidtab, sid);
+       else
+               context = sidtab_search(&sidtab, sid);
        if (!context) {
                printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
                        __func__, sid);
@@ -702,59 +706,54 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
        }
        rc = context_struct_to_string(context, scontext, scontext_len);
 out_unlock:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
 out:
        return rc;
 
 }
 
-static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
-                                       u32 *sid, u32 def_sid, gfp_t gfp_flags)
+/**
+ * security_sid_to_context - Obtain a context for a given SID.
+ * @sid: security identifier, SID
+ * @scontext: security context
+ * @scontext_len: length in bytes
+ *
+ * Write the string representation of the context associated with @sid
+ * into a dynamically allocated string of the correct size.  Set @scontext
+ * to point to this string and set @scontext_len to the length of the string.
+ */
+int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
+{
+       return security_sid_to_context_core(sid, scontext, scontext_len, 0);
+}
+
+int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len)
+{
+       return security_sid_to_context_core(sid, scontext, scontext_len, 1);
+}
+
+/*
+ * Caveat:  Mutates scontext.
+ */
+static int string_to_context_struct(struct policydb *pol,
+                                   struct sidtab *sidtabp,
+                                   char *scontext,
+                                   u32 scontext_len,
+                                   struct context *ctx,
+                                   u32 def_sid)
 {
-       char *scontext2;
-       struct context context;
        struct role_datum *role;
        struct type_datum *typdatum;
        struct user_datum *usrdatum;
        char *scontextp, *p, oldc;
        int rc = 0;
 
-       if (!ss_initialized) {
-               int i;
-
-               for (i = 1; i < SECINITSID_NUM; i++) {
-                       if (!strcmp(initial_sid_to_string[i], scontext)) {
-                               *sid = i;
-                               goto out;
-                       }
-               }
-               *sid = SECINITSID_KERNEL;
-               goto out;
-       }
-       *sid = SECSID_NULL;
-
-       /* Copy the string so that we can modify the copy as we parse it.
-          The string should already by null terminated, but we append a
-          null suffix to the copy to avoid problems with the existing
-          attr package, which doesn't view the null terminator as part
-          of the attribute value. */
-       scontext2 = kmalloc(scontext_len+1, gfp_flags);
-       if (!scontext2) {
-               rc = -ENOMEM;
-               goto out;
-       }
-       memcpy(scontext2, scontext, scontext_len);
-       scontext2[scontext_len] = 0;
-
-       context_init(&context);
-       *sid = SECSID_NULL;
-
-       POLICY_RDLOCK;
+       context_init(ctx);
 
        /* Parse the security context. */
 
        rc = -EINVAL;
-       scontextp = (char *) scontext2;
+       scontextp = (char *) scontext;
 
        /* Extract the user. */
        p = scontextp;
@@ -762,15 +761,15 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
                p++;
 
        if (*p == 0)
-               goto out_unlock;
+               goto out;
 
        *p++ = 0;
 
-       usrdatum = hashtab_search(policydb.p_users.table, scontextp);
+       usrdatum = hashtab_search(pol->p_users.table, scontextp);
        if (!usrdatum)
-               goto out_unlock;
+               goto out;
 
-       context.user = usrdatum->value;
+       ctx->user = usrdatum->value;
 
        /* Extract role. */
        scontextp = p;
@@ -778,14 +777,14 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
                p++;
 
        if (*p == 0)
-               goto out_unlock;
+               goto out;
 
        *p++ = 0;
 
-       role = hashtab_search(policydb.p_roles.table, scontextp);
+       role = hashtab_search(pol->p_roles.table, scontextp);
        if (!role)
-               goto out_unlock;
-       context.role = role->value;
+               goto out;
+       ctx->role = role->value;
 
        /* Extract type. */
        scontextp = p;
@@ -794,33 +793,87 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
        oldc = *p;
        *p++ = 0;
 
-       typdatum = hashtab_search(policydb.p_types.table, scontextp);
+       typdatum = hashtab_search(pol->p_types.table, scontextp);
        if (!typdatum)
-               goto out_unlock;
+               goto out;
 
-       context.type = typdatum->value;
+       ctx->type = typdatum->value;
 
-       rc = mls_context_to_sid(oldc, &p, &context, &sidtab, def_sid);
+       rc = mls_context_to_sid(pol, oldc, &p, ctx, sidtabp, def_sid);
        if (rc)
-               goto out_unlock;
+               goto out;
 
-       if ((p - scontext2) < scontext_len) {
+       if ((p - scontext) < scontext_len) {
                rc = -EINVAL;
-               goto out_unlock;
+               goto out;
        }
 
        /* Check the validity of the new context. */
-       if (!policydb_context_isvalid(&policydb, &context)) {
+       if (!policydb_context_isvalid(pol, ctx)) {
                rc = -EINVAL;
-               goto out_unlock;
+               context_destroy(ctx);
+               goto out;
        }
-       /* Obtain the new sid. */
+       rc = 0;
+out:
+       return rc;
+}
+
+static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
+                                       u32 *sid, u32 def_sid, gfp_t gfp_flags,
+                                       int force)
+{
+       char *scontext2, *str = NULL;
+       struct context context;
+       int rc = 0;
+
+       if (!ss_initialized) {
+               int i;
+
+               for (i = 1; i < SECINITSID_NUM; i++) {
+                       if (!strcmp(initial_sid_to_string[i], scontext)) {
+                               *sid = i;
+                               return 0;
+                       }
+               }
+               *sid = SECINITSID_KERNEL;
+               return 0;
+       }
+       *sid = SECSID_NULL;
+
+       /* Copy the string so that we can modify the copy as we parse it. */
+       scontext2 = kmalloc(scontext_len+1, gfp_flags);
+       if (!scontext2)
+               return -ENOMEM;
+       memcpy(scontext2, scontext, scontext_len);
+       scontext2[scontext_len] = 0;
+
+       if (force) {
+               /* Save another copy for storing in uninterpreted form */
+               str = kstrdup(scontext2, gfp_flags);
+               if (!str) {
+                       kfree(scontext2);
+                       return -ENOMEM;
+               }
+       }
+
+       read_lock(&policy_rwlock);
+       rc = string_to_context_struct(&policydb, &sidtab,
+                                     scontext2, scontext_len,
+                                     &context, def_sid);
+       if (rc == -EINVAL && force) {
+               context.str = str;
+               context.len = scontext_len;
+               str = NULL;
+       } else if (rc)
+               goto out;
        rc = sidtab_context_to_sid(&sidtab, &context, sid);
-out_unlock:
-       POLICY_RDUNLOCK;
-       context_destroy(&context);
-       kfree(scontext2);
+       if (rc)
+               context_destroy(&context);
 out:
+       read_unlock(&policy_rwlock);
+       kfree(scontext2);
+       kfree(str);
        return rc;
 }
 
@@ -838,7 +891,7 @@ out:
 int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid)
 {
        return security_context_to_sid_core(scontext, scontext_len,
-                                           sid, SECSID_NULL, GFP_KERNEL);
+                                           sid, SECSID_NULL, GFP_KERNEL, 0);
 }
 
 /**
@@ -855,6 +908,7 @@ int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid)
  * The default SID is passed to the MLS layer to be used to allow
  * kernel labeling of the MLS field if the MLS field is not present
  * (for upgrading to MLS without full relabel).
+ * Implicitly forces adding of the context even if it cannot be mapped yet.
  * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
  * memory is available, or 0 on success.
  */
@@ -862,7 +916,14 @@ int security_context_to_sid_default(const char *scontext, u32 scontext_len,
                                    u32 *sid, u32 def_sid, gfp_t gfp_flags)
 {
        return security_context_to_sid_core(scontext, scontext_len,
-                                           sid, def_sid, gfp_flags);
+                                           sid, def_sid, gfp_flags, 1);
+}
+
+int security_context_to_sid_force(const char *scontext, u32 scontext_len,
+                                 u32 *sid)
+{
+       return security_context_to_sid_core(scontext, scontext_len,
+                                           sid, SECSID_NULL, GFP_KERNEL, 1);
 }
 
 static int compute_sid_handle_invalid_context(
@@ -922,7 +983,7 @@ static int security_compute_sid(u32 ssid,
 
        context_init(&newcontext);
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        scontext = sidtab_search(&sidtab, ssid);
        if (!scontext) {
@@ -1027,7 +1088,7 @@ static int security_compute_sid(u32 ssid,
        /* Obtain the sid for the context. */
        rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
 out_unlock:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        context_destroy(&newcontext);
 out:
        return rc;
@@ -1110,6 +1171,7 @@ static int validate_classes(struct policydb *p)
        const struct selinux_class_perm *kdefs = &selinux_class_perm;
        const char *def_class, *def_perm, *pol_class;
        struct symtab *perms;
+       bool print_unknown_handle = 0;
 
        if (p->allow_unknown) {
                u32 num_classes = kdefs->cts_len;
@@ -1130,6 +1192,7 @@ static int validate_classes(struct policydb *p)
                                return -EINVAL;
                        if (p->allow_unknown)
                                p->undefined_perms[i-1] = ~0U;
+                       print_unknown_handle = 1;
                        continue;
                }
                pol_class = p->p_class_val_to_name[i-1];
@@ -1159,6 +1222,7 @@ static int validate_classes(struct policydb *p)
                                return -EINVAL;
                        if (p->allow_unknown)
                                p->undefined_perms[class_val-1] |= perm_val;
+                       print_unknown_handle = 1;
                        continue;
                }
                perdatum = hashtab_search(perms->table, def_perm);
@@ -1206,6 +1270,7 @@ static int validate_classes(struct policydb *p)
                                        return -EINVAL;
                                if (p->allow_unknown)
                                        p->undefined_perms[class_val-1] |= (1 << j);
+                               print_unknown_handle = 1;
                                continue;
                        }
                        perdatum = hashtab_search(perms->table, def_perm);
@@ -1223,6 +1288,9 @@ static int validate_classes(struct policydb *p)
                        }
                }
        }
+       if (print_unknown_handle)
+               printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n",
+                       (security_get_allow_unknown() ? "allowed" : "denied"));
        return 0;
 }
 
@@ -1246,9 +1314,12 @@ static inline int convert_context_handle_invalid_context(struct context *context
                char *s;
                u32 len;
 
-               context_struct_to_string(context, &s, &len);
-               printk(KERN_ERR "SELinux:  context %s is invalid\n", s);
-               kfree(s);
+               if (!context_struct_to_string(context, &s, &len)) {
+                       printk(KERN_WARNING
+                      "SELinux:  Context %s would be invalid if enforcing\n",
+                              s);
+                       kfree(s);
+               }
        }
        return rc;
 }
@@ -1280,6 +1351,37 @@ static int convert_context(u32 key,
 
        args = p;
 
+       if (c->str) {
+               struct context ctx;
+               s = kstrdup(c->str, GFP_KERNEL);
+               if (!s) {
+                       rc = -ENOMEM;
+                       goto out;
+               }
+               rc = string_to_context_struct(args->newp, NULL, s,
+                                             c->len, &ctx, SECSID_NULL);
+               kfree(s);
+               if (!rc) {
+                       printk(KERN_INFO
+                      "SELinux:  Context %s became valid (mapped).\n",
+                              c->str);
+                       /* Replace string with mapped representation. */
+                       kfree(c->str);
+                       memcpy(c, &ctx, sizeof(*c));
+                       goto out;
+               } else if (rc == -EINVAL) {
+                       /* Retain string representation for later mapping. */
+                       rc = 0;
+                       goto out;
+               } else {
+                       /* Other error condition, e.g. ENOMEM. */
+                       printk(KERN_ERR
+                      "SELinux:   Unable to map context %s, rc = %d.\n",
+                              c->str, -rc);
+                       goto out;
+               }
+       }
+
        rc = context_cpy(&oldc, c);
        if (rc)
                goto out;
@@ -1319,13 +1421,21 @@ static int convert_context(u32 key,
        }
 
        context_destroy(&oldc);
+       rc = 0;
 out:
        return rc;
 bad:
-       context_struct_to_string(&oldc, &s, &len);
+       /* Map old representation to string and save it. */
+       if (context_struct_to_string(&oldc, &s, &len))
+               return -ENOMEM;
        context_destroy(&oldc);
-       printk(KERN_ERR "SELinux:  invalidating context %s\n", s);
-       kfree(s);
+       context_destroy(c);
+       c->str = s;
+       c->len = len;
+       printk(KERN_INFO
+              "SELinux:  Context %s became invalid (unmapped).\n",
+              c->str);
+       rc = 0;
        goto out;
 }
 
@@ -1359,17 +1469,13 @@ int security_load_policy(void *data, size_t len)
        int rc = 0;
        struct policy_file file = { data, len }, *fp = &file;
 
-       LOAD_LOCK;
-
        if (!ss_initialized) {
                avtab_cache_init();
                if (policydb_read(&policydb, fp)) {
-                       LOAD_UNLOCK;
                        avtab_cache_destroy();
                        return -EINVAL;
                }
                if (policydb_load_isids(&policydb, &sidtab)) {
-                       LOAD_UNLOCK;
                        policydb_destroy(&policydb);
                        avtab_cache_destroy();
                        return -EINVAL;
@@ -1378,7 +1484,6 @@ int security_load_policy(void *data, size_t len)
                if (validate_classes(&policydb)) {
                        printk(KERN_ERR
                               "SELinux:  the definition of a class is incorrect\n");
-                       LOAD_UNLOCK;
                        sidtab_destroy(&sidtab);
                        policydb_destroy(&policydb);
                        avtab_cache_destroy();
@@ -1388,7 +1493,6 @@ int security_load_policy(void *data, size_t len)
                policydb_loaded_version = policydb.policyvers;
                ss_initialized = 1;
                seqno = ++latest_granting;
-               LOAD_UNLOCK;
                selinux_complete_init();
                avc_ss_reset(seqno);
                selnl_notify_policyload(seqno);
@@ -1401,12 +1505,13 @@ int security_load_policy(void *data, size_t len)
        sidtab_hash_eval(&sidtab, "sids");
 #endif
 
-       if (policydb_read(&newpolicydb, fp)) {
-               LOAD_UNLOCK;
+       if (policydb_read(&newpolicydb, fp))
                return -EINVAL;
-       }
 
-       sidtab_init(&newsidtab);
+       if (sidtab_init(&newsidtab)) {
+               policydb_destroy(&newpolicydb);
+               return -ENOMEM;
+       }
 
        /* Verify that the kernel defined classes are correct. */
        if (validate_classes(&newpolicydb)) {
@@ -1429,25 +1534,28 @@ int security_load_policy(void *data, size_t len)
                goto err;
        }
 
-       /* Convert the internal representations of contexts
-          in the new SID table and remove invalid SIDs. */
+       /*
+        * Convert the internal representations of contexts
+        * in the new SID table.
+        */
        args.oldp = &policydb;
        args.newp = &newpolicydb;
-       sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
+       rc = sidtab_map(&newsidtab, convert_context, &args);
+       if (rc)
+               goto err;
 
        /* Save the old policydb and SID table to free later. */
        memcpy(&oldpolicydb, &policydb, sizeof policydb);
        sidtab_set(&oldsidtab, &sidtab);
 
        /* Install the new policydb and SID table. */
-       POLICY_WRLOCK;
+       write_lock_irq(&policy_rwlock);
        memcpy(&policydb, &newpolicydb, sizeof policydb);
        sidtab_set(&sidtab, &newsidtab);
        security_load_policycaps();
        seqno = ++latest_granting;
        policydb_loaded_version = policydb.policyvers;
-       POLICY_WRUNLOCK;
-       LOAD_UNLOCK;
+       write_unlock_irq(&policy_rwlock);
 
        /* Free the old policydb and SID table. */
        policydb_destroy(&oldpolicydb);
@@ -1461,7 +1569,6 @@ int security_load_policy(void *data, size_t len)
        return 0;
 
 err:
-       LOAD_UNLOCK;
        sidtab_destroy(&newsidtab);
        policydb_destroy(&newpolicydb);
        return rc;
@@ -1479,7 +1586,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
        struct ocontext *c;
        int rc = 0;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        c = policydb.ocontexts[OCON_PORT];
        while (c) {
@@ -1504,7 +1611,7 @@ int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
        }
 
 out:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 }
 
@@ -1518,7 +1625,7 @@ int security_netif_sid(char *name, u32 *if_sid)
        int rc = 0;
        struct ocontext *c;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        c = policydb.ocontexts[OCON_NETIF];
        while (c) {
@@ -1545,7 +1652,7 @@ int security_netif_sid(char *name, u32 *if_sid)
                *if_sid = SECINITSID_NETIF;
 
 out:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 }
 
@@ -1577,7 +1684,7 @@ int security_node_sid(u16 domain,
        int rc = 0;
        struct ocontext *c;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        switch (domain) {
        case AF_INET: {
@@ -1632,7 +1739,7 @@ int security_node_sid(u16 domain,
        }
 
 out:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 }
 
@@ -1671,7 +1778,9 @@ int security_get_user_sids(u32 fromsid,
        if (!ss_initialized)
                goto out;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
+
+       context_init(&usercon);
 
        fromcon = sidtab_search(&sidtab, fromsid);
        if (!fromcon) {
@@ -1722,7 +1831,7 @@ int security_get_user_sids(u32 fromsid,
        }
 
 out_unlock:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        if (rc || !mynel) {
                kfree(mysids);
                goto out;
@@ -1775,7 +1884,7 @@ int security_genfs_sid(const char *fstype,
        while (path[0] == '/' && path[1] == '/')
                path++;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
                cmp = strcmp(fstype, genfs->fstype);
@@ -1812,7 +1921,7 @@ int security_genfs_sid(const char *fstype,
 
        *sid = c->sid[0];
 out:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 }
 
@@ -1825,12 +1934,13 @@ out:
 int security_fs_use(
        const char *fstype,
        unsigned int *behavior,
-       u32 *sid)
+       u32 *sid,
+       bool can_xattr)
 {
        int rc = 0;
        struct ocontext *c;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        c = policydb.ocontexts[OCON_FSUSE];
        while (c) {
@@ -1839,6 +1949,7 @@ int security_fs_use(
                c = c->next;
        }
 
+       /* look for labeling behavior defined in policy */
        if (c) {
                *behavior = c->v.behavior;
                if (!c->sid[0]) {
@@ -1849,18 +1960,27 @@ int security_fs_use(
                                goto out;
                }
                *sid = c->sid[0];
+               goto out;
+       }
+
+       /* labeling behavior not in policy, use xattrs if possible */
+       if (can_xattr) {
+               *behavior = SECURITY_FS_USE_XATTR;
+               *sid = SECINITSID_FS;
+               goto out;
+       }
+
+       /* no behavior in policy and can't use xattrs, try GENFS */
+       rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
+       if (rc) {
+               *behavior = SECURITY_FS_USE_NONE;
+               rc = 0;
        } else {
-               rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid);
-               if (rc) {
-                       *behavior = SECURITY_FS_USE_NONE;
-                       rc = 0;
-               } else {
-                       *behavior = SECURITY_FS_USE_GENFS;
-               }
+               *behavior = SECURITY_FS_USE_GENFS;
        }
 
 out:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 }
 
@@ -1868,7 +1988,7 @@ int security_get_bools(int *len, char ***names, int **values)
 {
        int i, rc = -ENOMEM;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
        *names = NULL;
        *values = NULL;
 
@@ -1898,7 +2018,7 @@ int security_get_bools(int *len, char ***names, int **values)
        }
        rc = 0;
 out:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 err:
        if (*names) {
@@ -1916,7 +2036,7 @@ int security_set_bools(int len, int *values)
        int lenp, seqno = 0;
        struct cond_node *cur;
 
-       POLICY_WRLOCK;
+       write_lock_irq(&policy_rwlock);
 
        lenp = policydb.p_bools.nprim;
        if (len != lenp) {
@@ -1950,7 +2070,7 @@ int security_set_bools(int len, int *values)
        seqno = ++latest_granting;
 
 out:
-       POLICY_WRUNLOCK;
+       write_unlock_irq(&policy_rwlock);
        if (!rc) {
                avc_ss_reset(seqno);
                selnl_notify_policyload(seqno);
@@ -1964,7 +2084,7 @@ int security_get_bool_value(int bool)
        int rc = 0;
        int len;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        len = policydb.p_bools.nprim;
        if (bool >= len) {
@@ -1974,7 +2094,7 @@ int security_get_bool_value(int bool)
 
        rc = policydb.bool_val_to_struct[bool]->state;
 out:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 }
 
@@ -2029,7 +2149,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 
        context_init(&newcon);
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
        context1 = sidtab_search(&sidtab, sid);
        if (!context1) {
                printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
@@ -2071,7 +2191,7 @@ bad:
        }
 
 out_unlock:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        context_destroy(&newcon);
 out:
        return rc;
@@ -2128,7 +2248,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
                return 0;
        }
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        nlbl_ctx = sidtab_search(&sidtab, nlbl_sid);
        if (!nlbl_ctx) {
@@ -2147,7 +2267,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
        rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES);
 
 out_slowpath:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        if (rc == 0)
                /* at present NetLabel SIDs/labels really only carry MLS
                 * information so if the MLS portion of the NetLabel SID
@@ -2177,7 +2297,7 @@ int security_get_classes(char ***classes, int *nclasses)
 {
        int rc = -ENOMEM;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        *nclasses = policydb.p_classes.nprim;
        *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC);
@@ -2194,7 +2314,7 @@ int security_get_classes(char ***classes, int *nclasses)
        }
 
 out:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 }
 
@@ -2216,7 +2336,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
        int rc = -ENOMEM, i;
        struct class_datum *match;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        match = hashtab_search(policydb.p_classes.table, class);
        if (!match) {
@@ -2244,11 +2364,11 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
                goto err;
 
 out:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 
 err:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        for (i = 0; i < *nperms; i++)
                kfree((*perms)[i]);
        kfree(*perms);
@@ -2279,9 +2399,9 @@ int security_policycap_supported(unsigned int req_cap)
 {
        int rc;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
        rc = ebitmap_get_bit(&policydb.policycaps, req_cap);
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
 
        return rc;
 }
@@ -2345,7 +2465,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 
        context_init(&tmprule->au_ctxt);
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        tmprule->au_seqno = latest_granting;
 
@@ -2382,7 +2502,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
                break;
        }
 
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
 
        if (rc) {
                selinux_audit_rule_free(tmprule);
@@ -2420,7 +2540,7 @@ int selinux_audit_rule_known(struct audit_krule *rule)
 }
 
 int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
-                             struct audit_context *actx)
+                            struct audit_context *actx)
 {
        struct context *ctxt;
        struct mls_level *level;
@@ -2433,7 +2553,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
                return -ENOENT;
        }
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        if (rule->au_seqno < latest_granting) {
                audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
@@ -2527,14 +2647,14 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
        }
 
 out:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return match;
 }
 
 static int (*aurule_callback)(void) = audit_update_lsm_rules;
 
 static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid,
-                               u16 class, u32 perms, u32 *retained)
+                              u16 class, u32 perms, u32 *retained)
 {
        int err = 0;
 
@@ -2615,7 +2735,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
                return 0;
        }
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
 
        if (secattr->flags & NETLBL_SECATTR_CACHE) {
                *sid = *(u32 *)secattr->cache->data;
@@ -2660,7 +2780,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
        }
 
 netlbl_secattr_to_sid_return:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 netlbl_secattr_to_sid_return_cleanup:
        ebitmap_destroy(&ctx_new.range.level[0].cat);
@@ -2685,7 +2805,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
        if (!ss_initialized)
                return 0;
 
-       POLICY_RDLOCK;
+       read_lock(&policy_rwlock);
        ctx = sidtab_search(&sidtab, sid);
        if (ctx == NULL)
                goto netlbl_sid_to_secattr_failure;
@@ -2696,12 +2816,12 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
        rc = mls_export_netlbl_cat(ctx, secattr);
        if (rc != 0)
                goto netlbl_sid_to_secattr_failure;
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
 
        return 0;
 
 netlbl_sid_to_secattr_failure:
-       POLICY_RDUNLOCK;
+       read_unlock(&policy_rwlock);
        return rc;
 }
 #endif /* CONFIG_NETLABEL */
index 4a516ff4bcdeb2b7e77df8a88ff57546eaef58c2..a81ded10412980ea9d4b186233210fec9b696ac2 100644 (file)
 #define SIDTAB_HASH(sid) \
 (sid & SIDTAB_HASH_MASK)
 
-#define INIT_SIDTAB_LOCK(s) spin_lock_init(&s->lock)
-#define SIDTAB_LOCK(s, x) spin_lock_irqsave(&s->lock, x)
-#define SIDTAB_UNLOCK(s, x) spin_unlock_irqrestore(&s->lock, x)
-
 int sidtab_init(struct sidtab *s)
 {
        int i;
@@ -30,7 +26,7 @@ int sidtab_init(struct sidtab *s)
        s->nel = 0;
        s->next_sid = 1;
        s->shutdown = 0;
-       INIT_SIDTAB_LOCK(s);
+       spin_lock_init(&s->lock);
        return 0;
 }
 
@@ -86,7 +82,7 @@ out:
        return rc;
 }
 
-struct context *sidtab_search(struct sidtab *s, u32 sid)
+static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force)
 {
        int hvalue;
        struct sidtab_node *cur;
@@ -99,7 +95,10 @@ struct context *sidtab_search(struct sidtab *s, u32 sid)
        while (cur != NULL && sid > cur->sid)
                cur = cur->next;
 
-       if (cur == NULL || sid != cur->sid) {
+       if (force && cur && sid == cur->sid && cur->context.len)
+               return &cur->context;
+
+       if (cur == NULL || sid != cur->sid || cur->context.len) {
                /* Remap invalid SIDs to the unlabeled SID. */
                sid = SECINITSID_UNLABELED;
                hvalue = SIDTAB_HASH(sid);
@@ -113,6 +112,16 @@ struct context *sidtab_search(struct sidtab *s, u32 sid)
        return &cur->context;
 }
 
+struct context *sidtab_search(struct sidtab *s, u32 sid)
+{
+       return sidtab_search_core(s, sid, 0);
+}
+
+struct context *sidtab_search_force(struct sidtab *s, u32 sid)
+{
+       return sidtab_search_core(s, sid, 1);
+}
+
 int sidtab_map(struct sidtab *s,
               int (*apply) (u32 sid,
                             struct context *context,
@@ -138,43 +147,6 @@ out:
        return rc;
 }
 
-void sidtab_map_remove_on_error(struct sidtab *s,
-                               int (*apply) (u32 sid,
-                                             struct context *context,
-                                             void *args),
-                               void *args)
-{
-       int i, ret;
-       struct sidtab_node *last, *cur, *temp;
-
-       if (!s)
-               return;
-
-       for (i = 0; i < SIDTAB_SIZE; i++) {
-               last = NULL;
-               cur = s->htable[i];
-               while (cur != NULL) {
-                       ret = apply(cur->sid, &cur->context, args);
-                       if (ret) {
-                               if (last)
-                                       last->next = cur->next;
-                               else
-                                       s->htable[i] = cur->next;
-                               temp = cur;
-                               cur = cur->next;
-                               context_destroy(&temp->context);
-                               kfree(temp);
-                               s->nel--;
-                       } else {
-                               last = cur;
-                               cur = cur->next;
-                       }
-               }
-       }
-
-       return;
-}
-
 static inline u32 sidtab_search_context(struct sidtab *s,
                                                  struct context *context)
 {
@@ -204,7 +176,7 @@ int sidtab_context_to_sid(struct sidtab *s,
 
        sid = sidtab_search_context(s, context);
        if (!sid) {
-               SIDTAB_LOCK(s, flags);
+               spin_lock_irqsave(&s->lock, flags);
                /* Rescan now that we hold the lock. */
                sid = sidtab_search_context(s, context);
                if (sid)
@@ -215,11 +187,15 @@ int sidtab_context_to_sid(struct sidtab *s,
                        goto unlock_out;
                }
                sid = s->next_sid++;
+               if (context->len)
+                       printk(KERN_INFO
+                      "SELinux:  Context %s is not valid (left unmapped).\n",
+                              context->str);
                ret = sidtab_insert(s, sid, context);
                if (ret)
                        s->next_sid--;
 unlock_out:
-               SIDTAB_UNLOCK(s, flags);
+               spin_unlock_irqrestore(&s->lock, flags);
        }
 
        if (ret)
@@ -284,19 +260,19 @@ void sidtab_set(struct sidtab *dst, struct sidtab *src)
 {
        unsigned long flags;
 
-       SIDTAB_LOCK(src, flags);
+       spin_lock_irqsave(&src->lock, flags);
        dst->htable = src->htable;
        dst->nel = src->nel;
        dst->next_sid = src->next_sid;
        dst->shutdown = 0;
-       SIDTAB_UNLOCK(src, flags);
+       spin_unlock_irqrestore(&src->lock, flags);
 }
 
 void sidtab_shutdown(struct sidtab *s)
 {
        unsigned long flags;
 
-       SIDTAB_LOCK(s, flags);
+       spin_lock_irqsave(&s->lock, flags);
        s->shutdown = 1;
-       SIDTAB_UNLOCK(s, flags);
+       spin_unlock_irqrestore(&s->lock, flags);
 }
index 2fe9dfa3eb3a3d45dfd0dd89a40a7b924d634b9c..64ea5b1cdea4775908a871e9c728aed6be5e3e30 100644 (file)
@@ -32,6 +32,7 @@ struct sidtab {
 int sidtab_init(struct sidtab *s);
 int sidtab_insert(struct sidtab *s, u32 sid, struct context *context);
 struct context *sidtab_search(struct sidtab *s, u32 sid);
+struct context *sidtab_search_force(struct sidtab *s, u32 sid);
 
 int sidtab_map(struct sidtab *s,
               int (*apply) (u32 sid,
@@ -39,12 +40,6 @@ int sidtab_map(struct sidtab *s,
                             void *args),
               void *args);
 
-void sidtab_map_remove_on_error(struct sidtab *s,
-                               int (*apply) (u32 sid,
-                                             struct context *context,
-                                             void *args),
-                               void *args);
-
 int sidtab_context_to_sid(struct sidtab *s,
                          struct context *context,
                          u32 *sid);
index 4a09293efa007329fdc56b39f2dc5dd923d45f42..ee5a51cbc5ebdd537997978760093f11994a59cc 100644 (file)
@@ -95,11 +95,12 @@ struct inode_smack *new_inode_smack(char *smack)
  *
  * Do the capability checks, and require read and write.
  */
-static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp)
+static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp,
+                       unsigned int mode)
 {
        int rc;
 
-       rc = cap_ptrace(ptp, ctp);
+       rc = cap_ptrace(ptp, ctp, mode);
        if (rc != 0)
                return rc;
 
@@ -1821,27 +1822,6 @@ static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid)
        *secid = smack_to_secid(smack);
 }
 
-/* module stacking operations */
-
-/**
- * smack_register_security - stack capability module
- * @name: module name
- * @ops: module operations - ignored
- *
- * Allow the capability module to register.
- */
-static int smack_register_security(const char *name,
-                                  struct security_operations *ops)
-{
-       if (strcmp(name, "capability") != 0)
-               return -EINVAL;
-
-       printk(KERN_INFO "%s:  Registering secondary module %s\n",
-              __func__, name);
-
-       return 0;
-}
-
 /**
  * smack_d_instantiate - Make sure the blob is correct on an inode
  * @opt_dentry: unused
@@ -2672,8 +2652,6 @@ struct security_operations smack_ops = {
        .netlink_send =                 cap_netlink_send,
        .netlink_recv =                 cap_netlink_recv,
 
-       .register_security =            smack_register_security,
-
        .d_instantiate =                smack_d_instantiate,
 
        .getprocattr =                  smack_getprocattr,
index 4247406160e7ef7c5684943a9c3065e1ec73eb9a..a37bee094eba4482c612612ae42366002e3b1134 100644 (file)
@@ -1,11 +1,9 @@
 # sound/Config.in
 #
 
-menu "Sound"
-       depends on HAS_IOMEM
-
-config SOUND
+menuconfig SOUND
        tristate "Sound card support"
+       depends on HAS_IOMEM
        help
          If you have a sound card in your computer, i.e. if it can say more
          than an occasional beep, say Y.  Be sure to have all the information
@@ -28,22 +26,22 @@ config SOUND
          and read <file:Documentation/sound/oss/README.modules>; the module
          will be called soundcore.
 
+if SOUND
+
 source "sound/oss/dmasound/Kconfig"
 
 if !M68K
 
-menu "Advanced Linux Sound Architecture"
-       depends on SOUND!=n
-
-config SND
+menuconfig SND
        tristate "Advanced Linux Sound Architecture"
-       depends on SOUND
        help
          Say 'Y' or 'M' to enable ALSA (Advanced Linux Sound Architecture),
          the new base sound system.
 
          For more information, see <http://www.alsa-project.org/>
 
+if SND
+
 source "sound/core/Kconfig"
 
 source "sound/drivers/Kconfig"
@@ -58,9 +56,7 @@ source "sound/aoa/Kconfig"
 
 source "sound/arm/Kconfig"
 
-if SPI
 source "sound/spi/Kconfig"
-endif
 
 source "sound/mips/Kconfig"
 
@@ -80,22 +76,20 @@ source "sound/parisc/Kconfig"
 
 source "sound/soc/Kconfig"
 
-endmenu
+endif # SND
 
-menu "Open Sound System"
-       depends on SOUND!=n
-
-config SOUND_PRIME
+menuconfig SOUND_PRIME
        tristate "Open Sound System (DEPRECATED)"
-       depends on SOUND
        help
          Say 'Y' or 'M' to enable Open Sound System drivers.
 
+if SOUND_PRIME
+
 source "sound/oss/Kconfig"
 
-endmenu
+endif # SOUND_PRIME
 
-endif
+endif # !M68K
 
 config AC97_BUS
        tristate
@@ -105,4 +99,4 @@ config AC97_BUS
          sound although they're sharing the AC97 bus. Concerned drivers
          should "select" this.
 
-endmenu
+endif # SOUND
index 5d5813cec4c859a1dafd4dc2d38d45029adf91c9..c081e18b95400fac658a4821c87373d200906c05 100644 (file)
@@ -1,18 +1,17 @@
-menu "Apple Onboard Audio driver"
-       depends on SND!=n && PPC_PMAC
-
-config SND_AOA
+menuconfig SND_AOA
        tristate "Apple Onboard Audio driver"
-       depends on SND
+       depends on PPC_PMAC
        select SND_PCM
        ---help---
        This option enables the new driver for the various
        Apple Onboard Audio components.
 
+if SND_AOA
+
 source "sound/aoa/fabrics/Kconfig"
 
 source "sound/aoa/codecs/Kconfig"
 
 source "sound/aoa/soundbus/Kconfig"
 
-endmenu
+endif  # SND_AOA
index d5fbd6016e9370ebd3493dc6e37f7658eacba3da..808eb11ebacdda3c44cb8ea04534681747a21e96 100644 (file)
@@ -1,6 +1,5 @@
 config SND_AOA_ONYX
        tristate "support Onyx chip"
-       depends on SND_AOA
        select I2C
        select I2C_POWERMAC
        ---help---
@@ -10,7 +9,6 @@ config SND_AOA_ONYX
 
 #config SND_AOA_TOPAZ
 #      tristate "support Topaz chips"
-#      depends on SND_AOA
 #      ---help---
 #      This option enables support for the Topaz (CS84xx)
 #      codec chips found in the latest Apple machines,
@@ -19,7 +17,6 @@ config SND_AOA_ONYX
 
 config SND_AOA_TAS
        tristate "support TAS chips"
-       depends on SND_AOA
        select I2C
        select I2C_POWERMAC
        ---help---
@@ -29,7 +26,6 @@ config SND_AOA_TAS
 
 config SND_AOA_TOONIE
        tristate "support Toonie chip"
-       depends on SND_AOA
        ---help---
        This option enables support for the toonie codec
        found in the Mac Mini. If you have a Mac Mini and
index 50d7021ff677f5e1d578d83ff7ec3c760ea600c3..3ca475a886b1c1c0deda72295746ddf9a8ec31ea 100644 (file)
@@ -1,6 +1,5 @@
 config SND_AOA_FABRIC_LAYOUT
        tristate "layout-id fabric"
-       depends on SND_AOA
        select SND_AOA_SOUNDBUS
        select SND_AOA_SOUNDBUS_I2S
        ---help---
index 7368b7ddfe0dd88f4f11f5973d8dfa186120c6d5..839d1137b9b23ca140574699c36e8ebaa8e960e6 100644 (file)
@@ -1,6 +1,5 @@
 config SND_AOA_SOUNDBUS
        tristate "Apple Soundbus support"
-       depends on SOUND
        select SND_PCM
        ---help---
        This option enables the generic driver for the soundbus
index 2e4a5e0d16db3726755dea8c8930f35138927395..351e19ea3785ce7159fe6957abc97a1b1c963971 100644 (file)
@@ -1,11 +1,19 @@
 # ALSA ARM drivers
 
-menu "ALSA ARM devices"
-       depends on SND!=n && ARM
+menuconfig SND_ARM
+       bool "ARM sound devices"
+       depends on ARM
+       default y
+       help
+         Support for sound devices specific to ARM architectures.
+         Drivers that are implemented on ASoC can be found in
+         "ALSA for SoC audio support" section.
+
+if SND_ARM
 
 config SND_SA11XX_UDA1341
        tristate "SA11xx UDA1341TS driver (iPaq H3600)"
-       depends on ARCH_SA1100 && SND && L3
+       depends on ARCH_SA1100 && L3
        select SND_PCM
        help
          Say Y here if you have a Compaq iPaq H3x00 handheld computer
@@ -16,7 +24,7 @@ config SND_SA11XX_UDA1341
 
 config SND_ARMAACI
        tristate "ARM PrimeCell PL041 AC Link support"
-       depends on SND && ARM_AMBA
+       depends on ARM_AMBA
        select SND_PCM
        select SND_AC97_CODEC
 
@@ -26,11 +34,12 @@ config SND_PXA2XX_PCM
 
 config SND_PXA2XX_AC97
        tristate "AC97 driver for the Intel PXA2xx chip"
-       depends on ARCH_PXA && SND
+       depends on ARCH_PXA
        select SND_PXA2XX_PCM
        select SND_AC97_CODEC
        help
          Say Y or M if you want to support any AC97 codec attached to
          the PXA2xx AC97 interface.
 
-endmenu
+endif  # SND_ARM
+
index 0eff33ca0f793742b97546deea5fa03b27dab220..faeddf3ecedb871835dbae30ddf74b07d85e42ad 100644 (file)
@@ -21,8 +21,6 @@
  *                              merged HAL layer (patches from Brian)
  */
 
-/* $Id: sa11xx-uda1341.c,v 1.27 2005/12/07 09:13:42 cladisch Exp $ */
-
 /***************************************************************************************************
 *
 * To understand what Alsa Drivers should be doing look at "Writing an Alsa Driver" by Takashi Iwai
index a8d71c6c8e7593f1619733bc7c9635bf118d43ca..335d45ecde6a19bc0d3f12a68363c669ea405a17 100644 (file)
@@ -1,24 +1,19 @@
 # ALSA soundcard-configuration
 config SND_TIMER
        tristate
-       depends on SND
 
 config SND_PCM
        tristate
        select SND_TIMER
-       depends on SND
 
 config SND_HWDEP
        tristate
-       depends on SND
 
 config SND_RAWMIDI
        tristate
-       depends on SND
 
 config SND_SEQUENCER
        tristate "Sequencer support"
-       depends on SND
        select SND_TIMER
        help
          Say Y or M to enable MIDI sequencer and router support.  This
@@ -44,11 +39,9 @@ config SND_SEQ_DUMMY
 
 config SND_OSSEMUL
        bool
-       depends on SND
 
 config SND_MIXER_OSS
        tristate "OSS Mixer API"
-       depends on SND
        select SND_OSSEMUL
        help
          To enable OSS mixer API emulation (/dev/mixer*), say Y here
@@ -61,7 +54,6 @@ config SND_MIXER_OSS
 
 config SND_PCM_OSS
        tristate "OSS PCM (digital audio) API"
-       depends on SND
        select SND_OSSEMUL
        select SND_PCM
        help
@@ -84,7 +76,7 @@ config SND_PCM_OSS_PLUGINS
 
 config SND_SEQUENCER_OSS
        bool "OSS Sequencer API"
-       depends on SND && SND_SEQUENCER
+       depends on SND_SEQUENCER
        select SND_OSSEMUL
        help
          Say Y here to enable OSS sequencer emulation (both
@@ -98,7 +90,7 @@ config SND_SEQUENCER_OSS
 
 config SND_RTCTIMER
        tristate "RTC Timer support"
-       depends on SND && RTC
+       depends on RTC
        select SND_TIMER
        help
          Say Y here to enable RTC timer support for ALSA.  ALSA uses
@@ -123,7 +115,6 @@ config SND_SEQ_RTCTIMER_DEFAULT
 
 config SND_DYNAMIC_MINORS
        bool "Dynamic device file minor numbers"
-       depends on SND
        help
          If you say Y here, the minor numbers of ALSA device files in
          /dev/snd/ are allocated dynamically.  This allows you to have
@@ -134,7 +125,6 @@ config SND_DYNAMIC_MINORS
 
 config SND_SUPPORT_OLD_API
        bool "Support old ALSA API"
-       depends on SND
        default y
        help
          Say Y here to support the obsolete ALSA PCM API (ver.0.9.0 rc3
@@ -142,7 +132,7 @@ config SND_SUPPORT_OLD_API
 
 config SND_VERBOSE_PROCFS
        bool "Verbose procfs contents"
-       depends on SND && PROC_FS
+       depends on PROC_FS
        default y
        help
          Say Y here to include code for verbose procfs contents (provides
@@ -151,7 +141,6 @@ config SND_VERBOSE_PROCFS
 
 config SND_VERBOSE_PRINTK
        bool "Verbose printk"
-       depends on SND
        help
          Say Y here to enable verbose log messages.  These messages
          will help to identify source file and position containing
@@ -161,16 +150,17 @@ config SND_VERBOSE_PRINTK
 
 config SND_DEBUG
        bool "Debug"
-       depends on SND
        help
          Say Y here to enable ALSA debug code.
 
-config SND_DEBUG_DETECT
-       bool "Debug detection"
+config SND_DEBUG_VERBOSE
+       bool "More verbose debug"
        depends on SND_DEBUG
        help
-         Say Y here to enable extra-verbose log messages printed when
-         detecting devices.
+         Say Y here to enable extra-verbose debugging messages.
+         
+         Let me repeat: it enables EXTRA-VERBOSE DEBUGGING messages.
+         So, say Y only if you are ready to be annoyed.
 
 config SND_PCM_XRUN_DEBUG
        bool "Enable PCM ring buffer overrun/underrun debugging"
@@ -184,4 +174,3 @@ config SND_PCM_XRUN_DEBUG
 
 config SND_VMASTER
        bool
-       depends on SND
index 01a1a5af47bb7749e90370c7ff92dbae528b6199..281b2e2ef0eac0bb4b87c4a475433a466459a98d 100644 (file)
@@ -684,7 +684,8 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
        return result;
 }
 
-int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control)
+static int snd_ctl_elem_read(struct snd_card *card,
+                            struct snd_ctl_elem_value *control)
 {
        struct snd_kcontrol *kctl;
        struct snd_kcontrol_volatile *vd;
@@ -734,8 +735,8 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
        return result;
 }
 
-int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
-                      struct snd_ctl_elem_value *control)
+static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
+                             struct snd_ctl_elem_value *control)
 {
        struct snd_kcontrol *kctl;
        struct snd_kcontrol_volatile *vd;
index ac0573416130d56b480caf2948a88f1017ad3bb8..5c254d498ae094d452bb0c85a143f468eaedde0a 100644 (file)
@@ -46,17 +46,24 @@ static char *slots[SNDRV_CARDS];
 module_param_array(slots, charp, NULL, 0444);
 MODULE_PARM_DESC(slots, "Module names assigned to the slots.");
 
-/* return non-zero if the given index is already reserved for another
+/* return non-zero if the given index is reserved for the given
  * module via slots option
  */
-static int module_slot_mismatch(struct module *module, int idx)
+static int module_slot_match(struct module *module, int idx)
 {
+       int match = 1;
 #ifdef MODULE
-       char *s1, *s2;
+       const char *s1, *s2;
+
        if (!module || !module->name || !slots[idx])
                return 0;
-       s1 = slots[idx];
-       s2 = module->name;
+
+       s1 = module->name;
+       s2 = slots[idx];
+       if (*s2 == '!') {
+               match = 0; /* negative match */
+               s2++;
+       }
        /* compare module name strings
         * hyphens are handled as equivalent with underscore
         */
@@ -68,12 +75,12 @@ static int module_slot_mismatch(struct module *module, int idx)
                if (c2 == '-')
                        c2 = '_';
                if (c1 != c2)
-                       return 1;
+                       return !match;
                if (!c1)
                        break;
        }
-#endif
-       return 0;
+#endif /* MODULE */
+       return match;
 }
 
 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
@@ -129,7 +136,7 @@ struct snd_card *snd_card_new(int idx, const char *xid,
                         struct module *module, int extra_size)
 {
        struct snd_card *card;
-       int err;
+       int err, idx2;
 
        if (extra_size < 0)
                extra_size = 0;
@@ -144,35 +151,41 @@ struct snd_card *snd_card_new(int idx, const char *xid,
        err = 0;
        mutex_lock(&snd_card_mutex);
        if (idx < 0) {
-               int idx2;
                for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
                        /* idx == -1 == 0xffff means: take any free slot */
                        if (~snd_cards_lock & idx & 1<<idx2) {
-                               if (module_slot_mismatch(module, idx2))
-                                       continue;
-                               idx = idx2;
-                               if (idx >= snd_ecards_limit)
-                                       snd_ecards_limit = idx + 1;
-                               break;
+                               if (module_slot_match(module, idx2)) {
+                                       idx = idx2;
+                                       break;
+                               }
+                       }
+       }
+       if (idx < 0) {
+               for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
+                       /* idx == -1 == 0xffff means: take any free slot */
+                       if (~snd_cards_lock & idx & 1<<idx2) {
+                               if (!slots[idx2] || !*slots[idx2]) {
+                                       idx = idx2;
+                                       break;
+                               }
                        }
-       } else {
-                if (idx < snd_ecards_limit) {
-                       if (snd_cards_lock & (1 << idx))
-                               err = -EBUSY;   /* invalid */
-               } else {
-                       if (idx < SNDRV_CARDS)
-                               snd_ecards_limit = idx + 1; /* increase the limit */
-                       else
-                               err = -ENODEV;
-               }
        }
-       if (idx < 0 || err < 0) {
+       if (idx < 0)
+               err = -ENODEV;
+       else if (idx < snd_ecards_limit) {
+               if (snd_cards_lock & (1 << idx))
+                       err = -EBUSY;   /* invalid */
+       } else if (idx >= SNDRV_CARDS)
+               err = -ENODEV;
+       if (err < 0) {
                mutex_unlock(&snd_card_mutex);
                snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",
                         idx, snd_ecards_limit - 1, err);
                goto __error;
        }
        snd_cards_lock |= 1 << idx;             /* lock it */
+       if (idx >= snd_ecards_limit)
+               snd_ecards_limit = idx + 1; /* increase the limit */
        mutex_unlock(&snd_card_mutex);
        card->number = idx;
        card->module = module;
index 23b7bc02728b44ac9ad1086a827ffd3b917418ea..f5d6d8d129790d8729b82c1f7221616a7ea19f63 100644 (file)
@@ -79,68 +79,6 @@ struct snd_mem_list {
 #define snd_assert(expr, args...) /**/
 #endif
 
-/*
- *  Hacks
- */
-
-#if defined(__i386__)
-/*
- * A hack to allocate large buffers via dma_alloc_coherent()
- *
- * since dma_alloc_coherent always tries GFP_DMA when the requested
- * pci memory region is below 32bit, it happens quite often that even
- * 2 order of pages cannot be allocated.
- *
- * so in the following, we allocate at first without dma_mask, so that
- * allocation will be done without GFP_DMA.  if the area doesn't match
- * with the requested region, then realloate with the original dma_mask
- * again.
- *
- * Really, we want to move this type of thing into dma_alloc_coherent()
- * so dma_mask doesn't have to be messed with.
- */
-
-static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size,
-                                        dma_addr_t *dma_handle,
-                                        gfp_t flags)
-{
-       void *ret;
-       u64 dma_mask, coherent_dma_mask;
-
-       if (dev == NULL || !dev->dma_mask)
-               return dma_alloc_coherent(dev, size, dma_handle, flags);
-       dma_mask = *dev->dma_mask;
-       coherent_dma_mask = dev->coherent_dma_mask;
-       *dev->dma_mask = 0xffffffff;    /* do without masking */
-       dev->coherent_dma_mask = 0xffffffff;    /* do without masking */
-       ret = dma_alloc_coherent(dev, size, dma_handle, flags);
-       *dev->dma_mask = dma_mask;      /* restore */
-       dev->coherent_dma_mask = coherent_dma_mask;     /* restore */
-       if (ret) {
-               /* obtained address is out of range? */
-               if (((unsigned long)*dma_handle + size - 1) & ~dma_mask) {
-                       /* reallocate with the proper mask */
-                       dma_free_coherent(dev, size, ret, *dma_handle);
-                       ret = dma_alloc_coherent(dev, size, dma_handle, flags);
-               }
-       } else {
-               /* wish to success now with the proper mask... */
-               if (dma_mask != 0xffffffffUL) {
-                       /* allocation with GFP_ATOMIC to avoid the long stall */
-                       flags &= ~GFP_KERNEL;
-                       flags |= GFP_ATOMIC;
-                       ret = dma_alloc_coherent(dev, size, dma_handle, flags);
-               }
-       }
-       return ret;
-}
-
-/* redefine dma_alloc_coherent for some architectures */
-#undef dma_alloc_coherent
-#define dma_alloc_coherent snd_dma_hack_alloc_coherent
-
-#endif /* arch */
-
 /*
  *
  *  Generic memory allocators
index 47cfa5186e34e15f4775f6c15172b136f90a3999..7a1545d2d9533f4ad53b6e1693969e34cb067965 100644 (file)
@@ -148,7 +148,7 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
                return NULL;
        }
        spin_unlock_irqrestore(&clients_lock, flags);
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
        if (!in_interrupt()) {
                static char client_requested[SNDRV_SEQ_GLOBAL_CLIENTS];
                static char card_requested[SNDRV_CARDS];
index 2f00ad28a2b73e1089df52642106aa2d4f82a8fe..05410e536a4f432c75289cdea5c1843a7bad88dd 100644 (file)
@@ -124,7 +124,7 @@ static void snd_seq_device_info(struct snd_info_entry *entry,
  * load all registered drivers (called from seq_clientmgr.c)
  */
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 /* avoid auto-loading during module_init() */
 static int snd_seq_in_init;
 void snd_seq_autoload_lock(void)
@@ -140,7 +140,7 @@ void snd_seq_autoload_unlock(void)
 
 void snd_seq_device_load_drivers(void)
 {
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
        struct ops_list *ops;
 
        /* Calling request_module during module_init()
@@ -566,7 +566,5 @@ EXPORT_SYMBOL(snd_seq_device_load_drivers);
 EXPORT_SYMBOL(snd_seq_device_new);
 EXPORT_SYMBOL(snd_seq_device_register_driver);
 EXPORT_SYMBOL(snd_seq_device_unregister_driver);
-#ifdef CONFIG_KMOD
 EXPORT_SYMBOL(snd_seq_autoload_lock);
 EXPORT_SYMBOL(snd_seq_autoload_unlock);
-#endif
index 6c8ab48c689a6bb17a6b4dd490ba26c1204e32fd..09a94953745a3835569e199e29070610638dd0c6 100644 (file)
@@ -60,14 +60,14 @@ EXPORT_SYMBOL(snd_ecards_limit);
 static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
 static DEFINE_MUTEX(sound_mutex);
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 
 /**
  * snd_request_card - try to load the card module
  * @card: the card number
  *
  * Tries to load the module "snd-card-X" for the given card number
- * via KMOD.  Returns immediately if already loaded.
+ * via request_module.  Returns immediately if already loaded.
  */
 void snd_request_card(int card)
 {
@@ -92,7 +92,7 @@ static void snd_request_other(int minor)
        request_module(str);
 }
 
-#endif                         /* request_module support */
+#endif /* modular kernel */
 
 /**
  * snd_lookup_minor_data - get user data of a registered device
@@ -132,7 +132,7 @@ static int snd_open(struct inode *inode, struct file *file)
                return -ENODEV;
        mptr = snd_minors[minor];
        if (mptr == NULL) {
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
                int dev = SNDRV_MINOR_DEVICE(minor);
                if (dev == SNDRV_MINOR_CONTROL) {
                        /* /dev/aloadC? */
index 9d8184a2c2d06350f44d294fdabd3d4797c6b638..0af337efc64e282367727e965bb36c090d0afd37 100644 (file)
@@ -146,7 +146,7 @@ static struct snd_timer *snd_timer_find(struct snd_timer_id *tid)
        return NULL;
 }
 
-#ifdef CONFIG_KMOD
+#ifdef CONFIG_MODULES
 
 static void snd_timer_request(struct snd_timer_id *tid)
 {
@@ -259,8 +259,8 @@ int snd_timer_open(struct snd_timer_instance **ti,
        /* open a master instance */
        mutex_lock(&register_mutex);
        timer = snd_timer_find(tid);
-#ifdef CONFIG_KMOD
-       if (timer == NULL) {
+#ifdef CONFIG_MODULES
+       if (!timer) {
                mutex_unlock(&register_mutex);
                snd_timer_request(tid);
                mutex_lock(&register_mutex);
index 602b58e3b55d198914f047c6d806871abfddd00e..255fd18b9aecc357730f16c1670706d5c5d95c1d 100644 (file)
@@ -1,15 +1,41 @@
-# ALSA generic drivers
+config SND_MPU401_UART
+        tristate
+        select SND_RAWMIDI
 
-menu "Generic devices"
-       depends on SND!=n
+config SND_OPL3_LIB
+       tristate
+       select SND_TIMER
+       select SND_HWDEP
 
+config SND_OPL4_LIB
+       tristate
+       select SND_TIMER
+       select SND_HWDEP
+
+config SND_VX_LIB
+       tristate
+       select SND_HWDEP
+       select SND_PCM
+
+config SND_AC97_CODEC
+       tristate
+       select SND_PCM
+       select AC97_BUS
+       select SND_VMASTER
+
+menuconfig SND_DRIVERS
+       bool "Generic sound devices"
+       default y
+       help
+         Support for generic sound devices.
+  
+if SND_DRIVERS
 
 config SND_PCSP
        tristate "PC-Speaker support (READ HELP!)"
        depends on PCSPKR_PLATFORM && X86_PC && HIGH_RES_TIMERS
        depends on INPUT
        depends on EXPERIMENTAL
-       depends on SND
        select SND_PCM
        help
          If you don't have a sound card in your computer, you can include a
@@ -35,33 +61,8 @@ config SND_PCSP
          Say M if you don't.
          Say Y only if you really know what you do.
 
-config SND_MPU401_UART
-        tristate
-        select SND_RAWMIDI
-
-config SND_OPL3_LIB
-       tristate
-       select SND_TIMER
-       select SND_HWDEP
-
-config SND_OPL4_LIB
-       tristate
-       select SND_TIMER
-       select SND_HWDEP
-
-config SND_VX_LIB
-       tristate
-       select SND_HWDEP
-       select SND_PCM
-
-config SND_AC97_CODEC
-       tristate
-       select SND_PCM
-       select AC97_BUS
-
 config SND_DUMMY
        tristate "Dummy (/dev/null) soundcard"
-       depends on SND
        select SND_PCM
        help
          Say Y here to include the dummy driver.  This driver does
@@ -90,7 +91,6 @@ config SND_VIRMIDI
 
 config SND_MTPAV
        tristate "MOTU MidiTimePiece AV multiport MIDI"
-       depends on SND
        select SND_RAWMIDI
        help
          To use a MOTU MidiTimePiece AV multiport MIDI adapter
@@ -102,7 +102,7 @@ config SND_MTPAV
 
 config SND_MTS64
        tristate "ESI Miditerminal 4140 driver"
-       depends on SND && PARPORT
+       depends on PARPORT
        select SND_RAWMIDI
        help
          The ESI Miditerminal 4140 is a 4 In 4 Out MIDI Interface with 
@@ -115,7 +115,6 @@ config SND_MTS64
 
 config SND_SERIAL_U16550
        tristate "UART16550 serial MIDI driver"
-       depends on SND
        select SND_RAWMIDI
        help
          To include support for MIDI serial port interfaces, say Y here
@@ -131,7 +130,6 @@ config SND_SERIAL_U16550
 
 config SND_MPU401
        tristate "Generic MPU-401 UART driver"
-       depends on SND
        select SND_MPU401_UART
        help
          Say Y here to include support for MIDI ports compatible with
@@ -142,7 +140,7 @@ config SND_MPU401
 
 config SND_PORTMAN2X4
        tristate "Portman 2x4 driver"
-       depends on SND && PARPORT
+       depends on PARPORT
        select SND_RAWMIDI
        help
          Say Y here to include support for Midiman Portman 2x4 parallel
@@ -153,7 +151,7 @@ config SND_PORTMAN2X4
 
 config SND_ML403_AC97CR
        tristate "Xilinx ML403 AC97 Controller Reference"
-       depends on SND && XILINX_VIRTEX
+       depends on XILINX_VIRTEX
        select SND_AC97_CODEC
        help
          Say Y here to include support for the
@@ -163,4 +161,25 @@ config SND_ML403_AC97CR
          To compile this driver as a module, choose M here: the module
          will be called snd-ml403_ac97cr.
 
-endmenu
+config SND_AC97_POWER_SAVE
+       bool "AC97 Power-Saving Mode"
+       depends on SND_AC97_CODEC && EXPERIMENTAL
+       default n
+       help
+         Say Y here to enable the aggressive power-saving support of
+         AC97 codecs.  In this mode, the power-mode is dynamically
+         controlled at each open/close.
+
+         The mode is activated by passing power_save=1 option to
+         snd-ac97-codec driver.  You can toggle it dynamically over
+         sysfs, too.
+
+config SND_AC97_POWER_SAVE_DEFAULT
+       int "Default time-out for AC97 power-save mode"
+       depends on SND_AC97_POWER_SAVE
+       default 0
+       help
+         The default time-out value in seconds for AC97 automatic
+         power-save mode.  0 means to disable the power-save mode.
+
+endif  # SND_DRIVERS
index 1dfe6948e6ffdb14d36438dad0940e520f862338..efd22e92bcedea68f2a1de780f8e2b919b3d33fe 100644 (file)
@@ -183,7 +183,7 @@ static int vx_hwdep_dsp_load(struct snd_hwdep *hw,
                kfree(fw);
                return -ENOMEM;
        }
-       if (copy_from_user(fw->data, dsp->image, dsp->length)) {
+       if (copy_from_user((void *)fw->data, dsp->image, dsp->length)) {
                free_fw(fw);
                return -EFAULT;
        }
index e57e9cbe6a0f99aa36d8090a222c91b76b555771..9c3d361accfb108e71bf2ceea04a42f0b12972dd 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <asm/unaligned.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/pcm.h>
@@ -264,10 +265,7 @@ int snd_cs8427_create(struct snd_i2c_bus *bus,
                goto __fail;
        }
        /* write default channel status bytes */
-       buf[0] = ((unsigned char)(SNDRV_PCM_DEFAULT_CON_SPDIF >> 0));
-       buf[1] = ((unsigned char)(SNDRV_PCM_DEFAULT_CON_SPDIF >> 8));
-       buf[2] = ((unsigned char)(SNDRV_PCM_DEFAULT_CON_SPDIF >> 16));
-       buf[3] = ((unsigned char)(SNDRV_PCM_DEFAULT_CON_SPDIF >> 24));
+       put_unaligned_le32(SNDRV_PCM_DEFAULT_CON_SPDIF, buf);
        memset(buf + 4, 0, 24 - 4);
        if (snd_cs8427_send_corudata(device, 0, buf, 24) < 0)
                goto __fail;
index bfa5d2c3608bfed3d412165357a3889b4205d24e..1f4942ea141433dfef8569fa3c3f3e478688ffb7 100644 (file)
@@ -17,8 +17,6 @@
  * 2002-05-12   Tomas Kasparek  another code cleanup
  */
 
-/* $Id: uda1341.c,v 1.18 2005/11/17 14:17:21 tiwai Exp $ */
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
index 2639a6ab8f2ea122425b1b8739cfad29ac73eb2c..25347a25d63cf7571a5db7bfb0309da0b1ac5181 100644 (file)
@@ -21,12 +21,17 @@ config SND_SB16_DSP
         select SND_PCM
         select SND_SB_COMMON
 
-menu "ISA devices"
-       depends on SND!=n && ISA && ISA_DMA_API
+menuconfig SND_ISA
+       bool "ISA sound devices"
+       depends on ISA && ISA_DMA_API
+       default y
+       help
+         Support for sound devices connected via the ISA bus.
+
+if SND_ISA
 
 config SND_ADLIB
        tristate "AdLib FM card"
-       depends on SND
        select SND_OPL3_LIB
        help
          Say Y here to include support for AdLib FM cards.
@@ -36,7 +41,7 @@ config SND_ADLIB
 
 config SND_AD1816A
        tristate "Analog Devices SoundPort AD1816A"
-       depends on SND && PNP && ISA
+       depends on PNP
        select ISAPNP
        select SND_OPL3_LIB
        select SND_MPU401_UART
@@ -50,7 +55,6 @@ config SND_AD1816A
 
 config SND_AD1848
        tristate "Generic AD1848/CS4248 driver"
-       depends on SND
        select SND_AD1848_LIB
        help
          Say Y here to include support for AD1848 (Analog Devices) or
@@ -64,7 +68,7 @@ config SND_AD1848
 
 config SND_ALS100
        tristate "Avance Logic ALS100/ALS120"
-       depends on SND && PNP && ISA
+       depends on PNP
        select ISAPNP
        select SND_OPL3_LIB
        select SND_MPU401_UART
@@ -78,7 +82,7 @@ config SND_ALS100
 
 config SND_AZT2320
        tristate "Aztech Systems AZT2320"
-       depends on SND && PNP && ISA
+       depends on PNP
        select ISAPNP
        select SND_OPL3_LIB
        select SND_MPU401_UART
@@ -92,7 +96,6 @@ config SND_AZT2320
 
 config SND_CMI8330
        tristate "C-Media CMI8330"
-       depends on SND
        select SND_AD1848_LIB
        select SND_SB16_DSP
        help
@@ -104,7 +107,6 @@ config SND_CMI8330
 
 config SND_CS4231
        tristate "Generic Cirrus Logic CS4231 driver"
-       depends on SND
        select SND_MPU401_UART
        select SND_CS4231_LIB
        help
@@ -116,7 +118,6 @@ config SND_CS4231
 
 config SND_CS4232
        tristate "Generic Cirrus Logic CS4232 driver"
-       depends on SND
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_CS4231_LIB
@@ -129,7 +130,6 @@ config SND_CS4232
 
 config SND_CS4236
        tristate "Generic Cirrus Logic CS4236+ driver"
-       depends on SND
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_CS4231_LIB
@@ -142,7 +142,7 @@ config SND_CS4236
 
 config SND_DT019X
        tristate "Diamond Technologies DT-019X, Avance Logic ALS-007"
-       depends on SND && PNP && ISA
+       depends on PNP
        select ISAPNP
        select SND_OPL3_LIB
        select SND_MPU401_UART
@@ -156,7 +156,7 @@ config SND_DT019X
 
 config SND_ES968
        tristate "Generic ESS ES968 driver"
-       depends on SND && PNP && ISA
+       depends on PNP
        select ISAPNP
        select SND_MPU401_UART
        select SND_SB8_DSP
@@ -168,7 +168,6 @@ config SND_ES968
 
 config SND_ES1688
        tristate "Generic ESS ES688/ES1688 driver"
-       depends on SND
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_PCM
@@ -181,7 +180,6 @@ config SND_ES1688
 
 config SND_ES18XX
        tristate "Generic ESS ES18xx driver"
-       depends on SND
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_PCM
@@ -193,7 +191,7 @@ config SND_ES18XX
 
 config SND_SC6000
        tristate "Gallant SC-6000, Audio Excel DSP 16"
-       depends on SND && HAS_IOPORT
+       depends on HAS_IOPORT
        select SND_AD1848_LIB
        select SND_OPL3_LIB
        select SND_MPU401_UART
@@ -204,15 +202,10 @@ config SND_SC6000
          To compile this driver as a module, choose M here: the module
          will be called snd-sc6000.
 
-config SND_GUS_SYNTH
-       tristate
-
 config SND_GUSCLASSIC
        tristate "Gravis UltraSound Classic"
-       depends on SND
        select SND_RAWMIDI
        select SND_PCM
-       select SND_GUS_SYNTH
        help
          Say Y here to include support for Gravis UltraSound Classic
          soundcards.
@@ -222,11 +215,9 @@ config SND_GUSCLASSIC
 
 config SND_GUSEXTREME
        tristate "Gravis UltraSound Extreme"
-       depends on SND
        select SND_HWDEP
        select SND_MPU401_UART
        select SND_PCM
-       select SND_GUS_SYNTH
        help
          Say Y here to include support for Gravis UltraSound Extreme
          soundcards.
@@ -236,10 +227,8 @@ config SND_GUSEXTREME
 
 config SND_GUSMAX
        tristate "Gravis UltraSound MAX"
-       depends on SND
        select SND_RAWMIDI
        select SND_CS4231_LIB
-       select SND_GUS_SYNTH
        help
          Say Y here to include support for Gravis UltraSound MAX
          soundcards.
@@ -249,10 +238,9 @@ config SND_GUSMAX
 
 config SND_INTERWAVE
        tristate "AMD InterWave, Gravis UltraSound PnP"
-       depends on SND && PNP && ISA
+       depends on PNP
        select SND_RAWMIDI
        select SND_CS4231_LIB
-       select SND_GUS_SYNTH
        help
          Say Y here to include support for AMD InterWave based
          soundcards (Gravis UltraSound Plug & Play, STB SoundRage32,
@@ -263,10 +251,9 @@ config SND_INTERWAVE
 
 config SND_INTERWAVE_STB
        tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)"
-       depends on SND && PNP && ISA
+       depends on PNP
        select SND_RAWMIDI
        select SND_CS4231_LIB
-       select SND_GUS_SYNTH
        help
          Say Y here to include support for AMD InterWave based
          soundcards with a TEA6330T bass and treble regulator
@@ -277,7 +264,6 @@ config SND_INTERWAVE_STB
 
 config SND_OPL3SA2
        tristate "Yamaha OPL3-SA2/SA3"
-       depends on SND
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_CS4231_LIB
@@ -290,7 +276,6 @@ config SND_OPL3SA2
 
 config SND_OPTI92X_AD1848
        tristate "OPTi 82C92x - AD1848"
-       depends on SND
        select SND_OPL3_LIB
        select SND_OPL4_LIB
        select SND_MPU401_UART
@@ -304,7 +289,6 @@ config SND_OPTI92X_AD1848
 
 config SND_OPTI92X_CS4231
        tristate "OPTi 82C92x - CS4231"
-       depends on SND
        select SND_OPL3_LIB
        select SND_OPL4_LIB
        select SND_MPU401_UART
@@ -318,10 +302,9 @@ config SND_OPTI92X_CS4231
 
 config SND_OPTI93X
        tristate "OPTi 82C93x"
-       depends on SND
        select SND_OPL3_LIB
        select SND_MPU401_UART
-       select SND_PCM
+       select SND_CS4231_LIB
        help
          Say Y here to include support for soundcards based on Opti
          82C93x chips.
@@ -331,7 +314,6 @@ config SND_OPTI93X
 
 config SND_MIRO
        tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver"
-       depends on SND
        select SND_OPL4_LIB
        select SND_CS4231_LIB
        select SND_MPU401_UART
@@ -345,7 +327,6 @@ config SND_MIRO
 
 config SND_SB8
        tristate "Sound Blaster 1.0/2.0/Pro (8-bit)"
-       depends on SND
        select SND_OPL3_LIB
        select SND_RAWMIDI
        select SND_SB8_DSP
@@ -358,7 +339,6 @@ config SND_SB8
 
 config SND_SB16
        tristate "Sound Blaster 16 (PnP)"
-       depends on SND
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_SB16_DSP
@@ -371,7 +351,6 @@ config SND_SB16
 
 config SND_SBAWE
        tristate "Sound Blaster AWE (32,64) (PnP)"
-       depends on SND
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_SB16_DSP
@@ -402,7 +381,6 @@ config SND_SB16_CSP_FIRMWARE_IN_KERNEL
 
 config SND_SGALAXY
        tristate "Aztech Sound Galaxy"
-       depends on SND
        select SND_AD1848_LIB
        help
          Say Y here to include support for Aztech Sound Galaxy
@@ -413,7 +391,6 @@ config SND_SGALAXY
 
 config SND_SSCAPE
        tristate "Ensoniq SoundScape PnP driver"
-       depends on SND
        select SND_HWDEP
        select SND_MPU401_UART
        select SND_CS4231_LIB
@@ -426,7 +403,6 @@ config SND_SSCAPE
 
 config SND_WAVEFRONT
        tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)"
-       depends on SND
        select FW_LOADER
        select SND_OPL3_LIB
        select SND_MPU401_UART
@@ -448,4 +424,5 @@ config SND_WAVEFRONT_FIRMWARE_IN_KERNEL
          you need to install the firmware files from the
          alsa-firmware package.
 
-endmenu
+endif  # SND_ISA
+
index 0aa8649e5c7f897b1c5fb283b69dcd5df5f56cfc..521db705d179f94a3edcb6963773448e0ded2f09 100644 (file)
@@ -119,6 +119,42 @@ static unsigned char snd_cs4231_original_image[32] =
        0x00,                   /* 1f/31 - cbrl */
 };
 
+static unsigned char snd_opti93x_original_image[32] =
+{
+       0x00,           /* 00/00 - l_mixout_outctrl */
+       0x00,           /* 01/01 - r_mixout_outctrl */
+       0x88,           /* 02/02 - l_cd_inctrl */
+       0x88,           /* 03/03 - r_cd_inctrl */
+       0x88,           /* 04/04 - l_a1/fm_inctrl */
+       0x88,           /* 05/05 - r_a1/fm_inctrl */
+       0x80,           /* 06/06 - l_dac_inctrl */
+       0x80,           /* 07/07 - r_dac_inctrl */
+       0x00,           /* 08/08 - ply_dataform_reg */
+       0x00,           /* 09/09 - if_conf */
+       0x00,           /* 0a/10 - pin_ctrl */
+       0x00,           /* 0b/11 - err_init_reg */
+       0x0a,           /* 0c/12 - id_reg */
+       0x00,           /* 0d/13 - reserved */
+       0x00,           /* 0e/14 - ply_upcount_reg */
+       0x00,           /* 0f/15 - ply_lowcount_reg */
+       0x88,           /* 10/16 - reserved/l_a1_inctrl */
+       0x88,           /* 11/17 - reserved/r_a1_inctrl */
+       0x88,           /* 12/18 - l_line_inctrl */
+       0x88,           /* 13/19 - r_line_inctrl */
+       0x88,           /* 14/20 - l_mic_inctrl */
+       0x88,           /* 15/21 - r_mic_inctrl */
+       0x80,           /* 16/22 - l_out_outctrl */
+       0x80,           /* 17/23 - r_out_outctrl */
+       0x00,           /* 18/24 - reserved */
+       0x00,           /* 19/25 - reserved */
+       0x00,           /* 1a/26 - reserved */
+       0x00,           /* 1b/27 - reserved */
+       0x00,           /* 1c/28 - cap_dataform_reg */
+       0x00,           /* 1d/29 - reserved */
+       0x00,           /* 1e/30 - cap_upcount_reg */
+       0x00            /* 1f/31 - cap_lowcount_reg */
+};
+
 /*
  *  Basic I/O functions
  */
@@ -895,7 +931,7 @@ static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static void snd_cs4231_overrange(struct snd_cs4231 *chip)
+void snd_cs4231_overrange(struct snd_cs4231 *chip)
 {
        unsigned long flags;
        unsigned char res;
@@ -1054,8 +1090,11 @@ static int snd_cs4231_probe(struct snd_cs4231 *chip)
        chip->image[CS4231_IFACE_CTRL] =
            (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) |
            (chip->single_dma ? CS4231_SINGLE_DMA : 0);
-       chip->image[CS4231_ALT_FEATURE_1] = 0x80;
-       chip->image[CS4231_ALT_FEATURE_2] = chip->hardware == CS4231_HW_INTERWAVE ? 0xc2 : 0x01;
+       if (chip->hardware != CS4231_HW_OPTI93X) {
+               chip->image[CS4231_ALT_FEATURE_1] = 0x80;
+               chip->image[CS4231_ALT_FEATURE_2] =
+                       chip->hardware == CS4231_HW_INTERWAVE ? 0xc2 : 0x01;
+       }
        ptr = (unsigned char *) &chip->image;
        snd_cs4231_mce_down(chip);
        spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1376,6 +1415,7 @@ const char *snd_cs4231_chip_id(struct snd_cs4231 *chip)
        case CS4231_HW_INTERWAVE: return "AMD InterWave";
        case CS4231_HW_OPL3SA2: return chip->card->shortname;
        case CS4231_HW_AD1845: return "AD1845";
+       case CS4231_HW_OPTI93X: return "OPTi 93x";
        default: return "???";
        }
 }
@@ -1401,8 +1441,13 @@ static int snd_cs4231_new(struct snd_card *card,
        chip->rate_constraint = snd_cs4231_xrate;
        chip->set_playback_format = snd_cs4231_playback_format;
        chip->set_capture_format = snd_cs4231_capture_format;
-        memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image));
-        
+       if (chip->hardware == CS4231_HW_OPTI93X)
+               memcpy(&chip->image, &snd_opti93x_original_image,
+                      sizeof(snd_opti93x_original_image));
+       else
+               memcpy(&chip->image, &snd_cs4231_original_image,
+                      sizeof(snd_cs4231_original_image));
+
         *rchip = chip;
         return 0;
 }
@@ -1790,6 +1835,48 @@ CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
 CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1)
 };
                                         
+static struct snd_kcontrol_new snd_opti93x_controls[] = {
+CS4231_DOUBLE("Master Playback Switch", 0,
+             OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
+CS4231_DOUBLE("Master Playback Volume", 0,
+             OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
+CS4231_DOUBLE("PCM Playback Switch", 0,
+             CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
+CS4231_DOUBLE("PCM Playback Volume", 0,
+             CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1),
+CS4231_DOUBLE("FM Playback Switch", 0,
+             CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
+CS4231_DOUBLE("FM Playback Volume", 0,
+             CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1),
+CS4231_DOUBLE("Line Playback Switch", 0,
+             CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
+CS4231_DOUBLE("Line Playback Volume", 0,
+             CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1),
+CS4231_DOUBLE("Mic Playback Switch", 0,
+             OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
+CS4231_DOUBLE("Mic Playback Volume", 0,
+             OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1),
+CS4231_DOUBLE("Mic Boost", 0,
+             CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
+CS4231_DOUBLE("CD Playback Switch", 0,
+             CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
+CS4231_DOUBLE("CD Playback Volume", 0,
+             CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1),
+CS4231_DOUBLE("Aux Playback Switch", 0,
+             OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
+CS4231_DOUBLE("Aux Playback Volume", 0,
+             OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1),
+CS4231_DOUBLE("Capture Volume", 0,
+             CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
+{
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Capture Source",
+       .info = snd_cs4231_info_mux,
+       .get = snd_cs4231_get_mux,
+       .put = snd_cs4231_put_mux,
+}
+};
+
 int snd_cs4231_mixer(struct snd_cs4231 *chip)
 {
        struct snd_card *card;
@@ -1802,10 +1889,22 @@ int snd_cs4231_mixer(struct snd_cs4231 *chip)
 
        strcpy(card->mixername, chip->pcm->name);
 
-       for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
-               if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4231_controls[idx], chip))) < 0)
-                       return err;
-       }
+       if (chip->hardware == CS4231_HW_OPTI93X)
+               for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
+                       err = snd_ctl_add(card,
+                                       snd_ctl_new1(&snd_opti93x_controls[idx],
+                                                    chip));
+                       if (err < 0)
+                               return err;
+               }
+       else
+               for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
+                       err = snd_ctl_add(card,
+                                       snd_ctl_new1(&snd_cs4231_controls[idx],
+                                                    chip));
+                       if (err < 0)
+                               return err;
+               }
        return 0;
 }
 
@@ -1815,6 +1914,7 @@ EXPORT_SYMBOL(snd_cs4236_ext_out);
 EXPORT_SYMBOL(snd_cs4236_ext_in);
 EXPORT_SYMBOL(snd_cs4231_mce_up);
 EXPORT_SYMBOL(snd_cs4231_mce_down);
+EXPORT_SYMBOL(snd_cs4231_overrange);
 EXPORT_SYMBOL(snd_cs4231_interrupt);
 EXPORT_SYMBOL(snd_cs4231_chip_id);
 EXPORT_SYMBOL(snd_cs4231_create);
index fe1afc13a01d4bdf6a373a40611f24e734788dcf..41c047e665ec7d62c6f85c25dbf45ce1441e901f 100644 (file)
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <sound/core.h>
-#ifdef CS4231
+#if defined(CS4231) || defined(OPTi93X)
 #include <sound/cs4231.h>
 #else
-#ifndef OPTi93X
 #include <sound/ad1848.h>
-#else
-#include <sound/control.h>
-#include <sound/pcm.h>
-#endif /* OPTi93X */
 #endif /* CS4231 */
 #include <sound/mpu401.h>
 #include <sound/opl3.h>
@@ -109,7 +104,6 @@ module_param(dma2, int, 0444);
 MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver.");
 #endif /* CS4231 || OPTi93X */
 
-#define OPTi9XX_HW_DETECT      0
 #define OPTi9XX_HW_82C928      1
 #define OPTi9XX_HW_82C929      2
 #define OPTi9XX_HW_82C924      3
@@ -123,105 +117,12 @@ MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver.");
 
 #ifdef OPTi93X
 
-#define OPTi93X_INDEX                  0x00
-#define OPTi93X_DATA                   0x01
 #define OPTi93X_STATUS                 0x02
-#define OPTi93X_DDATA                  0x03
 #define OPTi93X_PORT(chip, r)          ((chip)->port + OPTi93X_##r)
 
-#define OPTi93X_MIXOUT_LEFT            0x00
-#define OPTi93X_MIXOUT_RIGHT           0x01
-#define OPTi93X_CD_LEFT_INPUT          0x02
-#define OPTi93X_CD_RIGHT_INPUT         0x03
-#define OPTi930_AUX_LEFT_INPUT         0x04
-#define OPTi930_AUX_RIGHT_INPUT                0x05
-#define OPTi931_FM_LEFT_INPUT          0x04
-#define OPTi931_FM_RIGHT_INPUT         0x05
-#define OPTi93X_DAC_LEFT               0x06
-#define OPTi93X_DAC_RIGHT              0x07
-#define OPTi93X_PLAY_FORMAT            0x08
-#define OPTi93X_IFACE_CONF             0x09
-#define OPTi93X_PIN_CTRL               0x0a
-#define OPTi93X_ERR_INIT               0x0b
-#define OPTi93X_ID                     0x0c
-#define OPTi93X_PLAY_UPR_CNT           0x0e
-#define OPTi93X_PLAY_LWR_CNT           0x0f
-#define OPTi931_AUX_LEFT_INPUT         0x10
-#define OPTi931_AUX_RIGHT_INPUT                0x11
-#define OPTi93X_LINE_LEFT_INPUT                0x12
-#define OPTi93X_LINE_RIGHT_INPUT       0x13
-#define OPTi93X_MIC_LEFT_INPUT         0x14
-#define OPTi93X_MIC_RIGHT_INPUT                0x15
-#define OPTi93X_OUT_LEFT               0x16
-#define OPTi93X_OUT_RIGHT              0x17
-#define OPTi93X_CAPT_FORMAT            0x1c
-#define OPTi93X_CAPT_UPR_CNT           0x1e
-#define OPTi93X_CAPT_LWR_CNT           0x1f
-
-#define OPTi93X_TRD                    0x20
-#define OPTi93X_MCE                    0x40
-#define OPTi93X_INIT                   0x80
-
-#define OPTi93X_MIXOUT_MIC_GAIN                0x20
-#define OPTi93X_MIXOUT_LINE            0x00
-#define OPTi93X_MIXOUT_CD              0x40
-#define OPTi93X_MIXOUT_MIC             0x80
-#define OPTi93X_MIXOUT_MIXER           0xc0
-
-#define OPTi93X_STEREO                 0x10
-#define OPTi93X_LINEAR_8               0x00
-#define OPTi93X_ULAW_8                 0x20
-#define OPTi93X_LINEAR_16_LIT          0x40
-#define OPTi93X_ALAW_8                 0x60
-#define OPTi93X_ADPCM_16               0xa0
-#define OPTi93X_LINEAR_16_BIG          0xc0
-
-#define OPTi93X_CAPTURE_PIO            0x80
-#define OPTi93X_PLAYBACK_PIO           0x40
-#define OPTi93X_AUTOCALIB              0x08
-#define OPTi93X_SINGLE_DMA             0x04
-#define OPTi93X_CAPTURE_ENABLE         0x02
-#define OPTi93X_PLAYBACK_ENABLE                0x01
-
-#define OPTi93X_IRQ_ENABLE             0x02
-
-#define OPTi93X_DMA_REQUEST            0x10
-#define OPTi93X_CALIB_IN_PROGRESS      0x20
-
 #define OPTi93X_IRQ_PLAYBACK           0x04
 #define OPTi93X_IRQ_CAPTURE            0x08
 
-
-struct snd_opti93x {
-       unsigned long port;
-       struct resource *res_port;
-       int irq;
-       int dma1;
-       int dma2;
-
-       struct snd_opti9xx *chip;
-       unsigned short hardware;
-       unsigned char image[32];
-
-       unsigned char mce_bit;
-       unsigned short mode;
-       int mute;
-
-       spinlock_t lock;
-
-       struct snd_card *card;
-       struct snd_pcm *pcm;
-       struct snd_pcm_substream *playback_substream;
-       struct snd_pcm_substream *capture_substream;
-       unsigned int p_dma_size;
-       unsigned int c_dma_size;
-};
-
-#define OPTi93X_MODE_NONE      0x00
-#define OPTi93X_MODE_PLAY      0x01
-#define OPTi93X_MODE_CAPTURE   0x02
-#define OPTi93X_MODE_OPEN      (OPTi93X_MODE_PLAY | OPTi93X_MODE_CAPTURE)
-
 #endif /* OPTi93X */
 
 struct snd_opti9xx {
@@ -234,6 +135,7 @@ struct snd_opti9xx {
        unsigned long mc_base_size;
 #ifdef OPTi93X
        unsigned long mc_indir_index;
+       struct snd_cs4231 *codec;
 #endif /* OPTi93X */
        unsigned long pwd_reg;
 
@@ -491,16 +393,9 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip)
                break;
 
 #else  /* OPTi93X */
-       case OPTi9XX_HW_82C930:
        case OPTi9XX_HW_82C931:
        case OPTi9XX_HW_82C933:
-               snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03);
-               snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff);
-               snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x10 |
-                       (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04),
-                       0x34);
-               snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf);
-               /* 
+               /*
                 * The BTC 1817DW has QS1000 wavetable which is connected
                 * to the serial digital input of the OPTI931.
                 */
@@ -510,6 +405,13 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip)
                 * or digital input signal.
                 */
                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01);
+       case OPTi9XX_HW_82C930: /* FALL THROUGH */
+               snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03);
+               snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff);
+               snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x10 |
+                       (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04),
+                       0x34);
+               snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf);
                break;
 #endif /* OPTi93X */
 
@@ -654,979 +556,23 @@ __skip_mpu:
 
 #ifdef OPTi93X
 
-static unsigned char snd_opti93x_default_image[32] =
-{
-       0x00,           /* 00/00 - l_mixout_outctrl */
-       0x00,           /* 01/01 - r_mixout_outctrl */
-       0x88,           /* 02/02 - l_cd_inctrl */
-       0x88,           /* 03/03 - r_cd_inctrl */
-       0x88,           /* 04/04 - l_a1/fm_inctrl */
-       0x88,           /* 05/05 - r_a1/fm_inctrl */
-       0x80,           /* 06/06 - l_dac_inctrl */
-       0x80,           /* 07/07 - r_dac_inctrl */
-       0x00,           /* 08/08 - ply_dataform_reg */
-       0x00,           /* 09/09 - if_conf */
-       0x00,           /* 0a/10 - pin_ctrl */
-       0x00,           /* 0b/11 - err_init_reg */
-       0x0a,           /* 0c/12 - id_reg */
-       0x00,           /* 0d/13 - reserved */
-       0x00,           /* 0e/14 - ply_upcount_reg */
-       0x00,           /* 0f/15 - ply_lowcount_reg */
-       0x88,           /* 10/16 - reserved/l_a1_inctrl */
-       0x88,           /* 11/17 - reserved/r_a1_inctrl */
-       0x88,           /* 12/18 - l_line_inctrl */
-       0x88,           /* 13/19 - r_line_inctrl */
-       0x88,           /* 14/20 - l_mic_inctrl */
-       0x88,           /* 15/21 - r_mic_inctrl */
-       0x80,           /* 16/22 - l_out_outctrl */
-       0x80,           /* 17/23 - r_out_outctrl */
-       0x00,           /* 18/24 - reserved */
-       0x00,           /* 19/25 - reserved */
-       0x00,           /* 1a/26 - reserved */
-       0x00,           /* 1b/27 - reserved */
-       0x00,           /* 1c/28 - cap_dataform_reg */
-       0x00,           /* 1d/29 - reserved */
-       0x00,           /* 1e/30 - cap_upcount_reg */
-       0x00            /* 1f/31 - cap_lowcount_reg */
-};
-
-
-static int snd_opti93x_busy_wait(struct snd_opti93x *chip)
-{
-       int timeout;
-
-       for (timeout = 250; timeout-- > 0; udelay(10))
-               if (!(inb(OPTi93X_PORT(chip, INDEX)) & OPTi93X_INIT))
-                       return 0;
-
-       snd_printk("chip still busy.\n");
-       return -EBUSY;
-}
-
-static unsigned char snd_opti93x_in(struct snd_opti93x *chip, unsigned char reg)
-{
-       snd_opti93x_busy_wait(chip);
-       outb(chip->mce_bit | (reg & 0x1f), OPTi93X_PORT(chip, INDEX));
-       return inb(OPTi93X_PORT(chip, DATA));
-}
-
-static void snd_opti93x_out(struct snd_opti93x *chip, unsigned char reg,
-                           unsigned char value)
-{
-       snd_opti93x_busy_wait(chip);
-       outb(chip->mce_bit | (reg & 0x1f), OPTi93X_PORT(chip, INDEX));
-       outb(value, OPTi93X_PORT(chip, DATA));
-}
-
-static void snd_opti93x_out_image(struct snd_opti93x *chip, unsigned char reg,
-                                 unsigned char value)
-{
-       snd_opti93x_out(chip, reg, chip->image[reg] = value);
-}
-
-static void snd_opti93x_out_mask(struct snd_opti93x *chip, unsigned char reg,
-                                unsigned char mask, unsigned char value)
-{
-       snd_opti93x_out_image(chip, reg,
-               (chip->image[reg] & ~mask) | (value & mask));
-}
-
-
-static void snd_opti93x_mce_up(struct snd_opti93x *chip)
-{
-       snd_opti93x_busy_wait(chip);
-
-       chip->mce_bit = OPTi93X_MCE;
-       if (!(inb(OPTi93X_PORT(chip, INDEX)) & OPTi93X_MCE))
-               outb(chip->mce_bit, OPTi93X_PORT(chip, INDEX));
-}
-
-static void snd_opti93x_mce_down(struct snd_opti93x *chip)
-{
-       snd_opti93x_busy_wait(chip);
-
-       chip->mce_bit = 0;
-       if (inb(OPTi93X_PORT(chip, INDEX)) & OPTi93X_MCE)
-               outb(chip->mce_bit, OPTi93X_PORT(chip, INDEX));
-}
-
-#define snd_opti93x_mute_reg(chip, reg, mute)  \
-       snd_opti93x_out(chip, reg, mute ? 0x80 : chip->image[reg]);
-
-static void snd_opti93x_mute(struct snd_opti93x *chip, int mute)
-{
-       mute = mute ? 1 : 0;
-       if (chip->mute == mute)
-               return;
-
-       chip->mute = mute;
-
-       snd_opti93x_mute_reg(chip, OPTi93X_CD_LEFT_INPUT, mute);
-       snd_opti93x_mute_reg(chip, OPTi93X_CD_RIGHT_INPUT, mute);
-       switch (chip->hardware) {
-       case OPTi9XX_HW_82C930:
-               snd_opti93x_mute_reg(chip, OPTi930_AUX_LEFT_INPUT, mute);
-               snd_opti93x_mute_reg(chip, OPTi930_AUX_RIGHT_INPUT, mute);
-               break;
-       case OPTi9XX_HW_82C931:
-       case OPTi9XX_HW_82C933:
-               snd_opti93x_mute_reg(chip, OPTi931_FM_LEFT_INPUT, mute);
-               snd_opti93x_mute_reg(chip, OPTi931_FM_RIGHT_INPUT, mute);
-               snd_opti93x_mute_reg(chip, OPTi931_AUX_LEFT_INPUT, mute);
-               snd_opti93x_mute_reg(chip, OPTi931_AUX_RIGHT_INPUT, mute);
-       }
-       snd_opti93x_mute_reg(chip, OPTi93X_DAC_LEFT, mute);
-       snd_opti93x_mute_reg(chip, OPTi93X_DAC_RIGHT, mute);
-       snd_opti93x_mute_reg(chip, OPTi93X_LINE_LEFT_INPUT, mute);
-       snd_opti93x_mute_reg(chip, OPTi93X_LINE_RIGHT_INPUT, mute);
-       snd_opti93x_mute_reg(chip, OPTi93X_MIC_LEFT_INPUT, mute);
-       snd_opti93x_mute_reg(chip, OPTi93X_MIC_RIGHT_INPUT, mute);
-       snd_opti93x_mute_reg(chip, OPTi93X_OUT_LEFT, mute);
-       snd_opti93x_mute_reg(chip, OPTi93X_OUT_RIGHT, mute);
-}
-
-
-static unsigned int snd_opti93x_get_count(unsigned char format,
-                                         unsigned int size)
-{
-       switch (format & 0xe0) {
-       case OPTi93X_LINEAR_16_LIT:
-       case OPTi93X_LINEAR_16_BIG:
-               size >>= 1;
-               break;
-       case OPTi93X_ADPCM_16:
-               return size >> 2;
-       }
-       return (format & OPTi93X_STEREO) ? (size >> 1) : size;
-}
-
-static unsigned int rates[] = {  5512,  6615,  8000,  9600, 11025, 16000, 
-                               18900, 22050, 27428, 32000, 33075, 37800,
-                               44100, 48000 };
-#define RATES ARRAY_SIZE(rates)
-
-static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
-       .count = RATES,
-       .list = rates,
-       .mask = 0,
-};
-
-static unsigned char bits[] = {  0x01,  0x0f,  0x00,  0x0e,  0x03,  0x02,
-                                0x05,  0x07,  0x04,  0x06,  0x0d,  0x09,
-                                0x0b,  0x0c};
-
-static unsigned char snd_opti93x_get_freq(unsigned int rate)
-{
-       unsigned int i;
-
-       for (i = 0; i < RATES; i++) {
-               if (rate == rates[i])
-                       return bits[i];
-       }
-       snd_BUG();
-       return bits[RATES-1];
-}
-
-static unsigned char snd_opti93x_get_format(struct snd_opti93x *chip,
-                                           unsigned int format, int channels)
-{
-       unsigned char retval = OPTi93X_LINEAR_8;
-
-       switch (format) {
-       case SNDRV_PCM_FORMAT_MU_LAW:
-               retval = OPTi93X_ULAW_8;
-               break;
-       case SNDRV_PCM_FORMAT_A_LAW:
-               retval = OPTi93X_ALAW_8;
-               break;
-       case SNDRV_PCM_FORMAT_S16_LE:
-               retval = OPTi93X_LINEAR_16_LIT;
-               break;
-       case SNDRV_PCM_FORMAT_S16_BE:
-               retval = OPTi93X_LINEAR_16_BIG;
-               break;
-       case SNDRV_PCM_FORMAT_IMA_ADPCM:
-               retval = OPTi93X_ADPCM_16;
-       }
-       return (channels > 1) ? (retval | OPTi93X_STEREO) : retval;
-}
-
-
-static void snd_opti93x_playback_format(struct snd_opti93x *chip, unsigned char fmt)
-{
-       unsigned char mask;
-
-       snd_opti93x_mute(chip, 1);
-
-       snd_opti93x_mce_up(chip);
-       mask = (chip->mode & OPTi93X_MODE_CAPTURE) ? 0xf0 : 0xff;
-       snd_opti93x_out_mask(chip, OPTi93X_PLAY_FORMAT, mask, fmt);
-       snd_opti93x_mce_down(chip);
-
-       snd_opti93x_mute(chip, 0);
-}
-
-static void snd_opti93x_capture_format(struct snd_opti93x *chip, unsigned char fmt)
-{
-       snd_opti93x_mute(chip, 1);
-
-       snd_opti93x_mce_up(chip);
-       if (!(chip->mode & OPTi93X_MODE_PLAY))
-               snd_opti93x_out_mask(chip, OPTi93X_PLAY_FORMAT, 0x0f, fmt);
-       else
-               fmt = chip->image[OPTi93X_PLAY_FORMAT] & 0xf0;
-       snd_opti93x_out_image(chip, OPTi93X_CAPT_FORMAT, fmt);
-       snd_opti93x_mce_down(chip);
-
-       snd_opti93x_mute(chip, 0);
-}
-
-
-static int snd_opti93x_open(struct snd_opti93x *chip, unsigned int mode)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&chip->lock, flags);
-
-       if (chip->mode & mode) {
-               spin_unlock_irqrestore(&chip->lock, flags);
-               return -EAGAIN;
-       }
-
-       if (!(chip->mode & OPTi93X_MODE_OPEN)) {
-               outb(0x00, OPTi93X_PORT(chip, STATUS));
-               snd_opti93x_out_mask(chip, OPTi93X_PIN_CTRL,
-                       OPTi93X_IRQ_ENABLE, OPTi93X_IRQ_ENABLE);
-               chip->mode = mode;
-       }
-       else
-               chip->mode |= mode;
-
-       spin_unlock_irqrestore(&chip->lock, flags);
-       return 0;
-}
-
-static void snd_opti93x_close(struct snd_opti93x *chip, unsigned int mode)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&chip->lock, flags);
-
-       chip->mode &= ~mode;
-       if (chip->mode & OPTi93X_MODE_OPEN) {
-               spin_unlock_irqrestore(&chip->lock, flags);
-               return;
-       }
-
-       snd_opti93x_mute(chip, 1);
-
-       outb(0, OPTi93X_PORT(chip, STATUS));
-       snd_opti93x_out_mask(chip, OPTi93X_PIN_CTRL, OPTi93X_IRQ_ENABLE,
-               ~OPTi93X_IRQ_ENABLE);
-
-       snd_opti93x_mce_up(chip);
-       snd_opti93x_out_image(chip, OPTi93X_IFACE_CONF, 0x00);
-       snd_opti93x_mce_down(chip);
-       chip->mode = 0;
-
-       snd_opti93x_mute(chip, 0);
-       spin_unlock_irqrestore(&chip->lock, flags);
-}
-
-static int snd_opti93x_trigger(struct snd_pcm_substream *substream, 
-                              unsigned char what, int cmd)
-{
-       struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_STOP:
-       {
-               unsigned int what = 0;
-               struct snd_pcm_substream *s;
-               snd_pcm_group_for_each_entry(s, substream) {
-                       if (s == chip->playback_substream) {
-                               what |= OPTi93X_PLAYBACK_ENABLE;
-                               snd_pcm_trigger_done(s, substream);
-                       } else if (s == chip->capture_substream) {
-                               what |= OPTi93X_CAPTURE_ENABLE;
-                               snd_pcm_trigger_done(s, substream);
-                       }
-               }
-               spin_lock(&chip->lock);
-               if (cmd == SNDRV_PCM_TRIGGER_START) {
-                       snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF, what, what);
-                       if (what & OPTi93X_CAPTURE_ENABLE)
-                               udelay(50);
-               } else
-                       snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF, what, 0x00);
-               spin_unlock(&chip->lock);
-               break;
-       }
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int snd_opti93x_playback_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       return snd_opti93x_trigger(substream,
-                                  OPTi93X_PLAYBACK_ENABLE, cmd);
-}
-
-static int snd_opti93x_capture_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       return snd_opti93x_trigger(substream,
-                                  OPTi93X_CAPTURE_ENABLE, cmd);
-}
-
-static int snd_opti93x_hw_params(struct snd_pcm_substream *substream,
-                                struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-
-static int snd_opti93x_hw_free(struct snd_pcm_substream *substream)
-{
-       snd_pcm_lib_free_pages(substream);
-       return 0;
-}
-
-
-static int snd_opti93x_playback_prepare(struct snd_pcm_substream *substream)
-{
-       struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       unsigned long flags;
-       unsigned char format;
-       unsigned int count = snd_pcm_lib_period_bytes(substream);
-       unsigned int size = snd_pcm_lib_buffer_bytes(substream);
-
-       spin_lock_irqsave(&chip->lock, flags);
-
-       chip->p_dma_size = size;
-       snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF,
-               OPTi93X_PLAYBACK_ENABLE | OPTi93X_PLAYBACK_PIO,
-               ~(OPTi93X_PLAYBACK_ENABLE | OPTi93X_PLAYBACK_PIO));
-
-       snd_dma_program(chip->dma1, runtime->dma_addr, size,
-               DMA_MODE_WRITE | DMA_AUTOINIT);
-
-       format = snd_opti93x_get_freq(runtime->rate);
-       format |= snd_opti93x_get_format(chip, runtime->format,
-               runtime->channels);
-       snd_opti93x_playback_format(chip, format);
-       format = chip->image[OPTi93X_PLAY_FORMAT];
-
-       count = snd_opti93x_get_count(format, count) - 1;
-       snd_opti93x_out_image(chip, OPTi93X_PLAY_LWR_CNT, count);
-       snd_opti93x_out_image(chip, OPTi93X_PLAY_UPR_CNT, count >> 8);
-
-       spin_unlock_irqrestore(&chip->lock, flags);
-       return 0;
-}
-
-static int snd_opti93x_capture_prepare(struct snd_pcm_substream *substream)
-{
-       struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       unsigned long flags;
-       unsigned char format;
-       unsigned int count = snd_pcm_lib_period_bytes(substream);
-       unsigned int size = snd_pcm_lib_buffer_bytes(substream);
-
-       spin_lock_irqsave(&chip->lock, flags);
-
-       chip->c_dma_size = size;
-       snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF,
-               OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO, 0);
-
-       snd_dma_program(chip->dma2, runtime->dma_addr, size,
-               DMA_MODE_READ | DMA_AUTOINIT);
-
-       format = snd_opti93x_get_freq(runtime->rate);
-       format |= snd_opti93x_get_format(chip, runtime->format,
-               runtime->channels);
-       snd_opti93x_capture_format(chip, format);
-       format = chip->image[OPTi93X_CAPT_FORMAT];
-
-       count = snd_opti93x_get_count(format, count) - 1;
-       snd_opti93x_out_image(chip, OPTi93X_CAPT_LWR_CNT, count);
-       snd_opti93x_out_image(chip, OPTi93X_CAPT_UPR_CNT, count >> 8);
-
-       spin_unlock_irqrestore(&chip->lock, flags);
-       return 0;
-}
-
-static snd_pcm_uframes_t snd_opti93x_playback_pointer(struct snd_pcm_substream *substream)
-{
-       struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-       size_t ptr;
-
-       if (!(chip->image[OPTi93X_IFACE_CONF] & OPTi93X_PLAYBACK_ENABLE))
-               return 0;
-
-       ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
-       return bytes_to_frames(substream->runtime, ptr);
-}
-
-static snd_pcm_uframes_t snd_opti93x_capture_pointer(struct snd_pcm_substream *substream)
-{
-       struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-       size_t ptr;
-       
-       if (!(chip->image[OPTi93X_IFACE_CONF] & OPTi93X_CAPTURE_ENABLE))
-               return 0;
-
-       ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
-       return bytes_to_frames(substream->runtime, ptr);
-}
-
-
-static void snd_opti93x_overrange(struct snd_opti93x *chip)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&chip->lock, flags);
-
-       if (snd_opti93x_in(chip, OPTi93X_ERR_INIT) & (0x08 | 0x02))
-               chip->capture_substream->runtime->overrange++;
-
-       spin_unlock_irqrestore(&chip->lock, flags);
-}
-
 static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
 {
-       struct snd_opti93x *codec = dev_id;
+       struct snd_cs4231 *codec = dev_id;
+       struct snd_opti9xx *chip = codec->card->private_data;
        unsigned char status;
 
-       status = snd_opti9xx_read(codec->chip, OPTi9XX_MC_REG(11));
+       status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11));
        if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream)
                snd_pcm_period_elapsed(codec->playback_substream);
        if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) {
-               snd_opti93x_overrange(codec);
+               snd_cs4231_overrange(codec);
                snd_pcm_period_elapsed(codec->capture_substream);
        }
        outb(0x00, OPTi93X_PORT(codec, STATUS));
        return IRQ_HANDLED;
 }
 
-
-static struct snd_pcm_hardware snd_opti93x_playback = {
-       .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-                                SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
-       .formats =              (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
-                                SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
-       .rates =                SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
-       .rate_min =             5512,
-       .rate_max =             48000,
-       .channels_min =         1,
-       .channels_max =         2,
-       .buffer_bytes_max =     (128*1024),
-       .period_bytes_min =     64,
-       .period_bytes_max =     (128*1024),
-       .periods_min =          1,
-       .periods_max =          1024,
-       .fifo_size =            0,
-};
-
-static struct snd_pcm_hardware snd_opti93x_capture = {
-       .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-                                SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
-       .formats =              (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
-                                SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
-       .rates =                SNDRV_PCM_RATE_8000_48000,
-       .rate_min =             5512,
-       .rate_max =             48000,
-       .channels_min =         1,
-       .channels_max =         2,
-       .buffer_bytes_max =     (128*1024),
-       .period_bytes_min =     64,
-       .period_bytes_max =     (128*1024),
-       .periods_min =          1,
-       .periods_max =          1024,
-       .fifo_size =            0,
-};
-
-static int snd_opti93x_playback_open(struct snd_pcm_substream *substream)
-{
-       int error;
-       struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       if ((error = snd_opti93x_open(chip, OPTi93X_MODE_PLAY)) < 0)
-               return error;
-       snd_pcm_set_sync(substream);
-       chip->playback_substream = substream;
-       runtime->hw = snd_opti93x_playback;
-       snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
-       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
-       return error;
-}
-
-static int snd_opti93x_capture_open(struct snd_pcm_substream *substream)
-{
-       int error;
-       struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-
-       if ((error = snd_opti93x_open(chip, OPTi93X_MODE_CAPTURE)) < 0)
-               return error;
-       runtime->hw = snd_opti93x_capture;
-       snd_pcm_set_sync(substream);
-       chip->capture_substream = substream;
-       snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
-       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
-       return error;
-}
-
-static int snd_opti93x_playback_close(struct snd_pcm_substream *substream)
-{
-       struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-
-       chip->playback_substream = NULL;
-       snd_opti93x_close(chip, OPTi93X_MODE_PLAY);
-       return 0;
-}
-
-static int snd_opti93x_capture_close(struct snd_pcm_substream *substream)
-{
-       struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-
-       chip->capture_substream = NULL;
-       snd_opti93x_close(chip, OPTi93X_MODE_CAPTURE);
-       return 0;
-}
-
-
-static void snd_opti93x_init(struct snd_opti93x *chip)
-{
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&chip->lock, flags);
-       snd_opti93x_mce_up(chip);
-
-       for (i = 0; i < 32; i++)
-               snd_opti93x_out_image(chip, i, snd_opti93x_default_image[i]);
-
-       snd_opti93x_mce_down(chip);
-       spin_unlock_irqrestore(&chip->lock, flags);
-}
-
-static int snd_opti93x_probe(struct snd_opti93x *chip)
-{
-       unsigned long flags;
-       unsigned char val;
-
-       spin_lock_irqsave(&chip->lock, flags);
-       val = snd_opti93x_in(chip, OPTi93X_ID) & 0x0f;
-       spin_unlock_irqrestore(&chip->lock, flags);
-
-       return (val == 0x0a) ? 0 : -ENODEV;
-}
-
-static int snd_opti93x_free(struct snd_opti93x *chip)
-{
-       release_and_free_resource(chip->res_port);
-       if (chip->dma1 >= 0) {
-               disable_dma(chip->dma1);
-               free_dma(chip->dma1);
-       }
-       if (chip->dma2 >= 0) {
-               disable_dma(chip->dma2);
-               free_dma(chip->dma2);
-       }
-       if (chip->irq >= 0) {
-         free_irq(chip->irq, chip);
-       }
-       kfree(chip);
-       return 0;
-}
-
-static int snd_opti93x_dev_free(struct snd_device *device)
-{
-       struct snd_opti93x *chip = device->device_data;
-       return snd_opti93x_free(chip);
-}
-
-static const char *snd_opti93x_chip_id(struct snd_opti93x *codec)
-{
-       switch (codec->hardware) {
-       case OPTi9XX_HW_82C930: return "82C930";
-       case OPTi9XX_HW_82C931: return "82C931";
-       case OPTi9XX_HW_82C933: return "82C933";
-       default:                return "???";
-       }
-}
-
-static int snd_opti93x_create(struct snd_card *card, struct snd_opti9xx *chip,
-                             int dma1, int dma2,
-                             struct snd_opti93x **rcodec)
-{
-       static struct snd_device_ops ops = {
-               .dev_free =     snd_opti93x_dev_free,
-       };
-       int error;
-       struct snd_opti93x *codec;
-
-       *rcodec = NULL;
-       codec = kzalloc(sizeof(*codec), GFP_KERNEL);
-       if (codec == NULL)
-               return -ENOMEM;
-       codec->irq = -1;
-       codec->dma1 = -1;
-       codec->dma2 = -1;
-
-       if ((codec->res_port = request_region(chip->wss_base + 4, 4, "OPTI93x CODEC")) == NULL) {
-               snd_printk(KERN_ERR "opti9xx: can't grab port 0x%lx\n", chip->wss_base + 4);
-               snd_opti93x_free(codec);
-               return -EBUSY;
-       }
-       if (request_dma(dma1, "OPTI93x - 1")) {
-               snd_printk(KERN_ERR "opti9xx: can't grab DMA1 %d\n", dma1);
-               snd_opti93x_free(codec);
-               return -EBUSY;
-       }
-       codec->dma1 = chip->dma1;
-       if (request_dma(dma2, "OPTI93x - 2")) {
-               snd_printk(KERN_ERR "opti9xx: can't grab DMA2 %d\n", dma2);
-               snd_opti93x_free(codec);
-               return -EBUSY;
-       }
-       codec->dma2 = chip->dma2;
-
-       if (request_irq(chip->irq, snd_opti93x_interrupt, IRQF_DISABLED, DEV_NAME" - WSS", codec)) {
-               snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);
-               snd_opti93x_free(codec);
-               return -EBUSY;
-       }
-
-       codec->card = card;
-       codec->port = chip->wss_base + 4;
-       codec->irq = chip->irq;
-
-       spin_lock_init(&codec->lock);
-       codec->hardware = chip->hardware;
-       codec->chip = chip;
-
-       if ((error = snd_opti93x_probe(codec))) {
-               snd_opti93x_free(codec);
-               return error;
-       }
-
-       snd_opti93x_init(codec);
-
-       /* Register device */
-       if ((error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops)) < 0) {
-               snd_opti93x_free(codec);
-               return error;
-       }
-
-       *rcodec = codec;
-       return 0;
-}
-
-static struct snd_pcm_ops snd_opti93x_playback_ops = {
-       .open =         snd_opti93x_playback_open,
-       .close =        snd_opti93x_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_opti93x_hw_params,
-       .hw_free =      snd_opti93x_hw_free,
-       .prepare =      snd_opti93x_playback_prepare,
-       .trigger =      snd_opti93x_playback_trigger,
-       .pointer =      snd_opti93x_playback_pointer,
-};
-
-static struct snd_pcm_ops snd_opti93x_capture_ops = {
-       .open =         snd_opti93x_capture_open,
-       .close =        snd_opti93x_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_opti93x_hw_params,
-       .hw_free =      snd_opti93x_hw_free,
-       .prepare =      snd_opti93x_capture_prepare,
-       .trigger =      snd_opti93x_capture_trigger,
-       .pointer =      snd_opti93x_capture_pointer,
-};
-
-static int snd_opti93x_pcm(struct snd_opti93x *codec, int device, struct snd_pcm **rpcm)
-{
-       int error;
-       struct snd_pcm *pcm;
-
-       if ((error = snd_pcm_new(codec->card, "OPTi 82C93X", device, 1, 1, &pcm)) < 0)
-               return error;
-
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_opti93x_playback_ops);
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_opti93x_capture_ops);
-
-       pcm->private_data = codec;
-       pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
-
-       strcpy(pcm->name, snd_opti93x_chip_id(codec));
-
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             snd_dma_isa_data(),
-                                             64*1024, codec->dma1 > 3 || codec->dma2 > 3 ? 128*1024 : 64*1024);
-
-       codec->pcm = pcm;
-       if (rpcm)
-               *rpcm = pcm;
-       return 0;
-}
-
-/*
- *  MIXER part
- */
-
-static int snd_opti93x_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-       static char *texts[4] = {
-               "Line1", "Aux", "Mic", "Mix"
-       };
-
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-       uinfo->count = 2;
-       uinfo->value.enumerated.items = 4;
-       if (uinfo->value.enumerated.item > 3)
-               uinfo->value.enumerated.item = 3;
-       strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
-       return 0;
-}
-
-static int snd_opti93x_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
-       unsigned long flags;
-       
-       spin_lock_irqsave(&chip->lock, flags);
-       ucontrol->value.enumerated.item[0] = (chip->image[OPTi93X_MIXOUT_LEFT] & OPTi93X_MIXOUT_MIXER) >> 6;
-       ucontrol->value.enumerated.item[1] = (chip->image[OPTi93X_MIXOUT_RIGHT] & OPTi93X_MIXOUT_MIXER) >> 6;
-       spin_unlock_irqrestore(&chip->lock, flags);
-       return 0;
-}
-
-static int snd_opti93x_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
-       unsigned long flags;
-       unsigned short left, right;
-       int change;
-       
-       if (ucontrol->value.enumerated.item[0] > 3 ||
-           ucontrol->value.enumerated.item[1] > 3)
-               return -EINVAL;
-       left = ucontrol->value.enumerated.item[0] << 6;
-       right = ucontrol->value.enumerated.item[1] << 6;
-       spin_lock_irqsave(&chip->lock, flags);
-       left = (chip->image[OPTi93X_MIXOUT_LEFT] & ~OPTi93X_MIXOUT_MIXER) | left;
-       right = (chip->image[OPTi93X_MIXOUT_RIGHT] & ~OPTi93X_MIXOUT_MIXER) | right;
-       change = left != chip->image[OPTi93X_MIXOUT_LEFT] ||
-                right != chip->image[OPTi93X_MIXOUT_RIGHT];
-       snd_opti93x_out_image(chip, OPTi93X_MIXOUT_LEFT, left);
-       snd_opti93x_out_image(chip, OPTi93X_MIXOUT_RIGHT, right);
-       spin_unlock_irqrestore(&chip->lock, flags);
-       return change;
-}
-
-#if 0
-
-#define OPTi93X_SINGLE(xname, xindex, reg, shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
-  .info = snd_opti93x_info_single, \
-  .get = snd_opti93x_get_single, .put = snd_opti93x_put_single, \
-  .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-
-static int snd_opti93x_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-       int mask = (kcontrol->private_value >> 16) & 0xff;
-
-       uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
-       uinfo->count = 1;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = mask;
-       return 0;
-}
-
-static int snd_opti93x_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
-       unsigned long flags;
-       int reg = kcontrol->private_value & 0xff;
-       int shift = (kcontrol->private_value >> 8) & 0xff;
-       int mask = (kcontrol->private_value >> 16) & 0xff;
-       int invert = (kcontrol->private_value >> 24) & 0xff;
-       
-       spin_lock_irqsave(&chip->lock, flags);
-       ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
-       spin_unlock_irqrestore(&chip->lock, flags);
-       if (invert)
-               ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
-       return 0;
-}
-
-static int snd_opti93x_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
-       unsigned long flags;
-       int reg = kcontrol->private_value & 0xff;
-       int shift = (kcontrol->private_value >> 8) & 0xff;
-       int mask = (kcontrol->private_value >> 16) & 0xff;
-       int invert = (kcontrol->private_value >> 24) & 0xff;
-       int change;
-       unsigned short val;
-       
-       val = (ucontrol->value.integer.value[0] & mask);
-       if (invert)
-               val = mask - val;
-       val <<= shift;
-       spin_lock_irqsave(&chip->lock, flags);
-       val = (chip->image[reg] & ~(mask << shift)) | val;
-       change = val != chip->image[reg];
-       snd_opti93x_out(chip, reg, val);
-       spin_unlock_irqrestore(&chip->lock, flags);
-       return change;
-}
-
-#endif /* single */
-
-#define OPTi93X_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
-  .info = snd_opti93x_info_double, \
-  .get = snd_opti93x_get_double, .put = snd_opti93x_put_double, \
-  .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-
-#define OPTi93X_DOUBLE_INVERT_INVERT(xctl) \
-       do { xctl.private_value ^= 22; } while (0)
-#define OPTi93X_DOUBLE_CHANGE_REGS(xctl, left_reg, right_reg) \
-       do { xctl.private_value &= ~0x0000ffff; \
-            xctl.private_value |= left_reg | (right_reg << 8); } while (0)
-
-static int snd_opti93x_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-       int mask = (kcontrol->private_value >> 24) & 0xff;
-
-       uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
-       uinfo->count = 2;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = mask;
-       return 0;
-}
-
-static int snd_opti93x_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
-       unsigned long flags;
-       int left_reg = kcontrol->private_value & 0xff;
-       int right_reg = (kcontrol->private_value >> 8) & 0xff;
-       int shift_left = (kcontrol->private_value >> 16) & 0x07;
-       int shift_right = (kcontrol->private_value >> 19) & 0x07;
-       int mask = (kcontrol->private_value >> 24) & 0xff;
-       int invert = (kcontrol->private_value >> 22) & 1;
-       
-       spin_lock_irqsave(&chip->lock, flags);
-       ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
-       ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
-       spin_unlock_irqrestore(&chip->lock, flags);
-       if (invert) {
-               ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
-               ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
-       }
-       return 0;
-}
-
-static int snd_opti93x_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
-       unsigned long flags;
-       int left_reg = kcontrol->private_value & 0xff;
-       int right_reg = (kcontrol->private_value >> 8) & 0xff;
-       int shift_left = (kcontrol->private_value >> 16) & 0x07;
-       int shift_right = (kcontrol->private_value >> 19) & 0x07;
-       int mask = (kcontrol->private_value >> 24) & 0xff;
-       int invert = (kcontrol->private_value >> 22) & 1;
-       int change;
-       unsigned short val1, val2;
-       
-       val1 = ucontrol->value.integer.value[0] & mask;
-       val2 = ucontrol->value.integer.value[1] & mask;
-       if (invert) {
-               val1 = mask - val1;
-               val2 = mask - val2;
-       }
-       val1 <<= shift_left;
-       val2 <<= shift_right;
-       spin_lock_irqsave(&chip->lock, flags);
-       val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
-       val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
-       change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
-       snd_opti93x_out_image(chip, left_reg, val1);
-       snd_opti93x_out_image(chip, right_reg, val2);
-       spin_unlock_irqrestore(&chip->lock, flags);
-       return change;
-}
-
-static struct snd_kcontrol_new snd_opti93x_controls[] __devinitdata = {
-OPTi93X_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), 
-OPTi93X_DOUBLE("PCM Playback Switch", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("PCM Playback Volume", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 0, 0, 31, 1),
-OPTi93X_DOUBLE("FM Playback Switch", 0, OPTi931_FM_LEFT_INPUT, OPTi931_FM_RIGHT_INPUT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("FM Playback Volume", 0, OPTi931_FM_LEFT_INPUT, OPTi931_FM_RIGHT_INPUT, 1, 1, 15, 1),
-OPTi93X_DOUBLE("Line Playback Switch", 0, OPTi93X_LINE_LEFT_INPUT, OPTi93X_LINE_RIGHT_INPUT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("Line Playback Volume", 0, OPTi93X_LINE_LEFT_INPUT, OPTi93X_LINE_RIGHT_INPUT, 1, 1, 15, 1), 
-OPTi93X_DOUBLE("Mic Playback Switch", 0, OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("Mic Playback Volume", 0, OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1), 
-OPTi93X_DOUBLE("Mic Boost", 0, OPTi93X_MIXOUT_LEFT, OPTi93X_MIXOUT_RIGHT, 5, 5, 1, 1),
-OPTi93X_DOUBLE("CD Playback Switch", 0, OPTi93X_CD_LEFT_INPUT, OPTi93X_CD_RIGHT_INPUT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("CD Playback Volume", 0, OPTi93X_CD_LEFT_INPUT, OPTi93X_CD_RIGHT_INPUT, 1, 1, 15, 1),
-OPTi93X_DOUBLE("Aux Playback Switch", 0, OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("Aux Playback Volume", 0, OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1), 
-OPTi93X_DOUBLE("Capture Volume", 0, OPTi93X_MIXOUT_LEFT, OPTi93X_MIXOUT_RIGHT, 0, 0, 15, 0),
-{
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "Capture Source",
-       .info = snd_opti93x_info_mux,
-       .get = snd_opti93x_get_mux,
-       .put = snd_opti93x_put_mux,
-}
-};
-                                        
-static int __devinit snd_opti93x_mixer(struct snd_opti93x *chip)
-{
-       struct snd_card *card;
-       struct snd_kcontrol_new knew;
-       int err;
-       unsigned int idx;
-
-       snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
-
-       card = chip->card;
-
-       strcpy(card->mixername, snd_opti93x_chip_id(chip));
-
-       for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
-               knew = snd_opti93x_controls[idx];
-               if (chip->hardware == OPTi9XX_HW_82C930) {
-                       if (strstr(knew.name, "FM"))    /* skip FM controls */
-                               continue;
-                       else if (strcmp(knew.name, "Mic Playback Volume"))
-                               OPTi93X_DOUBLE_INVERT_INVERT(knew);
-                       else if (strstr(knew.name, "Aux"))
-                               OPTi93X_DOUBLE_CHANGE_REGS(knew, OPTi930_AUX_LEFT_INPUT, OPTi930_AUX_RIGHT_INPUT);
-                       else if (strcmp(knew.name, "PCM Playback Volume"))
-                               OPTi93X_DOUBLE_INVERT_INVERT(knew);
-                       else if (strcmp(knew.name, "Master Playback Volume"))
-                               OPTi93X_DOUBLE_INVERT_INVERT(knew);
-               }
-               if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_opti93x_controls[idx], chip))) < 0)
-                       return err;
-       }
-       return 0;
-}
-
 #endif /* OPTi93X */
 
 static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
@@ -1739,8 +685,16 @@ static void snd_card_opti9xx_free(struct snd_card *card)
 {
        struct snd_opti9xx *chip = card->private_data;
         
-       if (chip)
+       if (chip) {
+#ifdef OPTi93X
+               struct snd_cs4231 *codec = chip->codec;
+               if (codec->irq > 0) {
+                       disable_irq(codec->irq);
+                       free_irq(codec->irq, codec);
+               }
+#endif
                release_and_free_resource(chip->res_mc_base);
+       }
 }
 
 static int __devinit snd_opti9xx_probe(struct snd_card *card)
@@ -1748,11 +702,11 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
        static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
        int error;
        struct snd_opti9xx *chip = card->private_data;
-#if defined(OPTi93X)
-       struct snd_opti93x *codec;
-#elif defined(CS4231)
+#if defined(CS4231) || defined(OPTi93X)
        struct snd_cs4231 *codec;
+#ifdef CS4231
        struct snd_timer *timer;
+#endif
 #else
        struct snd_ad1848 *codec;
 #endif
@@ -1784,26 +738,34 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
        if ((error = snd_opti9xx_configure(chip)))
                return error;
 
-#if defined(OPTi93X)
-       if ((error = snd_opti93x_create(card, chip, chip->dma1, chip->dma2, &codec)))
-               return error;
-       if ((error = snd_opti93x_pcm(codec, 0, &pcm)) < 0)
-               return error;
-       if ((error = snd_opti93x_mixer(codec)) < 0)
-               return error;
-#elif defined(CS4231)
+#if defined(CS4231) || defined(OPTi93X)
        if ((error = snd_cs4231_create(card, chip->wss_base + 4, -1,
                                       chip->irq, chip->dma1, chip->dma2,
-                                      CS4231_HW_DETECT,
-                                      0,
+#ifdef CS4231
+                                      CS4231_HW_DETECT, 0,
+#else /* OPTi93x */
+                                      CS4231_HW_OPTI93X, CS4231_HWSHARE_IRQ,
+#endif
                                       &codec)) < 0)
                return error;
+#ifdef OPTi93X
+       chip->codec = codec;
+#endif
        if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0)
                return error;
        if ((error = snd_cs4231_mixer(codec)) < 0)
                return error;
+#ifdef CS4231
        if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0)
                return error;
+#else /* OPTI93X */
+       error = request_irq(chip->irq, snd_opti93x_interrupt,
+                           IRQF_DISABLED, DEV_NAME" - WSS", codec);
+       if (error < 0) {
+               snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);
+               return error;
+       }
+#endif
 #else
        if ((error = snd_ad1848_create(card, chip->wss_base + 4,
                                       chip->irq, chip->dma1,
index c9d1c986d70e753f784235c26a806307a1af3598..1098a56b2f4b878898aca659d3096eafa6fd3edc 100644 (file)
@@ -34,5 +34,3 @@ ifeq ($(CONFIG_SND_SB16_CSP),y)
   obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o
 endif
 obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-emu8000-synth.o
-
-obj-m := $(sort $(obj-m))
index 95eeca163354b5303b89554bdeafb8053bc54fcd..0bb9b92566010875f148106c8423bf04a5b3cff8 100644 (file)
@@ -1939,7 +1939,7 @@ static int __devinit
 wavefront_download_firmware (snd_wavefront_t *dev, char *path)
 
 {
-       unsigned char *buf;
+       const unsigned char *buf;
        int len, err;
        int section_cnt_downloaded = 0;
        const struct firmware *firmware;
index 531f8ba96a71ae40d05b810cc6b42e36fe2ec165..a9823fad85c2d9ecaf0bbc2bfd0ad13d3e254796 100644 (file)
@@ -1,15 +1,34 @@
 # ALSA MIPS drivers
 
-menu "ALSA MIPS devices"
-       depends on SND!=n && MIPS
+menuconfig SND_MIPS
+       bool "MIPS sound devices"
+       depends on MIPS
+       default y
+       help
+         Support for sound devices of MIPS architectures.
+
+if SND_MIPS
+
+config SND_SGI_O2
+       tristate "SGI O2 Audio"
+       depends on SGI_IP32
+        help
+                Sound support for the SGI O2 Workstation. 
+
+config SND_SGI_HAL2
+        tristate "SGI HAL2 Audio"
+        depends on SGI_HAS_HAL2
+        help
+                Sound support for the SGI Indy and Indigo2 Workstation.
+
 
 config SND_AU1X00
        tristate "Au1x00 AC97 Port Driver"
-       depends on (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && SND
+       depends on SOC_AU1000 || SOC_AU1100 || SOC_AU1500
        select SND_PCM
        select SND_AC97_CODEC
        help
          ALSA Sound driver for the Au1x00's AC97 port.
 
-endmenu
+endif  # SND_MIPS
 
index 47afed971fba6f81c7f06b841200f597e0794474..861ec0a574b46efd5315878f4666edc87d288271 100644 (file)
@@ -3,6 +3,10 @@
 #
 
 snd-au1x00-objs := au1x00.o
+snd-sgi-o2-objs := sgio2audio.o ad1843.o
+snd-sgi-hal2-objs := hal2.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_AU1X00) += snd-au1x00.o
+obj-$(CONFIG_SND_SGI_O2) += snd-sgi-o2.o
+obj-$(CONFIG_SND_SGI_HAL2) += snd-sgi-hal2.o
diff --git a/sound/mips/ad1843.c b/sound/mips/ad1843.c
new file mode 100644 (file)
index 0000000..c624510
--- /dev/null
@@ -0,0 +1,561 @@
+/*
+ *   AD1843 low level driver
+ *
+ *   Copyright 2003 Vivien Chappelier <vivien.chappelier@linux-mips.org>
+ *   Copyright 2008 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+ *
+ *   inspired from vwsnd.c (SGI VW audio driver)
+ *     Copyright 1999 Silicon Graphics, Inc.  All rights reserved.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This 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/sched.h>
+#include <linux/errno.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/ad1843.h>
+
+/*
+ * AD1843 bitfield definitions.  All are named as in the AD1843 data
+ * sheet, with ad1843_ prepended and individual bit numbers removed.
+ *
+ * E.g., bits LSS0 through LSS2 become ad1843_LSS.
+ *
+ * Only the bitfields we need are defined.
+ */
+
+struct ad1843_bitfield {
+       char reg;
+       char lo_bit;
+       char nbits;
+};
+
+static const struct ad1843_bitfield
+       ad1843_PDNO   = {  0, 14,  1 }, /* Converter Power-Down Flag */
+       ad1843_INIT   = {  0, 15,  1 }, /* Clock Initialization Flag */
+       ad1843_RIG    = {  2,  0,  4 }, /* Right ADC Input Gain */
+       ad1843_RMGE   = {  2,  4,  1 }, /* Right ADC Mic Gain Enable */
+       ad1843_RSS    = {  2,  5,  3 }, /* Right ADC Source Select */
+       ad1843_LIG    = {  2,  8,  4 }, /* Left ADC Input Gain */
+       ad1843_LMGE   = {  2, 12,  1 }, /* Left ADC Mic Gain Enable */
+       ad1843_LSS    = {  2, 13,  3 }, /* Left ADC Source Select */
+       ad1843_RD2M   = {  3,  0,  5 }, /* Right DAC 2 Mix Gain/Atten */
+       ad1843_RD2MM  = {  3,  7,  1 }, /* Right DAC 2 Mix Mute */
+       ad1843_LD2M   = {  3,  8,  5 }, /* Left DAC 2 Mix Gain/Atten */
+       ad1843_LD2MM  = {  3, 15,  1 }, /* Left DAC 2 Mix Mute */
+       ad1843_RX1M   = {  4,  0,  5 }, /* Right Aux 1 Mix Gain/Atten */
+       ad1843_RX1MM  = {  4,  7,  1 }, /* Right Aux 1 Mix Mute */
+       ad1843_LX1M   = {  4,  8,  5 }, /* Left Aux 1 Mix Gain/Atten */
+       ad1843_LX1MM  = {  4, 15,  1 }, /* Left Aux 1 Mix Mute */
+       ad1843_RX2M   = {  5,  0,  5 }, /* Right Aux 2 Mix Gain/Atten */
+       ad1843_RX2MM  = {  5,  7,  1 }, /* Right Aux 2 Mix Mute */
+       ad1843_LX2M   = {  5,  8,  5 }, /* Left Aux 2 Mix Gain/Atten */
+       ad1843_LX2MM  = {  5, 15,  1 }, /* Left Aux 2 Mix Mute */
+       ad1843_RMCM   = {  7,  0,  5 }, /* Right Mic Mix Gain/Atten */
+       ad1843_RMCMM  = {  7,  7,  1 }, /* Right Mic Mix Mute */
+       ad1843_LMCM   = {  7,  8,  5 }, /* Left Mic Mix Gain/Atten */
+       ad1843_LMCMM  = {  7, 15,  1 }, /* Left Mic Mix Mute */
+       ad1843_HPOS   = {  8,  4,  1 }, /* Headphone Output Voltage Swing */
+       ad1843_HPOM   = {  8,  5,  1 }, /* Headphone Output Mute */
+       ad1843_MPOM   = {  8,  6,  1 }, /* Mono Output Mute */
+       ad1843_RDA1G  = {  9,  0,  6 }, /* Right DAC1 Analog/Digital Gain */
+       ad1843_RDA1GM = {  9,  7,  1 }, /* Right DAC1 Analog Mute */
+       ad1843_LDA1G  = {  9,  8,  6 }, /* Left DAC1 Analog/Digital Gain */
+       ad1843_LDA1GM = {  9, 15,  1 }, /* Left DAC1 Analog Mute */
+       ad1843_RDA2G  = { 10,  0,  6 }, /* Right DAC2 Analog/Digital Gain */
+       ad1843_RDA2GM = { 10,  7,  1 }, /* Right DAC2 Analog Mute */
+       ad1843_LDA2G  = { 10,  8,  6 }, /* Left DAC2 Analog/Digital Gain */
+       ad1843_LDA2GM = { 10, 15,  1 }, /* Left DAC2 Analog Mute */
+       ad1843_RDA1AM = { 11,  7,  1 }, /* Right DAC1 Digital Mute */
+       ad1843_LDA1AM = { 11, 15,  1 }, /* Left DAC1 Digital Mute */
+       ad1843_RDA2AM = { 12,  7,  1 }, /* Right DAC2 Digital Mute */
+       ad1843_LDA2AM = { 12, 15,  1 }, /* Left DAC2 Digital Mute */
+       ad1843_ADLC   = { 15,  0,  2 }, /* ADC Left Sample Rate Source */
+       ad1843_ADRC   = { 15,  2,  2 }, /* ADC Right Sample Rate Source */
+       ad1843_DA1C   = { 15,  8,  2 }, /* DAC1 Sample Rate Source */
+       ad1843_DA2C   = { 15, 10,  2 }, /* DAC2 Sample Rate Source */
+       ad1843_C1C    = { 17,  0, 16 }, /* Clock 1 Sample Rate Select */
+       ad1843_C2C    = { 20,  0, 16 }, /* Clock 2 Sample Rate Select */
+       ad1843_C3C    = { 23,  0, 16 }, /* Clock 3 Sample Rate Select */
+       ad1843_DAADL  = { 25,  4,  2 }, /* Digital ADC Left Source Select */
+       ad1843_DAADR  = { 25,  6,  2 }, /* Digital ADC Right Source Select */
+       ad1843_DAMIX  = { 25, 14,  1 }, /* DAC Digital Mix Enable */
+       ad1843_DRSFLT = { 25, 15,  1 }, /* Digital Reampler Filter Mode */
+       ad1843_ADLF   = { 26,  0,  2 }, /* ADC Left Channel Data Format */
+       ad1843_ADRF   = { 26,  2,  2 }, /* ADC Right Channel Data Format */
+       ad1843_ADTLK  = { 26,  4,  1 }, /* ADC Transmit Lock Mode Select */
+       ad1843_SCF    = { 26,  7,  1 }, /* SCLK Frequency Select */
+       ad1843_DA1F   = { 26,  8,  2 }, /* DAC1 Data Format Select */
+       ad1843_DA2F   = { 26, 10,  2 }, /* DAC2 Data Format Select */
+       ad1843_DA1SM  = { 26, 14,  1 }, /* DAC1 Stereo/Mono Mode Select */
+       ad1843_DA2SM  = { 26, 15,  1 }, /* DAC2 Stereo/Mono Mode Select */
+       ad1843_ADLEN  = { 27,  0,  1 }, /* ADC Left Channel Enable */
+       ad1843_ADREN  = { 27,  1,  1 }, /* ADC Right Channel Enable */
+       ad1843_AAMEN  = { 27,  4,  1 }, /* Analog to Analog Mix Enable */
+       ad1843_ANAEN  = { 27,  7,  1 }, /* Analog Channel Enable */
+       ad1843_DA1EN  = { 27,  8,  1 }, /* DAC1 Enable */
+       ad1843_DA2EN  = { 27,  9,  1 }, /* DAC2 Enable */
+       ad1843_DDMEN  = { 27, 12,  1 }, /* DAC2 to DAC1 Mix  Enable */
+       ad1843_C1EN   = { 28, 11,  1 }, /* Clock Generator 1 Enable */
+       ad1843_C2EN   = { 28, 12,  1 }, /* Clock Generator 2 Enable */
+       ad1843_C3EN   = { 28, 13,  1 }, /* Clock Generator 3 Enable */
+       ad1843_PDNI   = { 28, 15,  1 }; /* Converter Power Down */
+
+/*
+ * The various registers of the AD1843 use three different formats for
+ * specifying gain.  The ad1843_gain structure parameterizes the
+ * formats.
+ */
+
+struct ad1843_gain {
+       int     negative;               /* nonzero if gain is negative. */
+       const struct ad1843_bitfield *lfield;
+       const struct ad1843_bitfield *rfield;
+       const struct ad1843_bitfield *lmute;
+       const struct ad1843_bitfield *rmute;
+};
+
+static const struct ad1843_gain ad1843_gain_RECLEV = {
+       .negative = 0,
+       .lfield   = &ad1843_LIG,
+       .rfield   = &ad1843_RIG
+};
+static const struct ad1843_gain ad1843_gain_LINE = {
+       .negative = 1,
+       .lfield   = &ad1843_LX1M,
+       .rfield   = &ad1843_RX1M,
+       .lmute    = &ad1843_LX1MM,
+       .rmute    = &ad1843_RX1MM
+};
+static const struct ad1843_gain ad1843_gain_LINE_2 = {
+       .negative = 1,
+       .lfield   = &ad1843_LDA2G,
+       .rfield   = &ad1843_RDA2G,
+       .lmute    = &ad1843_LDA2GM,
+       .rmute    = &ad1843_RDA2GM
+};
+static const struct ad1843_gain ad1843_gain_MIC = {
+       .negative = 1,
+       .lfield   = &ad1843_LMCM,
+       .rfield   = &ad1843_RMCM,
+       .lmute    = &ad1843_LMCMM,
+       .rmute    = &ad1843_RMCMM
+};
+static const struct ad1843_gain ad1843_gain_PCM_0 = {
+       .negative = 1,
+       .lfield   = &ad1843_LDA1G,
+       .rfield   = &ad1843_RDA1G,
+       .lmute    = &ad1843_LDA1GM,
+       .rmute    = &ad1843_RDA1GM
+};
+static const struct ad1843_gain ad1843_gain_PCM_1 = {
+       .negative = 1,
+       .lfield   = &ad1843_LD2M,
+       .rfield   = &ad1843_RD2M,
+       .lmute    = &ad1843_LD2MM,
+       .rmute    = &ad1843_RD2MM
+};
+
+static const struct ad1843_gain *ad1843_gain[AD1843_GAIN_SIZE] =
+{
+       &ad1843_gain_RECLEV,
+       &ad1843_gain_LINE,
+       &ad1843_gain_LINE_2,
+       &ad1843_gain_MIC,
+       &ad1843_gain_PCM_0,
+       &ad1843_gain_PCM_1,
+};
+
+/* read the current value of an AD1843 bitfield. */
+
+static int ad1843_read_bits(struct snd_ad1843 *ad1843,
+                           const struct ad1843_bitfield *field)
+{
+       int w;
+
+       w = ad1843->read(ad1843->chip, field->reg);
+       return w >> field->lo_bit & ((1 << field->nbits) - 1);
+}
+
+/*
+ * write a new value to an AD1843 bitfield and return the old value.
+ */
+
+static int ad1843_write_bits(struct snd_ad1843 *ad1843,
+                            const struct ad1843_bitfield *field,
+                            int newval)
+{
+       int w, mask, oldval, newbits;
+
+       w = ad1843->read(ad1843->chip, field->reg);
+       mask = ((1 << field->nbits) - 1) << field->lo_bit;
+       oldval = (w & mask) >> field->lo_bit;
+       newbits = (newval << field->lo_bit) & mask;
+       w = (w & ~mask) | newbits;
+       ad1843->write(ad1843->chip, field->reg, w);
+
+       return oldval;
+}
+
+/*
+ * ad1843_read_multi reads multiple bitfields from the same AD1843
+ * register.  It uses a single read cycle to do it.  (Reading the
+ * ad1843 requires 256 bit times at 12.288 MHz, or nearly 20
+ * microseconds.)
+ *
+ * Called like this.
+ *
+ *  ad1843_read_multi(ad1843, nfields,
+ *                   &ad1843_FIELD1, &val1,
+ *                   &ad1843_FIELD2, &val2, ...);
+ */
+
+static void ad1843_read_multi(struct snd_ad1843 *ad1843, int argcount, ...)
+{
+       va_list ap;
+       const struct ad1843_bitfield *fp;
+       int w = 0, mask, *value, reg = -1;
+
+       va_start(ap, argcount);
+       while (--argcount >= 0) {
+               fp = va_arg(ap, const struct ad1843_bitfield *);
+               value = va_arg(ap, int *);
+               if (reg == -1) {
+                       reg = fp->reg;
+                       w = ad1843->read(ad1843->chip, reg);
+               }
+
+               mask = (1 << fp->nbits) - 1;
+               *value = w >> fp->lo_bit & mask;
+       }
+       va_end(ap);
+}
+
+/*
+ * ad1843_write_multi stores multiple bitfields into the same AD1843
+ * register.  It uses one read and one write cycle to do it.
+ *
+ * Called like this.
+ *
+ *  ad1843_write_multi(ad1843, nfields,
+ *                    &ad1843_FIELD1, val1,
+ *                    &ad1843_FIELF2, val2, ...);
+ */
+
+static void ad1843_write_multi(struct snd_ad1843 *ad1843, int argcount, ...)
+{
+       va_list ap;
+       int reg;
+       const struct ad1843_bitfield *fp;
+       int value;
+       int w, m, mask, bits;
+
+       mask = 0;
+       bits = 0;
+       reg = -1;
+
+       va_start(ap, argcount);
+       while (--argcount >= 0) {
+               fp = va_arg(ap, const struct ad1843_bitfield *);
+               value = va_arg(ap, int);
+               if (reg == -1)
+                       reg = fp->reg;
+               else
+                       BUG_ON(reg != fp->reg);
+               m = ((1 << fp->nbits) - 1) << fp->lo_bit;
+               mask |= m;
+               bits |= (value << fp->lo_bit) & m;
+       }
+       va_end(ap);
+
+       if (~mask & 0xFFFF)
+               w = ad1843->read(ad1843->chip, reg);
+       else
+               w = 0;
+       w = (w & ~mask) | bits;
+       ad1843->write(ad1843->chip, reg, w);
+}
+
+int ad1843_get_gain_max(struct snd_ad1843 *ad1843, int id)
+{
+       const struct ad1843_gain *gp = ad1843_gain[id];
+       int ret;
+
+       ret = (1 << gp->lfield->nbits);
+       if (!gp->lmute)
+               ret -= 1;
+       return ret;
+}
+
+/*
+ * ad1843_get_gain reads the specified register and extracts the gain value
+ * using the supplied gain type.
+ */
+
+int ad1843_get_gain(struct snd_ad1843 *ad1843, int id)
+{
+       int lg, rg, lm, rm;
+       const struct ad1843_gain *gp = ad1843_gain[id];
+       unsigned short mask = (1 << gp->lfield->nbits) - 1;
+
+       ad1843_read_multi(ad1843, 2, gp->lfield, &lg, gp->rfield, &rg);
+       if (gp->negative) {
+               lg = mask - lg;
+               rg = mask - rg;
+       }
+       if (gp->lmute) {
+               ad1843_read_multi(ad1843, 2, gp->lmute, &lm, gp->rmute, &rm);
+               if (lm)
+                       lg = 0;
+               if (rm)
+                       rg = 0;
+       }
+       return lg << 0 | rg << 8;
+}
+
+/*
+ * Set an audio channel's gain.
+ *
+ * Returns the new gain, which may be lower than the old gain.
+ */
+
+int ad1843_set_gain(struct snd_ad1843 *ad1843, int id, int newval)
+{
+       const struct ad1843_gain *gp = ad1843_gain[id];
+       unsigned short mask = (1 << gp->lfield->nbits) - 1;
+
+       int lg = (newval >> 0) & mask;
+       int rg = (newval >> 8) & mask;
+       int lm = (lg == 0) ? 1 : 0;
+       int rm = (rg == 0) ? 1 : 0;
+
+       if (gp->negative) {
+               lg = mask - lg;
+               rg = mask - rg;
+       }
+       if (gp->lmute)
+               ad1843_write_multi(ad1843, 2, gp->lmute, lm, gp->rmute, rm);
+       ad1843_write_multi(ad1843, 2, gp->lfield, lg, gp->rfield, rg);
+       return ad1843_get_gain(ad1843, id);
+}
+
+/* Returns the current recording source */
+
+int ad1843_get_recsrc(struct snd_ad1843 *ad1843)
+{
+       int val = ad1843_read_bits(ad1843, &ad1843_LSS);
+
+       if (val < 0 || val > 2) {
+               val = 2;
+               ad1843_write_multi(ad1843, 2,
+                                  &ad1843_LSS, val, &ad1843_RSS, val);
+       }
+       return val;
+}
+
+/*
+ * Set recording source.
+ *
+ * Returns newsrc on success, -errno on failure.
+ */
+
+int ad1843_set_recsrc(struct snd_ad1843 *ad1843, int newsrc)
+{
+       if (newsrc < 0 || newsrc > 2)
+               return -EINVAL;
+
+       ad1843_write_multi(ad1843, 2, &ad1843_LSS, newsrc, &ad1843_RSS, newsrc);
+       return newsrc;
+}
+
+/* Setup ad1843 for D/A conversion. */
+
+void ad1843_setup_dac(struct snd_ad1843 *ad1843,
+                     unsigned int id,
+                     unsigned int framerate,
+                     snd_pcm_format_t fmt,
+                     unsigned int channels)
+{
+       int ad_fmt = 0, ad_mode = 0;
+
+       switch (fmt) {
+       case SNDRV_PCM_FORMAT_S8:
+               ad_fmt = 0;
+               break;
+       case SNDRV_PCM_FORMAT_U8:
+               ad_fmt = 0;
+               break;
+       case SNDRV_PCM_FORMAT_S16_LE:
+               ad_fmt = 1;
+               break;
+       case SNDRV_PCM_FORMAT_MU_LAW:
+               ad_fmt = 2;
+               break;
+       case SNDRV_PCM_FORMAT_A_LAW:
+               ad_fmt = 3;
+               break;
+       default:
+               break;
+       }
+
+       switch (channels) {
+       case 2:
+               ad_mode = 0;
+               break;
+       case 1:
+               ad_mode = 1;
+               break;
+       default:
+               break;
+       }
+
+       if (id) {
+               ad1843_write_bits(ad1843, &ad1843_C2C, framerate);
+               ad1843_write_multi(ad1843, 2,
+                                  &ad1843_DA2SM, ad_mode,
+                                  &ad1843_DA2F, ad_fmt);
+       } else {
+               ad1843_write_bits(ad1843, &ad1843_C1C, framerate);
+               ad1843_write_multi(ad1843, 2,
+                                  &ad1843_DA1SM, ad_mode,
+                                  &ad1843_DA1F, ad_fmt);
+       }
+}
+
+void ad1843_shutdown_dac(struct snd_ad1843 *ad1843, unsigned int id)
+{
+       if (id)
+               ad1843_write_bits(ad1843, &ad1843_DA2F, 1);
+       else
+               ad1843_write_bits(ad1843, &ad1843_DA1F, 1);
+}
+
+void ad1843_setup_adc(struct snd_ad1843 *ad1843,
+                     unsigned int framerate,
+                     snd_pcm_format_t fmt,
+                     unsigned int channels)
+{
+       int da_fmt = 0;
+
+       switch (fmt) {
+       case SNDRV_PCM_FORMAT_S8:       da_fmt = 0; break;
+       case SNDRV_PCM_FORMAT_U8:       da_fmt = 0; break;
+       case SNDRV_PCM_FORMAT_S16_LE:   da_fmt = 1; break;
+       case SNDRV_PCM_FORMAT_MU_LAW:   da_fmt = 2; break;
+       case SNDRV_PCM_FORMAT_A_LAW:    da_fmt = 3; break;
+       default:                break;
+       }
+
+       ad1843_write_bits(ad1843, &ad1843_C3C, framerate);
+       ad1843_write_multi(ad1843, 2,
+                          &ad1843_ADLF, da_fmt, &ad1843_ADRF, da_fmt);
+}
+
+void ad1843_shutdown_adc(struct snd_ad1843 *ad1843)
+{
+       /* nothing to do */
+}
+
+/*
+ * Fully initialize the ad1843.  As described in the AD1843 data
+ * sheet, section "START-UP SEQUENCE".  The numbered comments are
+ * subsection headings from the data sheet.  See the data sheet, pages
+ * 52-54, for more info.
+ *
+ * return 0 on success, -errno on failure.  */
+
+int ad1843_init(struct snd_ad1843 *ad1843)
+{
+       unsigned long later;
+
+       if (ad1843_read_bits(ad1843, &ad1843_INIT) != 0) {
+               printk(KERN_ERR "ad1843: AD1843 won't initialize\n");
+               return -EIO;
+       }
+
+       ad1843_write_bits(ad1843, &ad1843_SCF, 1);
+
+       /* 4. Put the conversion resources into standby. */
+       ad1843_write_bits(ad1843, &ad1843_PDNI, 0);
+       later = jiffies + msecs_to_jiffies(500);
+
+       while (ad1843_read_bits(ad1843, &ad1843_PDNO)) {
+               if (time_after(jiffies, later)) {
+                       printk(KERN_ERR
+                              "ad1843: AD1843 won't power up\n");
+                       return -EIO;
+               }
+               schedule_timeout_interruptible(5);
+       }
+
+       /* 5. Power up the clock generators and enable clock output pins. */
+       ad1843_write_multi(ad1843, 3,
+                          &ad1843_C1EN, 1,
+                          &ad1843_C2EN, 1,
+                          &ad1843_C3EN, 1);
+
+       /* 6. Configure conversion resources while they are in standby. */
+
+       /* DAC1/2 use clock 1/2 as source, ADC uses clock 3.  Always. */
+       ad1843_write_multi(ad1843, 4,
+                          &ad1843_DA1C, 1,
+                          &ad1843_DA2C, 2,
+                          &ad1843_ADLC, 3,
+                          &ad1843_ADRC, 3);
+
+       /* 7. Enable conversion resources. */
+       ad1843_write_bits(ad1843, &ad1843_ADTLK, 1);
+       ad1843_write_multi(ad1843, 7,
+                          &ad1843_ANAEN, 1,
+                          &ad1843_AAMEN, 1,
+                          &ad1843_DA1EN, 1,
+                          &ad1843_DA2EN, 1,
+                          &ad1843_DDMEN, 1,
+                          &ad1843_ADLEN, 1,
+                          &ad1843_ADREN, 1);
+
+       /* 8. Configure conversion resources while they are enabled. */
+
+       /* set gain to 0 for all channels */
+       ad1843_set_gain(ad1843, AD1843_GAIN_RECLEV, 0);
+       ad1843_set_gain(ad1843, AD1843_GAIN_LINE, 0);
+       ad1843_set_gain(ad1843, AD1843_GAIN_LINE_2, 0);
+       ad1843_set_gain(ad1843, AD1843_GAIN_MIC, 0);
+       ad1843_set_gain(ad1843, AD1843_GAIN_PCM_0, 0);
+       ad1843_set_gain(ad1843, AD1843_GAIN_PCM_1, 0);
+
+       /* Unmute all channels. */
+       /* DAC1 */
+       ad1843_write_multi(ad1843, 2, &ad1843_LDA1GM, 0, &ad1843_RDA1GM, 0);
+       /* DAC2 */
+       ad1843_write_multi(ad1843, 2, &ad1843_LDA2GM, 0, &ad1843_RDA2GM, 0);
+
+       /* Set default recording source to Line In and set
+        * mic gain to +20 dB.
+        */
+       ad1843_set_recsrc(ad1843, 2);
+       ad1843_write_multi(ad1843, 2, &ad1843_LMGE, 1, &ad1843_RMGE, 1);
+
+       /* Set Speaker Out level to +/- 4V and unmute it. */
+       ad1843_write_multi(ad1843, 3,
+                          &ad1843_HPOS, 1,
+                          &ad1843_HPOM, 0,
+                          &ad1843_MPOM, 0);
+
+       return 0;
+}
diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c
new file mode 100644 (file)
index 0000000..db495be
--- /dev/null
@@ -0,0 +1,947 @@
+/*
+ *  Driver for A2 audio system used in SGI machines
+ *  Copyright (c) 2008 Thomas Bogendoerfer <tsbogend@alpha.fanken.de>
+ *
+ *  Based on OSS code from Ladislav Michl <ladis@linux-mips.org>, which
+ *  was based on code from Ulf Carlsson
+ *
+ *  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.
+ *
+ *  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/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/ip22.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm-indirect.h>
+#include <sound/initval.h>
+
+#include "hal2.h"
+
+static int index = SNDRV_DEFAULT_IDX1;  /* Index 0-MAX */
+static char *id = SNDRV_DEFAULT_STR1;   /* ID for this card */
+
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "Index value for SGI HAL2 soundcard.");
+module_param(id, charp, 0444);
+MODULE_PARM_DESC(id, "ID string for SGI HAL2 soundcard.");
+MODULE_DESCRIPTION("ALSA driver for SGI HAL2 audio");
+MODULE_AUTHOR("Thomas Bogendoerfer");
+MODULE_LICENSE("GPL");
+
+
+#define H2_BLOCK_SIZE  1024
+#define H2_BUF_SIZE    16384
+
+struct hal2_pbus {
+       struct hpc3_pbus_dmacregs *pbus;
+       int pbusnr;
+       unsigned int ctrl;              /* Current state of pbus->pbdma_ctrl */
+};
+
+struct hal2_desc {
+       struct hpc_dma_desc desc;
+       u32 pad;                        /* padding */
+};
+
+struct hal2_codec {
+       struct snd_pcm_indirect pcm_indirect;
+       struct snd_pcm_substream *substream;
+
+       unsigned char *buffer;
+       dma_addr_t buffer_dma;
+       struct hal2_desc *desc;
+       dma_addr_t desc_dma;
+       int desc_count;
+       struct hal2_pbus pbus;
+       int voices;                     /* mono/stereo */
+       unsigned int sample_rate;
+       unsigned int master;            /* Master frequency */
+       unsigned short mod;             /* MOD value */
+       unsigned short inc;             /* INC value */
+};
+
+#define H2_MIX_OUTPUT_ATT      0
+#define H2_MIX_INPUT_GAIN      1
+
+struct snd_hal2 {
+       struct snd_card *card;
+
+       struct hal2_ctl_regs *ctl_regs; /* HAL2 ctl registers */
+       struct hal2_aes_regs *aes_regs; /* HAL2 aes registers */
+       struct hal2_vol_regs *vol_regs; /* HAL2 vol registers */
+       struct hal2_syn_regs *syn_regs; /* HAL2 syn registers */
+
+       struct hal2_codec dac;
+       struct hal2_codec adc;
+};
+
+#define H2_INDIRECT_WAIT(regs) while (hal2_read(&regs->isr) & H2_ISR_TSTATUS);
+
+#define H2_READ_ADDR(addr)     (addr | (1<<7))
+#define H2_WRITE_ADDR(addr)    (addr)
+
+static inline u32 hal2_read(u32 *reg)
+{
+       return __raw_readl(reg);
+}
+
+static inline void hal2_write(u32 val, u32 *reg)
+{
+       __raw_writel(val, reg);
+}
+
+
+static u32 hal2_i_read32(struct snd_hal2 *hal2, u16 addr)
+{
+       u32 ret;
+       struct hal2_ctl_regs *regs = hal2->ctl_regs;
+
+       hal2_write(H2_READ_ADDR(addr), &regs->iar);
+       H2_INDIRECT_WAIT(regs);
+       ret = hal2_read(&regs->idr0) & 0xffff;
+       hal2_write(H2_READ_ADDR(addr) | 0x1, &regs->iar);
+       H2_INDIRECT_WAIT(regs);
+       ret |= (hal2_read(&regs->idr0) & 0xffff) << 16;
+       return ret;
+}
+
+static void hal2_i_write16(struct snd_hal2 *hal2, u16 addr, u16 val)
+{
+       struct hal2_ctl_regs *regs = hal2->ctl_regs;
+
+       hal2_write(val, &regs->idr0);
+       hal2_write(0, &regs->idr1);
+       hal2_write(0, &regs->idr2);
+       hal2_write(0, &regs->idr3);
+       hal2_write(H2_WRITE_ADDR(addr), &regs->iar);
+       H2_INDIRECT_WAIT(regs);
+}
+
+static void hal2_i_write32(struct snd_hal2 *hal2, u16 addr, u32 val)
+{
+       struct hal2_ctl_regs *regs = hal2->ctl_regs;
+
+       hal2_write(val & 0xffff, &regs->idr0);
+       hal2_write(val >> 16, &regs->idr1);
+       hal2_write(0, &regs->idr2);
+       hal2_write(0, &regs->idr3);
+       hal2_write(H2_WRITE_ADDR(addr), &regs->iar);
+       H2_INDIRECT_WAIT(regs);
+}
+
+static void hal2_i_setbit16(struct snd_hal2 *hal2, u16 addr, u16 bit)
+{
+       struct hal2_ctl_regs *regs = hal2->ctl_regs;
+
+       hal2_write(H2_READ_ADDR(addr), &regs->iar);
+       H2_INDIRECT_WAIT(regs);
+       hal2_write((hal2_read(&regs->idr0) & 0xffff) | bit, &regs->idr0);
+       hal2_write(0, &regs->idr1);
+       hal2_write(0, &regs->idr2);
+       hal2_write(0, &regs->idr3);
+       hal2_write(H2_WRITE_ADDR(addr), &regs->iar);
+       H2_INDIRECT_WAIT(regs);
+}
+
+static void hal2_i_clearbit16(struct snd_hal2 *hal2, u16 addr, u16 bit)
+{
+       struct hal2_ctl_regs *regs = hal2->ctl_regs;
+
+       hal2_write(H2_READ_ADDR(addr), &regs->iar);
+       H2_INDIRECT_WAIT(regs);
+       hal2_write((hal2_read(&regs->idr0) & 0xffff) & ~bit, &regs->idr0);
+       hal2_write(0, &regs->idr1);
+       hal2_write(0, &regs->idr2);
+       hal2_write(0, &regs->idr3);
+       hal2_write(H2_WRITE_ADDR(addr), &regs->iar);
+       H2_INDIRECT_WAIT(regs);
+}
+
+static int hal2_gain_info(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       switch ((int)kcontrol->private_value) {
+       case H2_MIX_OUTPUT_ATT:
+               uinfo->value.integer.max = 31;
+               break;
+       case H2_MIX_INPUT_GAIN:
+               uinfo->value.integer.max = 15;
+               break;
+       }
+       return 0;
+}
+
+static int hal2_gain_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_hal2 *hal2 = snd_kcontrol_chip(kcontrol);
+       u32 tmp;
+       int l, r;
+
+       switch ((int)kcontrol->private_value) {
+       case H2_MIX_OUTPUT_ATT:
+               tmp = hal2_i_read32(hal2, H2I_DAC_C2);
+               if (tmp & H2I_C2_MUTE) {
+                       l = 0;
+                       r = 0;
+               } else {
+                       l = 31 - ((tmp >> H2I_C2_L_ATT_SHIFT) & 31);
+                       r = 31 - ((tmp >> H2I_C2_R_ATT_SHIFT) & 31);
+               }
+               break;
+       case H2_MIX_INPUT_GAIN:
+               tmp = hal2_i_read32(hal2, H2I_ADC_C2);
+               l = (tmp >> H2I_C2_L_GAIN_SHIFT) & 15;
+               r = (tmp >> H2I_C2_R_GAIN_SHIFT) & 15;
+               break;
+       }
+       ucontrol->value.integer.value[0] = l;
+       ucontrol->value.integer.value[1] = r;
+
+       return 0;
+}
+
+static int hal2_gain_put(struct snd_kcontrol *kcontrol,
+                        struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_hal2 *hal2 = snd_kcontrol_chip(kcontrol);
+       u32 old, new;
+       int l, r;
+
+       l = ucontrol->value.integer.value[0];
+       r = ucontrol->value.integer.value[1];
+
+       switch ((int)kcontrol->private_value) {
+       case H2_MIX_OUTPUT_ATT:
+               old = hal2_i_read32(hal2, H2I_DAC_C2);
+               new = old & ~(H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE);
+               if (l | r) {
+                       l = 31 - l;
+                       r = 31 - r;
+                       new |= (l << H2I_C2_L_ATT_SHIFT);
+                       new |= (r << H2I_C2_R_ATT_SHIFT);
+               } else
+                       new |= H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE;
+               hal2_i_write32(hal2, H2I_DAC_C2, new);
+               break;
+       case H2_MIX_INPUT_GAIN:
+               old = hal2_i_read32(hal2, H2I_ADC_C2);
+               new = old & ~(H2I_C2_L_GAIN_M | H2I_C2_R_GAIN_M);
+               new |= (l << H2I_C2_L_GAIN_SHIFT);
+               new |= (r << H2I_C2_R_GAIN_SHIFT);
+               hal2_i_write32(hal2, H2I_ADC_C2, new);
+               break;
+       }
+       return old != new;
+}
+
+static struct snd_kcontrol_new hal2_ctrl_headphone __devinitdata = {
+       .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name           = "Headphone Playback Volume",
+       .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .private_value  = H2_MIX_OUTPUT_ATT,
+       .info           = hal2_gain_info,
+       .get            = hal2_gain_get,
+       .put            = hal2_gain_put,
+};
+
+static struct snd_kcontrol_new hal2_ctrl_mic __devinitdata = {
+       .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name           = "Mic Capture Volume",
+       .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .private_value  = H2_MIX_INPUT_GAIN,
+       .info           = hal2_gain_info,
+       .get            = hal2_gain_get,
+       .put            = hal2_gain_put,
+};
+
+static int __devinit hal2_mixer_create(struct snd_hal2 *hal2)
+{
+       int err;
+
+       /* mute DAC */
+       hal2_i_write32(hal2, H2I_DAC_C2,
+                      H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE);
+       /* mute ADC */
+       hal2_i_write32(hal2, H2I_ADC_C2, 0);
+
+       err = snd_ctl_add(hal2->card,
+                         snd_ctl_new1(&hal2_ctrl_headphone, hal2));
+       if (err < 0)
+               return err;
+
+       err = snd_ctl_add(hal2->card,
+                         snd_ctl_new1(&hal2_ctrl_mic, hal2));
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static irqreturn_t hal2_interrupt(int irq, void *dev_id)
+{
+       struct snd_hal2 *hal2 = dev_id;
+       irqreturn_t ret = IRQ_NONE;
+
+       /* decide what caused this interrupt */
+       if (hal2->dac.pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_INT) {
+               snd_pcm_period_elapsed(hal2->dac.substream);
+               ret = IRQ_HANDLED;
+       }
+       if (hal2->adc.pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_INT) {
+               snd_pcm_period_elapsed(hal2->adc.substream);
+               ret = IRQ_HANDLED;
+       }
+       return ret;
+}
+
+static int hal2_compute_rate(struct hal2_codec *codec, unsigned int rate)
+{
+       unsigned short mod;
+
+       if (44100 % rate < 48000 % rate) {
+               mod = 4 * 44100 / rate;
+               codec->master = 44100;
+       } else {
+               mod = 4 * 48000 / rate;
+               codec->master = 48000;
+       }
+
+       codec->inc = 4;
+       codec->mod = mod;
+       rate = 4 * codec->master / mod;
+
+       return rate;
+}
+
+static void hal2_set_dac_rate(struct snd_hal2 *hal2)
+{
+       unsigned int master = hal2->dac.master;
+       int inc = hal2->dac.inc;
+       int mod = hal2->dac.mod;
+
+       hal2_i_write16(hal2, H2I_BRES1_C1, (master == 44100) ? 1 : 0);
+       hal2_i_write32(hal2, H2I_BRES1_C2,
+                      ((0xffff & (inc - mod - 1)) << 16) | inc);
+}
+
+static void hal2_set_adc_rate(struct snd_hal2 *hal2)
+{
+       unsigned int master = hal2->adc.master;
+       int inc = hal2->adc.inc;
+       int mod = hal2->adc.mod;
+
+       hal2_i_write16(hal2, H2I_BRES2_C1, (master == 44100) ? 1 : 0);
+       hal2_i_write32(hal2, H2I_BRES2_C2,
+                      ((0xffff & (inc - mod - 1)) << 16) | inc);
+}
+
+static void hal2_setup_dac(struct snd_hal2 *hal2)
+{
+       unsigned int fifobeg, fifoend, highwater, sample_size;
+       struct hal2_pbus *pbus = &hal2->dac.pbus;
+
+       /* Now we set up some PBUS information. The PBUS needs information about
+        * what portion of the fifo it will use. If it's receiving or
+        * transmitting, and finally whether the stream is little endian or big
+        * endian. The information is written later, on the start call.
+        */
+       sample_size = 2 * hal2->dac.voices;
+       /* Fifo should be set to hold exactly four samples. Highwater mark
+        * should be set to two samples. */
+       highwater = (sample_size * 2) >> 1;     /* halfwords */
+       fifobeg = 0;                            /* playback is first */
+       fifoend = (sample_size * 4) >> 3;       /* doublewords */
+       pbus->ctrl = HPC3_PDMACTRL_RT | HPC3_PDMACTRL_LD |
+                    (highwater << 8) | (fifobeg << 16) | (fifoend << 24);
+       /* We disable everything before we do anything at all */
+       pbus->pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
+       hal2_i_clearbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX);
+       /* Setup the HAL2 for playback */
+       hal2_set_dac_rate(hal2);
+       /* Set endianess */
+       hal2_i_clearbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECTX);
+       /* Set DMA bus */
+       hal2_i_setbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr));
+       /* We are using 1st Bresenham clock generator for playback */
+       hal2_i_write16(hal2, H2I_DAC_C1, (pbus->pbusnr << H2I_C1_DMA_SHIFT)
+                       | (1 << H2I_C1_CLKID_SHIFT)
+                       | (hal2->dac.voices << H2I_C1_DATAT_SHIFT));
+}
+
+static void hal2_setup_adc(struct snd_hal2 *hal2)
+{
+       unsigned int fifobeg, fifoend, highwater, sample_size;
+       struct hal2_pbus *pbus = &hal2->adc.pbus;
+
+       sample_size = 2 * hal2->adc.voices;
+       highwater = (sample_size * 2) >> 1;             /* halfwords */
+       fifobeg = (4 * 4) >> 3;                         /* record is second */
+       fifoend = (4 * 4 + sample_size * 4) >> 3;       /* doublewords */
+       pbus->ctrl = HPC3_PDMACTRL_RT | HPC3_PDMACTRL_RCV | HPC3_PDMACTRL_LD |
+                    (highwater << 8) | (fifobeg << 16) | (fifoend << 24);
+       pbus->pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
+       hal2_i_clearbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR);
+       /* Setup the HAL2 for record */
+       hal2_set_adc_rate(hal2);
+       /* Set endianess */
+       hal2_i_clearbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECR);
+       /* Set DMA bus */
+       hal2_i_setbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr));
+       /* We are using 2nd Bresenham clock generator for record */
+       hal2_i_write16(hal2, H2I_ADC_C1, (pbus->pbusnr << H2I_C1_DMA_SHIFT)
+                       | (2 << H2I_C1_CLKID_SHIFT)
+                       | (hal2->adc.voices << H2I_C1_DATAT_SHIFT));
+}
+
+static void hal2_start_dac(struct snd_hal2 *hal2)
+{
+       struct hal2_pbus *pbus = &hal2->dac.pbus;
+
+       pbus->pbus->pbdma_dptr = hal2->dac.desc_dma;
+       pbus->pbus->pbdma_ctrl = pbus->ctrl | HPC3_PDMACTRL_ACT;
+       /* enable DAC */
+       hal2_i_setbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX);
+}
+
+static void hal2_start_adc(struct snd_hal2 *hal2)
+{
+       struct hal2_pbus *pbus = &hal2->adc.pbus;
+
+       pbus->pbus->pbdma_dptr = hal2->adc.desc_dma;
+       pbus->pbus->pbdma_ctrl = pbus->ctrl | HPC3_PDMACTRL_ACT;
+       /* enable ADC */
+       hal2_i_setbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR);
+}
+
+static inline void hal2_stop_dac(struct snd_hal2 *hal2)
+{
+       hal2->dac.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
+       /* The HAL2 itself may remain enabled safely */
+}
+
+static inline void hal2_stop_adc(struct snd_hal2 *hal2)
+{
+       hal2->adc.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD;
+}
+
+static int hal2_alloc_dmabuf(struct hal2_codec *codec)
+{
+       struct hal2_desc *desc;
+       dma_addr_t desc_dma, buffer_dma;
+       int count = H2_BUF_SIZE / H2_BLOCK_SIZE;
+       int i;
+
+       codec->buffer = dma_alloc_noncoherent(NULL, H2_BUF_SIZE,
+                                             &buffer_dma, GFP_KERNEL);
+       if (!codec->buffer)
+               return -ENOMEM;
+       desc = dma_alloc_noncoherent(NULL, count * sizeof(struct hal2_desc),
+                                    &desc_dma, GFP_KERNEL);
+       if (!desc) {
+               dma_free_noncoherent(NULL, H2_BUF_SIZE,
+                                    codec->buffer, buffer_dma);
+               return -ENOMEM;
+       }
+       codec->buffer_dma = buffer_dma;
+       codec->desc_dma = desc_dma;
+       codec->desc = desc;
+       for (i = 0; i < count; i++) {
+               desc->desc.pbuf = buffer_dma + i * H2_BLOCK_SIZE;
+               desc->desc.cntinfo = HPCDMA_XIE | H2_BLOCK_SIZE;
+               desc->desc.pnext = (i == count - 1) ?
+                     desc_dma : desc_dma + (i + 1) * sizeof(struct hal2_desc);
+               desc++;
+       }
+       dma_cache_sync(NULL, codec->desc, count * sizeof(struct hal2_desc),
+                      DMA_TO_DEVICE);
+       codec->desc_count = count;
+       return 0;
+}
+
+static void hal2_free_dmabuf(struct hal2_codec *codec)
+{
+       dma_free_noncoherent(NULL, codec->desc_count * sizeof(struct hal2_desc),
+                            codec->desc, codec->desc_dma);
+       dma_free_noncoherent(NULL, H2_BUF_SIZE, codec->buffer,
+                            codec->buffer_dma);
+}
+
+static struct snd_pcm_hardware hal2_pcm_hw = {
+       .info = (SNDRV_PCM_INFO_MMAP |
+                SNDRV_PCM_INFO_MMAP_VALID |
+                SNDRV_PCM_INFO_INTERLEAVED |
+                SNDRV_PCM_INFO_BLOCK_TRANSFER),
+       .formats =          SNDRV_PCM_FMTBIT_S16_BE,
+       .rates =            SNDRV_PCM_RATE_8000_48000,
+       .rate_min =         8000,
+       .rate_max =         48000,
+       .channels_min =     2,
+       .channels_max =     2,
+       .buffer_bytes_max = 65536,
+       .period_bytes_min = 1024,
+       .period_bytes_max = 65536,
+       .periods_min =      2,
+       .periods_max =      1024,
+};
+
+static int hal2_pcm_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *params)
+{
+       int err;
+
+       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int hal2_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       return snd_pcm_lib_free_pages(substream);
+}
+
+static int hal2_playback_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+       int err;
+
+       runtime->hw = hal2_pcm_hw;
+
+       err = hal2_alloc_dmabuf(&hal2->dac);
+       if (err)
+               return err;
+       return 0;
+}
+
+static int hal2_playback_close(struct snd_pcm_substream *substream)
+{
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+
+       hal2_free_dmabuf(&hal2->dac);
+       return 0;
+}
+
+static int hal2_playback_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct hal2_codec *dac = &hal2->dac;
+
+       dac->voices = runtime->channels;
+       dac->sample_rate = hal2_compute_rate(dac, runtime->rate);
+       memset(&dac->pcm_indirect, 0, sizeof(dac->pcm_indirect));
+       dac->pcm_indirect.hw_buffer_size = H2_BUF_SIZE;
+       dac->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+       dac->substream = substream;
+       hal2_setup_dac(hal2);
+       return 0;
+}
+
+static int hal2_playback_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               hal2->dac.pcm_indirect.hw_io = hal2->dac.buffer_dma;
+               hal2->dac.pcm_indirect.hw_data = 0;
+               substream->ops->ack(substream);
+               hal2_start_dac(hal2);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               hal2_stop_dac(hal2);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static snd_pcm_uframes_t
+hal2_playback_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+       struct hal2_codec *dac = &hal2->dac;
+
+       return snd_pcm_indirect_playback_pointer(substream, &dac->pcm_indirect,
+                                                dac->pbus.pbus->pbdma_bptr);
+}
+
+static void hal2_playback_transfer(struct snd_pcm_substream *substream,
+                                  struct snd_pcm_indirect *rec, size_t bytes)
+{
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+       unsigned char *buf = hal2->dac.buffer + rec->hw_data;
+
+       memcpy(buf, substream->runtime->dma_area + rec->sw_data, bytes);
+       dma_cache_sync(NULL, buf, bytes, DMA_TO_DEVICE);
+
+}
+
+static int hal2_playback_ack(struct snd_pcm_substream *substream)
+{
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+       struct hal2_codec *dac = &hal2->dac;
+
+       dac->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2;
+       snd_pcm_indirect_playback_transfer(substream,
+                                          &dac->pcm_indirect,
+                                          hal2_playback_transfer);
+       return 0;
+}
+
+static int hal2_capture_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+       struct hal2_codec *adc = &hal2->adc;
+       int err;
+
+       runtime->hw = hal2_pcm_hw;
+
+       err = hal2_alloc_dmabuf(adc);
+       if (err)
+               return err;
+       return 0;
+}
+
+static int hal2_capture_close(struct snd_pcm_substream *substream)
+{
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+
+       hal2_free_dmabuf(&hal2->adc);
+       return 0;
+}
+
+static int hal2_capture_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct hal2_codec *adc = &hal2->adc;
+
+       adc->voices = runtime->channels;
+       adc->sample_rate = hal2_compute_rate(adc, runtime->rate);
+       memset(&adc->pcm_indirect, 0, sizeof(adc->pcm_indirect));
+       adc->pcm_indirect.hw_buffer_size = H2_BUF_SIZE;
+       adc->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2;
+       adc->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+       adc->substream = substream;
+       hal2_setup_adc(hal2);
+       return 0;
+}
+
+static int hal2_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               hal2->adc.pcm_indirect.hw_io = hal2->adc.buffer_dma;
+               hal2->adc.pcm_indirect.hw_data = 0;
+               printk(KERN_DEBUG "buffer_dma %x\n", hal2->adc.buffer_dma);
+               hal2_start_adc(hal2);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               hal2_stop_adc(hal2);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static snd_pcm_uframes_t
+hal2_capture_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+       struct hal2_codec *adc = &hal2->adc;
+
+       return snd_pcm_indirect_capture_pointer(substream, &adc->pcm_indirect,
+                                               adc->pbus.pbus->pbdma_bptr);
+}
+
+static void hal2_capture_transfer(struct snd_pcm_substream *substream,
+                                 struct snd_pcm_indirect *rec, size_t bytes)
+{
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+       unsigned char *buf = hal2->adc.buffer + rec->hw_data;
+
+       dma_cache_sync(NULL, buf, bytes, DMA_FROM_DEVICE);
+       memcpy(substream->runtime->dma_area + rec->sw_data, buf, bytes);
+}
+
+static int hal2_capture_ack(struct snd_pcm_substream *substream)
+{
+       struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
+       struct hal2_codec *adc = &hal2->adc;
+
+       snd_pcm_indirect_capture_transfer(substream,
+                                         &adc->pcm_indirect,
+                                         hal2_capture_transfer);
+       return 0;
+}
+
+static struct snd_pcm_ops hal2_playback_ops = {
+       .open =        hal2_playback_open,
+       .close =       hal2_playback_close,
+       .ioctl =       snd_pcm_lib_ioctl,
+       .hw_params =   hal2_pcm_hw_params,
+       .hw_free =     hal2_pcm_hw_free,
+       .prepare =     hal2_playback_prepare,
+       .trigger =     hal2_playback_trigger,
+       .pointer =     hal2_playback_pointer,
+       .ack =         hal2_playback_ack,
+};
+
+static struct snd_pcm_ops hal2_capture_ops = {
+       .open =        hal2_capture_open,
+       .close =       hal2_capture_close,
+       .ioctl =       snd_pcm_lib_ioctl,
+       .hw_params =   hal2_pcm_hw_params,
+       .hw_free =     hal2_pcm_hw_free,
+       .prepare =     hal2_capture_prepare,
+       .trigger =     hal2_capture_trigger,
+       .pointer =     hal2_capture_pointer,
+       .ack =         hal2_capture_ack,
+};
+
+static int __devinit hal2_pcm_create(struct snd_hal2 *hal2)
+{
+       struct snd_pcm *pcm;
+       int err;
+
+       /* create first pcm device with one outputs and one input */
+       err = snd_pcm_new(hal2->card, "SGI HAL2 Audio", 0, 1, 1, &pcm);
+       if (err < 0)
+               return err;
+
+       pcm->private_data = hal2;
+       strcpy(pcm->name, "SGI HAL2");
+
+       /* set operators */
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                       &hal2_playback_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                       &hal2_capture_ops);
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+                                          snd_dma_continuous_data(GFP_KERNEL),
+                                          0, 1024 * 1024);
+
+       return 0;
+}
+
+static int hal2_dev_free(struct snd_device *device)
+{
+       struct snd_hal2 *hal2 = device->device_data;
+
+       free_irq(SGI_HPCDMA_IRQ, hal2);
+       kfree(hal2);
+       return 0;
+}
+
+static struct snd_device_ops hal2_ops = {
+       .dev_free = hal2_dev_free,
+};
+
+static void hal2_init_codec(struct hal2_codec *codec, struct hpc3_regs *hpc3,
+                           int index)
+{
+       codec->pbus.pbusnr = index;
+       codec->pbus.pbus = &hpc3->pbdma[index];
+}
+
+static int hal2_detect(struct snd_hal2 *hal2)
+{
+       unsigned short board, major, minor;
+       unsigned short rev;
+
+       /* reset HAL2 */
+       hal2_write(0, &hal2->ctl_regs->isr);
+
+       /* release reset */
+       hal2_write(H2_ISR_GLOBAL_RESET_N | H2_ISR_CODEC_RESET_N,
+                  &hal2->ctl_regs->isr);
+
+
+       hal2_i_write16(hal2, H2I_RELAY_C, H2I_RELAY_C_STATE);
+       rev = hal2_read(&hal2->ctl_regs->rev);
+       if (rev & H2_REV_AUDIO_PRESENT)
+               return -ENODEV;
+
+       board = (rev & H2_REV_BOARD_M) >> 12;
+       major = (rev & H2_REV_MAJOR_CHIP_M) >> 4;
+       minor = (rev & H2_REV_MINOR_CHIP_M);
+
+       printk(KERN_INFO "SGI HAL2 revision %i.%i.%i\n",
+              board, major, minor);
+
+       return 0;
+}
+
+static int hal2_create(struct snd_card *card, struct snd_hal2 **rchip)
+{
+       struct snd_hal2 *hal2;
+       struct hpc3_regs *hpc3 = hpc3c0;
+       int err;
+
+       hal2 = kzalloc(sizeof(struct snd_hal2), GFP_KERNEL);
+       if (!hal2)
+               return -ENOMEM;
+
+       hal2->card = card;
+
+       if (request_irq(SGI_HPCDMA_IRQ, hal2_interrupt, IRQF_SHARED,
+                       "SGI HAL2", hal2)) {
+               printk(KERN_ERR "HAL2: Can't get irq %d\n", SGI_HPCDMA_IRQ);
+               kfree(hal2);
+               return -EAGAIN;
+       }
+
+       hal2->ctl_regs = (struct hal2_ctl_regs *)hpc3->pbus_extregs[0];
+       hal2->aes_regs = (struct hal2_aes_regs *)hpc3->pbus_extregs[1];
+       hal2->vol_regs = (struct hal2_vol_regs *)hpc3->pbus_extregs[2];
+       hal2->syn_regs = (struct hal2_syn_regs *)hpc3->pbus_extregs[3];
+
+       if (hal2_detect(hal2) < 0) {
+               kfree(hal2);
+               return -ENODEV;
+       }
+
+       hal2_init_codec(&hal2->dac, hpc3, 0);
+       hal2_init_codec(&hal2->adc, hpc3, 1);
+
+       /*
+        * All DMA channel interfaces in HAL2 are designed to operate with
+        * PBUS programmed for 2 cycles in D3, 2 cycles in D4 and 2 cycles
+        * in D5. HAL2 is a 16-bit device which can accept both big and little
+        * endian format. It assumes that even address bytes are on high
+        * portion of PBUS (15:8) and assumes that HPC3 is programmed to
+        * accept a live (unsynchronized) version of P_DREQ_N from HAL2.
+        */
+#define HAL2_PBUS_DMACFG ((0 << HPC3_DMACFG_D3R_SHIFT) | \
+                         (2 << HPC3_DMACFG_D4R_SHIFT) | \
+                         (2 << HPC3_DMACFG_D5R_SHIFT) | \
+                         (0 << HPC3_DMACFG_D3W_SHIFT) | \
+                         (2 << HPC3_DMACFG_D4W_SHIFT) | \
+                         (2 << HPC3_DMACFG_D5W_SHIFT) | \
+                               HPC3_DMACFG_DS16 | \
+                               HPC3_DMACFG_EVENHI | \
+                               HPC3_DMACFG_RTIME | \
+                         (8 << HPC3_DMACFG_BURST_SHIFT) | \
+                               HPC3_DMACFG_DRQLIVE)
+       /*
+        * Ignore what's mentioned in the specification and write value which
+        * works in The Real World (TM)
+        */
+       hpc3->pbus_dmacfg[hal2->dac.pbus.pbusnr][0] = 0x8208844;
+       hpc3->pbus_dmacfg[hal2->adc.pbus.pbusnr][0] = 0x8208844;
+
+       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, hal2, &hal2_ops);
+       if (err < 0) {
+               free_irq(SGI_HPCDMA_IRQ, hal2);
+               kfree(hal2);
+               return err;
+       }
+       *rchip = hal2;
+       return 0;
+}
+
+static int __devinit hal2_probe(struct platform_device *pdev)
+{
+       struct snd_card *card;
+       struct snd_hal2 *chip;
+       int err;
+
+       card = snd_card_new(index, id, THIS_MODULE, 0);
+       if (card == NULL)
+               return -ENOMEM;
+
+       err = hal2_create(card, &chip);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+       snd_card_set_dev(card, &pdev->dev);
+
+       err = hal2_pcm_create(chip);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+       err = hal2_mixer_create(chip);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+       strcpy(card->driver, "SGI HAL2 Audio");
+       strcpy(card->shortname, "SGI HAL2 Audio");
+       sprintf(card->longname, "%s irq %i",
+               card->shortname,
+               SGI_HPCDMA_IRQ);
+
+       err = snd_card_register(card);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+       platform_set_drvdata(pdev, card);
+       return 0;
+}
+
+static int __exit hal2_remove(struct platform_device *pdev)
+{
+       struct snd_card *card = platform_get_drvdata(pdev);
+
+       snd_card_free(card);
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+static struct platform_driver hal2_driver = {
+       .probe  = hal2_probe,
+       .remove = __devexit_p(hal2_remove),
+       .driver = {
+               .name   = "sgihal2",
+               .owner  = THIS_MODULE,
+       }
+};
+
+static int __init alsa_card_hal2_init(void)
+{
+       return platform_driver_register(&hal2_driver);
+}
+
+static void __exit alsa_card_hal2_exit(void)
+{
+       platform_driver_unregister(&hal2_driver);
+}
+
+module_init(alsa_card_hal2_init);
+module_exit(alsa_card_hal2_exit);
diff --git a/sound/mips/hal2.h b/sound/mips/hal2.h
new file mode 100644 (file)
index 0000000..f19828b
--- /dev/null
@@ -0,0 +1,245 @@
+#ifndef __HAL2_H
+#define __HAL2_H
+
+/*
+ *  Driver for HAL2 sound processors
+ *  Copyright (c) 1999 Ulf Carlsson <ulfc@bun.falkenberg.se>
+ *  Copyright (c) 2001, 2002, 2003 Ladislav Michl <ladis@linux-mips.org>
+ *
+ *  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.
+ *
+ *  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/types.h>
+
+/* Indirect status register */
+
+#define H2_ISR_TSTATUS         0x01    /* RO: transaction status 1=busy */
+#define H2_ISR_USTATUS         0x02    /* RO: utime status bit 1=armed */
+#define H2_ISR_QUAD_MODE       0x04    /* codec mode 0=indigo 1=quad */
+#define H2_ISR_GLOBAL_RESET_N  0x08    /* chip global reset 0=reset */
+#define H2_ISR_CODEC_RESET_N   0x10    /* codec/synth reset 0=reset  */
+
+/* Revision register */
+
+#define H2_REV_AUDIO_PRESENT   0x8000  /* RO: audio present 0=present */
+#define H2_REV_BOARD_M         0x7000  /* RO: bits 14:12, board revision */
+#define H2_REV_MAJOR_CHIP_M    0x00F0  /* RO: bits 7:4, major chip revision */
+#define H2_REV_MINOR_CHIP_M    0x000F  /* RO: bits 3:0, minor chip revision */
+
+/* Indirect address register */
+
+/*
+ * Address of indirect internal register to be accessed. A write to this
+ * register initiates read or write access to the indirect registers in the
+ * HAL2. Note that there af four indirect data registers for write access to
+ * registers larger than 16 byte.
+ */
+
+#define H2_IAR_TYPE_M          0xF000  /* bits 15:12, type of functional */
+                                       /* block the register resides in */
+                                       /* 1=DMA Port */
+                                       /* 9=Global DMA Control */
+                                       /* 2=Bresenham */
+                                       /* 3=Unix Timer */
+#define H2_IAR_NUM_M           0x0F00  /* bits 11:8 instance of the */
+                                       /* blockin which the indirect */
+                                       /* register resides */
+                                       /* If IAR_TYPE_M=DMA Port: */
+                                       /* 1=Synth In */
+                                       /* 2=AES In */
+                                       /* 3=AES Out */
+                                       /* 4=DAC Out */
+                                       /* 5=ADC Out */
+                                       /* 6=Synth Control */
+                                       /* If IAR_TYPE_M=Global DMA Control: */
+                                       /* 1=Control */
+                                       /* If IAR_TYPE_M=Bresenham: */
+                                       /* 1=Bresenham Clock Gen 1 */
+                                       /* 2=Bresenham Clock Gen 2 */
+                                       /* 3=Bresenham Clock Gen 3 */
+                                       /* If IAR_TYPE_M=Unix Timer: */
+                                       /* 1=Unix Timer */
+#define H2_IAR_ACCESS_SELECT   0x0080  /* 1=read 0=write */
+#define H2_IAR_PARAM           0x000C  /* Parameter Select */
+#define H2_IAR_RB_INDEX_M      0x0003  /* Read Back Index */
+                                       /* 00:word0 */
+                                       /* 01:word1 */
+                                       /* 10:word2 */
+                                       /* 11:word3 */
+/*
+ * HAL2 internal addressing
+ *
+ * The HAL2 has "indirect registers" (idr) which are accessed by writing to the
+ * Indirect Data registers. Write the address to the Indirect Address register
+ * to transfer the data.
+ *
+ * We define the H2IR_* to the read address and H2IW_* to the write address and
+ * H2I_* to be fields in whatever register is referred to.
+ *
+ * When we write to indirect registers which are larger than one word (16 bit)
+ * we have to fill more than one indirect register before writing. When we read
+ * back however we have to read several times, each time with different Read
+ * Back Indexes (there are defs for doing this easily).
+ */
+
+/*
+ * Relay Control
+ */
+#define H2I_RELAY_C            0x9100
+#define H2I_RELAY_C_STATE      0x01            /* state of RELAY pin signal */
+
+/* DMA port enable */
+
+#define H2I_DMA_PORT_EN                0x9104
+#define H2I_DMA_PORT_EN_SY_IN  0x01            /* Synth_in DMA port */
+#define H2I_DMA_PORT_EN_AESRX  0x02            /* AES receiver DMA port */
+#define H2I_DMA_PORT_EN_AESTX  0x04            /* AES transmitter DMA port */
+#define H2I_DMA_PORT_EN_CODECTX        0x08            /* CODEC transmit DMA port */
+#define H2I_DMA_PORT_EN_CODECR 0x10            /* CODEC receive DMA port */
+
+#define H2I_DMA_END            0x9108          /* global dma endian select */
+#define H2I_DMA_END_SY_IN      0x01            /* Synth_in DMA port */
+#define H2I_DMA_END_AESRX      0x02            /* AES receiver DMA port */
+#define H2I_DMA_END_AESTX      0x04            /* AES transmitter DMA port */
+#define H2I_DMA_END_CODECTX    0x08            /* CODEC transmit DMA port */
+#define H2I_DMA_END_CODECR     0x10            /* CODEC receive DMA port */
+                                               /* 0=b_end 1=l_end */
+
+#define H2I_DMA_DRV            0x910C          /* global PBUS DMA enable */
+
+#define H2I_SYNTH_C            0x1104          /* Synth DMA control */
+
+#define H2I_AESRX_C            0x1204          /* AES RX dma control */
+
+#define H2I_C_TS_EN            0x20            /* Timestamp enable */
+#define H2I_C_TS_FRMT          0x40            /* Timestamp format */
+#define H2I_C_NAUDIO           0x80            /* Sign extend */
+
+/* AESRX CTL, 16 bit */
+
+#define H2I_AESTX_C            0x1304          /* AES TX DMA control */
+#define H2I_AESTX_C_CLKID_SHIFT        3               /* Bresenham Clock Gen 1-3 */
+#define H2I_AESTX_C_CLKID_M    0x18
+#define H2I_AESTX_C_DATAT_SHIFT        8               /* 1=mono 2=stereo (3=quad) */
+#define H2I_AESTX_C_DATAT_M    0x300
+
+/* CODEC registers */
+
+#define H2I_DAC_C1             0x1404          /* DAC DMA control, 16 bit */
+#define H2I_DAC_C2             0x1408          /* DAC DMA control, 32 bit */
+#define H2I_ADC_C1             0x1504          /* ADC DMA control, 16 bit */
+#define H2I_ADC_C2             0x1508          /* ADC DMA control, 32 bit */
+
+/* Bits in CTL1 register */
+
+#define H2I_C1_DMA_SHIFT       0               /* DMA channel */
+#define H2I_C1_DMA_M           0x7
+#define H2I_C1_CLKID_SHIFT     3               /* Bresenham Clock Gen 1-3 */
+#define H2I_C1_CLKID_M         0x18
+#define H2I_C1_DATAT_SHIFT     8               /* 1=mono 2=stereo (3=quad) */
+#define H2I_C1_DATAT_M         0x300
+
+/* Bits in CTL2 register */
+
+#define H2I_C2_R_GAIN_SHIFT    0               /* right a/d input gain */
+#define H2I_C2_R_GAIN_M                0xf
+#define H2I_C2_L_GAIN_SHIFT    4               /* left a/d input gain */
+#define H2I_C2_L_GAIN_M                0xf0
+#define H2I_C2_R_SEL           0x100           /* right input select */
+#define H2I_C2_L_SEL           0x200           /* left input select */
+#define H2I_C2_MUTE            0x400           /* mute */
+#define H2I_C2_DO1             0x00010000      /* digital output port bit 0 */
+#define H2I_C2_DO2             0x00020000      /* digital output port bit 1 */
+#define H2I_C2_R_ATT_SHIFT     18              /* right d/a output - */
+#define H2I_C2_R_ATT_M         0x007c0000      /* attenuation */
+#define H2I_C2_L_ATT_SHIFT     23              /* left d/a output - */
+#define H2I_C2_L_ATT_M         0x0f800000      /* attenuation */
+
+#define H2I_SYNTH_MAP_C                0x1104          /* synth dma handshake ctrl */
+
+/* Clock generator CTL 1, 16 bit */
+
+#define H2I_BRES1_C1           0x2104
+#define H2I_BRES2_C1           0x2204
+#define H2I_BRES3_C1           0x2304
+
+#define H2I_BRES_C1_SHIFT      0               /* 0=48.0 1=44.1 2=aes_rx */
+#define H2I_BRES_C1_M          0x03
+
+/* Clock generator CTL 2, 32 bit */
+
+#define H2I_BRES1_C2           0x2108
+#define H2I_BRES2_C2           0x2208
+#define H2I_BRES3_C2           0x2308
+
+#define H2I_BRES_C2_INC_SHIFT  0               /* increment value */
+#define H2I_BRES_C2_INC_M      0xffff
+#define H2I_BRES_C2_MOD_SHIFT  16              /* modcontrol value */
+#define H2I_BRES_C2_MOD_M      0xffff0000      /* modctrl=0xffff&(modinc-1) */
+
+/* Unix timer, 64 bit */
+
+#define H2I_UTIME              0x3104
+#define H2I_UTIME_0_LD         0xffff          /* microseconds, LSB's */
+#define H2I_UTIME_1_LD0                0x0f            /* microseconds, MSB's */
+#define H2I_UTIME_1_LD1                0xf0            /* tenths of microseconds */
+#define H2I_UTIME_2_LD         0xffff          /* seconds, LSB's */
+#define H2I_UTIME_3_LD         0xffff          /* seconds, MSB's */
+
+struct hal2_ctl_regs {
+       u32 _unused0[4];
+       u32 isr;                /* 0x10 Status Register */
+       u32 _unused1[3];
+       u32 rev;                /* 0x20 Revision Register */
+       u32 _unused2[3];
+       u32 iar;                /* 0x30 Indirect Address Register */
+       u32 _unused3[3];
+       u32 idr0;               /* 0x40 Indirect Data Register 0 */
+       u32 _unused4[3];
+       u32 idr1;               /* 0x50 Indirect Data Register 1 */
+       u32 _unused5[3];
+       u32 idr2;               /* 0x60 Indirect Data Register 2 */
+       u32 _unused6[3];
+       u32 idr3;               /* 0x70 Indirect Data Register 3 */
+};
+
+struct hal2_aes_regs {
+       u32 rx_stat[2]; /* Status registers */
+       u32 rx_cr[2];           /* Control registers */
+       u32 rx_ud[4];           /* User data window */
+       u32 rx_st[24];          /* Channel status data */
+
+       u32 tx_stat[1]; /* Status register */
+       u32 tx_cr[3];           /* Control registers */
+       u32 tx_ud[4];           /* User data window */
+       u32 tx_st[24];          /* Channel status data */
+};
+
+struct hal2_vol_regs {
+       u32 right;              /* Right volume */
+       u32 left;               /* Left volume */
+};
+
+struct hal2_syn_regs {
+       u32 _unused0[2];
+       u32 page;               /* DOC Page register */
+       u32 regsel;             /* DOC Register selection */
+       u32 dlow;               /* DOC Data low */
+       u32 dhigh;              /* DOC Data high */
+       u32 irq;                /* IRQ Status */
+       u32 dram;               /* DRAM Access */
+};
+
+#endif /* __HAL2_H */
diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c
new file mode 100644 (file)
index 0000000..4c63504
--- /dev/null
@@ -0,0 +1,1006 @@
+/*
+ *   Sound driver for Silicon Graphics O2 Workstations A/V board audio.
+ *
+ *   Copyright 2003 Vivien Chappelier <vivien.chappelier@linux-mips.org>
+ *   Copyright 2008 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+ *   Mxier part taken from mace_audio.c:
+ *   Copyright 2007 Thorben Jändling <tj.trevelyan@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 the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/gfp.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <asm/ip32/ip32_ints.h>
+#include <asm/ip32/mace.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#define SNDRV_GET_ID
+#include <sound/initval.h>
+#include <sound/ad1843.h>
+
+
+MODULE_AUTHOR("Vivien Chappelier <vivien.chappelier@linux-mips.org>");
+MODULE_DESCRIPTION("SGI O2 Audio");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Silicon Graphics, O2 Audio}}");
+
+static int index = SNDRV_DEFAULT_IDX1;  /* Index 0-MAX */
+static char *id = SNDRV_DEFAULT_STR1;   /* ID for this card */
+
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "Index value for SGI O2 soundcard.");
+module_param(id, charp, 0444);
+MODULE_PARM_DESC(id, "ID string for SGI O2 soundcard.");
+
+
+#define AUDIO_CONTROL_RESET              BIT(0) /* 1: reset audio interface */
+#define AUDIO_CONTROL_CODEC_PRESENT      BIT(1) /* 1: codec detected */
+
+#define CODEC_CONTROL_WORD_SHIFT        0
+#define CODEC_CONTROL_READ              BIT(16)
+#define CODEC_CONTROL_ADDRESS_SHIFT     17
+
+#define CHANNEL_CONTROL_RESET           BIT(10) /* 1: reset channel */
+#define CHANNEL_DMA_ENABLE              BIT(9)  /* 1: enable DMA transfer */
+#define CHANNEL_INT_THRESHOLD_DISABLED  (0 << 5) /* interrupt disabled */
+#define CHANNEL_INT_THRESHOLD_25        (1 << 5) /* int on buffer >25% full */
+#define CHANNEL_INT_THRESHOLD_50        (2 << 5) /* int on buffer >50% full */
+#define CHANNEL_INT_THRESHOLD_75        (3 << 5) /* int on buffer >75% full */
+#define CHANNEL_INT_THRESHOLD_EMPTY     (4 << 5) /* int on buffer empty */
+#define CHANNEL_INT_THRESHOLD_NOT_EMPTY (5 << 5) /* int on buffer !empty */
+#define CHANNEL_INT_THRESHOLD_FULL      (6 << 5) /* int on buffer empty */
+#define CHANNEL_INT_THRESHOLD_NOT_FULL  (7 << 5) /* int on buffer !empty */
+
+#define CHANNEL_RING_SHIFT              12
+#define CHANNEL_RING_SIZE               (1 << CHANNEL_RING_SHIFT)
+#define CHANNEL_RING_MASK               (CHANNEL_RING_SIZE - 1)
+
+#define CHANNEL_LEFT_SHIFT 40
+#define CHANNEL_RIGHT_SHIFT 8
+
+struct snd_sgio2audio_chan {
+       int idx;
+       struct snd_pcm_substream *substream;
+       int pos;
+       snd_pcm_uframes_t size;
+       spinlock_t lock;
+};
+
+/* definition of the chip-specific record */
+struct snd_sgio2audio {
+       struct snd_card *card;
+
+       /* codec */
+       struct snd_ad1843 ad1843;
+       spinlock_t ad1843_lock;
+
+       /* channels */
+       struct snd_sgio2audio_chan channel[3];
+
+       /* resources */
+       void *ring_base;
+       dma_addr_t ring_base_dma;
+};
+
+/* AD1843 access */
+
+/*
+ * read_ad1843_reg returns the current contents of a 16 bit AD1843 register.
+ *
+ * Returns unsigned register value on success, -errno on failure.
+ */
+static int read_ad1843_reg(void *priv, int reg)
+{
+       struct snd_sgio2audio *chip = priv;
+       int val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->ad1843_lock, flags);
+
+       writeq((reg << CODEC_CONTROL_ADDRESS_SHIFT) |
+              CODEC_CONTROL_READ, &mace->perif.audio.codec_control);
+       wmb();
+       val = readq(&mace->perif.audio.codec_control); /* flush bus */
+       udelay(200);
+
+       val = readq(&mace->perif.audio.codec_read);
+
+       spin_unlock_irqrestore(&chip->ad1843_lock, flags);
+       return val;
+}
+
+/*
+ * write_ad1843_reg writes the specified value to a 16 bit AD1843 register.
+ */
+static int write_ad1843_reg(void *priv, int reg, int word)
+{
+       struct snd_sgio2audio *chip = priv;
+       int val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->ad1843_lock, flags);
+
+       writeq((reg << CODEC_CONTROL_ADDRESS_SHIFT) |
+              (word << CODEC_CONTROL_WORD_SHIFT),
+              &mace->perif.audio.codec_control);
+       wmb();
+       val = readq(&mace->perif.audio.codec_control); /* flush bus */
+       udelay(200);
+
+       spin_unlock_irqrestore(&chip->ad1843_lock, flags);
+       return 0;
+}
+
+static int sgio2audio_gain_info(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_info *uinfo)
+{
+       struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol);
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = ad1843_get_gain_max(&chip->ad1843,
+                                            (int)kcontrol->private_value);
+       return 0;
+}
+
+static int sgio2audio_gain_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol);
+       int vol;
+
+       vol = ad1843_get_gain(&chip->ad1843, (int)kcontrol->private_value);
+
+       ucontrol->value.integer.value[0] = (vol >> 8) & 0xFF;
+       ucontrol->value.integer.value[1] = vol & 0xFF;
+
+       return 0;
+}
+
+static int sgio2audio_gain_put(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol);
+       int newvol, oldvol;
+
+       oldvol = ad1843_get_gain(&chip->ad1843, kcontrol->private_value);
+       newvol = (ucontrol->value.integer.value[0] << 8) |
+               ucontrol->value.integer.value[1];
+
+       newvol = ad1843_set_gain(&chip->ad1843, kcontrol->private_value,
+               newvol);
+
+       return newvol != oldvol;
+}
+
+static int sgio2audio_source_info(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_info *uinfo)
+{
+       static const char *texts[3] = {
+               "Cam Mic", "Mic", "Line"
+       };
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+       uinfo->count = 1;
+       uinfo->value.enumerated.items = 3;
+       if (uinfo->value.enumerated.item >= 3)
+               uinfo->value.enumerated.item = 1;
+       strcpy(uinfo->value.enumerated.name,
+              texts[uinfo->value.enumerated.item]);
+       return 0;
+}
+
+static int sgio2audio_source_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.enumerated.item[0] = ad1843_get_recsrc(&chip->ad1843);
+       return 0;
+}
+
+static int sgio2audio_source_put(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_sgio2audio *chip = snd_kcontrol_chip(kcontrol);
+       int newsrc, oldsrc;
+
+       oldsrc = ad1843_get_recsrc(&chip->ad1843);
+       newsrc = ad1843_set_recsrc(&chip->ad1843,
+                                  ucontrol->value.enumerated.item[0]);
+
+       return newsrc != oldsrc;
+}
+
+/* dac1/pcm0 mixer control */
+static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 __devinitdata = {
+       .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name           = "PCM Playback Volume",
+       .index          = 0,
+       .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .private_value  = AD1843_GAIN_PCM_0,
+       .info           = sgio2audio_gain_info,
+       .get            = sgio2audio_gain_get,
+       .put            = sgio2audio_gain_put,
+};
+
+/* dac2/pcm1 mixer control */
+static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 __devinitdata = {
+       .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name           = "PCM Playback Volume",
+       .index          = 1,
+       .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .private_value  = AD1843_GAIN_PCM_1,
+       .info           = sgio2audio_gain_info,
+       .get            = sgio2audio_gain_get,
+       .put            = sgio2audio_gain_put,
+};
+
+/* record level mixer control */
+static struct snd_kcontrol_new sgio2audio_ctrl_reclevel __devinitdata = {
+       .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name           = "Capture Volume",
+       .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .private_value  = AD1843_GAIN_RECLEV,
+       .info           = sgio2audio_gain_info,
+       .get            = sgio2audio_gain_get,
+       .put            = sgio2audio_gain_put,
+};
+
+/* record level source control */
+static struct snd_kcontrol_new sgio2audio_ctrl_recsource __devinitdata = {
+       .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name           = "Capture Source",
+       .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info           = sgio2audio_source_info,
+       .get            = sgio2audio_source_get,
+       .put            = sgio2audio_source_put,
+};
+
+/* line mixer control */
+static struct snd_kcontrol_new sgio2audio_ctrl_line __devinitdata = {
+       .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name           = "Line Playback Volume",
+       .index          = 0,
+       .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .private_value  = AD1843_GAIN_LINE,
+       .info           = sgio2audio_gain_info,
+       .get            = sgio2audio_gain_get,
+       .put            = sgio2audio_gain_put,
+};
+
+/* cd mixer control */
+static struct snd_kcontrol_new sgio2audio_ctrl_cd __devinitdata = {
+       .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name           = "Line Playback Volume",
+       .index          = 1,
+       .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .private_value  = AD1843_GAIN_LINE_2,
+       .info           = sgio2audio_gain_info,
+       .get            = sgio2audio_gain_get,
+       .put            = sgio2audio_gain_put,
+};
+
+/* mic mixer control */
+static struct snd_kcontrol_new sgio2audio_ctrl_mic __devinitdata = {
+       .iface          = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name           = "Mic Playback Volume",
+       .access         = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .private_value  = AD1843_GAIN_MIC,
+       .info           = sgio2audio_gain_info,
+       .get            = sgio2audio_gain_get,
+       .put            = sgio2audio_gain_put,
+};
+
+
+static int __devinit snd_sgio2audio_new_mixer(struct snd_sgio2audio *chip)
+{
+       int err;
+
+       err = snd_ctl_add(chip->card,
+                         snd_ctl_new1(&sgio2audio_ctrl_pcm0, chip));
+       if (err < 0)
+               return err;
+
+       err = snd_ctl_add(chip->card,
+                         snd_ctl_new1(&sgio2audio_ctrl_pcm1, chip));
+       if (err < 0)
+               return err;
+
+       err = snd_ctl_add(chip->card,
+                         snd_ctl_new1(&sgio2audio_ctrl_reclevel, chip));
+       if (err < 0)
+               return err;
+
+       err = snd_ctl_add(chip->card,
+                         snd_ctl_new1(&sgio2audio_ctrl_recsource, chip));
+       if (err < 0)
+               return err;
+       err = snd_ctl_add(chip->card,
+                         snd_ctl_new1(&sgio2audio_ctrl_line, chip));
+       if (err < 0)
+               return err;
+
+       err = snd_ctl_add(chip->card,
+                         snd_ctl_new1(&sgio2audio_ctrl_cd, chip));
+       if (err < 0)
+               return err;
+
+       err = snd_ctl_add(chip->card,
+                         snd_ctl_new1(&sgio2audio_ctrl_mic, chip));
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+/* low-level audio interface DMA */
+
+/* get data out of bounce buffer, count must be a multiple of 32 */
+/* returns 1 if a period has elapsed */
+static int snd_sgio2audio_dma_pull_frag(struct snd_sgio2audio *chip,
+                                       unsigned int ch, unsigned int count)
+{
+       int ret;
+       unsigned long src_base, src_pos, dst_mask;
+       unsigned char *dst_base;
+       int dst_pos;
+       u64 *src;
+       s16 *dst;
+       u64 x;
+       unsigned long flags;
+       struct snd_pcm_runtime *runtime = chip->channel[ch].substream->runtime;
+
+       spin_lock_irqsave(&chip->channel[ch].lock, flags);
+
+       src_base = (unsigned long) chip->ring_base | (ch << CHANNEL_RING_SHIFT);
+       src_pos = readq(&mace->perif.audio.chan[ch].read_ptr);
+       dst_base = runtime->dma_area;
+       dst_pos = chip->channel[ch].pos;
+       dst_mask = frames_to_bytes(runtime, runtime->buffer_size) - 1;
+
+       /* check if a period has elapsed */
+       chip->channel[ch].size += (count >> 3); /* in frames */
+       ret = chip->channel[ch].size >= runtime->period_size;
+       chip->channel[ch].size %= runtime->period_size;
+
+       while (count) {
+               src = (u64 *)(src_base + src_pos);
+               dst = (s16 *)(dst_base + dst_pos);
+
+               x = *src;
+               dst[0] = (x >> CHANNEL_LEFT_SHIFT) & 0xffff;
+               dst[1] = (x >> CHANNEL_RIGHT_SHIFT) & 0xffff;
+
+               src_pos = (src_pos + sizeof(u64)) & CHANNEL_RING_MASK;
+               dst_pos = (dst_pos + 2 * sizeof(s16)) & dst_mask;
+               count -= sizeof(u64);
+       }
+
+       writeq(src_pos, &mace->perif.audio.chan[ch].read_ptr); /* in bytes */
+       chip->channel[ch].pos = dst_pos;
+
+       spin_unlock_irqrestore(&chip->channel[ch].lock, flags);
+       return ret;
+}
+
+/* put some DMA data in bounce buffer, count must be a multiple of 32 */
+/* returns 1 if a period has elapsed */
+static int snd_sgio2audio_dma_push_frag(struct snd_sgio2audio *chip,
+                                       unsigned int ch, unsigned int count)
+{
+       int ret;
+       s64 l, r;
+       unsigned long dst_base, dst_pos, src_mask;
+       unsigned char *src_base;
+       int src_pos;
+       u64 *dst;
+       s16 *src;
+       unsigned long flags;
+       struct snd_pcm_runtime *runtime = chip->channel[ch].substream->runtime;
+
+       spin_lock_irqsave(&chip->channel[ch].lock, flags);
+
+       dst_base = (unsigned long)chip->ring_base | (ch << CHANNEL_RING_SHIFT);
+       dst_pos = readq(&mace->perif.audio.chan[ch].write_ptr);
+       src_base = runtime->dma_area;
+       src_pos = chip->channel[ch].pos;
+       src_mask = frames_to_bytes(runtime, runtime->buffer_size) - 1;
+
+       /* check if a period has elapsed */
+       chip->channel[ch].size += (count >> 3); /* in frames */
+       ret = chip->channel[ch].size >= runtime->period_size;
+       chip->channel[ch].size %= runtime->period_size;
+
+       while (count) {
+               src = (s16 *)(src_base + src_pos);
+               dst = (u64 *)(dst_base + dst_pos);
+
+               l = src[0]; /* sign extend */
+               r = src[1]; /* sign extend */
+
+               *dst = ((l & 0x00ffffff) << CHANNEL_LEFT_SHIFT) |
+                       ((r & 0x00ffffff) << CHANNEL_RIGHT_SHIFT);
+
+               dst_pos = (dst_pos + sizeof(u64)) & CHANNEL_RING_MASK;
+               src_pos = (src_pos + 2 * sizeof(s16)) & src_mask;
+               count -= sizeof(u64);
+       }
+
+       writeq(dst_pos, &mace->perif.audio.chan[ch].write_ptr); /* in bytes */
+       chip->channel[ch].pos = src_pos;
+
+       spin_unlock_irqrestore(&chip->channel[ch].lock, flags);
+       return ret;
+}
+
+static int snd_sgio2audio_dma_start(struct snd_pcm_substream *substream)
+{
+       struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream);
+       struct snd_sgio2audio_chan *chan = substream->runtime->private_data;
+       int ch = chan->idx;
+
+       /* reset DMA channel */
+       writeq(CHANNEL_CONTROL_RESET, &mace->perif.audio.chan[ch].control);
+       udelay(10);
+       writeq(0, &mace->perif.audio.chan[ch].control);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               /* push a full buffer */
+               snd_sgio2audio_dma_push_frag(chip, ch, CHANNEL_RING_SIZE - 32);
+       }
+       /* set DMA to wake on 50% empty and enable interrupt */
+       writeq(CHANNEL_DMA_ENABLE | CHANNEL_INT_THRESHOLD_50,
+              &mace->perif.audio.chan[ch].control);
+       return 0;
+}
+
+static int snd_sgio2audio_dma_stop(struct snd_pcm_substream *substream)
+{
+       struct snd_sgio2audio_chan *chan = substream->runtime->private_data;
+
+       writeq(0, &mace->perif.audio.chan[chan->idx].control);
+       return 0;
+}
+
+static irqreturn_t snd_sgio2audio_dma_in_isr(int irq, void *dev_id)
+{
+       struct snd_sgio2audio_chan *chan = dev_id;
+       struct snd_pcm_substream *substream;
+       struct snd_sgio2audio *chip;
+       int count, ch;
+
+       substream = chan->substream;
+       chip = snd_pcm_substream_chip(substream);
+       ch = chan->idx;
+
+       /* empty the ring */
+       count = CHANNEL_RING_SIZE -
+               readq(&mace->perif.audio.chan[ch].depth) - 32;
+       if (snd_sgio2audio_dma_pull_frag(chip, ch, count))
+               snd_pcm_period_elapsed(substream);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t snd_sgio2audio_dma_out_isr(int irq, void *dev_id)
+{
+       struct snd_sgio2audio_chan *chan = dev_id;
+       struct snd_pcm_substream *substream;
+       struct snd_sgio2audio *chip;
+       int count, ch;
+
+       substream = chan->substream;
+       chip = snd_pcm_substream_chip(substream);
+       ch = chan->idx;
+       /* fill the ring */
+       count = CHANNEL_RING_SIZE -
+               readq(&mace->perif.audio.chan[ch].depth) - 32;
+       if (snd_sgio2audio_dma_push_frag(chip, ch, count))
+               snd_pcm_period_elapsed(substream);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t snd_sgio2audio_error_isr(int irq, void *dev_id)
+{
+       struct snd_sgio2audio_chan *chan = dev_id;
+       struct snd_pcm_substream *substream;
+
+       substream = chan->substream;
+       snd_sgio2audio_dma_stop(substream);
+       snd_sgio2audio_dma_start(substream);
+       return IRQ_HANDLED;
+}
+
+/* PCM part */
+/* PCM hardware definition */
+static struct snd_pcm_hardware snd_sgio2audio_pcm_hw = {
+       .info = (SNDRV_PCM_INFO_MMAP |
+                SNDRV_PCM_INFO_MMAP_VALID |
+                SNDRV_PCM_INFO_INTERLEAVED |
+                SNDRV_PCM_INFO_BLOCK_TRANSFER),
+       .formats =          SNDRV_PCM_FMTBIT_S16_BE,
+       .rates =            SNDRV_PCM_RATE_8000_48000,
+       .rate_min =         8000,
+       .rate_max =         48000,
+       .channels_min =     2,
+       .channels_max =     2,
+       .buffer_bytes_max = 65536,
+       .period_bytes_min = 32768,
+       .period_bytes_max = 65536,
+       .periods_min =      1,
+       .periods_max =      1024,
+};
+
+/* PCM playback open callback */
+static int snd_sgio2audio_playback1_open(struct snd_pcm_substream *substream)
+{
+       struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       runtime->hw = snd_sgio2audio_pcm_hw;
+       runtime->private_data = &chip->channel[1];
+       return 0;
+}
+
+static int snd_sgio2audio_playback2_open(struct snd_pcm_substream *substream)
+{
+       struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       runtime->hw = snd_sgio2audio_pcm_hw;
+       runtime->private_data = &chip->channel[2];
+       return 0;
+}
+
+/* PCM capture open callback */
+static int snd_sgio2audio_capture_open(struct snd_pcm_substream *substream)
+{
+       struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       runtime->hw = snd_sgio2audio_pcm_hw;
+       runtime->private_data = &chip->channel[0];
+       return 0;
+}
+
+/* PCM close callback */
+static int snd_sgio2audio_pcm_close(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       runtime->private_data = NULL;
+       return 0;
+}
+
+
+/* hw_params callback */
+static int snd_sgio2audio_pcm_hw_params(struct snd_pcm_substream *substream,
+                                       struct snd_pcm_hw_params *hw_params)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int size = params_buffer_bytes(hw_params);
+
+       /* alloc virtual 'dma' area */
+       if (runtime->dma_area)
+               vfree(runtime->dma_area);
+       runtime->dma_area = vmalloc(size);
+       if (runtime->dma_area == NULL)
+               return -ENOMEM;
+       runtime->dma_bytes = size;
+       return 0;
+}
+
+/* hw_free callback */
+static int snd_sgio2audio_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       if (substream->runtime->dma_area)
+               vfree(substream->runtime->dma_area);
+       substream->runtime->dma_area = NULL;
+       return 0;
+}
+
+/* prepare callback */
+static int snd_sgio2audio_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_sgio2audio_chan *chan = substream->runtime->private_data;
+       int ch = chan->idx;
+       unsigned long flags;
+
+       spin_lock_irqsave(&chip->channel[ch].lock, flags);
+
+       /* Setup the pseudo-dma transfer pointers.  */
+       chip->channel[ch].pos = 0;
+       chip->channel[ch].size = 0;
+       chip->channel[ch].substream = substream;
+
+       /* set AD1843 format */
+       /* hardware format is always S16_LE */
+       switch (substream->stream) {
+       case SNDRV_PCM_STREAM_PLAYBACK:
+               ad1843_setup_dac(&chip->ad1843,
+                                ch - 1,
+                                runtime->rate,
+                                SNDRV_PCM_FORMAT_S16_LE,
+                                runtime->channels);
+               break;
+       case SNDRV_PCM_STREAM_CAPTURE:
+               ad1843_setup_adc(&chip->ad1843,
+                                runtime->rate,
+                                SNDRV_PCM_FORMAT_S16_LE,
+                                runtime->channels);
+               break;
+       }
+       spin_unlock_irqrestore(&chip->channel[ch].lock, flags);
+       return 0;
+}
+
+/* trigger callback */
+static int snd_sgio2audio_pcm_trigger(struct snd_pcm_substream *substream,
+                                     int cmd)
+{
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               /* start the PCM engine */
+               snd_sgio2audio_dma_start(substream);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               /* stop the PCM engine */
+               snd_sgio2audio_dma_stop(substream);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* pointer callback */
+static snd_pcm_uframes_t
+snd_sgio2audio_pcm_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_sgio2audio *chip = snd_pcm_substream_chip(substream);
+       struct snd_sgio2audio_chan *chan = substream->runtime->private_data;
+
+       /* get the current hardware pointer */
+       return bytes_to_frames(substream->runtime,
+                              chip->channel[chan->idx].pos);
+}
+
+/* get the physical page pointer on the given offset */
+static struct page *snd_sgio2audio_page(struct snd_pcm_substream *substream,
+                                       unsigned long offset)
+{
+       return vmalloc_to_page(substream->runtime->dma_area + offset);
+}
+
+/* operators */
+static struct snd_pcm_ops snd_sgio2audio_playback1_ops = {
+       .open =        snd_sgio2audio_playback1_open,
+       .close =       snd_sgio2audio_pcm_close,
+       .ioctl =       snd_pcm_lib_ioctl,
+       .hw_params =   snd_sgio2audio_pcm_hw_params,
+       .hw_free =     snd_sgio2audio_pcm_hw_free,
+       .prepare =     snd_sgio2audio_pcm_prepare,
+       .trigger =     snd_sgio2audio_pcm_trigger,
+       .pointer =     snd_sgio2audio_pcm_pointer,
+       .page =        snd_sgio2audio_page,
+};
+
+static struct snd_pcm_ops snd_sgio2audio_playback2_ops = {
+       .open =        snd_sgio2audio_playback2_open,
+       .close =       snd_sgio2audio_pcm_close,
+       .ioctl =       snd_pcm_lib_ioctl,
+       .hw_params =   snd_sgio2audio_pcm_hw_params,
+       .hw_free =     snd_sgio2audio_pcm_hw_free,
+       .prepare =     snd_sgio2audio_pcm_prepare,
+       .trigger =     snd_sgio2audio_pcm_trigger,
+       .pointer =     snd_sgio2audio_pcm_pointer,
+       .page =        snd_sgio2audio_page,
+};
+
+static struct snd_pcm_ops snd_sgio2audio_capture_ops = {
+       .open =        snd_sgio2audio_capture_open,
+       .close =       snd_sgio2audio_pcm_close,
+       .ioctl =       snd_pcm_lib_ioctl,
+       .hw_params =   snd_sgio2audio_pcm_hw_params,
+       .hw_free =     snd_sgio2audio_pcm_hw_free,
+       .prepare =     snd_sgio2audio_pcm_prepare,
+       .trigger =     snd_sgio2audio_pcm_trigger,
+       .pointer =     snd_sgio2audio_pcm_pointer,
+       .page =        snd_sgio2audio_page,
+};
+
+/*
+ *  definitions of capture are omitted here...
+ */
+
+/* create a pcm device */
+static int __devinit snd_sgio2audio_new_pcm(struct snd_sgio2audio *chip)
+{
+       struct snd_pcm *pcm;
+       int err;
+
+       /* create first pcm device with one outputs and one input */
+       err = snd_pcm_new(chip->card, "SGI O2 Audio", 0, 1, 1, &pcm);
+       if (err < 0)
+               return err;
+
+       pcm->private_data = chip;
+       strcpy(pcm->name, "SGI O2 DAC1");
+
+       /* set operators */
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                       &snd_sgio2audio_playback1_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                       &snd_sgio2audio_capture_ops);
+
+       /* create second  pcm device with one outputs and no input */
+       err = snd_pcm_new(chip->card, "SGI O2 Audio", 1, 1, 0, &pcm);
+       if (err < 0)
+               return err;
+
+       pcm->private_data = chip;
+       strcpy(pcm->name, "SGI O2 DAC2");
+
+       /* set operators */
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                       &snd_sgio2audio_playback2_ops);
+
+       return 0;
+}
+
+static struct {
+       int idx;
+       int irq;
+       irqreturn_t (*isr)(int, void *);
+       const char *desc;
+} snd_sgio2_isr_table[] = {
+       {
+               .idx = 0,
+               .irq = MACEISA_AUDIO1_DMAT_IRQ,
+               .isr = snd_sgio2audio_dma_in_isr,
+               .desc = "Capture DMA Channel 0"
+       }, {
+               .idx = 0,
+               .irq = MACEISA_AUDIO1_OF_IRQ,
+               .isr = snd_sgio2audio_error_isr,
+               .desc = "Capture Overflow"
+       }, {
+               .idx = 1,
+               .irq = MACEISA_AUDIO2_DMAT_IRQ,
+               .isr = snd_sgio2audio_dma_out_isr,
+               .desc = "Playback DMA Channel 1"
+       }, {
+               .idx = 1,
+               .irq = MACEISA_AUDIO2_MERR_IRQ,
+               .isr = snd_sgio2audio_error_isr,
+               .desc = "Memory Error Channel 1"
+       }, {
+               .idx = 2,
+               .irq = MACEISA_AUDIO3_DMAT_IRQ,
+               .isr = snd_sgio2audio_dma_out_isr,
+               .desc = "Playback DMA Channel 2"
+       }, {
+               .idx = 2,
+               .irq = MACEISA_AUDIO3_MERR_IRQ,
+               .isr = snd_sgio2audio_error_isr,
+               .desc = "Memory Error Channel 2"
+       }
+};
+
+/* ALSA driver */
+
+static int snd_sgio2audio_free(struct snd_sgio2audio *chip)
+{
+       int i;
+
+       /* reset interface */
+       writeq(AUDIO_CONTROL_RESET, &mace->perif.audio.control);
+       udelay(1);
+       writeq(0, &mace->perif.audio.control);
+
+       /* release IRQ's */
+       for (i = 0; i < ARRAY_SIZE(snd_sgio2_isr_table); i++)
+               free_irq(snd_sgio2_isr_table[i].irq,
+                        &chip->channel[snd_sgio2_isr_table[i].idx]);
+
+       dma_free_coherent(NULL, MACEISA_RINGBUFFERS_SIZE,
+                         chip->ring_base, chip->ring_base_dma);
+
+       /* release card data */
+       kfree(chip);
+       return 0;
+}
+
+static int snd_sgio2audio_dev_free(struct snd_device *device)
+{
+       struct snd_sgio2audio *chip = device->device_data;
+
+       return snd_sgio2audio_free(chip);
+}
+
+static struct snd_device_ops ops = {
+       .dev_free = snd_sgio2audio_dev_free,
+};
+
+static int __devinit snd_sgio2audio_create(struct snd_card *card,
+                                          struct snd_sgio2audio **rchip)
+{
+       struct snd_sgio2audio *chip;
+       int i, err;
+
+       *rchip = NULL;
+
+       /* check if a codec is attached to the interface */
+       /* (Audio or Audio/Video board present) */
+       if (!(readq(&mace->perif.audio.control) & AUDIO_CONTROL_CODEC_PRESENT))
+               return -ENOENT;
+
+       chip = kzalloc(sizeof(struct snd_sgio2audio), GFP_KERNEL);
+       if (chip == NULL)
+               return -ENOMEM;
+
+       chip->card = card;
+
+       chip->ring_base = dma_alloc_coherent(NULL, MACEISA_RINGBUFFERS_SIZE,
+                                            &chip->ring_base_dma, GFP_USER);
+       if (chip->ring_base == NULL) {
+               printk(KERN_ERR
+                      "sgio2audio: could not allocate ring buffers\n");
+               kfree(chip);
+               return -ENOMEM;
+       }
+
+       spin_lock_init(&chip->ad1843_lock);
+
+       /* initialize channels */
+       for (i = 0; i < 3; i++) {
+               spin_lock_init(&chip->channel[i].lock);
+               chip->channel[i].idx = i;
+       }
+
+       /* allocate IRQs */
+       for (i = 0; i < ARRAY_SIZE(snd_sgio2_isr_table); i++) {
+               if (request_irq(snd_sgio2_isr_table[i].irq,
+                               snd_sgio2_isr_table[i].isr,
+                               0,
+                               snd_sgio2_isr_table[i].desc,
+                               &chip->channel[snd_sgio2_isr_table[i].idx])) {
+                       snd_sgio2audio_free(chip);
+                       printk(KERN_ERR "sgio2audio: cannot allocate irq %d\n",
+                              snd_sgio2_isr_table[i].irq);
+                       return -EBUSY;
+               }
+       }
+
+       /* reset the interface */
+       writeq(AUDIO_CONTROL_RESET, &mace->perif.audio.control);
+       udelay(1);
+       writeq(0, &mace->perif.audio.control);
+       msleep_interruptible(1); /* give time to recover */
+
+       /* set ring base */
+       writeq(chip->ring_base_dma, &mace->perif.ctrl.ringbase);
+
+       /* attach the AD1843 codec */
+       chip->ad1843.read = read_ad1843_reg;
+       chip->ad1843.write = write_ad1843_reg;
+       chip->ad1843.chip = chip;
+
+       /* initialize the AD1843 codec */
+       err = ad1843_init(&chip->ad1843);
+       if (err < 0) {
+               snd_sgio2audio_free(chip);
+               return err;
+       }
+
+       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+       if (err < 0) {
+               snd_sgio2audio_free(chip);
+               return err;
+       }
+       *rchip = chip;
+       return 0;
+}
+
+static int __devinit snd_sgio2audio_probe(struct platform_device *pdev)
+{
+       struct snd_card *card;
+       struct snd_sgio2audio *chip;
+       int err;
+
+       card = snd_card_new(index, id, THIS_MODULE, 0);
+       if (card == NULL)
+               return -ENOMEM;
+
+       err = snd_sgio2audio_create(card, &chip);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+       snd_card_set_dev(card, &pdev->dev);
+
+       err = snd_sgio2audio_new_pcm(chip);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+       err = snd_sgio2audio_new_mixer(chip);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+       strcpy(card->driver, "SGI O2 Audio");
+       strcpy(card->shortname, "SGI O2 Audio");
+       sprintf(card->longname, "%s irq %i-%i",
+               card->shortname,
+               MACEISA_AUDIO1_DMAT_IRQ,
+               MACEISA_AUDIO3_MERR_IRQ);
+
+       err = snd_card_register(card);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+       platform_set_drvdata(pdev, card);
+       return 0;
+}
+
+static int __exit snd_sgio2audio_remove(struct platform_device *pdev)
+{
+       struct snd_card *card = platform_get_drvdata(pdev);
+
+       snd_card_free(card);
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+static struct platform_driver sgio2audio_driver = {
+       .probe  = snd_sgio2audio_probe,
+       .remove = __devexit_p(snd_sgio2audio_remove),
+       .driver = {
+               .name   = "sgio2audio",
+               .owner  = THIS_MODULE,
+       }
+};
+
+static int __init alsa_card_sgio2audio_init(void)
+{
+       return platform_driver_register(&sgio2audio_driver);
+}
+
+static void __exit alsa_card_sgio2audio_exit(void)
+{
+       platform_driver_unregister(&sgio2audio_driver);
+}
+
+module_init(alsa_card_sgio2audio_init)
+module_exit(alsa_card_sgio2audio_exit)
index 3be2dc1025b50592ef29f61e5480e4431a6de103..33940139844bf3893ab5487e711a728682c1c096 100644 (file)
@@ -7,7 +7,7 @@
 
 config SOUND_BCM_CS4297A
        tristate "Crystal Sound CS4297a (for Swarm)"
-       depends on SOUND_PRIME && SIBYTE_SWARM
+       depends on SIBYTE_SWARM
        help
          The BCM91250A has a Crystal CS4297a on synchronous serial
          port B (in addition to the DB-9 serial port).  Say Y or M
@@ -17,7 +17,7 @@ config SOUND_BCM_CS4297A
 
 config SOUND_VWSND
        tristate "SGI Visual Workstation Sound"
-       depends on SOUND_PRIME && X86_VISWS
+       depends on X86_VISWS
        help
          Say Y or M if you have an SGI Visual Workstation and you want to be
          able to use its on-board audio.  Read
@@ -26,19 +26,18 @@ config SOUND_VWSND
 
 config SOUND_HAL2
        tristate "SGI HAL2 sound (EXPERIMENTAL)"
-       depends on SOUND_PRIME && SGI_IP22 && EXPERIMENTAL
+       depends on SGI_IP22 && EXPERIMENTAL
        help
          Say Y or M if you have an SGI Indy or Indigo2 system and want to be able to
          use its on-board A2 audio system.
 
 config SOUND_AU1550_AC97
        tristate "Au1550/Au1200 AC97 Sound"
-       select SND_AC97_CODEC
-       depends on SOUND_PRIME && (SOC_AU1550 || SOC_AU1200)
+       depends on SOC_AU1550 || SOC_AU1200
 
 config SOUND_TRIDENT
        tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core"
-       depends on SOUND_PRIME && PCI
+       depends on PCI
        ---help---
          Say Y or M if you have a PCI sound card utilizing the Trident
          4DWave-DX/NX chipset or your mother board chipset has SiS 7018
@@ -79,7 +78,7 @@ config SOUND_TRIDENT
 
 config SOUND_MSNDCLAS
        tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
-       depends on SOUND_PRIME && (m || !STANDALONE) && ISA
+       depends on (m || !STANDALONE) && ISA
        help
          Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or
          Monterey (not for the Pinnacle or Fiji).
@@ -143,7 +142,7 @@ config MSNDCLAS_IO
 
 config SOUND_MSNDPIN
        tristate "Support for Turtle Beach MultiSound Pinnacle, Fiji"
-       depends on SOUND_PRIME && (m || !STANDALONE) && ISA
+       depends on (m || !STANDALONE) && ISA
        help
          Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji.
          See <file:Documentation/sound/oss/MultiSound> for important information
@@ -229,7 +228,7 @@ config MSNDPIN_NONPNP
          configure the card's resources.
 
 comment "MSND Pinnacle DSP section will be configured to above parameters."
-       depends on SOUND_PRIME && SOUND_MSNDPIN=y && MSNDPIN_NONPNP
+       depends on SOUND_MSNDPIN=y && MSNDPIN_NONPNP
 
 config MSNDPIN_CFG
        hex "MSND Pinnacle config port 250,260,270"
@@ -242,7 +241,7 @@ config MSNDPIN_CFG
          Mode".
 
 comment "Pinnacle-specific Device Configuration (0 disables)"
-       depends on SOUND_PRIME && SOUND_MSNDPIN=y && MSNDPIN_NONPNP
+       depends on SOUND_MSNDPIN=y && MSNDPIN_NONPNP
 
 config MSNDPIN_MPU_IO
        hex "MSND Pinnacle MPU I/O (e.g. 330)"
@@ -294,7 +293,7 @@ config MSNDPIN_JOYSTICK_IO
 
 config MSND_FIFOSIZE
        int "MSND buffer size (kB)"
-       depends on SOUND_PRIME && (SOUND_MSNDPIN=y || SOUND_MSNDCLAS=y)
+       depends on SOUND_MSNDPIN=y || SOUND_MSNDCLAS=y
        default "128"
        help
          Configures the size of each audio buffer, in kilobytes, for
@@ -302,9 +301,9 @@ config MSND_FIFOSIZE
          and Pinnacle). Larger values reduce the chance of data overruns at
          the expense of overall latency. If unsure, use the default.
 
-config SOUND_OSS
+menuconfig SOUND_OSS
        tristate "OSS sound modules"
-       depends on SOUND_PRIME && ISA_DMA_API && VIRT_TO_BUS
+       depends on ISA_DMA_API && VIRT_TO_BUS
        help
          OSS is the Open Sound System suite of sound card drivers.  They make
          sound programming easier since they provide a common API.  Say Y or
@@ -312,16 +311,16 @@ config SOUND_OSS
          driver for your sound card above, then pick your driver from the
          list below.
 
+if SOUND_OSS
+
 config SOUND_TRACEINIT
        bool "Verbose initialisation"
-       depends on SOUND_OSS
        help
          Verbose soundcard initialization -- affects the format of autoprobe
          and initialization messages at boot time.
 
 config SOUND_DMAP
        bool "Persistent DMA buffers"
-       depends on SOUND_OSS
        ---help---
          Linux can often have problems allocating DMA buffers for ISA sound
          cards on machines with more than 16MB of RAM. This is because ISA
@@ -338,8 +337,6 @@ config SOUND_DMAP
 
 config SOUND_SSCAPE
        tristate "Ensoniq SoundScape support"
-       depends on SOUND_OSS
-       depends on VIRT_TO_BUS
        help
          Answer Y if you have a sound card based on the Ensoniq SoundScape
          chipset. Such cards are being manufactured at least by Ensoniq, Spea
@@ -352,13 +349,11 @@ config SOUND_SSCAPE
 
 config SOUND_VMIDI
        tristate "Loopback MIDI device support"
-       depends on SOUND_OSS
        help
          Support for MIDI loopback on port 1 or 2.
 
 config SOUND_TRIX
        tristate "MediaTrix AudioTrix Pro support"
-       depends on SOUND_OSS
        help
          Answer Y if you have the AudioTriX Pro sound card manufactured
          by MediaTrix.
@@ -382,7 +377,6 @@ config TRIX_BOOT_FILE
 
 config SOUND_MSS
        tristate "Microsoft Sound System support"
-       depends on SOUND_OSS
        ---help---
          Again think carefully before answering Y to this question.  It's
          safe to answer Y if you have the original Windows Sound System card
@@ -414,7 +408,6 @@ config SOUND_MSS
 
 config SOUND_MPU401
        tristate "MPU-401 support (NOT for SB16)"
-       depends on SOUND_OSS
        ---help---
          Be careful with this question.  The MPU401 interface is supported by
          all sound cards.  However, some natively supported cards have their
@@ -430,7 +423,6 @@ config SOUND_MPU401
 
 config SOUND_PAS
        tristate "ProAudioSpectrum 16 support"
-       depends on SOUND_OSS
        ---help---
          Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio
          16 or Logitech SoundMan 16 sound card. Answer N if you have some
@@ -452,7 +444,6 @@ config PAS_JOYSTICK
 
 config SOUND_PSS
        tristate "PSS (AD1848, ADSP-2115, ESC614) support"
-       depends on SOUND_OSS
        help
          Answer Y or M if you have an Orchid SW32, Cardinal DSP16, Beethoven
          ADSP-16 or some other card based on the PSS chipset (AD1848 codec +
@@ -495,7 +486,6 @@ config PSS_BOOT_FILE
 
 config SOUND_SB
        tristate "100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support"
-       depends on SOUND_OSS
        ---help---
          Answer Y if you have an original Sound Blaster card made by Creative
          Labs or a 100% hardware compatible clone (like the Thunderboard or
@@ -522,7 +512,6 @@ config SOUND_SB
 
 config SOUND_YM3812
        tristate "Yamaha FM synthesizer (YM3812/OPL-3) support"
-       depends on SOUND_OSS
        ---help---
          Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
          Answering Y is usually a safe and recommended choice, however some
@@ -538,7 +527,6 @@ config SOUND_YM3812
 
 config SOUND_UART6850
        tristate "6850 UART support"
-       depends on SOUND_OSS
        help
          This option enables support for MIDI interfaces based on the 6850
          UART chip. This interface is rarely found on sound cards. It's safe
@@ -549,7 +537,6 @@ config SOUND_UART6850
 
 config SOUND_AEDSP16
        tristate "Gallant Audio Cards (SC-6000 and SC-6600 based)"
-       depends on SOUND_OSS
        ---help---
          Answer Y if you have a Gallant's Audio Excel DSP 16 card. This
          driver supports Audio Excel DSP 16 but not the III nor PnP versions
@@ -630,14 +617,14 @@ endchoice
 
 config SOUND_VIDC
        tristate "VIDC 16-bit sound"
-       depends on ARM && (ARCH_ACORN || ARCH_CLPS7500) && SOUND_OSS
+       depends on ARM && (ARCH_ACORN || ARCH_CLPS7500)
        help
          16-bit support for the VIDC onboard sound hardware found on Acorn
          machines.
 
 config SOUND_WAVEARTIST
        tristate "Netwinder WaveArtist"
-       depends on ARM && SOUND_OSS && ARCH_NETWINDER
+       depends on ARM && ARCH_NETWINDER
        help
          Say Y here to include support for the Rockwell WaveArtist sound
          system.  This driver is mainly for the NetWinder.
@@ -646,9 +633,11 @@ config SOUND_KAHLUA
        tristate "XpressAudio Sound Blaster emulation"
        depends on SOUND_SB
 
+endif  # SOUND_OSS
+
 config SOUND_SH_DAC_AUDIO
        tristate "SuperH DAC audio support"
-       depends on SOUND_PRIME && CPU_SH3
+       depends on CPU_SH3
 
 config SOUND_SH_DAC_AUDIO_CHANNEL
        int "DAC channel"
index a003c0ea9303f800f27e6de612773d0a2f5012e2..95fc5c681755eafff96d7165c1eeb3b9da72a781 100644 (file)
@@ -211,10 +211,6 @@ static int state_unit = -1;
 static int irq_installed;
 #endif /* MODULE */
 
-/* software implemented recording volume! */
-uint software_input_volume = SW_INPUT_VOLUME_SCALE * SW_INPUT_VOLUME_DEFAULT;
-EXPORT_SYMBOL(software_input_volume);
-
 /* control over who can modify resources shared between play/record */
 static mode_t shared_resource_owner;
 static int shared_resources_initialised;
@@ -1188,7 +1184,7 @@ static struct {
 
 /* publish this function for use by low-level code, if required */
 
-char *get_afmt_string(int afmt)
+static char *get_afmt_string(int afmt)
 {
         switch(afmt) {
             case AFMT_MU_LAW:
@@ -1551,4 +1547,3 @@ EXPORT_SYMBOL(dmasound_catchRadius);
 EXPORT_SYMBOL(dmasound_ulaw2dma8);
 EXPORT_SYMBOL(dmasound_alaw2dma8);
 #endif
-EXPORT_SYMBOL(get_afmt_string) ;
index 202e8103dc4da39bffe0d740ae56bef1de2a2ceb..06e9e88e4c05dd9e0735279fd9d4356163034224 100644 (file)
@@ -710,7 +710,7 @@ static MACHINE machAmiga = {
 /*** Config & Setup **********************************************************/
 
 
-int __init dmasound_paula_init(void)
+static int __init dmasound_paula_init(void)
 {
        int err;
 
index b3379dd7ca5e1d49d5cc8d0a13c533b891ef8875..1855b14d90c3922989abfd43a0e53b57423174f6 100644 (file)
@@ -611,7 +611,7 @@ static MACHINE machQ40 = {
 /*** Config & Setup **********************************************************/
 
 
-int __init dmasound_q40_init(void)
+static int __init dmasound_q40_init(void)
 {
        if (MACH_IS_Q40) {
            dmasound.mach = machQ40;
index ba38d6200099f883f3f188d6e9255bf07afa80b6..e4282d93a1aaa121aaac6eeac5c9f22cd92083ec 100644 (file)
@@ -20,8 +20,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd.c,v 1.17 1999/03/21 16:50:09 andrewtv Exp $
- *
  ********************************************************************/
 
 #include <linux/module.h>
index d0ca582c4583e302f171c21e653ea4e5c43f7959..61b3955481c56da1f7b88ca2ac43fd08ed5ef15a 100644 (file)
@@ -24,8 +24,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd.h,v 1.36 1999/03/21 17:05:42 andrewtv Exp $
- *
  ********************************************************************/
 #ifndef __MSND_H
 #define __MSND_H
index 7ffea5267f9699dd4ca22aa2557f1ca777505c91..1a17dde2f650ea04f14cafd68b7cd8cd086c027b 100644 (file)
@@ -24,8 +24,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * 
- * $Id: msnd_classic.h,v 1.10 1999/03/21 17:36:09 andrewtv Exp $
- *
  ********************************************************************/
 #ifndef __MSND_CLASSIC_H
 #define __MSND_CLASSIC_H
index f1f49ebf752ea0a6ee109fbf9622b1a0265c92f0..bf27e008f465f29aed345549b583c3e7dcb75213 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd_pinnacle.c,v 1.8 2000/12/30 00:33:21 sycamore Exp $
- *
  * 12-3-2000  Modified IO port validation  Steve Sycamore
  *
- *
- * $$$: msnd_pinnacle.c,v 1.75 1999/03/21 16:50:09 andrewtv $$$ $
- *
  ********************************************************************/
 
 #include <linux/kernel.h>
index cce91148700481b1ac28aa67729311d0ebcbf2e5..c18d66cbbe3fdb0d235174e2f768acf6e34e3918 100644 (file)
@@ -24,8 +24,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd_pinnacle.h,v 1.11 1999/03/21 17:36:09 andrewtv Exp $
- *
  ********************************************************************/
 #ifndef __MSND_PINNACLE_H
 #define __MSND_PINNACLE_H
index a5a7f9d75d051e37398b094a2e42100adbf19029..9b61d95010f07134e481eed1a481d77d13d8ca88 100644 (file)
@@ -1,15 +1,20 @@
 # ALSA PA-RISC drivers
 
-menu "GSC devices"
-       depends on SND!=n && GSC
+menuconfig SND_GSC
+       bool "GSC sound devices"
+       depends on GSC
+       default y
+       help
+         Support for GSC sound devices on PA-RISC architectures.
+
+if SND_GSC
 
 config SND_HARMONY
        tristate "Harmony/Vivace sound chip"
-       depends on SND
        select SND_PCM
        help
          Say 'Y' or 'M' to include support for the Harmony/Vivace sound
          chip found in most GSC-based PA-RISC workstations.  It's frequently
          provided as part of the Lasi multi-function IC.
 
-endmenu
+endif  # SND_GSC
index 7e47421095726afd72650cffe20e2306aebfa252..8fe5dac3942824a8c9274eb1ce0dea74e80f8e99 100644 (file)
@@ -1,11 +1,16 @@
 # ALSA PCI drivers
 
-menu "PCI devices"
-       depends on SND!=n && PCI
+menuconfig SND_PCI
+       bool "PCI sound devices"
+       depends on PCI
+       default y
+       help
+         Support for sound devices connected via the PCI bus.
+
+if SND_PCI
 
 config SND_AD1889
        tristate "Analog Devices AD1889"
-       depends on SND
        select SND_AC97_CODEC
        help
          Say Y here to include support for the integrated AC97 sound
@@ -17,7 +22,6 @@ config SND_AD1889
 
 config SND_ALS300
        tristate "Avance Logic ALS300/ALS300+"
-       depends on SND
        select SND_PCM
        select SND_AC97_CODEC
        select SND_OPL3_LIB
@@ -29,7 +33,7 @@ config SND_ALS300
 
 config SND_ALS4000
        tristate "Avance Logic ALS4000"
-       depends on SND && ISA_DMA_API
+       depends on ISA_DMA_API
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_PCM
@@ -43,7 +47,6 @@ config SND_ALS4000
 
 config SND_ALI5451
        tristate "ALi M5451 PCI Audio Controller"
-       depends on SND
        select SND_MPU401_UART
        select SND_AC97_CODEC
        help
@@ -57,7 +60,6 @@ config SND_ALI5451
 
 config SND_ATIIXP
        tristate "ATI IXP AC97 Controller"
-       depends on SND
        select SND_AC97_CODEC
        help
          Say Y here to include support for the integrated AC97 sound
@@ -69,7 +71,6 @@ config SND_ATIIXP
 
 config SND_ATIIXP_MODEM
        tristate "ATI IXP Modem"
-       depends on SND
        select SND_AC97_CODEC
        help
          Say Y here to include support for the integrated MC97 modem on
@@ -80,7 +81,6 @@ config SND_ATIIXP_MODEM
 
 config SND_AU8810
        tristate "Aureal Advantage"
-       depends on SND
        select SND_MPU401_UART
        select SND_AC97_CODEC
        help
@@ -95,7 +95,6 @@ config SND_AU8810
 
 config SND_AU8820
        tristate "Aureal Vortex"
-       depends on SND
        select SND_MPU401_UART
        select SND_AC97_CODEC
        help
@@ -109,7 +108,6 @@ config SND_AU8820
 
 config SND_AU8830
        tristate "Aureal Vortex 2"
-       depends on SND
        select SND_MPU401_UART
        select SND_AC97_CODEC
        help
@@ -124,7 +122,6 @@ config SND_AU8830
 
 config SND_AW2
        tristate "Emagic Audiowerk 2"
-       depends on SND
        help
          Say Y here to include support for Emagic Audiowerk 2 soundcards.
 
@@ -139,7 +136,7 @@ config SND_AW2
 
 config SND_AZT3328
        tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)"
-       depends on SND && EXPERIMENTAL
+       depends on EXPERIMENTAL
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_PCM
@@ -152,7 +149,6 @@ config SND_AZT3328
 
 config SND_BT87X
        tristate "Bt87x Audio Capture"
-       depends on SND
        select SND_PCM
        help
          If you want to record audio from TV cards based on
@@ -174,7 +170,6 @@ config SND_BT87X_OVERCLOCK
 
 config SND_CA0106
        tristate "SB Audigy LS / Live 24bit"
-       depends on SND
        select SND_AC97_CODEC
        select SND_RAWMIDI
        select SND_VMASTER
@@ -187,7 +182,6 @@ config SND_CA0106
 
 config SND_CMIPCI
        tristate "C-Media 8338, 8738, 8768, 8770"
-       depends on SND
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_PCM
@@ -201,13 +195,11 @@ config SND_CMIPCI
 
 config SND_OXYGEN_LIB
         tristate
-       depends on SND
        select SND_PCM
        select SND_MPU401_UART
 
 config SND_OXYGEN
        tristate "C-Media 8788 (Oxygen)"
-       depends on SND
        select SND_OXYGEN_LIB
        help
          Say Y here to include support for sound cards based on the
@@ -225,7 +217,6 @@ config SND_OXYGEN
 
 config SND_CS4281
        tristate "Cirrus Logic (Sound Fusion) CS4281"
-       depends on SND
        select SND_OPL3_LIB
        select SND_RAWMIDI
        select SND_AC97_CODEC
@@ -237,7 +228,6 @@ config SND_CS4281
 
 config SND_CS46XX
        tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x"
-       depends on SND
        select SND_RAWMIDI
        select SND_AC97_CODEC
        help
@@ -258,7 +248,7 @@ config SND_CS46XX_NEW_DSP
 
 config SND_CS5530
        tristate "CS5530 Audio"
-       depends on SND && ISA_DMA_API
+       depends on ISA_DMA_API
        select SND_SB16_DSP
        help
          Say Y here to include support for audio on Cyrix/NatSemi CS5530 chips.
@@ -268,7 +258,7 @@ config SND_CS5530
 
 config SND_CS5535AUDIO
        tristate "CS5535/CS5536 Audio"
-       depends on SND && X86 && !X86_64
+       depends on X86 && !X86_64
        select SND_PCM
        select SND_AC97_CODEC
        help
@@ -286,7 +276,6 @@ config SND_CS5535AUDIO
 
 config SND_DARLA20
        tristate "(Echoaudio) Darla20"
-       depends on SND
        select FW_LOADER
        select SND_PCM
        help
@@ -297,7 +286,6 @@ config SND_DARLA20
 
 config SND_GINA20
        tristate "(Echoaudio) Gina20"
-       depends on SND
        select FW_LOADER
        select SND_PCM
        help
@@ -308,7 +296,6 @@ config SND_GINA20
 
 config SND_LAYLA20
        tristate "(Echoaudio) Layla20"
-       depends on SND
        select FW_LOADER
        select SND_RAWMIDI
        select SND_PCM
@@ -320,7 +307,6 @@ config SND_LAYLA20
 
 config SND_DARLA24
        tristate "(Echoaudio) Darla24"
-       depends on SND
        select FW_LOADER
        select SND_PCM
        help
@@ -331,7 +317,6 @@ config SND_DARLA24
 
 config SND_GINA24
        tristate "(Echoaudio) Gina24"
-       depends on SND
        select FW_LOADER
        select SND_PCM
        help
@@ -342,7 +327,6 @@ config SND_GINA24
 
 config SND_LAYLA24
        tristate "(Echoaudio) Layla24"
-       depends on SND
        select FW_LOADER
        select SND_RAWMIDI
        select SND_PCM
@@ -354,7 +338,6 @@ config SND_LAYLA24
 
 config SND_MONA
        tristate "(Echoaudio) Mona"
-       depends on SND
        select FW_LOADER
        select SND_RAWMIDI
        select SND_PCM
@@ -366,7 +349,6 @@ config SND_MONA
 
 config SND_MIA
        tristate "(Echoaudio) Mia"
-       depends on SND
        select FW_LOADER
        select SND_RAWMIDI
        select SND_PCM
@@ -378,7 +360,6 @@ config SND_MIA
 
 config SND_ECHO3G
        tristate "(Echoaudio) 3G cards"
-       depends on SND
        select FW_LOADER
        select SND_RAWMIDI
        select SND_PCM
@@ -390,7 +371,6 @@ config SND_ECHO3G
 
 config SND_INDIGO
        tristate "(Echoaudio) Indigo"
-       depends on SND
        select FW_LOADER
        select SND_PCM
        help
@@ -401,7 +381,6 @@ config SND_INDIGO
 
 config SND_INDIGOIO
        tristate "(Echoaudio) Indigo IO"
-       depends on SND
        select FW_LOADER
        select SND_PCM
        help
@@ -412,7 +391,6 @@ config SND_INDIGOIO
 
 config SND_INDIGODJ
        tristate "(Echoaudio) Indigo DJ"
-       depends on SND
        select FW_LOADER
        select SND_PCM
        help
@@ -423,7 +401,6 @@ config SND_INDIGODJ
 
 config SND_EMU10K1
        tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)"
-       depends on SND
        select FW_LOADER
        select SND_HWDEP
        select SND_RAWMIDI
@@ -441,7 +418,6 @@ config SND_EMU10K1
 
 config SND_EMU10K1X
        tristate "Emu10k1X (Dell OEM Version)"
-       depends on SND
        select SND_AC97_CODEC
        select SND_RAWMIDI
        help
@@ -453,7 +429,6 @@ config SND_EMU10K1X
 
 config SND_ENS1370
        tristate "(Creative) Ensoniq AudioPCI 1370"
-       depends on SND
        select SND_RAWMIDI
        select SND_PCM
        help
@@ -464,7 +439,6 @@ config SND_ENS1370
 
 config SND_ENS1371
        tristate "(Creative) Ensoniq AudioPCI 1371/1373"
-       depends on SND
        select SND_RAWMIDI
        select SND_AC97_CODEC
        help
@@ -476,7 +450,6 @@ config SND_ENS1371
 
 config SND_ES1938
        tristate "ESS ES1938/1946/1969 (Solo-1)"
-       depends on SND
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_AC97_CODEC
@@ -489,7 +462,6 @@ config SND_ES1938
 
 config SND_ES1968
        tristate "ESS ES1968/1978 (Maestro-1/2/2E)"
-       depends on SND
        select SND_MPU401_UART
        select SND_AC97_CODEC
        help
@@ -501,7 +473,6 @@ config SND_ES1968
 
 config SND_FM801
        tristate "ForteMedia FM801"
-       depends on SND
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_AC97_CODEC
@@ -528,7 +499,6 @@ config SND_FM801_TEA575X
 
 config SND_HDA_INTEL
        tristate "Intel HD Audio"
-       depends on SND
        select SND_PCM
        select SND_VMASTER
        help
@@ -637,7 +607,6 @@ config SND_HDA_POWER_SAVE_DEFAULT
 
 config SND_HDSP
        tristate "RME Hammerfall DSP Audio"
-       depends on SND
        select SND_HWDEP
        select SND_RAWMIDI
        select SND_PCM
@@ -650,7 +619,6 @@ config SND_HDSP
 
 config SND_HDSPM
        tristate "RME Hammerfall DSP MADI"
-       depends on SND
        select SND_HWDEP
        select SND_RAWMIDI
        select SND_PCM
@@ -663,7 +631,6 @@ config SND_HDSPM
 
 config SND_HIFIER
        tristate "TempoTec HiFier Fantasia"
-       depends on SND
        select SND_OXYGEN_LIB
        help
          Say Y here to include support for the MediaTek/TempoTec HiFier
@@ -674,7 +641,6 @@ config SND_HIFIER
 
 config SND_ICE1712
        tristate "ICEnsemble ICE1712 (Envy24)"
-       depends on SND
        select SND_MPU401_UART
        select SND_AC97_CODEC
        help
@@ -691,8 +657,7 @@ config SND_ICE1712
 
 config SND_ICE1724
        tristate "ICE/VT1724/1720 (Envy24HT/PT)"
-       depends on SND
-       select SND_MPU401_UART
+       select SND_RAWMIDI
        select SND_AC97_CODEC
        select SND_VMASTER
        help
@@ -709,7 +674,6 @@ config SND_ICE1724
 
 config SND_INTEL8X0
        tristate "Intel/SiS/nVidia/AMD/ALi AC97 Controller"
-       depends on SND
        select SND_AC97_CODEC
        help
          Say Y here to include support for the integrated AC97 sound
@@ -722,7 +686,6 @@ config SND_INTEL8X0
 
 config SND_INTEL8X0M
        tristate "Intel/SiS/nVidia/AMD MC97 Modem"
-       depends on SND
        select SND_AC97_CODEC
        help
          Say Y here to include support for the integrated MC97 modem on
@@ -733,7 +696,6 @@ config SND_INTEL8X0M
 
 config SND_KORG1212
        tristate "Korg 1212 IO"
-       depends on SND
        select FW_LOADER if !SND_KORG1212_FIRMWARE_IN_KERNEL
        select SND_PCM
        help
@@ -753,7 +715,6 @@ config SND_KORG1212_FIRMWARE_IN_KERNEL
 
 config SND_MAESTRO3
        tristate "ESS Allegro/Maestro3"
-       depends on SND
        select FW_LOADER if !SND_MAESTRO3_FIRMWARE_IN_KERNEL
        select SND_AC97_CODEC
        help
@@ -774,7 +735,6 @@ config SND_MAESTRO3_FIRMWARE_IN_KERNEL
 
 config SND_MIXART
        tristate "Digigram miXart"
-       depends on SND
        select SND_HWDEP
        select SND_PCM
        help
@@ -786,7 +746,6 @@ config SND_MIXART
 
 config SND_NM256
        tristate "NeoMagic NM256AV/ZX"
-       depends on SND
        select SND_AC97_CODEC
        help
          Say Y here to include support for NeoMagic NM256AV/ZX chips.
@@ -796,7 +755,6 @@ config SND_NM256
 
 config SND_PCXHR
        tristate "Digigram PCXHR"
-       depends on SND
        select SND_PCM
        select SND_HWDEP
        help
@@ -807,7 +765,6 @@ config SND_PCXHR
 
 config SND_RIPTIDE
        tristate "Conexant Riptide"
-       depends on SND
        select FW_LOADER
        select SND_OPL3_LIB
        select SND_MPU401_UART
@@ -820,7 +777,6 @@ config SND_RIPTIDE
 
 config SND_RME32
        tristate "RME Digi32, 32/8, 32 PRO"
-       depends on SND
        select SND_PCM
        help
          Say Y to include support for RME Digi32, Digi32 PRO and
@@ -832,7 +788,6 @@ config SND_RME32
 
 config SND_RME96
        tristate "RME Digi96, 96/8, 96/8 PRO"
-       depends on SND
        select SND_PCM
        help
          Say Y here to include support for RME Digi96, Digi96/8 and
@@ -843,7 +798,6 @@ config SND_RME96
 
 config SND_RME9652
        tristate "RME Digi9652 (Hammerfall)"
-       depends on SND
        select SND_PCM
        help
          Say Y here to include support for RME Hammerfall (RME
@@ -854,7 +808,7 @@ config SND_RME9652
 
 config SND_SIS7019
        tristate "SiS 7019 Audio Accelerator"
-       depends on SND && X86 && !X86_64
+       depends on X86 && !X86_64
        select SND_AC97_CODEC
        help
          Say Y here to include support for the SiS 7019 Audio Accelerator.
@@ -864,7 +818,6 @@ config SND_SIS7019
 
 config SND_SONICVIBES
        tristate "S3 SonicVibes"
-       depends on SND
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_AC97_CODEC
@@ -877,7 +830,6 @@ config SND_SONICVIBES
 
 config SND_TRIDENT
        tristate "Trident 4D-Wave DX/NX; SiS 7018"
-       depends on SND
        select SND_MPU401_UART
        select SND_AC97_CODEC
        help
@@ -889,7 +841,6 @@ config SND_TRIDENT
 
 config SND_VIA82XX
        tristate "VIA 82C686A/B, 8233/8235 AC97 Controller"
-       depends on SND
        select SND_MPU401_UART
        select SND_AC97_CODEC
        help
@@ -901,7 +852,6 @@ config SND_VIA82XX
 
 config SND_VIA82XX_MODEM
        tristate "VIA 82C686A/B, 8233 based Modems"
-       depends on SND
        select SND_AC97_CODEC
        help
          Say Y here to include support for the integrated MC97 modem on
@@ -912,7 +862,6 @@ config SND_VIA82XX_MODEM
 
 config SND_VIRTUOSO
        tristate "Asus Virtuoso 100/200 (Xonar)"
-       depends on SND
        select SND_OXYGEN_LIB
        help
          Say Y here to include support for sound cards based on the
@@ -923,7 +872,6 @@ config SND_VIRTUOSO
 
 config SND_VX222
        tristate "Digigram VX222"
-       depends on SND
        select SND_VX_LIB
        help
          Say Y here to include support for Digigram VX222 soundcards.
@@ -933,7 +881,6 @@ config SND_VX222
 
 config SND_YMFPCI
        tristate "Yamaha YMF724/740/744/754"
-       depends on SND
        select FW_LOADER if !SND_YMFPCI_FIRMWARE_IN_KERNEL
        select SND_OPL3_LIB
        select SND_MPU401_UART
@@ -954,25 +901,4 @@ config SND_YMFPCI_FIRMWARE_IN_KERNEL
          for the YMFPCI driver.  If you choose N here, you need to
          install the firmware files from the alsa-firmware package.
 
-config SND_AC97_POWER_SAVE
-       bool "AC97 Power-Saving Mode"
-       depends on SND_AC97_CODEC && EXPERIMENTAL
-       default n
-       help
-         Say Y here to enable the aggressive power-saving support of
-         AC97 codecs.  In this mode, the power-mode is dynamically
-         controlled at each open/close.
-
-         The mode is activated by passing power_save=1 option to
-         snd-ac97-codec driver.  You can toggle it dynamically over
-         sysfs, too.
-
-config SND_AC97_POWER_SAVE_DEFAULT
-       int "Default time-out for AC97 power-save mode"
-       depends on SND_AC97_POWER_SAVE
-       default 0
-       help
-         The default time-out value in seconds for AC97 automatic
-         power-save mode.  0 means to disable the power-save mode.
-
-endmenu
+endif  # SND_PCI
index 85ef14bc805649611b51873d8ff7de6de9ba4d6c..65b25d221cd2795135f265dcbb05d47f1dfc8a8f 100644 (file)
@@ -13,7 +13,7 @@ snd-bt87x-objs := bt87x.o
 snd-cmipci-objs := cmipci.o
 snd-cs4281-objs := cs4281.o
 snd-cs5530-objs := cs5530.o
-snd-ens1370-objs := ens1370.o
+snd-ens1370-objs := ens1370.o ak4531_codec.o
 snd-ens1371-objs := ens1371.o
 snd-es1938-objs := es1938.o
 snd-es1968-objs := es1968.o
index 0be48b1a22d04c018e1434d9710b0f8981468466..41fa322f0971677382fcb9ab3ba94492139ee20c 100644 (file)
@@ -3,16 +3,8 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
 #
 
-snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o
-
-ifneq ($(CONFIG_PROC_FS),)
-snd-ac97-codec-objs += ac97_proc.o
-endif
-
-snd-ak4531-codec-objs := ak4531_codec.o
+snd-ac97-codec-y := ac97_codec.o ac97_pcm.o
+snd-ac97-codec-$(CONFIG_PROC_FS) += ac97_proc.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_AC97_CODEC) += snd-ac97-codec.o
-obj-$(CONFIG_SND_ENS1370) += snd-ak4531-codec.o
-
-obj-m := $(sort $(obj-m))
index 45fd29017ddd59ded7e731ece20c977a4a4bde20..07364c00768a4dd90f8eceeb338d899955a17685 100644 (file)
@@ -49,8 +49,9 @@ MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control");
 
 #ifdef CONFIG_SND_AC97_POWER_SAVE
 static int power_save = CONFIG_SND_AC97_POWER_SAVE_DEFAULT;
-module_param(power_save, bool, 0644);
-MODULE_PARM_DESC(power_save, "Enable AC97 power-saving control");
+module_param(power_save, int, 0644);
+MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
+                "(in second, 0 = disable).");
 #endif
 /*
 
@@ -2294,9 +2295,11 @@ static void snd_ac97_powerdown(struct snd_ac97 *ac97)
        power |= AC97_PD_PR0 | AC97_PD_PR1;     /* ADC & DAC powerdown */
        snd_ac97_write(ac97, AC97_POWERDOWN, power);
        udelay(100);
-       power |= AC97_PD_PR2 | AC97_PD_PR3;     /* Analog Mixer powerdown */
+       power |= AC97_PD_PR2;   /* Analog Mixer powerdown (Vref on) */
        snd_ac97_write(ac97, AC97_POWERDOWN, power);
        if (ac97_is_power_save_mode(ac97)) {
+               power |= AC97_PD_PR3;   /* Analog Mixer powerdown */
+               snd_ac97_write(ac97, AC97_POWERDOWN, power);
                udelay(100);
                /* AC-link powerdown, internal Clk disable */
                /* FIXME: this may cause click noises on some boards */
@@ -2362,7 +2365,7 @@ int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup)
                 *  that open/close frequently)
                 */
                schedule_delayed_work(&ac97->power_work,
-                                     msecs_to_jiffies(2000));
+                                     msecs_to_jiffies(power_save * 1000));
        else {
                cancel_delayed_work(&ac97->power_work);
                update_power_regs(ac97);
index 1292dcee072df21b34aa39daecaee841a429dfe0..0746e9ccc20b1572ec1cae300b0178c1ad6f90e9 100644 (file)
@@ -669,6 +669,7 @@ AC97_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
 AC97_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
 AC97_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
 
+AC97_SINGLE("Master Left Inv Switch", AC97_MASTER, 6, 1, 0),
 AC97_SINGLE("Master ZC Switch", AC97_MASTER, 7, 1, 0),
 AC97_SINGLE("Headphone ZC Switch", AC97_HEADPHONE, 7, 1, 0),
 AC97_SINGLE("Mono ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
@@ -3352,8 +3353,66 @@ AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
 AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
 };
 
+static const char *slave_vols_vt1616[] = {
+       "Front Playback Volume",
+       "Surround Playback Volume",
+       "Center Playback Volume",
+       "LFE Playback Volume",
+       NULL
+};
+
+static const char *slave_sws_vt1616[] = {
+       "Front Playback Switch",
+       "Surround Playback Switch",
+       "Center Playback Switch",
+       "LFE Playback Switch",
+       NULL
+};
+
+/* find a mixer control element with the given name */
+static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
+                                                   const char *name)
+{
+       struct snd_ctl_elem_id id;
+       memset(&id, 0, sizeof(id));
+       id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       strcpy(id.name, name);
+       return snd_ctl_find_id(ac97->bus->card, &id);
+}
+
+/* create a virtual master control and add slaves */
+int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
+                        const unsigned int *tlv, const char **slaves)
+{
+       struct snd_kcontrol *kctl;
+       const char **s;
+       int err;
+
+       kctl = snd_ctl_make_virtual_master(name, tlv);
+       if (!kctl)
+               return -ENOMEM;
+       err = snd_ctl_add(ac97->bus->card, kctl);
+       if (err < 0)
+               return err;
+
+       for (s = slaves; *s; s++) {
+               struct snd_kcontrol *sctl;
+
+               sctl = snd_ac97_find_mixer_ctl(ac97, *s);
+               if (!sctl) {
+                       snd_printdd("Cannot find slave %s, skipped\n", *s);
+                       continue;
+               }
+               err = snd_ctl_add_slave(kctl, sctl);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
 static int patch_vt1616_specific(struct snd_ac97 * ac97)
 {
+       struct snd_kcontrol *kctl;
        int err;
 
        if (snd_ac97_try_bit(ac97, 0x5a, 9))
@@ -3361,6 +3420,24 @@ static int patch_vt1616_specific(struct snd_ac97 * ac97)
                        return err;
        if ((err = patch_build_controls(ac97, &snd_ac97_controls_vt1616[1], ARRAY_SIZE(snd_ac97_controls_vt1616) - 1)) < 0)
                return err;
+
+       /* There is already a misnamed master switch.  Rename it.  */
+       kctl = snd_ac97_find_mixer_ctl(ac97, "Master Playback Volume");
+       if (!kctl)
+               return -EINVAL;
+
+       snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Front Playback");
+
+       err = snd_ac97_add_vmaster(ac97, "Master Playback Volume",
+                                  kctl->tlv.p, slave_vols_vt1616);
+       if (err < 0)
+               return err;
+
+       err = snd_ac97_add_vmaster(ac97, "Master Playback Switch",
+                                  NULL, slave_sws_vt1616);
+       if (err < 0)
+               return err;
+
        return 0;
 }
 
@@ -3633,7 +3710,7 @@ static int patch_ucb1400(struct snd_ac97 * ac97)
 {
        ac97->build_ops = &patch_ucb1400_ops;
        /* enable headphone driver and smart low power mode by default */
-       snd_ac97_write(ac97, 0x6a, 0x0050);
-       snd_ac97_write(ac97, 0x6c, 0x0030);
+       snd_ac97_write_cache(ac97, 0x6a, 0x0050);
+       snd_ac97_write_cache(ac97, 0x6c, 0x0030);
        return 0;
 }
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
deleted file mode 100644 (file)
index c0c1633..0000000
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *  Universal routines for AK4531 codec
- *
- *
- *   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/delay.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-#include <sound/core.h>
-#include <sound/ak4531_codec.h>
-#include <sound/tlv.h>
-
-MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("Universal routines for AK4531 codec");
-MODULE_LICENSE("GPL");
-
-#ifdef CONFIG_PROC_FS
-static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531);
-#else
-#define snd_ak4531_proc_init(card,ak)
-#endif
-
-/*
- *
- */
-#if 0
-
-static void snd_ak4531_dump(struct snd_ak4531 *ak4531)
-{
-       int idx;
-       
-       for (idx = 0; idx < 0x19; idx++)
-               printk("ak4531 0x%x: 0x%x\n", idx, ak4531->regs[idx]);
-}
-
-#endif
-
-/*
- *
- */
-
-#define AK4531_SINGLE(xname, xindex, reg, shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
-  .info = snd_ak4531_info_single, \
-  .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \
-  .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22) }
-#define AK4531_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv)    \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
-  .name = xname, .index = xindex, \
-  .info = snd_ak4531_info_single, \
-  .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \
-  .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22), \
-  .tlv = { .p = (xtlv) } }
-
-static int snd_ak4531_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-       int mask = (kcontrol->private_value >> 24) & 0xff;
-
-       uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
-       uinfo->count = 1;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = mask;
-       return 0;
-}
-static int snd_ak4531_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
-       int reg = kcontrol->private_value & 0xff;
-       int shift = (kcontrol->private_value >> 16) & 0x07;
-       int mask = (kcontrol->private_value >> 24) & 0xff;
-       int invert = (kcontrol->private_value >> 22) & 1;
-       int val;
-
-       mutex_lock(&ak4531->reg_mutex);
-       val = (ak4531->regs[reg] >> shift) & mask;
-       mutex_unlock(&ak4531->reg_mutex);
-       if (invert) {
-               val = mask - val;
-       }
-       ucontrol->value.integer.value[0] = val;
-       return 0;
-}
-
-static int snd_ak4531_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
-       int reg = kcontrol->private_value & 0xff;
-       int shift = (kcontrol->private_value >> 16) & 0x07;
-       int mask = (kcontrol->private_value >> 24) & 0xff;
-       int invert = (kcontrol->private_value >> 22) & 1;
-       int change;
-       int val;
-
-       val = ucontrol->value.integer.value[0] & mask;
-       if (invert) {
-               val = mask - val;
-       }
-       val <<= shift;
-       mutex_lock(&ak4531->reg_mutex);
-       val = (ak4531->regs[reg] & ~(mask << shift)) | val;
-       change = val != ak4531->regs[reg];
-       ak4531->write(ak4531, reg, ak4531->regs[reg] = val);
-       mutex_unlock(&ak4531->reg_mutex);
-       return change;
-}
-
-#define AK4531_DOUBLE(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
-  .info = snd_ak4531_info_double, \
-  .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \
-  .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22) }
-#define AK4531_DOUBLE_TLV(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert, xtlv) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
-  .name = xname, .index = xindex, \
-  .info = snd_ak4531_info_double, \
-  .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \
-  .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22), \
-  .tlv = { .p = (xtlv) } }
-
-static int snd_ak4531_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-       int mask = (kcontrol->private_value >> 24) & 0xff;
-
-       uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
-       uinfo->count = 2;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = mask;
-       return 0;
-}
-static int snd_ak4531_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
-       int left_reg = kcontrol->private_value & 0xff;
-       int right_reg = (kcontrol->private_value >> 8) & 0xff;
-       int left_shift = (kcontrol->private_value >> 16) & 0x07;
-       int right_shift = (kcontrol->private_value >> 19) & 0x07;
-       int mask = (kcontrol->private_value >> 24) & 0xff;
-       int invert = (kcontrol->private_value >> 22) & 1;
-       int left, right;
-
-       mutex_lock(&ak4531->reg_mutex);
-       left = (ak4531->regs[left_reg] >> left_shift) & mask;
-       right = (ak4531->regs[right_reg] >> right_shift) & mask;
-       mutex_unlock(&ak4531->reg_mutex);
-       if (invert) {
-               left = mask - left;
-               right = mask - right;
-       }
-       ucontrol->value.integer.value[0] = left;
-       ucontrol->value.integer.value[1] = right;
-       return 0;
-}
-
-static int snd_ak4531_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
-       int left_reg = kcontrol->private_value & 0xff;
-       int right_reg = (kcontrol->private_value >> 8) & 0xff;
-       int left_shift = (kcontrol->private_value >> 16) & 0x07;
-       int right_shift = (kcontrol->private_value >> 19) & 0x07;
-       int mask = (kcontrol->private_value >> 24) & 0xff;
-       int invert = (kcontrol->private_value >> 22) & 1;
-       int change;
-       int left, right;
-
-       left = ucontrol->value.integer.value[0] & mask;
-       right = ucontrol->value.integer.value[1] & mask;
-       if (invert) {
-               left = mask - left;
-               right = mask - right;
-       }
-       left <<= left_shift;
-       right <<= right_shift;
-       mutex_lock(&ak4531->reg_mutex);
-       if (left_reg == right_reg) {
-               left = (ak4531->regs[left_reg] & ~((mask << left_shift) | (mask << right_shift))) | left | right;
-               change = left != ak4531->regs[left_reg];
-               ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left);
-       } else {
-               left = (ak4531->regs[left_reg] & ~(mask << left_shift)) | left;
-               right = (ak4531->regs[right_reg] & ~(mask << right_shift)) | right;
-               change = left != ak4531->regs[left_reg] || right != ak4531->regs[right_reg];
-               ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left);
-               ak4531->write(ak4531, right_reg, ak4531->regs[right_reg] = right);
-       }
-       mutex_unlock(&ak4531->reg_mutex);
-       return change;
-}
-
-#define AK4531_INPUT_SW(xname, xindex, reg1, reg2, left_shift, right_shift) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
-  .info = snd_ak4531_info_input_sw, \
-  .get = snd_ak4531_get_input_sw, .put = snd_ak4531_put_input_sw, \
-  .private_value = reg1 | (reg2 << 8) | (left_shift << 16) | (right_shift << 24) }
-
-static int snd_ak4531_info_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       uinfo->count = 4;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 1;
-       return 0;
-}
-static int snd_ak4531_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
-       int reg1 = kcontrol->private_value & 0xff;
-       int reg2 = (kcontrol->private_value >> 8) & 0xff;
-       int left_shift = (kcontrol->private_value >> 16) & 0x0f;
-       int right_shift = (kcontrol->private_value >> 24) & 0x0f;
-
-       mutex_lock(&ak4531->reg_mutex);
-       ucontrol->value.integer.value[0] = (ak4531->regs[reg1] >> left_shift) & 1;
-       ucontrol->value.integer.value[1] = (ak4531->regs[reg2] >> left_shift) & 1;
-       ucontrol->value.integer.value[2] = (ak4531->regs[reg1] >> right_shift) & 1;
-       ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1;
-       mutex_unlock(&ak4531->reg_mutex);
-       return 0;
-}
-
-static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
-       int reg1 = kcontrol->private_value & 0xff;
-       int reg2 = (kcontrol->private_value >> 8) & 0xff;
-       int left_shift = (kcontrol->private_value >> 16) & 0x0f;
-       int right_shift = (kcontrol->private_value >> 24) & 0x0f;
-       int change;
-       int val1, val2;
-
-       mutex_lock(&ak4531->reg_mutex);
-       val1 = ak4531->regs[reg1] & ~((1 << left_shift) | (1 << right_shift));
-       val2 = ak4531->regs[reg2] & ~((1 << left_shift) | (1 << right_shift));
-       val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift;
-       val2 |= (ucontrol->value.integer.value[1] & 1) << left_shift;
-       val1 |= (ucontrol->value.integer.value[2] & 1) << right_shift;
-       val2 |= (ucontrol->value.integer.value[3] & 1) << right_shift;
-       change = val1 != ak4531->regs[reg1] || val2 != ak4531->regs[reg2];
-       ak4531->write(ak4531, reg1, ak4531->regs[reg1] = val1);
-       ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2);
-       mutex_unlock(&ak4531->reg_mutex);
-       return change;
-}
-
-static const DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0);
-static const DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0);
-static const DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0);
-
-static struct snd_kcontrol_new snd_ak4531_controls[] = {
-
-AK4531_DOUBLE_TLV("Master Playback Switch", 0,
-                 AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1,
-                 db_scale_master),
-AK4531_DOUBLE("Master Playback Volume", 0, AK4531_LMASTER, AK4531_RMASTER, 0, 0, 0x1f, 1),
-
-AK4531_SINGLE_TLV("Master Mono Playback Switch", 0, AK4531_MONO_OUT, 7, 1, 1,
-                 db_scale_mono),
-AK4531_SINGLE("Master Mono Playback Volume", 0, AK4531_MONO_OUT, 0, 0x07, 1),
-
-AK4531_DOUBLE("PCM Switch", 0, AK4531_LVOICE, AK4531_RVOICE, 7, 7, 1, 1),
-AK4531_DOUBLE_TLV("PCM Volume", 0, AK4531_LVOICE, AK4531_RVOICE, 0, 0, 0x1f, 1,
-                 db_scale_input),
-AK4531_DOUBLE("PCM Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 3, 2, 1, 0),
-AK4531_DOUBLE("PCM Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 2, 2, 1, 0),
-
-AK4531_DOUBLE("PCM Switch", 1, AK4531_LFM, AK4531_RFM, 7, 7, 1, 1),
-AK4531_DOUBLE_TLV("PCM Volume", 1, AK4531_LFM, AK4531_RFM, 0, 0, 0x1f, 1,
-                 db_scale_input),
-AK4531_DOUBLE("PCM Playback Switch", 1, AK4531_OUT_SW1, AK4531_OUT_SW1, 6, 5, 1, 0),
-AK4531_INPUT_SW("PCM Capture Route", 1, AK4531_LIN_SW1, AK4531_RIN_SW1, 6, 5),
-
-AK4531_DOUBLE("CD Switch", 0, AK4531_LCD, AK4531_RCD, 7, 7, 1, 1),
-AK4531_DOUBLE_TLV("CD Volume", 0, AK4531_LCD, AK4531_RCD, 0, 0, 0x1f, 1,
-                 db_scale_input),
-AK4531_DOUBLE("CD Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 2, 1, 1, 0),
-AK4531_INPUT_SW("CD Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 2, 1),
-
-AK4531_DOUBLE("Line Switch", 0, AK4531_LLINE, AK4531_RLINE, 7, 7, 1, 1),
-AK4531_DOUBLE_TLV("Line Volume", 0, AK4531_LLINE, AK4531_RLINE, 0, 0, 0x1f, 1,
-                 db_scale_input),
-AK4531_DOUBLE("Line Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 4, 3, 1, 0),
-AK4531_INPUT_SW("Line Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 4, 3),
-
-AK4531_DOUBLE("Aux Switch", 0, AK4531_LAUXA, AK4531_RAUXA, 7, 7, 1, 1),
-AK4531_DOUBLE_TLV("Aux Volume", 0, AK4531_LAUXA, AK4531_RAUXA, 0, 0, 0x1f, 1,
-                 db_scale_input),
-AK4531_DOUBLE("Aux Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 5, 4, 1, 0),
-AK4531_INPUT_SW("Aux Capture Route", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 4, 3),
-
-AK4531_SINGLE("Mono Switch", 0, AK4531_MONO1, 7, 1, 1),
-AK4531_SINGLE_TLV("Mono Volume", 0, AK4531_MONO1, 0, 0x1f, 1, db_scale_input),
-AK4531_SINGLE("Mono Playback Switch", 0, AK4531_OUT_SW2, 0, 1, 0),
-AK4531_DOUBLE("Mono Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 0, 0, 1, 0),
-
-AK4531_SINGLE("Mono Switch", 1, AK4531_MONO2, 7, 1, 1),
-AK4531_SINGLE_TLV("Mono Volume", 1, AK4531_MONO2, 0, 0x1f, 1, db_scale_input),
-AK4531_SINGLE("Mono Playback Switch", 1, AK4531_OUT_SW2, 1, 1, 0),
-AK4531_DOUBLE("Mono Capture Switch", 1, AK4531_LIN_SW2, AK4531_RIN_SW2, 1, 1, 1, 0),
-
-AK4531_SINGLE_TLV("Mic Volume", 0, AK4531_MIC, 0, 0x1f, 1, db_scale_input),
-AK4531_SINGLE("Mic Switch", 0, AK4531_MIC, 7, 1, 1),
-AK4531_SINGLE("Mic Playback Switch", 0, AK4531_OUT_SW1, 0, 1, 0),
-AK4531_DOUBLE("Mic Capture Switch", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 0, 0, 1, 0),
-
-AK4531_DOUBLE("Mic Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 7, 7, 1, 0),
-AK4531_DOUBLE("Mono1 Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 6, 6, 1, 0),
-AK4531_DOUBLE("Mono2 Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 5, 5, 1, 0),
-
-AK4531_SINGLE("AD Input Select", 0, AK4531_AD_IN, 0, 1, 0),
-AK4531_SINGLE("Mic Boost (+30dB)", 0, AK4531_MIC_GAIN, 0, 1, 0)
-};
-
-static int snd_ak4531_free(struct snd_ak4531 *ak4531)
-{
-       if (ak4531) {
-               if (ak4531->private_free)
-                       ak4531->private_free(ak4531);
-               kfree(ak4531);
-       }
-       return 0;
-}
-
-static int snd_ak4531_dev_free(struct snd_device *device)
-{
-       struct snd_ak4531 *ak4531 = device->device_data;
-       return snd_ak4531_free(ak4531);
-}
-
-static u8 snd_ak4531_initial_map[0x19 + 1] = {
-       0x9f,           /* 00: Master Volume Lch */
-       0x9f,           /* 01: Master Volume Rch */
-       0x9f,           /* 02: Voice Volume Lch */
-       0x9f,           /* 03: Voice Volume Rch */
-       0x9f,           /* 04: FM Volume Lch */
-       0x9f,           /* 05: FM Volume Rch */
-       0x9f,           /* 06: CD Audio Volume Lch */
-       0x9f,           /* 07: CD Audio Volume Rch */
-       0x9f,           /* 08: Line Volume Lch */
-       0x9f,           /* 09: Line Volume Rch */
-       0x9f,           /* 0a: Aux Volume Lch */
-       0x9f,           /* 0b: Aux Volume Rch */
-       0x9f,           /* 0c: Mono1 Volume */
-       0x9f,           /* 0d: Mono2 Volume */
-       0x9f,           /* 0e: Mic Volume */
-       0x87,           /* 0f: Mono-out Volume */
-       0x00,           /* 10: Output Mixer SW1 */
-       0x00,           /* 11: Output Mixer SW2 */
-       0x00,           /* 12: Lch Input Mixer SW1 */
-       0x00,           /* 13: Rch Input Mixer SW1 */
-       0x00,           /* 14: Lch Input Mixer SW2 */
-       0x00,           /* 15: Rch Input Mixer SW2 */
-       0x00,           /* 16: Reset & Power Down */
-       0x00,           /* 17: Clock Select */
-       0x00,           /* 18: AD Input Select */
-       0x01            /* 19: Mic Amp Setup */
-};
-
-int snd_ak4531_mixer(struct snd_card *card, struct snd_ak4531 *_ak4531,
-                    struct snd_ak4531 **rak4531)
-{
-       unsigned int idx;
-       int err;
-       struct snd_ak4531 *ak4531;
-       static struct snd_device_ops ops = {
-               .dev_free =     snd_ak4531_dev_free,
-       };
-
-       snd_assert(rak4531 != NULL, return -EINVAL);
-       *rak4531 = NULL;
-       snd_assert(card != NULL && _ak4531 != NULL, return -EINVAL);
-       ak4531 = kzalloc(sizeof(*ak4531), GFP_KERNEL);
-       if (ak4531 == NULL)
-               return -ENOMEM;
-       *ak4531 = *_ak4531;
-       mutex_init(&ak4531->reg_mutex);
-       if ((err = snd_component_add(card, "AK4531")) < 0) {
-               snd_ak4531_free(ak4531);
-               return err;
-       }
-       strcpy(card->mixername, "Asahi Kasei AK4531");
-       ak4531->write(ak4531, AK4531_RESET, 0x03);      /* no RST, PD */
-       udelay(100);
-       ak4531->write(ak4531, AK4531_CLOCK, 0x00);      /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off LRCLK2 PLL */
-       for (idx = 0; idx <= 0x19; idx++) {
-               if (idx == AK4531_RESET || idx == AK4531_CLOCK)
-                       continue;
-               ak4531->write(ak4531, idx, ak4531->regs[idx] = snd_ak4531_initial_map[idx]);    /* recording source is mixer */
-       }
-       for (idx = 0; idx < ARRAY_SIZE(snd_ak4531_controls); idx++) {
-               if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ak4531_controls[idx], ak4531))) < 0) {
-                       snd_ak4531_free(ak4531);
-                       return err;
-               }
-       }
-       snd_ak4531_proc_init(card, ak4531);
-       if ((err = snd_device_new(card, SNDRV_DEV_CODEC, ak4531, &ops)) < 0) {
-               snd_ak4531_free(ak4531);
-               return err;
-       }
-
-#if 0
-       snd_ak4531_dump(ak4531);
-#endif
-       *rak4531 = ak4531;
-       return 0;
-}
-
-/*
- * power management
- */
-#ifdef CONFIG_PM
-void snd_ak4531_suspend(struct snd_ak4531 *ak4531)
-{
-       /* mute */
-       ak4531->write(ak4531, AK4531_LMASTER, 0x9f);
-       ak4531->write(ak4531, AK4531_RMASTER, 0x9f);
-       /* powerdown */
-       ak4531->write(ak4531, AK4531_RESET, 0x01);
-}
-
-void snd_ak4531_resume(struct snd_ak4531 *ak4531)
-{
-       int idx;
-
-       /* initialize */
-       ak4531->write(ak4531, AK4531_RESET, 0x03);
-       udelay(100);
-       ak4531->write(ak4531, AK4531_CLOCK, 0x00);
-       /* restore mixer registers */
-       for (idx = 0; idx <= 0x19; idx++) {
-               if (idx == AK4531_RESET || idx == AK4531_CLOCK)
-                       continue;
-               ak4531->write(ak4531, idx, ak4531->regs[idx]);
-       }
-}
-#endif
-
-#ifdef CONFIG_PROC_FS
-/*
- * /proc interface
- */
-
-static void snd_ak4531_proc_read(struct snd_info_entry *entry, 
-                                struct snd_info_buffer *buffer)
-{
-       struct snd_ak4531 *ak4531 = entry->private_data;
-
-       snd_iprintf(buffer, "Asahi Kasei AK4531\n\n");
-       snd_iprintf(buffer, "Recording source   : %s\n"
-                   "MIC gain           : %s\n",
-                   ak4531->regs[AK4531_AD_IN] & 1 ? "external" : "mixer",
-                   ak4531->regs[AK4531_MIC_GAIN] & 1 ? "+30dB" : "+0dB");
-}
-
-static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531)
-{
-       struct snd_info_entry *entry;
-
-       if (! snd_card_proc_new(card, "ak4531", &entry))
-               snd_info_set_text_ops(entry, ak4531, snd_ak4531_proc_read);
-}
-#endif
-
-EXPORT_SYMBOL(snd_ak4531_mixer);
-#ifdef CONFIG_PM
-EXPORT_SYMBOL(snd_ak4531_suspend);
-EXPORT_SYMBOL(snd_ak4531_resume);
-#endif
-
-/*
- *  INIT part
- */
-
-static int __init alsa_ak4531_init(void)
-{
-       return 0;
-}
-
-static void __exit alsa_ak4531_exit(void)
-{
-}
-
-module_init(alsa_ak4531_init)
-module_exit(alsa_ak4531_exit)
diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c
new file mode 100644 (file)
index 0000000..33d37b1
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+ *  Universal routines for AK4531 codec
+ *
+ *
+ *   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/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+
+#include <sound/core.h>
+#include <sound/ak4531_codec.h>
+#include <sound/tlv.h>
+
+/*
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
+MODULE_DESCRIPTION("Universal routines for AK4531 codec");
+MODULE_LICENSE("GPL");
+*/
+
+#ifdef CONFIG_PROC_FS
+static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531);
+#else
+#define snd_ak4531_proc_init(card,ak)
+#endif
+
+/*
+ *
+ */
+#if 0
+
+static void snd_ak4531_dump(struct snd_ak4531 *ak4531)
+{
+       int idx;
+       
+       for (idx = 0; idx < 0x19; idx++)
+               printk("ak4531 0x%x: 0x%x\n", idx, ak4531->regs[idx]);
+}
+
+#endif
+
+/*
+ *
+ */
+
+#define AK4531_SINGLE(xname, xindex, reg, shift, mask, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
+  .info = snd_ak4531_info_single, \
+  .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \
+  .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22) }
+#define AK4531_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv)    \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
+  .name = xname, .index = xindex, \
+  .info = snd_ak4531_info_single, \
+  .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \
+  .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22), \
+  .tlv = { .p = (xtlv) } }
+
+static int snd_ak4531_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+{
+       int mask = (kcontrol->private_value >> 24) & 0xff;
+
+       uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = mask;
+       return 0;
+}
+static int snd_ak4531_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
+       int reg = kcontrol->private_value & 0xff;
+       int shift = (kcontrol->private_value >> 16) & 0x07;
+       int mask = (kcontrol->private_value >> 24) & 0xff;
+       int invert = (kcontrol->private_value >> 22) & 1;
+       int val;
+
+       mutex_lock(&ak4531->reg_mutex);
+       val = (ak4531->regs[reg] >> shift) & mask;
+       mutex_unlock(&ak4531->reg_mutex);
+       if (invert) {
+               val = mask - val;
+       }
+       ucontrol->value.integer.value[0] = val;
+       return 0;
+}
+
+static int snd_ak4531_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
+       int reg = kcontrol->private_value & 0xff;
+       int shift = (kcontrol->private_value >> 16) & 0x07;
+       int mask = (kcontrol->private_value >> 24) & 0xff;
+       int invert = (kcontrol->private_value >> 22) & 1;
+       int change;
+       int val;
+
+       val = ucontrol->value.integer.value[0] & mask;
+       if (invert) {
+               val = mask - val;
+       }
+       val <<= shift;
+       mutex_lock(&ak4531->reg_mutex);
+       val = (ak4531->regs[reg] & ~(mask << shift)) | val;
+       change = val != ak4531->regs[reg];
+       ak4531->write(ak4531, reg, ak4531->regs[reg] = val);
+       mutex_unlock(&ak4531->reg_mutex);
+       return change;
+}
+
+#define AK4531_DOUBLE(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
+  .info = snd_ak4531_info_double, \
+  .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \
+  .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22) }
+#define AK4531_DOUBLE_TLV(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert, xtlv) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
+  .name = xname, .index = xindex, \
+  .info = snd_ak4531_info_double, \
+  .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \
+  .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22), \
+  .tlv = { .p = (xtlv) } }
+
+static int snd_ak4531_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+{
+       int mask = (kcontrol->private_value >> 24) & 0xff;
+
+       uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = mask;
+       return 0;
+}
+static int snd_ak4531_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
+       int left_reg = kcontrol->private_value & 0xff;
+       int right_reg = (kcontrol->private_value >> 8) & 0xff;
+       int left_shift = (kcontrol->private_value >> 16) & 0x07;
+       int right_shift = (kcontrol->private_value >> 19) & 0x07;
+       int mask = (kcontrol->private_value >> 24) & 0xff;
+       int invert = (kcontrol->private_value >> 22) & 1;
+       int left, right;
+
+       mutex_lock(&ak4531->reg_mutex);
+       left = (ak4531->regs[left_reg] >> left_shift) & mask;
+       right = (ak4531->regs[right_reg] >> right_shift) & mask;
+       mutex_unlock(&ak4531->reg_mutex);
+       if (invert) {
+               left = mask - left;
+               right = mask - right;
+       }
+       ucontrol->value.integer.value[0] = left;
+       ucontrol->value.integer.value[1] = right;
+       return 0;
+}
+
+static int snd_ak4531_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
+       int left_reg = kcontrol->private_value & 0xff;
+       int right_reg = (kcontrol->private_value >> 8) & 0xff;
+       int left_shift = (kcontrol->private_value >> 16) & 0x07;
+       int right_shift = (kcontrol->private_value >> 19) & 0x07;
+       int mask = (kcontrol->private_value >> 24) & 0xff;
+       int invert = (kcontrol->private_value >> 22) & 1;
+       int change;
+       int left, right;
+
+       left = ucontrol->value.integer.value[0] & mask;
+       right = ucontrol->value.integer.value[1] & mask;
+       if (invert) {
+               left = mask - left;
+               right = mask - right;
+       }
+       left <<= left_shift;
+       right <<= right_shift;
+       mutex_lock(&ak4531->reg_mutex);
+       if (left_reg == right_reg) {
+               left = (ak4531->regs[left_reg] & ~((mask << left_shift) | (mask << right_shift))) | left | right;
+               change = left != ak4531->regs[left_reg];
+               ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left);
+       } else {
+               left = (ak4531->regs[left_reg] & ~(mask << left_shift)) | left;
+               right = (ak4531->regs[right_reg] & ~(mask << right_shift)) | right;
+               change = left != ak4531->regs[left_reg] || right != ak4531->regs[right_reg];
+               ak4531->write(ak4531, left_reg, ak4531->regs[left_reg] = left);
+               ak4531->write(ak4531, right_reg, ak4531->regs[right_reg] = right);
+       }
+       mutex_unlock(&ak4531->reg_mutex);
+       return change;
+}
+
+#define AK4531_INPUT_SW(xname, xindex, reg1, reg2, left_shift, right_shift) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
+  .info = snd_ak4531_info_input_sw, \
+  .get = snd_ak4531_get_input_sw, .put = snd_ak4531_put_input_sw, \
+  .private_value = reg1 | (reg2 << 8) | (left_shift << 16) | (right_shift << 24) }
+
+static int snd_ak4531_info_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 4;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+static int snd_ak4531_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
+       int reg1 = kcontrol->private_value & 0xff;
+       int reg2 = (kcontrol->private_value >> 8) & 0xff;
+       int left_shift = (kcontrol->private_value >> 16) & 0x0f;
+       int right_shift = (kcontrol->private_value >> 24) & 0x0f;
+
+       mutex_lock(&ak4531->reg_mutex);
+       ucontrol->value.integer.value[0] = (ak4531->regs[reg1] >> left_shift) & 1;
+       ucontrol->value.integer.value[1] = (ak4531->regs[reg2] >> left_shift) & 1;
+       ucontrol->value.integer.value[2] = (ak4531->regs[reg1] >> right_shift) & 1;
+       ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1;
+       mutex_unlock(&ak4531->reg_mutex);
+       return 0;
+}
+
+static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
+       int reg1 = kcontrol->private_value & 0xff;
+       int reg2 = (kcontrol->private_value >> 8) & 0xff;
+       int left_shift = (kcontrol->private_value >> 16) & 0x0f;
+       int right_shift = (kcontrol->private_value >> 24) & 0x0f;
+       int change;
+       int val1, val2;
+
+       mutex_lock(&ak4531->reg_mutex);
+       val1 = ak4531->regs[reg1] & ~((1 << left_shift) | (1 << right_shift));
+       val2 = ak4531->regs[reg2] & ~((1 << left_shift) | (1 << right_shift));
+       val1 |= (ucontrol->value.integer.value[0] & 1) << left_shift;
+       val2 |= (ucontrol->value.integer.value[1] & 1) << left_shift;
+       val1 |= (ucontrol->value.integer.value[2] & 1) << right_shift;
+       val2 |= (ucontrol->value.integer.value[3] & 1) << right_shift;
+       change = val1 != ak4531->regs[reg1] || val2 != ak4531->regs[reg2];
+       ak4531->write(ak4531, reg1, ak4531->regs[reg1] = val1);
+       ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2);
+       mutex_unlock(&ak4531->reg_mutex);
+       return change;
+}
+
+static const DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0);
+
+static struct snd_kcontrol_new snd_ak4531_controls[] __devinitdata = {
+
+AK4531_DOUBLE_TLV("Master Playback Switch", 0,
+                 AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1,
+                 db_scale_master),
+AK4531_DOUBLE("Master Playback Volume", 0, AK4531_LMASTER, AK4531_RMASTER, 0, 0, 0x1f, 1),
+
+AK4531_SINGLE_TLV("Master Mono Playback Switch", 0, AK4531_MONO_OUT, 7, 1, 1,
+                 db_scale_mono),
+AK4531_SINGLE("Master Mono Playback Volume", 0, AK4531_MONO_OUT, 0, 0x07, 1),
+
+AK4531_DOUBLE("PCM Switch", 0, AK4531_LVOICE, AK4531_RVOICE, 7, 7, 1, 1),
+AK4531_DOUBLE_TLV("PCM Volume", 0, AK4531_LVOICE, AK4531_RVOICE, 0, 0, 0x1f, 1,
+                 db_scale_input),
+AK4531_DOUBLE("PCM Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 3, 2, 1, 0),
+AK4531_DOUBLE("PCM Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 2, 2, 1, 0),
+
+AK4531_DOUBLE("PCM Switch", 1, AK4531_LFM, AK4531_RFM, 7, 7, 1, 1),
+AK4531_DOUBLE_TLV("PCM Volume", 1, AK4531_LFM, AK4531_RFM, 0, 0, 0x1f, 1,
+                 db_scale_input),
+AK4531_DOUBLE("PCM Playback Switch", 1, AK4531_OUT_SW1, AK4531_OUT_SW1, 6, 5, 1, 0),
+AK4531_INPUT_SW("PCM Capture Route", 1, AK4531_LIN_SW1, AK4531_RIN_SW1, 6, 5),
+
+AK4531_DOUBLE("CD Switch", 0, AK4531_LCD, AK4531_RCD, 7, 7, 1, 1),
+AK4531_DOUBLE_TLV("CD Volume", 0, AK4531_LCD, AK4531_RCD, 0, 0, 0x1f, 1,
+                 db_scale_input),
+AK4531_DOUBLE("CD Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 2, 1, 1, 0),
+AK4531_INPUT_SW("CD Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 2, 1),
+
+AK4531_DOUBLE("Line Switch", 0, AK4531_LLINE, AK4531_RLINE, 7, 7, 1, 1),
+AK4531_DOUBLE_TLV("Line Volume", 0, AK4531_LLINE, AK4531_RLINE, 0, 0, 0x1f, 1,
+                 db_scale_input),
+AK4531_DOUBLE("Line Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 4, 3, 1, 0),
+AK4531_INPUT_SW("Line Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 4, 3),
+
+AK4531_DOUBLE("Aux Switch", 0, AK4531_LAUXA, AK4531_RAUXA, 7, 7, 1, 1),
+AK4531_DOUBLE_TLV("Aux Volume", 0, AK4531_LAUXA, AK4531_RAUXA, 0, 0, 0x1f, 1,
+                 db_scale_input),
+AK4531_DOUBLE("Aux Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 5, 4, 1, 0),
+AK4531_INPUT_SW("Aux Capture Route", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 4, 3),
+
+AK4531_SINGLE("Mono Switch", 0, AK4531_MONO1, 7, 1, 1),
+AK4531_SINGLE_TLV("Mono Volume", 0, AK4531_MONO1, 0, 0x1f, 1, db_scale_input),
+AK4531_SINGLE("Mono Playback Switch", 0, AK4531_OUT_SW2, 0, 1, 0),
+AK4531_DOUBLE("Mono Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 0, 0, 1, 0),
+
+AK4531_SINGLE("Mono Switch", 1, AK4531_MONO2, 7, 1, 1),
+AK4531_SINGLE_TLV("Mono Volume", 1, AK4531_MONO2, 0, 0x1f, 1, db_scale_input),
+AK4531_SINGLE("Mono Playback Switch", 1, AK4531_OUT_SW2, 1, 1, 0),
+AK4531_DOUBLE("Mono Capture Switch", 1, AK4531_LIN_SW2, AK4531_RIN_SW2, 1, 1, 1, 0),
+
+AK4531_SINGLE_TLV("Mic Volume", 0, AK4531_MIC, 0, 0x1f, 1, db_scale_input),
+AK4531_SINGLE("Mic Switch", 0, AK4531_MIC, 7, 1, 1),
+AK4531_SINGLE("Mic Playback Switch", 0, AK4531_OUT_SW1, 0, 1, 0),
+AK4531_DOUBLE("Mic Capture Switch", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 0, 0, 1, 0),
+
+AK4531_DOUBLE("Mic Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 7, 7, 1, 0),
+AK4531_DOUBLE("Mono1 Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 6, 6, 1, 0),
+AK4531_DOUBLE("Mono2 Bypass Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 5, 5, 1, 0),
+
+AK4531_SINGLE("AD Input Select", 0, AK4531_AD_IN, 0, 1, 0),
+AK4531_SINGLE("Mic Boost (+30dB)", 0, AK4531_MIC_GAIN, 0, 1, 0)
+};
+
+static int snd_ak4531_free(struct snd_ak4531 *ak4531)
+{
+       if (ak4531) {
+               if (ak4531->private_free)
+                       ak4531->private_free(ak4531);
+               kfree(ak4531);
+       }
+       return 0;
+}
+
+static int snd_ak4531_dev_free(struct snd_device *device)
+{
+       struct snd_ak4531 *ak4531 = device->device_data;
+       return snd_ak4531_free(ak4531);
+}
+
+static u8 snd_ak4531_initial_map[0x19 + 1] = {
+       0x9f,           /* 00: Master Volume Lch */
+       0x9f,           /* 01: Master Volume Rch */
+       0x9f,           /* 02: Voice Volume Lch */
+       0x9f,           /* 03: Voice Volume Rch */
+       0x9f,           /* 04: FM Volume Lch */
+       0x9f,           /* 05: FM Volume Rch */
+       0x9f,           /* 06: CD Audio Volume Lch */
+       0x9f,           /* 07: CD Audio Volume Rch */
+       0x9f,           /* 08: Line Volume Lch */
+       0x9f,           /* 09: Line Volume Rch */
+       0x9f,           /* 0a: Aux Volume Lch */
+       0x9f,           /* 0b: Aux Volume Rch */
+       0x9f,           /* 0c: Mono1 Volume */
+       0x9f,           /* 0d: Mono2 Volume */
+       0x9f,           /* 0e: Mic Volume */
+       0x87,           /* 0f: Mono-out Volume */
+       0x00,           /* 10: Output Mixer SW1 */
+       0x00,           /* 11: Output Mixer SW2 */
+       0x00,           /* 12: Lch Input Mixer SW1 */
+       0x00,           /* 13: Rch Input Mixer SW1 */
+       0x00,           /* 14: Lch Input Mixer SW2 */
+       0x00,           /* 15: Rch Input Mixer SW2 */
+       0x00,           /* 16: Reset & Power Down */
+       0x00,           /* 17: Clock Select */
+       0x00,           /* 18: AD Input Select */
+       0x01            /* 19: Mic Amp Setup */
+};
+
+int __devinit snd_ak4531_mixer(struct snd_card *card,
+                              struct snd_ak4531 *_ak4531,
+                              struct snd_ak4531 **rak4531)
+{
+       unsigned int idx;
+       int err;
+       struct snd_ak4531 *ak4531;
+       static struct snd_device_ops ops = {
+               .dev_free =     snd_ak4531_dev_free,
+       };
+
+       snd_assert(rak4531 != NULL, return -EINVAL);
+       *rak4531 = NULL;
+       snd_assert(card != NULL && _ak4531 != NULL, return -EINVAL);
+       ak4531 = kzalloc(sizeof(*ak4531), GFP_KERNEL);
+       if (ak4531 == NULL)
+               return -ENOMEM;
+       *ak4531 = *_ak4531;
+       mutex_init(&ak4531->reg_mutex);
+       if ((err = snd_component_add(card, "AK4531")) < 0) {
+               snd_ak4531_free(ak4531);
+               return err;
+       }
+       strcpy(card->mixername, "Asahi Kasei AK4531");
+       ak4531->write(ak4531, AK4531_RESET, 0x03);      /* no RST, PD */
+       udelay(100);
+       ak4531->write(ak4531, AK4531_CLOCK, 0x00);      /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off LRCLK2 PLL */
+       for (idx = 0; idx <= 0x19; idx++) {
+               if (idx == AK4531_RESET || idx == AK4531_CLOCK)
+                       continue;
+               ak4531->write(ak4531, idx, ak4531->regs[idx] = snd_ak4531_initial_map[idx]);    /* recording source is mixer */
+       }
+       for (idx = 0; idx < ARRAY_SIZE(snd_ak4531_controls); idx++) {
+               if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ak4531_controls[idx], ak4531))) < 0) {
+                       snd_ak4531_free(ak4531);
+                       return err;
+               }
+       }
+       snd_ak4531_proc_init(card, ak4531);
+       if ((err = snd_device_new(card, SNDRV_DEV_CODEC, ak4531, &ops)) < 0) {
+               snd_ak4531_free(ak4531);
+               return err;
+       }
+
+#if 0
+       snd_ak4531_dump(ak4531);
+#endif
+       *rak4531 = ak4531;
+       return 0;
+}
+
+/*
+ * power management
+ */
+#ifdef CONFIG_PM
+void snd_ak4531_suspend(struct snd_ak4531 *ak4531)
+{
+       /* mute */
+       ak4531->write(ak4531, AK4531_LMASTER, 0x9f);
+       ak4531->write(ak4531, AK4531_RMASTER, 0x9f);
+       /* powerdown */
+       ak4531->write(ak4531, AK4531_RESET, 0x01);
+}
+
+void snd_ak4531_resume(struct snd_ak4531 *ak4531)
+{
+       int idx;
+
+       /* initialize */
+       ak4531->write(ak4531, AK4531_RESET, 0x03);
+       udelay(100);
+       ak4531->write(ak4531, AK4531_CLOCK, 0x00);
+       /* restore mixer registers */
+       for (idx = 0; idx <= 0x19; idx++) {
+               if (idx == AK4531_RESET || idx == AK4531_CLOCK)
+                       continue;
+               ak4531->write(ak4531, idx, ak4531->regs[idx]);
+       }
+}
+#endif
+
+#ifdef CONFIG_PROC_FS
+/*
+ * /proc interface
+ */
+
+static void snd_ak4531_proc_read(struct snd_info_entry *entry, 
+                                struct snd_info_buffer *buffer)
+{
+       struct snd_ak4531 *ak4531 = entry->private_data;
+
+       snd_iprintf(buffer, "Asahi Kasei AK4531\n\n");
+       snd_iprintf(buffer, "Recording source   : %s\n"
+                   "MIC gain           : %s\n",
+                   ak4531->regs[AK4531_AD_IN] & 1 ? "external" : "mixer",
+                   ak4531->regs[AK4531_MIC_GAIN] & 1 ? "+30dB" : "+0dB");
+}
+
+static void __devinit
+snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531)
+{
+       struct snd_info_entry *entry;
+
+       if (! snd_card_proc_new(card, "ak4531", &entry))
+               snd_info_set_text_ops(entry, ak4531, snd_ak4531_proc_read);
+}
+#endif
index bc212f41a38a611a84ee679502813377208602e1..e291aa59742e7c31c85e8f220a5248c661916c80 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: au88x0_game.c,v 1.9 2003/09/22 03:51:28 mjander Exp $
- *
  *  Manuel Jander.
  *
  *  Based on the work of:
index 5f63af6b88a29d35c1c906b6e1e34d88f07780a8..22f18f3cfbc9f45d1b7921aa25ab2399029fe663 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168).
- *  Copyright (C) 2002, 2005, 2006, 2007 by Andreas Mohr <andi AT lisas.de>
+ *  Copyright (C) 2002, 2005 - 2008 by Andreas Mohr <andi AT lisas.de>
  *
  *  Framework borrowed from Bart Hartgers's als4000.c.
  *  Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801),
  *  (3 weeks' worth of evenings filled with driver work).
  *  (and no, I did NOT go the easy way: to pick up a SB PCI128 for 9 Euros)
  *
+ *  It is quite likely that the AZF3328 chip is the PCI cousin of the
+ *  AZF3318 ("azt1020 pnp", "MM Pro 16") ISA chip, given very similar specs.
+ *
  *  The AZF3328 chip (note: AZF3328, *not* AZT3328, that's just the driver name
- *  for compatibility reasons) has the following features:
+ *  for compatibility reasons) from Azfin (joint-venture of Aztech and Fincitec,
+ *  Fincitec acquired by National Semiconductor in 2002, together with the
+ *  Fincitec-related company ARSmikro) has the following features:
  *
+ *  - compatibility & compliance:
+ *    - Microsoft PC 97 ("PC 97 Hardware Design Guide",
+ *                       http://www.microsoft.com/whdc/archive/pcguides.mspx)
+ *    - Microsoft PC 98 Baseline Audio
+ *    - MPU401 UART
+ *    - Sound Blaster Emulation (DOS Box)
  *  - builtin AC97 conformant codec (SNR over 80dB)
  *    Note that "conformant" != "compliant"!! this chip's mixer register layout
  *    *differs* from the standard AC97 layout:
  *    addresses illegally. So far unfortunately it looks like the very flexible
  *    ALSA AC97 support is still not enough to easily compensate for such a
  *    grave layout violation despite all tweaks and quirks mechanisms it offers.
- *  - builtin genuine OPL3
+ *  - builtin genuine OPL3 - verified to work fine, 20080506
  *  - full duplex 16bit playback/record at independent sampling rate
- *  - MPU401 (+ legacy address support) FIXME: how to enable legacy addr??
+ *  - MPU401 (+ legacy address support, claimed by one official spec sheet)
+ *    FIXME: how to enable legacy addr??
  *  - game port (legacy address support)
- *  - builtin 3D enhancement (said to be YAMAHA Ymersion)
  *  - builtin DirectInput support, helps reduce CPU overhead (interrupt-driven
- *    features supported)
+ *    features supported). - See common term "Digital Enhanced Game Port"...
+ *    (probably DirectInput 3.0 spec - confirm)
+ *  - builtin 3D enhancement (said to be YAMAHA Ymersion)
  *  - built-in General DirectX timer having a 20 bits counter
  *    with 1us resolution (see below!)
- *  - I2S serial port for external DAC
+ *  - I2S serial output port for external DAC
  *  - supports 33MHz PCI spec 2.1, PCI power management 1.0, compliant with ACPI
  *  - supports hardware volume control
  *  - single chip low cost solution (128 pin QFP)
  *  - supports programmable Sub-vendor and Sub-system ID
  *    required for Microsoft's logo compliance (FIXME: where?)
+ *    At least the Trident 4D Wave DX has one bit somewhere
+ *    to enable writes to PCI subsystem VID registers, that should be it.
+ *    This might easily be in extended PCI reg space, since PCI168 also has
+ *    some custom data starting at 0x80. What kind of config settings
+ *    are located in our extended PCI space anyway??
  *  - PCI168 AP(W) card: power amplifier with 4 Watts/channel at 4 Ohms
  *
  *  Note that this driver now is actually *better* than the Windows driver,
  *  - "timidity -iAv -B2,8 -Os -EFreverb=0"
  *  - "pmidi -p 128:0 jazz.mid"
  *
+ *  OPL3 hardware playback testing, try something like:
+ *  cat /proc/asound/hwdep
+ *  and
+ *  aconnect -o
+ *  Then use
+ *  sbiload -Dhw:x,y --opl3 /usr/share/sounds/opl3/std.o3 ......./drums.o3
+ *  where x,y is the xx-yy number as given in hwdep.
+ *  Then try
+ *  pmidi -p a:b jazz.mid
+ *  where a:b is the client number plus 0 usually, as given by aconnect above.
+ *  Oh, and make sure to unmute the FM mixer control (doh!)
+ *  NOTE: power use during OPL3 playback is _VERY_ high (70W --> 90W!)
+ *  despite no CPU activity, possibly due to hindering ACPI idling somehow.
+ *  Shouldn't be a problem of the AZF3328 chip itself, I'd hope.
+ *  Higher PCM / FM mixer levels seem to conflict (causes crackling),
+ *  at least sometimes.   Maybe even use with hardware sequencer timer above :)
+ *  adplay/adplug-utils might soon offer hardware-based OPL3 playback, too.
+ *
  *  Certain PCI versions of this card are susceptible to DMA traffic underruns
  *  in some systems (resulting in sound crackling/clicking/popping),
  *  probably because they don't have a DMA FIFO buffer or so.
  *  better than a VIA, yet ironically I still get crackling, like many other
  *  people with the same chipset.
  *  Possible remedies:
+ *  - use speaker (amplifier) output instead of headphone output
+ *    (in case crackling is due to overloaded output clipping)
  *  - plug card into a different PCI slot, preferrably one that isn't shared
  *    too much (this helps a lot, but not completely!)
  *  - get rid of PCI VGA card, use AGP instead
  *  - fiddle with PCI latency settings (setpci -v -s BUSID latency_timer=XX)
  *    Not too helpful.
  *  - Disable ACPI/power management/"Auto Detect RAM/PCI Clk" in BIOS
- * 
+ *
  * BUGS
- *  - full-duplex might *still* be problematic, not fully tested recently
+ *  - full-duplex might *still* be problematic, however a recent test was fine
  *  - (non-bug) "Bass/Treble or 3D settings don't work" - they do get evaluated
  *    if you set PCM output switch to "pre 3D" instead of "post 3D".
  *    If this can't be set, then get a mixer application that Isn't Stupid (tm)
  *    (e.g. kmix, gamix) - unfortunately several are!!
- * 
+ *  - locking is not entirely clean, especially the audio stream activity
+ *    ints --> may be racy
+ *  - an _unconnected_ secondary joystick at the gameport will be reported
+ *    to be "active" (floating values, not precisely -1) due to the way we need
+ *    to read the Digital Enhanced Game Port. Not sure whether it is fixable.
+ *
  * TODO
  *  - test MPU401 MIDI playback etc.
- *  - add some power micro-management (disable various units of the card
- *    as long as they're unused). However this requires I/O ports which I
+ *  - add more power micro-management (disable various units of the card
+ *    as long as they're unused). However this requires more I/O ports which I
  *    haven't figured out yet and which thus might not even exist...
  *    The standard suspend/resume functionality could probably make use of
  *    some improvement, too...
  *  - figure out some cleverly evil scheme to possibly make ALSA AC97 code
  *    fully accept our quite incompatible ""AC97"" mixer and thus save some
  *    code (but I'm not too optimistic that doing this is possible at all)
+ *  - use MMIO (memory-mapped I/O)? Slightly faster access, e.g. for gameport.
  */
 
 #include <asm/io.h>
@@ -138,7 +182,7 @@ MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
 
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-#define SUPPORT_JOYSTICK 1
+#define SUPPORT_GAMEPORT 1
 #endif
 
 #define DEBUG_MISC     0
@@ -147,13 +191,14 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
 #define DEBUG_PLAY_REC 0
 #define DEBUG_IO       0
 #define DEBUG_TIMER    0
+#define DEBUG_GAME     0
 #define MIXER_TESTING  0
 
 #if DEBUG_MISC
 #define snd_azf3328_dbgmisc(format, args...) printk(KERN_ERR format, ##args)
 #else
 #define snd_azf3328_dbgmisc(format, args...)
-#endif         
+#endif
 
 #if DEBUG_CALLS
 #define snd_azf3328_dbgcalls(format, args...) printk(format, ##args)
@@ -163,25 +208,31 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
 #define snd_azf3328_dbgcalls(format, args...)
 #define snd_azf3328_dbgcallenter()
 #define snd_azf3328_dbgcallleave()
-#endif         
+#endif
 
 #if DEBUG_MIXER
 #define snd_azf3328_dbgmixer(format, args...) printk(format, ##args)
 #else
 #define snd_azf3328_dbgmixer(format, args...)
-#endif         
+#endif
 
 #if DEBUG_PLAY_REC
 #define snd_azf3328_dbgplay(format, args...) printk(KERN_ERR format, ##args)
 #else
 #define snd_azf3328_dbgplay(format, args...)
-#endif         
+#endif
 
 #if DEBUG_MISC
 #define snd_azf3328_dbgtimer(format, args...) printk(KERN_ERR format, ##args)
 #else
 #define snd_azf3328_dbgtimer(format, args...)
-#endif         
+#endif
+
+#if DEBUG_GAME
+#define snd_azf3328_dbggame(format, args...) printk(KERN_ERR format, ##args)
+#else
+#define snd_azf3328_dbggame(format, args...)
+#endif
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
 module_param_array(index, int, NULL, 0444);
@@ -195,51 +246,62 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;        /* Enable this card *
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable AZF3328 soundcard.");
 
-#ifdef SUPPORT_JOYSTICK
-static int joystick[SNDRV_CARDS];
-module_param_array(joystick, bool, NULL, 0444);
-MODULE_PARM_DESC(joystick, "Enable joystick for AZF3328 soundcard.");
-#endif
-
 static int seqtimer_scaling = 128;
 module_param(seqtimer_scaling, int, 0444);
 MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128.");
 
+struct snd_azf3328_audio_stream {
+       struct snd_pcm_substream *substream;
+       int enabled;
+       int running;
+       unsigned long portbase;
+};
+
+enum snd_azf3328_stream_index {
+  AZF_PLAYBACK = 0,
+  AZF_CAPTURE = 1,
+};
+
 struct snd_azf3328 {
        /* often-used fields towards beginning, then grouped */
-       unsigned long codec_port;
-       unsigned long io2_port;
-       unsigned long mpu_port;
-       unsigned long synth_port;
-       unsigned long mixer_port;
+
+       unsigned long codec_io; /* usually 0xb000, size 128 */
+       unsigned long game_io;  /* usually 0xb400, size 8 */
+       unsigned long mpu_io;   /* usually 0xb800, size 4 */
+       unsigned long opl3_io; /* usually 0xbc00, size 8 */
+       unsigned long mixer_io; /* usually 0xc000, size 64 */
 
        spinlock_t reg_lock;
 
        struct snd_timer *timer;
-       
+
        struct snd_pcm *pcm;
-       struct snd_pcm_substream *playback_substream;
-       struct snd_pcm_substream *capture_substream;
-       unsigned int is_playing;
-       unsigned int is_recording;
+       struct snd_azf3328_audio_stream audio_stream[2];
 
        struct snd_card *card;
        struct snd_rawmidi *rmidi;
 
-#ifdef SUPPORT_JOYSTICK
+#ifdef SUPPORT_GAMEPORT
        struct gameport *gameport;
+       int axes[4];
 #endif
 
        struct pci_dev *pci;
        int irq;
 
+       /* register 0x6a is write-only, thus need to remember setting.
+        * If we need to add more registers here, then we might try to fold this
+        * into some transparent combined shadow register handling with
+        * CONFIG_PM register storage below, but that's slightly difficult. */
+       u16 shadow_reg_codec_6AH;
+
 #ifdef CONFIG_PM
        /* register value containers for power management
         * Note: not always full I/O range preserved (just like Win driver!) */
-       u16 saved_regs_codec [AZF_IO_SIZE_CODEC_PM / 2];
-       u16 saved_regs_io2   [AZF_IO_SIZE_IO2_PM / 2];
-       u16 saved_regs_mpu   [AZF_IO_SIZE_MPU_PM / 2];
-       u16 saved_regs_synth[AZF_IO_SIZE_SYNTH_PM / 2];
+       u16 saved_regs_codec[AZF_IO_SIZE_CODEC_PM / 2];
+       u16 saved_regs_game [AZF_IO_SIZE_GAME_PM / 2];
+       u16 saved_regs_mpu  [AZF_IO_SIZE_MPU_PM / 2];
+       u16 saved_regs_opl3 [AZF_IO_SIZE_OPL3_PM / 2];
        u16 saved_regs_mixer[AZF_IO_SIZE_MIXER_PM / 2];
 #endif
 };
@@ -252,126 +314,166 @@ static const struct pci_device_id snd_azf3328_ids[] = {
 
 MODULE_DEVICE_TABLE(pci, snd_azf3328_ids);
 
+
+static int
+snd_azf3328_io_reg_setb(unsigned reg, u8 mask, int do_set)
+{
+       u8 prev = inb(reg), new;
+
+       new = (do_set) ? (prev|mask) : (prev & ~mask);
+       /* we need to always write the new value no matter whether it differs
+        * or not, since some register bits don't indicate their setting */
+       outb(new, reg);
+       if (new != prev)
+               return 1;
+
+       return 0;
+}
+
 static inline void
-snd_azf3328_codec_outb(const struct snd_azf3328 *chip, int reg, u8 value)
+snd_azf3328_codec_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value)
 {
-       outb(value, chip->codec_port + reg);
+       outb(value, chip->codec_io + reg);
 }
 
 static inline u8
-snd_azf3328_codec_inb(const struct snd_azf3328 *chip, int reg)
+snd_azf3328_codec_inb(const struct snd_azf3328 *chip, unsigned reg)
 {
-       return inb(chip->codec_port + reg);
+       return inb(chip->codec_io + reg);
 }
 
 static inline void
-snd_azf3328_codec_outw(const struct snd_azf3328 *chip, int reg, u16 value)
+snd_azf3328_codec_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value)
 {
-       outw(value, chip->codec_port + reg);
+       outw(value, chip->codec_io + reg);
 }
 
 static inline u16
-snd_azf3328_codec_inw(const struct snd_azf3328 *chip, int reg)
+snd_azf3328_codec_inw(const struct snd_azf3328 *chip, unsigned reg)
+{
+       return inw(chip->codec_io + reg);
+}
+
+static inline void
+snd_azf3328_codec_outl(const struct snd_azf3328 *chip, unsigned reg, u32 value)
+{
+       outl(value, chip->codec_io + reg);
+}
+
+static inline u32
+snd_azf3328_codec_inl(const struct snd_azf3328 *chip, unsigned reg)
 {
-       return inw(chip->codec_port + reg);
+       return inl(chip->codec_io + reg);
 }
 
 static inline void
-snd_azf3328_codec_outl(const struct snd_azf3328 *chip, int reg, u32 value)
+snd_azf3328_game_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value)
 {
-       outl(value, chip->codec_port + reg);
+       outb(value, chip->game_io + reg);
 }
 
 static inline void
-snd_azf3328_io2_outb(const struct snd_azf3328 *chip, int reg, u8 value)
+snd_azf3328_game_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value)
 {
-       outb(value, chip->io2_port + reg);
+       outw(value, chip->game_io + reg);
 }
 
 static inline u8
-snd_azf3328_io2_inb(const struct snd_azf3328 *chip, int reg)
+snd_azf3328_game_inb(const struct snd_azf3328 *chip, unsigned reg)
 {
-       return inb(chip->io2_port + reg);
+       return inb(chip->game_io + reg);
+}
+
+static inline u16
+snd_azf3328_game_inw(const struct snd_azf3328 *chip, unsigned reg)
+{
+       return inw(chip->game_io + reg);
 }
 
 static inline void
-snd_azf3328_mixer_outw(const struct snd_azf3328 *chip, int reg, u16 value)
+snd_azf3328_mixer_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value)
 {
-       outw(value, chip->mixer_port + reg);
+       outw(value, chip->mixer_io + reg);
 }
 
 static inline u16
-snd_azf3328_mixer_inw(const struct snd_azf3328 *chip, int reg)
+snd_azf3328_mixer_inw(const struct snd_azf3328 *chip, unsigned reg)
 {
-       return inw(chip->mixer_port + reg);
+       return inw(chip->mixer_io + reg);
 }
 
-static void
-snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip, int reg, int do_mute)
+#define AZF_MUTE_BIT 0x80
+
+static int
+snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip,
+                          unsigned reg, int do_mute
+)
 {
-       unsigned long portbase = chip->mixer_port + reg + 1;
-       unsigned char oldval;
+       unsigned long portbase = chip->mixer_io + reg + 1;
+       int updated;
 
        /* the mute bit is on the *second* (i.e. right) register of a
         * left/right channel setting */
-       oldval = inb(portbase);
-       if (do_mute)
-               oldval |= 0x80;
-       else
-               oldval &= ~0x80;
-       outb(oldval, portbase);
+       updated = snd_azf3328_io_reg_setb(portbase, AZF_MUTE_BIT, do_mute);
+
+       /* indicate whether it was muted before */
+       return (do_mute) ? !updated : updated;
 }
 
 static void
-snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg, unsigned char dst_vol_left, unsigned char dst_vol_right, int chan_sel, int delay)
+snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip,
+                                        unsigned reg,
+                                        unsigned char dst_vol_left,
+                                        unsigned char dst_vol_right,
+                                        int chan_sel, int delay
+)
 {
-       unsigned long portbase = chip->mixer_port + reg;
+       unsigned long portbase = chip->mixer_io + reg;
        unsigned char curr_vol_left = 0, curr_vol_right = 0;
-       int left_done = 0, right_done = 0;
-       
+       int left_change = 0, right_change = 0;
+
        snd_azf3328_dbgcallenter();
-       if (chan_sel & SET_CHAN_LEFT)
+
+       if (chan_sel & SET_CHAN_LEFT) {
                curr_vol_left  = inb(portbase + 1);
-       else
-               left_done = 1;
-       if (chan_sel & SET_CHAN_RIGHT)
+
+               /* take care of muting flag contained in left channel */
+               if (curr_vol_left & AZF_MUTE_BIT)
+                       dst_vol_left |= AZF_MUTE_BIT;
+               else
+                       dst_vol_left &= ~AZF_MUTE_BIT;
+
+               left_change = (curr_vol_left > dst_vol_left) ? -1 : 1;
+       }
+
+       if (chan_sel & SET_CHAN_RIGHT) {
                curr_vol_right = inb(portbase + 0);
-       else
-               right_done = 1;
-       
-       /* take care of muting flag (0x80) contained in left channel */
-       if (curr_vol_left & 0x80)
-               dst_vol_left |= 0x80;
-       else
-               dst_vol_left &= ~0x80;
+
+               right_change = (curr_vol_right > dst_vol_right) ? -1 : 1;
+       }
 
        do {
-               if (!left_done) {
-                       if (curr_vol_left > dst_vol_left)
-                               curr_vol_left--;
-                       else
-                       if (curr_vol_left < dst_vol_left)
-                               curr_vol_left++;
-                       else
-                           left_done = 1;
-                       outb(curr_vol_left, portbase + 1);
+               if (left_change) {
+                       if (curr_vol_left != dst_vol_left) {
+                               curr_vol_left += left_change;
+                               outb(curr_vol_left, portbase + 1);
+                       } else
+                           left_change = 0;
                }
-               if (!right_done) {
-                       if (curr_vol_right > dst_vol_right)
-                               curr_vol_right--;
-                       else
-                       if (curr_vol_right < dst_vol_right)
-                               curr_vol_right++;
-                       else
-                           right_done = 1;
+               if (right_change) {
+                       if (curr_vol_right != dst_vol_right) {
+                               curr_vol_right += right_change;
+
                        /* during volume change, the right channel is crackling
                         * somewhat more than the left channel, unfortunately.
                         * This seems to be a hardware issue. */
-                       outb(curr_vol_right, portbase + 0);
+                               outb(curr_vol_right, portbase + 0);
+                       } else
+                           right_change = 0;
                }
                if (delay)
                        mdelay(delay);
-       } while ((!left_done) || (!right_done));
+       } while ((left_change) || (right_change));
        snd_azf3328_dbgcallleave();
 }
 
@@ -379,7 +481,7 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg
  * general mixer element
  */
 struct azf3328_mixer_reg {
-       unsigned int reg;
+       unsigned reg;
        unsigned int lchan_shift, rchan_shift;
        unsigned int mask;
        unsigned int invert: 1;
@@ -544,13 +646,14 @@ snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol,
                "Mix", "Mic"
        };
        static const char * const texts3[] = {
-                "Mic", "CD", "Video", "Aux",
+               "Mic", "CD", "Video", "Aux",
                "Line", "Mix", "Mix Mono", "Phone"
         };
        static const char * const texts4[] = {
                "pre 3D", "post 3D"
         };
        struct azf3328_mixer_reg reg;
+       const char * const *p = NULL;
 
        snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -561,18 +664,20 @@ snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol,
        if (reg.reg == IDX_MIXER_ADVCTL2) {
                switch(reg.lchan_shift) {
                case 8: /* modem out sel */
-                       strcpy(uinfo->value.enumerated.name, texts1[uinfo->value.enumerated.item]);
+                       p = texts1;
                        break;
                case 9: /* mono sel source */
-                       strcpy(uinfo->value.enumerated.name, texts2[uinfo->value.enumerated.item]);
+                       p = texts2;
                        break;
                case 15: /* PCM Out Path */
-                       strcpy(uinfo->value.enumerated.name, texts4[uinfo->value.enumerated.item]);
+                       p = texts4;
                        break;
                }
        } else
-               strcpy(uinfo->value.enumerated.name, texts3[uinfo->value.enumerated.item]
-);
+       if (reg.reg == IDX_MIXER_REC_SELECT)
+               p = texts3;
+
+       strcpy(uinfo->value.enumerated.name, p[uinfo->value.enumerated.item]);
         return 0;
 }
 
@@ -583,7 +688,7 @@ snd_azf3328_get_mixer_enum(struct snd_kcontrol *kcontrol,
         struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
        struct azf3328_mixer_reg reg;
         unsigned short val;
-        
+
        snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
        val = snd_azf3328_mixer_inw(chip, reg.reg);
        if (reg.reg == IDX_MIXER_REC_SELECT) {
@@ -605,7 +710,7 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
         struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
        struct azf3328_mixer_reg reg;
        unsigned int oreg, nreg, val;
-        
+
        snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
        oreg = snd_azf3328_mixer_inw(chip, reg.reg);
        val = oreg;
@@ -631,9 +736,11 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
 static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {
        AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1),
        AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1),
-       AZF3328_MIXER_SWITCH("Wave Playback Switch", IDX_MIXER_WAVEOUT, 15, 1),
-       AZF3328_MIXER_VOL_STEREO("Wave Playback Volume", IDX_MIXER_WAVEOUT, 0x1f, 1),
-       AZF3328_MIXER_SWITCH("Wave 3D Bypass Playback Switch", IDX_MIXER_ADVCTL2, 7, 1),
+       AZF3328_MIXER_SWITCH("PCM Playback Switch", IDX_MIXER_WAVEOUT, 15, 1),
+       AZF3328_MIXER_VOL_STEREO("PCM Playback Volume",
+                                       IDX_MIXER_WAVEOUT, 0x1f, 1),
+       AZF3328_MIXER_SWITCH("PCM 3D Bypass Playback Switch",
+                                       IDX_MIXER_ADVCTL2, 7, 1),
        AZF3328_MIXER_SWITCH("FM Playback Switch", IDX_MIXER_FMSYNTH, 15, 1),
        AZF3328_MIXER_VOL_STEREO("FM Playback Volume", IDX_MIXER_FMSYNTH, 0x1f, 1),
        AZF3328_MIXER_SWITCH("CD Playback Switch", IDX_MIXER_CDAUDIO, 15, 1),
@@ -717,15 +824,16 @@ snd_azf3328_mixer_new(struct snd_azf3328 *chip)
        snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000);
 
        /* mute and zero volume channels */
-       for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_init_values); idx++) {
+       for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_init_values); ++idx) {
                snd_azf3328_mixer_outw(chip,
                        snd_azf3328_init_values[idx][0],
                        snd_azf3328_init_values[idx][1]);
        }
-       
+
        /* add mixer controls */
        sw = snd_azf3328_mixer_controls;
-       for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_mixer_controls); idx++, sw++) {
+       for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_mixer_controls);
+                       ++idx, ++sw) {
                if ((err = snd_ctl_add(chip->card, snd_ctl_new1(sw, chip))) < 0)
                        return err;
        }
@@ -757,9 +865,9 @@ snd_azf3328_hw_free(struct snd_pcm_substream *substream)
 }
 
 static void
-snd_azf3328_setfmt(struct snd_azf3328 *chip,
-                              unsigned int reg,
-                              unsigned int bitrate,
+snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
+                              unsigned reg,
+                              enum azf_freq_t bitrate,
                               unsigned int format_width,
                               unsigned int channels
 )
@@ -769,24 +877,25 @@ snd_azf3328_setfmt(struct snd_azf3328 *chip,
 
        snd_azf3328_dbgcallenter();
        switch (bitrate) {
-       case  4000: val |= SOUNDFORMAT_FREQ_SUSPECTED_4000; break;
-       case  4800: val |= SOUNDFORMAT_FREQ_SUSPECTED_4800; break;
-       case  5512: val |= SOUNDFORMAT_FREQ_5510; break; /* the AZF3328 names it "5510" for some strange reason */
-       case  6620: val |= SOUNDFORMAT_FREQ_6620; break;
-       case  8000: val |= SOUNDFORMAT_FREQ_8000; break;
-       case  9600: val |= SOUNDFORMAT_FREQ_9600; break;
-       case 11025: val |= SOUNDFORMAT_FREQ_11025; break;
-       case 13240: val |= SOUNDFORMAT_FREQ_SUSPECTED_13240; break;
-       case 16000: val |= SOUNDFORMAT_FREQ_16000; break;
-       case 22050: val |= SOUNDFORMAT_FREQ_22050; break;
-       case 32000: val |= SOUNDFORMAT_FREQ_32000; break;
-       case 44100: val |= SOUNDFORMAT_FREQ_44100; break;
-       case 48000: val |= SOUNDFORMAT_FREQ_48000; break;
-       case 66200: val |= SOUNDFORMAT_FREQ_SUSPECTED_66200; break;
+       case AZF_FREQ_4000:  val |= SOUNDFORMAT_FREQ_SUSPECTED_4000; break;
+       case AZF_FREQ_4800:  val |= SOUNDFORMAT_FREQ_SUSPECTED_4800; break;
+       case AZF_FREQ_5512:
+               /* the AZF3328 names it "5510" for some strange reason */
+                            val |= SOUNDFORMAT_FREQ_5510; break;
+       case AZF_FREQ_6620:  val |= SOUNDFORMAT_FREQ_6620; break;
+       case AZF_FREQ_8000:  val |= SOUNDFORMAT_FREQ_8000; break;
+       case AZF_FREQ_9600:  val |= SOUNDFORMAT_FREQ_9600; break;
+       case AZF_FREQ_11025: val |= SOUNDFORMAT_FREQ_11025; break;
+       case AZF_FREQ_13240: val |= SOUNDFORMAT_FREQ_SUSPECTED_13240; break;
+       case AZF_FREQ_16000: val |= SOUNDFORMAT_FREQ_16000; break;
+       case AZF_FREQ_22050: val |= SOUNDFORMAT_FREQ_22050; break;
+       case AZF_FREQ_32000: val |= SOUNDFORMAT_FREQ_32000; break;
        default:
                snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate);
-               val |= SOUNDFORMAT_FREQ_44100;
-               break;
+               /* fall-through */
+       case AZF_FREQ_44100: val |= SOUNDFORMAT_FREQ_44100; break;
+       case AZF_FREQ_48000: val |= SOUNDFORMAT_FREQ_48000; break;
+       case AZF_FREQ_66200: val |= SOUNDFORMAT_FREQ_SUSPECTED_66200; break;
        }
        /* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) hmm, 66120, 65967, 66123 */
        /* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) hmm, 13237.2Hz? */
@@ -805,10 +914,10 @@ snd_azf3328_setfmt(struct snd_azf3328 *chip,
                val |= SOUNDFORMAT_FLAG_16BIT;
 
        spin_lock_irqsave(&chip->reg_lock, flags);
-       
+
        /* set bitrate/format */
        snd_azf3328_codec_outw(chip, reg, val);
-       
+
        /* changing the bitrate/format settings switches off the
         * audio output with an annoying click in case of 8/16bit format change
         * (maybe shutting down DAC/ADC?), thus immediately
@@ -830,31 +939,95 @@ snd_azf3328_setfmt(struct snd_azf3328 *chip,
        snd_azf3328_dbgcallleave();
 }
 
+static inline void
+snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328 *chip,
+                           unsigned reg
+)
+{
+       /* choose lowest frequency for low power consumption.
+        * While this will cause louder noise due to rather coarse frequency,
+        * it should never matter since output should always
+        * get disabled properly when idle anyway. */
+       snd_azf3328_codec_setfmt(chip, reg, AZF_FREQ_4000, 8, 1);
+}
+
+static void
+snd_azf3328_codec_reg_6AH_update(struct snd_azf3328 *chip,
+                                       unsigned bitmask,
+                                       int enable
+)
+{
+       if (enable)
+               chip->shadow_reg_codec_6AH &= ~bitmask;
+       else
+               chip->shadow_reg_codec_6AH |= bitmask;
+       snd_azf3328_dbgplay("6AH_update mask 0x%04x enable %d: val 0x%04x\n",
+                       bitmask, enable, chip->shadow_reg_codec_6AH);
+       snd_azf3328_codec_outw(chip, IDX_IO_6AH, chip->shadow_reg_codec_6AH);
+}
+
+static inline void
+snd_azf3328_codec_enable(struct snd_azf3328 *chip, int enable)
+{
+       snd_azf3328_dbgplay("codec_enable %d\n", enable);
+       /* no idea what exactly is being done here, but I strongly assume it's
+        * PM related */
+       snd_azf3328_codec_reg_6AH_update(
+               chip, IO_6A_PAUSE_PLAYBACK_BIT8, enable
+       );
+}
+
+static void
+snd_azf3328_codec_activity(struct snd_azf3328 *chip,
+                               enum snd_azf3328_stream_index stream_type,
+                               int enable
+)
+{
+       int need_change = (chip->audio_stream[stream_type].running != enable);
+
+       snd_azf3328_dbgplay(
+               "codec_activity: type %d, enable %d, need_change %d\n",
+                               stream_type, enable, need_change
+       );
+       if (need_change) {
+               enum snd_azf3328_stream_index other =
+                       (stream_type == AZF_PLAYBACK) ?
+                               AZF_CAPTURE : AZF_PLAYBACK;
+               /* small check to prevent shutting down the other party
+                * in case it's active */
+               if ((enable) || !(chip->audio_stream[other].running))
+                       snd_azf3328_codec_enable(chip, enable);
+
+               /* ...and adjust clock, too
+                * (reduce noise and power consumption) */
+               if (!enable)
+                       snd_azf3328_codec_setfmt_lowpower(
+                               chip,
+                               chip->audio_stream[stream_type].portbase
+                                       + IDX_IO_PLAY_SOUNDFORMAT
+                       );
+       }
+       chip->audio_stream[stream_type].running = enable;
+}
+
 static void
 snd_azf3328_setdmaa(struct snd_azf3328 *chip,
                                long unsigned int addr,
                                 unsigned int count,
                                 unsigned int size,
-                               int do_recording)
+                               enum snd_azf3328_stream_index stream_type
+)
 {
-       unsigned long flags, portbase;
-       unsigned int is_running;
-
        snd_azf3328_dbgcallenter();
-       if (do_recording) {
-               /* access capture registers, i.e. skip playback reg section */
-               portbase = chip->codec_port + 0x20;
-               is_running = chip->is_recording;
-       } else {
-               /* access the playback register section */
-               portbase = chip->codec_port + 0x00;
-               is_running = chip->is_playing;
-       }
+       if (!chip->audio_stream[stream_type].running) {
+               /* AZF3328 uses a two buffer pointer DMA playback approach */
 
-       /* AZF3328 uses a two buffer pointer DMA playback approach */
-       if (!is_running) {
-               unsigned long addr_area2;
-               unsigned long count_areas, count_tmp; /* width 32bit -- overflow!! */
+               unsigned long flags, portbase, addr_area2;
+
+               /* width 32bit (prevent overflow): */
+               unsigned long count_areas, count_tmp;
+
+               portbase = chip->audio_stream[stream_type].portbase;
                count_areas = size/2;
                addr_area2 = addr+count_areas;
                count_areas--; /* max. index */
@@ -884,11 +1057,11 @@ snd_azf3328_playback_prepare(struct snd_pcm_substream *substream)
 
        snd_azf3328_dbgcallenter();
 #if 0
-       snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT,
+       snd_azf3328_codec_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT,
                runtime->rate,
                snd_pcm_format_width(runtime->format),
                runtime->channels);
-       snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, 0);
+       snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, AZF_PLAYBACK);
 #endif
        snd_azf3328_dbgcallleave();
        return 0;
@@ -906,11 +1079,11 @@ snd_azf3328_capture_prepare(struct snd_pcm_substream *substream)
 
        snd_azf3328_dbgcallenter();
 #if 0
-       snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT,
+       snd_azf3328_codec_setfmt(chip, IDX_IO_REC_SOUNDFORMAT,
                runtime->rate,
                snd_pcm_format_width(runtime->format),
                runtime->channels);
-       snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, 1);
+       snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, AZF_CAPTURE);
 #endif
        snd_azf3328_dbgcallleave();
        return 0;
@@ -923,6 +1096,7 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
        struct snd_pcm_runtime *runtime = substream->runtime;
        int result = 0;
        unsigned int status1;
+       int previously_muted;
 
        snd_azf3328_dbgcalls("snd_azf3328_playback_trigger cmd %d\n", cmd);
 
@@ -930,20 +1104,23 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_START:
                snd_azf3328_dbgplay("START PLAYBACK\n");
 
-               /* mute WaveOut */
-               snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
+               /* mute WaveOut (avoid clicking during setup) */
+               previously_muted =
+                       snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
 
-               snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT,
+               snd_azf3328_codec_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT,
                        runtime->rate,
                        snd_pcm_format_width(runtime->format),
                        runtime->channels);
 
                spin_lock(&chip->reg_lock);
-               /* stop playback */
+               /* first, remember current value: */
                status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS);
+
+               /* stop playback */
                status1 &= ~DMA_RESUME;
                snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);
-           
+
                /* FIXME: clear interrupts or what??? */
                snd_azf3328_codec_outw(chip, IDX_IO_PLAY_IRQTYPE, 0xffff);
                spin_unlock(&chip->reg_lock);
@@ -951,7 +1128,7 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
                snd_azf3328_setdmaa(chip, runtime->dma_addr,
                        snd_pcm_lib_period_bytes(substream),
                        snd_pcm_lib_buffer_bytes(substream),
-                       0);
+                       AZF_PLAYBACK);
 
                spin_lock(&chip->reg_lock);
 #ifdef WIN9X
@@ -978,30 +1155,35 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
                        DMA_SOMETHING_ELSE);
 #endif
                spin_unlock(&chip->reg_lock);
+               snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 1);
 
                /* now unmute WaveOut */
-               snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0);
+               if (!previously_muted)
+                       snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0);
 
-               chip->is_playing = 1;
                snd_azf3328_dbgplay("STARTED PLAYBACK\n");
                break;
        case SNDRV_PCM_TRIGGER_RESUME:
                snd_azf3328_dbgplay("RESUME PLAYBACK\n");
                /* resume playback if we were active */
-               if (chip->is_playing)
+               spin_lock(&chip->reg_lock);
+               if (chip->audio_stream[AZF_PLAYBACK].running)
                        snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,
                                snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | DMA_RESUME);
+               spin_unlock(&chip->reg_lock);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
                snd_azf3328_dbgplay("STOP PLAYBACK\n");
 
-               /* mute WaveOut */
-               snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
+               /* mute WaveOut (avoid clicking during setup) */
+               previously_muted =
+                       snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
 
                spin_lock(&chip->reg_lock);
-               /* stop playback */
+               /* first, remember current value: */
                status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS);
 
+               /* stop playback */
                status1 &= ~DMA_RESUME;
                snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);
 
@@ -1013,10 +1195,12 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
                status1 &= ~DMA_PLAY_SOMETHING1;
                snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);
                spin_unlock(&chip->reg_lock);
-           
+               snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 0);
+
                /* now unmute WaveOut */
-               snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0);
-               chip->is_playing = 0;
+               if (!previously_muted)
+                       snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0);
+
                snd_azf3328_dbgplay("STOPPED PLAYBACK\n");
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -1035,7 +1219,7 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
                printk(KERN_ERR "FIXME: unknown trigger mode!\n");
                 return -EINVAL;
        }
-       
+
        snd_azf3328_dbgcallleave();
        return result;
 }
@@ -1057,17 +1241,19 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd)
 
                snd_azf3328_dbgplay("START CAPTURE\n");
 
-               snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT,
+               snd_azf3328_codec_setfmt(chip, IDX_IO_REC_SOUNDFORMAT,
                        runtime->rate,
                        snd_pcm_format_width(runtime->format),
                        runtime->channels);
 
                spin_lock(&chip->reg_lock);
-               /* stop recording */
+               /* first, remember current value: */
                status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS);
+
+               /* stop recording */
                status1 &= ~DMA_RESUME;
                snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
-           
+
                /* FIXME: clear interrupts or what??? */
                snd_azf3328_codec_outw(chip, IDX_IO_REC_IRQTYPE, 0xffff);
                spin_unlock(&chip->reg_lock);
@@ -1075,7 +1261,7 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd)
                snd_azf3328_setdmaa(chip, runtime->dma_addr,
                        snd_pcm_lib_period_bytes(substream),
                        snd_pcm_lib_buffer_bytes(substream),
-                       1);
+                       AZF_CAPTURE);
 
                spin_lock(&chip->reg_lock);
 #ifdef WIN9X
@@ -1102,24 +1288,27 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd)
                        DMA_SOMETHING_ELSE);
 #endif
                spin_unlock(&chip->reg_lock);
+               snd_azf3328_codec_activity(chip, AZF_CAPTURE, 1);
 
-               chip->is_recording = 1;
                snd_azf3328_dbgplay("STARTED CAPTURE\n");
                break;
        case SNDRV_PCM_TRIGGER_RESUME:
                snd_azf3328_dbgplay("RESUME CAPTURE\n");
                /* resume recording if we were active */
-               if (chip->is_recording)
+               spin_lock(&chip->reg_lock);
+               if (chip->audio_stream[AZF_CAPTURE].running)
                        snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
                                snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) | DMA_RESUME);
+               spin_unlock(&chip->reg_lock);
                break;
         case SNDRV_PCM_TRIGGER_STOP:
                snd_azf3328_dbgplay("STOP CAPTURE\n");
 
                spin_lock(&chip->reg_lock);
-               /* stop recording */
+               /* first, remember current value: */
                status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS);
 
+               /* stop recording */
                status1 &= ~DMA_RESUME;
                snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
 
@@ -1129,8 +1318,8 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd)
                status1 &= ~DMA_PLAY_SOMETHING1;
                snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
                spin_unlock(&chip->reg_lock);
-           
-               chip->is_recording = 0;
+               snd_azf3328_codec_activity(chip, AZF_CAPTURE, 0);
+
                snd_azf3328_dbgplay("STOPPED CAPTURE\n");
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -1149,7 +1338,7 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd)
                printk(KERN_ERR "FIXME: unknown trigger mode!\n");
                 return -EINVAL;
        }
-       
+
        snd_azf3328_dbgcallleave();
        return result;
 }
@@ -1162,11 +1351,11 @@ snd_azf3328_playback_pointer(struct snd_pcm_substream *substream)
        snd_pcm_uframes_t frmres;
 
 #ifdef QUERY_HARDWARE
-       bufptr = inl(chip->codec_port+IDX_IO_PLAY_DMA_START_1);
+       bufptr = snd_azf3328_codec_inl(chip, IDX_IO_PLAY_DMA_START_1);
 #else
        bufptr = substream->runtime->dma_addr;
 #endif
-       result = inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS);
+       result = snd_azf3328_codec_inl(chip, IDX_IO_PLAY_DMA_CURRPOS);
 
        /* calculate offset */
        result -= bufptr;
@@ -1183,11 +1372,11 @@ snd_azf3328_capture_pointer(struct snd_pcm_substream *substream)
        snd_pcm_uframes_t frmres;
 
 #ifdef QUERY_HARDWARE
-       bufptr = inl(chip->codec_port+IDX_IO_REC_DMA_START_1);
+       bufptr = snd_azf3328_codec_inl(chip, IDX_IO_REC_DMA_START_1);
 #else
        bufptr = substream->runtime->dma_addr;
 #endif
-       result = inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS);
+       result = snd_azf3328_codec_inl(chip, IDX_IO_REC_DMA_CURRPOS);
 
        /* calculate offset */
        result -= bufptr;
@@ -1196,27 +1385,241 @@ snd_azf3328_capture_pointer(struct snd_pcm_substream *substream)
        return frmres;
 }
 
+/******************************************************************/
+
+#ifdef SUPPORT_GAMEPORT
+static inline void
+snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip, int enable)
+{
+       snd_azf3328_io_reg_setb(
+               chip->game_io+IDX_GAME_HWCONFIG,
+               GAME_HWCFG_IRQ_ENABLE,
+               enable
+       );
+}
+
+static inline void
+snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip, int enable)
+{
+       snd_azf3328_io_reg_setb(
+               chip->game_io+IDX_GAME_HWCONFIG,
+               GAME_HWCFG_LEGACY_ADDRESS_ENABLE,
+               enable
+       );
+}
+
+static inline void
+snd_azf3328_gameport_axis_circuit_enable(struct snd_azf3328 *chip, int enable)
+{
+       snd_azf3328_codec_reg_6AH_update(
+               chip, IO_6A_SOMETHING2_GAMEPORT, enable
+       );
+}
+
+static inline void
+snd_azf3328_gameport_interrupt(struct snd_azf3328 *chip)
+{
+       /*
+        * skeleton handler only
+        * (we do not want axis reading in interrupt handler - too much load!)
+        */
+       snd_azf3328_dbggame("gameport irq\n");
+
+        /* this should ACK the gameport IRQ properly, hopefully. */
+       snd_azf3328_game_inw(chip, IDX_GAME_AXIS_VALUE);
+}
+
+static int
+snd_azf3328_gameport_open(struct gameport *gameport, int mode)
+{
+       struct snd_azf3328 *chip = gameport_get_port_data(gameport);
+       int res;
+
+       snd_azf3328_dbggame("gameport_open, mode %d\n", mode);
+       switch (mode) {
+       case GAMEPORT_MODE_COOKED:
+       case GAMEPORT_MODE_RAW:
+               res = 0;
+               break;
+       default:
+               res = -1;
+               break;
+       }
+
+       snd_azf3328_gameport_axis_circuit_enable(chip, (res == 0));
+
+       return res;
+}
+
+static void
+snd_azf3328_gameport_close(struct gameport *gameport)
+{
+       struct snd_azf3328 *chip = gameport_get_port_data(gameport);
+
+       snd_azf3328_dbggame("gameport_close\n");
+       snd_azf3328_gameport_axis_circuit_enable(chip, 0);
+}
+
+static int
+snd_azf3328_gameport_cooked_read(struct gameport *gameport,
+                                int *axes,
+                                int *buttons
+)
+{
+       struct snd_azf3328 *chip = gameport_get_port_data(gameport);
+       int i;
+       u8 val;
+       unsigned long flags;
+
+       snd_assert(chip, return 0);
+
+       spin_lock_irqsave(&chip->reg_lock, flags);
+       val = snd_azf3328_game_inb(chip, IDX_GAME_LEGACY_COMPATIBLE);
+       *buttons = (~(val) >> 4) & 0xf;
+
+       /* ok, this one is a bit dirty: cooked_read is being polled by a timer,
+        * thus we're atomic and cannot actively wait in here
+        * (which would be useful for us since it probably would be better
+        * to trigger a measurement in here, then wait a short amount of
+        * time until it's finished, then read values of _this_ measurement).
+        *
+        * Thus we simply resort to reading values if they're available already
+        * and trigger the next measurement.
+        */
+
+       val = snd_azf3328_game_inb(chip, IDX_GAME_AXES_CONFIG);
+       if (val & GAME_AXES_SAMPLING_READY) {
+               for (i = 0; i < 4; ++i) {
+                       /* configure the axis to read */
+                       val = (i << 4) | 0x0f;
+                       snd_azf3328_game_outb(chip, IDX_GAME_AXES_CONFIG, val);
+
+                       chip->axes[i] = snd_azf3328_game_inw(
+                                               chip, IDX_GAME_AXIS_VALUE
+                                       );
+               }
+       }
+
+       /* trigger next axes sampling, to be evaluated the next time we
+        * enter this function */
+
+       /* for some very, very strange reason we cannot enable
+        * Measurement Ready monitoring for all axes here,
+        * at least not when only one joystick connected */
+       val = 0x03; /* we're able to monitor axes 1 and 2 only */
+       snd_azf3328_game_outb(chip, IDX_GAME_AXES_CONFIG, val);
+
+       snd_azf3328_game_outw(chip, IDX_GAME_AXIS_VALUE, 0xffff);
+       spin_unlock_irqrestore(&chip->reg_lock, flags);
+
+       for (i = 0; i < 4; i++) {
+               axes[i] = chip->axes[i];
+               if (axes[i] == 0xffff)
+                       axes[i] = -1;
+       }
+
+       snd_azf3328_dbggame("cooked_read: axes %d %d %d %d buttons %d\n",
+               axes[0], axes[1], axes[2], axes[3], *buttons
+       );
+
+       return 0;
+}
+
+static int __devinit
+snd_azf3328_gameport(struct snd_azf3328 *chip, int dev)
+{
+       struct gameport *gp;
+
+       chip->gameport = gp = gameport_allocate_port();
+       if (!gp) {
+               printk(KERN_ERR "azt3328: cannot alloc memory for gameport\n");
+               return -ENOMEM;
+       }
+
+       gameport_set_name(gp, "AZF3328 Gameport");
+       gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+       gameport_set_dev_parent(gp, &chip->pci->dev);
+       gp->io = chip->game_io;
+       gameport_set_port_data(gp, chip);
+
+       gp->open = snd_azf3328_gameport_open;
+       gp->close = snd_azf3328_gameport_close;
+       gp->fuzz = 16; /* seems ok */
+       gp->cooked_read = snd_azf3328_gameport_cooked_read;
+
+       /* DISABLE legacy address: we don't need it! */
+       snd_azf3328_gameport_legacy_address_enable(chip, 0);
+
+       snd_azf3328_gameport_axis_circuit_enable(chip, 0);
+
+       gameport_register_port(chip->gameport);
+
+       return 0;
+}
+
+static void
+snd_azf3328_gameport_free(struct snd_azf3328 *chip)
+{
+       if (chip->gameport) {
+               gameport_unregister_port(chip->gameport);
+               chip->gameport = NULL;
+       }
+       snd_azf3328_gameport_irq_enable(chip, 0);
+}
+#else
+static inline int
+snd_azf3328_gameport(struct snd_azf3328 *chip, int dev) { return -ENOSYS; }
+static inline void
+snd_azf3328_gameport_free(struct snd_azf3328 *chip) { }
+static inline void
+snd_azf3328_gameport_interrupt(struct snd_azf3328 *chip)
+{
+       printk(KERN_WARNING "huh, game port IRQ occurred!?\n");
+}
+#endif /* SUPPORT_GAMEPORT */
+
+/******************************************************************/
+
+static inline void
+snd_azf3328_irq_log_unknown_type(u8 which)
+{
+       snd_azf3328_dbgplay(
+       "azt3328: unknown IRQ type (%x) occurred, please report!\n",
+               which
+       );
+}
+
 static irqreturn_t
 snd_azf3328_interrupt(int irq, void *dev_id)
 {
        struct snd_azf3328 *chip = dev_id;
        u8 status, which;
+#if DEBUG_PLAY_REC
        static unsigned long irq_count;
+#endif
 
        status = snd_azf3328_codec_inb(chip, IDX_IO_IRQSTATUS);
 
         /* fast path out, to ease interrupt sharing */
-       if (!(status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_MPU401|IRQ_TIMER)))
+       if (!(status &
+               (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_GAMEPORT|IRQ_MPU401|IRQ_TIMER)
+       ))
                return IRQ_NONE; /* must be interrupt for another device */
 
-       snd_azf3328_dbgplay("Interrupt %ld!\nIDX_IO_PLAY_FLAGS %04x, IDX_IO_PLAY_IRQTYPE %04x, IDX_IO_IRQSTATUS %04x\n",
-               irq_count,
-               snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS),
-               snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE),
-               status);
-               
+       snd_azf3328_dbgplay(
+               "irq_count %ld! IDX_IO_PLAY_FLAGS %04x, "
+               "IDX_IO_PLAY_IRQTYPE %04x, IDX_IO_IRQSTATUS %04x\n",
+                       irq_count++ /* debug-only */,
+                       snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS),
+                       snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE),
+                       status
+       );
+
        if (status & IRQ_TIMER) {
-               /* snd_azf3328_dbgplay("timer %ld\n", inl(chip->codec_port+IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK); */
+               /* snd_azf3328_dbgplay("timer %ld\n",
+                       snd_azf3328_codec_inl(chip, IDX_IO_TIMER_VALUE)
+                               & TIMER_VALUE_MASK
+               ); */
                if (chip->timer)
                        snd_timer_interrupt(chip->timer, chip->timer->sticks);
                /* ACK timer */
@@ -1232,15 +1635,20 @@ snd_azf3328_interrupt(int irq, void *dev_id)
                snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which);
                        spin_unlock(&chip->reg_lock);
 
-               if (chip->pcm && chip->playback_substream) {
-                       snd_pcm_period_elapsed(chip->playback_substream);
+               if (chip->pcm && chip->audio_stream[AZF_PLAYBACK].substream) {
+                       snd_pcm_period_elapsed(
+                               chip->audio_stream[AZF_PLAYBACK].substream
+                       );
                        snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n",
                                which,
-                               inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS));
+                               snd_azf3328_codec_inl(
+                                       chip, IDX_IO_PLAY_DMA_CURRPOS
+                               )
+                       );
                } else
-                       snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n");
+                       printk(KERN_WARNING "azt3328: irq handler problem!\n");
                if (which & IRQ_PLAY_SOMETHING)
-                       snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n");
+                       snd_azf3328_irq_log_unknown_type(which);
        }
        if (status & IRQ_RECORDING) {
                 spin_lock(&chip->reg_lock);
@@ -1249,16 +1657,23 @@ snd_azf3328_interrupt(int irq, void *dev_id)
                snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which);
                spin_unlock(&chip->reg_lock);
 
-               if (chip->pcm && chip->capture_substream) {
-                       snd_pcm_period_elapsed(chip->capture_substream);
+               if (chip->pcm && chip->audio_stream[AZF_CAPTURE].substream) {
+                       snd_pcm_period_elapsed(
+                               chip->audio_stream[AZF_CAPTURE].substream
+                       );
                        snd_azf3328_dbgplay("REC  period done (#%x), @ %x\n",
                                which,
-                               inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS));
+                               snd_azf3328_codec_inl(
+                                       chip, IDX_IO_REC_DMA_CURRPOS
+                               )
+                       );
                } else
-                       snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n");
+                       printk(KERN_WARNING "azt3328: irq handler problem!\n");
                if (which & IRQ_REC_SOMETHING)
-                       snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n");
+                       snd_azf3328_irq_log_unknown_type(which);
        }
+       if (status & IRQ_GAMEPORT)
+               snd_azf3328_gameport_interrupt(chip);
        /* MPU401 has less critical IRQ requirements
         * than timer and playback/recording, right? */
        if (status & IRQ_MPU401) {
@@ -1268,7 +1683,6 @@ snd_azf3328_interrupt(int irq, void *dev_id)
                 * If so, then I don't know how... */
                snd_azf3328_dbgplay("azt3328: MPU401 IRQ\n");
        }
-       irq_count++;
        return IRQ_HANDLED;
 }
 
@@ -1287,8 +1701,8 @@ static const struct snd_pcm_hardware snd_azf3328_playback =
        .rates =                SNDRV_PCM_RATE_5512 |
                                SNDRV_PCM_RATE_8000_48000 |
                                SNDRV_PCM_RATE_KNOT,
-       .rate_min =             4000,
-       .rate_max =             66200,
+       .rate_min =             AZF_FREQ_4000,
+       .rate_max =             AZF_FREQ_66200,
        .channels_min =         1,
        .channels_max =         2,
        .buffer_bytes_max =     65536,
@@ -1315,8 +1729,8 @@ static const struct snd_pcm_hardware snd_azf3328_capture =
        .rates =                SNDRV_PCM_RATE_5512 |
                                SNDRV_PCM_RATE_8000_48000 |
                                SNDRV_PCM_RATE_KNOT,
-       .rate_min =             4000,
-       .rate_max =             66200,
+       .rate_min =             AZF_FREQ_4000,
+       .rate_max =             AZF_FREQ_66200,
        .channels_min =         1,
        .channels_max =         2,
        .buffer_bytes_max =     65536,
@@ -1329,10 +1743,24 @@ static const struct snd_pcm_hardware snd_azf3328_capture =
 
 
 static unsigned int snd_azf3328_fixed_rates[] = {
-       4000, 4800, 5512, 6620, 8000, 9600, 11025, 13240, 16000, 22050, 32000,
-       44100, 48000, 66200 };
+       AZF_FREQ_4000,
+       AZF_FREQ_4800,
+       AZF_FREQ_5512,
+       AZF_FREQ_6620,
+       AZF_FREQ_8000,
+       AZF_FREQ_9600,
+       AZF_FREQ_11025,
+       AZF_FREQ_13240,
+       AZF_FREQ_16000,
+       AZF_FREQ_22050,
+       AZF_FREQ_32000,
+       AZF_FREQ_44100,
+       AZF_FREQ_48000,
+       AZF_FREQ_66200
+};
+
 static struct snd_pcm_hw_constraint_list snd_azf3328_hw_constraints_rates = {
-       .count = ARRAY_SIZE(snd_azf3328_fixed_rates), 
+       .count = ARRAY_SIZE(snd_azf3328_fixed_rates),
        .list = snd_azf3328_fixed_rates,
        .mask = 0,
 };
@@ -1346,7 +1774,7 @@ snd_azf3328_playback_open(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
 
        snd_azf3328_dbgcallenter();
-       chip->playback_substream = substream;
+       chip->audio_stream[AZF_PLAYBACK].substream = substream;
        runtime->hw = snd_azf3328_playback;
        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                   &snd_azf3328_hw_constraints_rates);
@@ -1361,7 +1789,7 @@ snd_azf3328_capture_open(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
 
        snd_azf3328_dbgcallenter();
-       chip->capture_substream = substream;
+       chip->audio_stream[AZF_CAPTURE].substream = substream;
        runtime->hw = snd_azf3328_capture;
        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                   &snd_azf3328_hw_constraints_rates);
@@ -1375,7 +1803,7 @@ snd_azf3328_playback_close(struct snd_pcm_substream *substream)
        struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
 
        snd_azf3328_dbgcallenter();
-       chip->playback_substream = NULL;
+       chip->audio_stream[AZF_PLAYBACK].substream = NULL;
        snd_azf3328_dbgcallleave();
        return 0;
 }
@@ -1386,7 +1814,7 @@ snd_azf3328_capture_close(struct snd_pcm_substream *substream)
        struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
 
        snd_azf3328_dbgcallenter();
-       chip->capture_substream = NULL;
+       chip->audio_stream[AZF_CAPTURE].substream = NULL;
        snd_azf3328_dbgcallleave();
        return 0;
 }
@@ -1441,102 +1869,8 @@ snd_azf3328_pcm(struct snd_azf3328 *chip, int device)
 
 /******************************************************************/
 
-#ifdef SUPPORT_JOYSTICK
-static int __devinit
-snd_azf3328_config_joystick(struct snd_azf3328 *chip, int dev)
-{
-       struct gameport *gp;
-       struct resource *r;
-
-       if (!joystick[dev])
-               return -ENODEV;
-
-       if (!(r = request_region(0x200, 8, "AZF3328 gameport"))) {
-               printk(KERN_WARNING "azt3328: cannot reserve joystick ports\n");
-               return -EBUSY;
-       }
-
-       chip->gameport = gp = gameport_allocate_port();
-       if (!gp) {
-               printk(KERN_ERR "azt3328: cannot allocate memory for gameport\n");
-               release_and_free_resource(r);
-               return -ENOMEM;
-       }
-
-       gameport_set_name(gp, "AZF3328 Gameport");
-       gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
-       gameport_set_dev_parent(gp, &chip->pci->dev);
-       gp->io = 0x200;
-       gameport_set_port_data(gp, r);
-
-       snd_azf3328_io2_outb(chip, IDX_IO2_LEGACY_ADDR,
-                             snd_azf3328_io2_inb(chip, IDX_IO2_LEGACY_ADDR) | LEGACY_JOY);
-
-       gameport_register_port(chip->gameport);
-
-       return 0;
-}
-
-static void
-snd_azf3328_free_joystick(struct snd_azf3328 *chip)
-{
-       if (chip->gameport) {
-               struct resource *r = gameport_get_port_data(chip->gameport);
-
-               gameport_unregister_port(chip->gameport);
-               chip->gameport = NULL;
-               /* disable gameport */
-               snd_azf3328_io2_outb(chip, IDX_IO2_LEGACY_ADDR,
-                                     snd_azf3328_io2_inb(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY);
-               release_and_free_resource(r);
-       }
-}
-#else
-static inline int
-snd_azf3328_config_joystick(struct snd_azf3328 *chip, int dev) { return -ENOSYS; }
-static inline void
-snd_azf3328_free_joystick(struct snd_azf3328 *chip) { }
-#endif
-
-/******************************************************************/
-
-static int
-snd_azf3328_free(struct snd_azf3328 *chip)
-{
-        if (chip->irq < 0)
-                goto __end_hw;
-
-       /* reset (close) mixer */
-       snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1); /* first mute master volume */
-       snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000);
-
-        /* interrupt setup - mask everything (FIXME!) */
-       /* well, at least we know how to disable the timer IRQ */
-       snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x00);
-
-       if (chip->irq >= 0)
-               synchronize_irq(chip->irq);
-__end_hw:
-       snd_azf3328_free_joystick(chip);
-        if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-       pci_release_regions(chip->pci);
-       pci_disable_device(chip->pci);
-
-        kfree(chip);
-        return 0;
-}
-
-static int
-snd_azf3328_dev_free(struct snd_device *device)
-{
-       struct snd_azf3328 *chip = device->device_data;
-       return snd_azf3328_free(chip);
-}
-
-/******************************************************************/
-
-/*** NOTE: the physical timer resolution actually is 1024000 ticks per second,
+/*** NOTE: the physical timer resolution actually is 1024000 ticks per second
+ *** (probably derived from main crystal via a divider of 24),
  *** but announcing those attributes to user-space would make programs
  *** configure the timer to a 1 tick value, resulting in an absolutely fatal
  *** timer IRQ storm.
@@ -1564,7 +1898,7 @@ snd_azf3328_timer_start(struct snd_timer *timer)
                delay = 49; /* minimum time is 49 ticks */
        }
        snd_azf3328_dbgtimer("setting timer countdown value %d, add COUNTDOWN|IRQ\n", delay);
-       delay |= TIMER_ENABLE_COUNTDOWN | TIMER_ENABLE_IRQ;
+       delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE;
        spin_lock_irqsave(&chip->reg_lock, flags);
        snd_azf3328_codec_outl(chip, IDX_IO_TIMER_VALUE, delay);
        spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -1582,7 +1916,7 @@ snd_azf3328_timer_stop(struct snd_timer *timer)
        chip = snd_timer_chip(timer);
        spin_lock_irqsave(&chip->reg_lock, flags);
        /* disable timer countdown and interrupt */
-       /* FIXME: should we write TIMER_ACK_IRQ here? */
+       /* FIXME: should we write TIMER_IRQ_ACK here? */
        snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0);
        spin_unlock_irqrestore(&chip->reg_lock, flags);
        snd_azf3328_dbgcallleave();
@@ -1626,9 +1960,10 @@ snd_azf3328_timer(struct snd_azf3328 *chip, int device)
 
        snd_azf3328_timer_hw.resolution *= seqtimer_scaling;
        snd_azf3328_timer_hw.ticks /= seqtimer_scaling;
-       if ((err = snd_timer_new(chip->card, "AZF3328", &tid, &timer)) < 0) {
+
+       err = snd_timer_new(chip->card, "AZF3328", &tid, &timer);
+       if (err < 0)
                goto out;
-       }
 
        strcpy(timer->name, "AZF3328 timer");
        timer->private_data = chip;
@@ -1636,6 +1971,8 @@ snd_azf3328_timer(struct snd_azf3328 *chip, int device)
 
        chip->timer = timer;
 
+       snd_azf3328_timer_stop(timer);
+
        err = 0;
 
 out:
@@ -1645,10 +1982,44 @@ out:
 
 /******************************************************************/
 
+static int
+snd_azf3328_free(struct snd_azf3328 *chip)
+{
+       if (chip->irq < 0)
+               goto __end_hw;
+
+       /* reset (close) mixer:
+        * first mute master volume, then reset
+        */
+       snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1);
+       snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000);
+
+       snd_azf3328_timer_stop(chip->timer);
+       snd_azf3328_gameport_free(chip);
+
+       if (chip->irq >= 0)
+               synchronize_irq(chip->irq);
+__end_hw:
+       if (chip->irq >= 0)
+               free_irq(chip->irq, chip);
+       pci_release_regions(chip->pci);
+       pci_disable_device(chip->pci);
+
+       kfree(chip);
+       return 0;
+}
+
+static int
+snd_azf3328_dev_free(struct snd_device *device)
+{
+       struct snd_azf3328 *chip = device->device_data;
+       return snd_azf3328_free(chip);
+}
+
 #if 0
 /* check whether a bit can be modified */
 static void
-snd_azf3328_test_bit(unsigned int reg, int bit)
+snd_azf3328_test_bit(unsigned unsigned reg, int bit)
 {
        unsigned char val, valoff, valon;
 
@@ -1659,42 +2030,74 @@ snd_azf3328_test_bit(unsigned int reg, int bit)
 
        outb(val|(1 << bit), reg);
        valon = inb(reg);
-       
+
        outb(val, reg);
 
-       printk(KERN_ERR "reg %04x bit %d: %02x %02x %02x\n", reg, bit, val, valoff, valon);
+       printk(KERN_ERR "reg %04x bit %d: %02x %02x %02x\n",
+                               reg, bit, val, valoff, valon
+       );
 }
 #endif
 
-#if DEBUG_MISC
-static void
+static inline void
 snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
 {
+#if DEBUG_MISC
        u16 tmp;
 
-       snd_azf3328_dbgmisc("codec_port 0x%lx, io2_port 0x%lx, mpu_port 0x%lx, synth_port 0x%lx, mixer_port 0x%lx, irq %d\n", chip->codec_port, chip->io2_port, chip->mpu_port, chip->synth_port, chip->mixer_port, chip->irq);
-
-       snd_azf3328_dbgmisc("io2 %02x %02x %02x %02x %02x %02x\n", snd_azf3328_io2_inb(chip, 0), snd_azf3328_io2_inb(chip, 1), snd_azf3328_io2_inb(chip, 2), snd_azf3328_io2_inb(chip, 3), snd_azf3328_io2_inb(chip, 4), snd_azf3328_io2_inb(chip, 5));
-
-       for (tmp=0; tmp <= 0x01; tmp += 1)
-               snd_azf3328_dbgmisc("0x%02x: opl 0x%04x, mpu300 0x%04x, mpu310 0x%04x, mpu320 0x%04x, mpu330 0x%04x\n", tmp, inb(0x388 + tmp), inb(0x300 + tmp), inb(0x310 + tmp), inb(0x320 + tmp), inb(0x330 + tmp));
+       snd_azf3328_dbgmisc(
+               "codec_io 0x%lx, game_io 0x%lx, mpu_io 0x%lx, "
+               "opl3_io 0x%lx, mixer_io 0x%lx, irq %d\n",
+               chip->codec_io, chip->game_io, chip->mpu_io,
+               chip->opl3_io, chip->mixer_io, chip->irq
+       );
+
+       snd_azf3328_dbgmisc("game %02x %02x %02x %02x %02x %02x\n",
+               snd_azf3328_game_inb(chip, 0),
+               snd_azf3328_game_inb(chip, 1),
+               snd_azf3328_game_inb(chip, 2),
+               snd_azf3328_game_inb(chip, 3),
+               snd_azf3328_game_inb(chip, 4),
+               snd_azf3328_game_inb(chip, 5)
+       );
+
+       for (tmp = 0; tmp < 0x07; tmp += 1)
+               snd_azf3328_dbgmisc("mpu_io 0x%04x\n", inb(chip->mpu_io + tmp));
+
+       for (tmp = 0; tmp <= 0x07; tmp += 1)
+               snd_azf3328_dbgmisc("0x%02x: game200 0x%04x, game208 0x%04x\n",
+                       tmp, inb(0x200 + tmp), inb(0x208 + tmp));
+
+       for (tmp = 0; tmp <= 0x01; tmp += 1)
+               snd_azf3328_dbgmisc(
+                       "0x%02x: mpu300 0x%04x, mpu310 0x%04x, mpu320 0x%04x, "
+                       "mpu330 0x%04x opl388 0x%04x opl38c 0x%04x\n",
+                               tmp,
+                               inb(0x300 + tmp),
+                               inb(0x310 + tmp),
+                               inb(0x320 + tmp),
+                               inb(0x330 + tmp),
+                               inb(0x388 + tmp),
+                               inb(0x38c + tmp)
+               );
 
        for (tmp = 0; tmp < AZF_IO_SIZE_CODEC; tmp += 2)
-               snd_azf3328_dbgmisc("codec 0x%02x: 0x%04x\n", tmp, snd_azf3328_codec_inw(chip, tmp));
+               snd_azf3328_dbgmisc("codec 0x%02x: 0x%04x\n",
+                       tmp, snd_azf3328_codec_inw(chip, tmp)
+               );
 
        for (tmp = 0; tmp < AZF_IO_SIZE_MIXER; tmp += 2)
-               snd_azf3328_dbgmisc("mixer 0x%02x: 0x%04x\n", tmp, snd_azf3328_mixer_inw(chip, tmp));
+               snd_azf3328_dbgmisc("mixer 0x%02x: 0x%04x\n",
+                       tmp, snd_azf3328_mixer_inw(chip, tmp)
+               );
+#endif /* DEBUG_MISC */
 }
-#else
-static inline void
-snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip) {}
-#endif
 
 static int __devinit
 snd_azf3328_create(struct snd_card *card,
-                                         struct pci_dev *pci,
-                                         unsigned long device_type,
-                                         struct snd_azf3328 ** rchip)
+                  struct pci_dev *pci,
+                  unsigned long device_type,
+                  struct snd_azf3328 **rchip)
 {
        struct snd_azf3328 *chip;
        int err;
@@ -1705,7 +2108,8 @@ snd_azf3328_create(struct snd_card *card,
 
        *rchip = NULL;
 
-       if ((err = pci_enable_device(pci)) < 0)
+       err = pci_enable_device(pci);
+       if (err < 0)
                return err;
 
        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
@@ -1721,20 +2125,25 @@ snd_azf3328_create(struct snd_card *card,
        /* check if we can restrict PCI DMA transfers to 24 bits */
        if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 ||
            pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) {
-               snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n");
+               snd_printk(KERN_ERR "architecture does not support "
+                                       "24bit PCI busmaster DMA\n"
+               );
                err = -ENXIO;
                goto out_err;
        }
 
-       if ((err = pci_request_regions(pci, "Aztech AZF3328")) < 0) {
+       err = pci_request_regions(pci, "Aztech AZF3328");
+       if (err < 0)
                goto out_err;
-       }
 
-       chip->codec_port = pci_resource_start(pci, 0);
-       chip->io2_port   = pci_resource_start(pci, 1);
-       chip->mpu_port   = pci_resource_start(pci, 2);
-       chip->synth_port = pci_resource_start(pci, 3);
-       chip->mixer_port = pci_resource_start(pci, 4);
+       chip->codec_io = pci_resource_start(pci, 0);
+       chip->game_io  = pci_resource_start(pci, 1);
+       chip->mpu_io   = pci_resource_start(pci, 2);
+       chip->opl3_io = pci_resource_start(pci, 3);
+       chip->mixer_io = pci_resource_start(pci, 4);
+
+       chip->audio_stream[AZF_PLAYBACK].portbase = chip->codec_io + 0x00;
+       chip->audio_stream[AZF_CAPTURE].portbase   = chip->codec_io + 0x20;
 
        if (request_irq(pci->irq, snd_azf3328_interrupt,
                        IRQF_SHARED, card->shortname, chip)) {
@@ -1747,29 +2156,29 @@ snd_azf3328_create(struct snd_card *card,
        synchronize_irq(chip->irq);
 
        snd_azf3328_debug_show_ports(chip);
-       
-       if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+
+       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+       if (err < 0)
                goto out_err;
-       }
 
        /* create mixer interface & switches */
-       if ((err = snd_azf3328_mixer_new(chip)) < 0)
+       err = snd_azf3328_mixer_new(chip);
+       if (err < 0)
                goto out_err;
 
-#if 0
-       /* set very low bitrate to reduce noise and power consumption? */
-       snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, 5512, 8, 1);
-#endif
+       /* shutdown codecs to save power */
+               /* have snd_azf3328_codec_activity() act properly */
+       chip->audio_stream[AZF_PLAYBACK].running = 1;
+       snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 0);
 
        /* standard chip init stuff */
-       /* default IRQ init value */
+               /* default IRQ init value */
        tmp = DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE;
 
        spin_lock_irq(&chip->reg_lock);
        snd_azf3328_codec_outb(chip, IDX_IO_PLAY_FLAGS, tmp);
        snd_azf3328_codec_outb(chip, IDX_IO_REC_FLAGS, tmp);
        snd_azf3328_codec_outb(chip, IDX_IO_SOMETHING_FLAGS, tmp);
-       snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x00); /* disable timer */
        spin_unlock_irq(&chip->reg_lock);
 
        snd_card_set_dev(card, &pci->dev);
@@ -1805,52 +2214,61 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                return -ENOENT;
        }
 
-       card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0 );
+       card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
        if (card == NULL)
                return -ENOMEM;
 
        strcpy(card->driver, "AZF3328");
        strcpy(card->shortname, "Aztech AZF3328 (PCI168)");
 
-        if ((err = snd_azf3328_create(card, pci, pci_id->driver_data, &chip)) < 0) {
+       err = snd_azf3328_create(card, pci, pci_id->driver_data, &chip);
+       if (err < 0)
                goto out_err;
-       }
 
        card->private_data = chip;
 
-       if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_MPU401,
-                                       chip->mpu_port, MPU401_INFO_INTEGRATED,
-                                       pci->irq, 0, &chip->rmidi)) < 0) {
-               snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", chip->mpu_port);
+       err = snd_mpu401_uart_new(
+               card, 0, MPU401_HW_MPU401, chip->mpu_io, MPU401_INFO_INTEGRATED,
+               pci->irq, 0, &chip->rmidi
+       );
+       if (err < 0) {
+               snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n",
+                               chip->mpu_io
+               );
                goto out_err;
        }
 
-       if ((err = snd_azf3328_timer(chip, 0)) < 0) {
+       err = snd_azf3328_timer(chip, 0);
+       if (err < 0)
                goto out_err;
-       }
 
-       if ((err = snd_azf3328_pcm(chip, 0)) < 0) {
+       err = snd_azf3328_pcm(chip, 0);
+       if (err < 0)
                goto out_err;
-       }
 
-       if (snd_opl3_create(card, chip->synth_port, chip->synth_port+2,
+       if (snd_opl3_create(card, chip->opl3_io, chip->opl3_io+2,
                            OPL3_HW_AUTO, 1, &opl3) < 0) {
                snd_printk(KERN_ERR "azf3328: no OPL3 device at 0x%lx-0x%lx?\n",
-                          chip->synth_port, chip->synth_port+2 );
+                          chip->opl3_io, chip->opl3_io+2
+               );
        } else {
-               if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
+               /* need to use IDs 1, 2 since ID 0 is snd_azf3328_timer above */
+               err = snd_opl3_timer_new(opl3, 1, 2);
+               if (err < 0)
+                       goto out_err;
+               err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
+               if (err < 0)
                        goto out_err;
-               }
        }
 
        opl3->private_data = chip;
 
        sprintf(card->longname, "%s at 0x%lx, irq %i",
-               card->shortname, chip->codec_port, chip->irq);
+               card->shortname, chip->codec_io, chip->irq);
 
-       if ((err = snd_card_register(card)) < 0) {
+       err = snd_card_register(card);
+       if (err < 0)
                goto out_err;
-       }
 
 #ifdef MODULE
        printk(
@@ -1861,19 +2279,18 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        1024000 / seqtimer_scaling, seqtimer_scaling);
 #endif
 
-       if (snd_azf3328_config_joystick(chip, dev) < 0)
-               snd_azf3328_io2_outb(chip, IDX_IO2_LEGACY_ADDR,
-                             snd_azf3328_io2_inb(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY);
+       snd_azf3328_gameport(chip, dev);
 
        pci_set_drvdata(pci, card);
        dev++;
 
        err = 0;
        goto out;
-       
+
 out_err:
+       snd_printk(KERN_ERR "azf3328: something failed, exiting\n");
        snd_card_free(card);
-       
+
 out:
        snd_azf3328_dbgcallleave();
        return err;
@@ -1894,27 +2311,31 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
 {
        struct snd_card *card = pci_get_drvdata(pci);
        struct snd_azf3328 *chip = card->private_data;
-       int reg;
+       unsigned reg;
 
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-       
+
        snd_pcm_suspend_all(chip->pcm);
 
-       for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; reg++)
-               chip->saved_regs_mixer[reg] = inw(chip->mixer_port + reg * 2);
+       for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg)
+               chip->saved_regs_mixer[reg] = inw(chip->mixer_io + reg * 2);
 
        /* make sure to disable master volume etc. to prevent looping sound */
        snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1);
        snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
-       
-       for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; reg++)
-               chip->saved_regs_codec[reg] = inw(chip->codec_port + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++)
-               chip->saved_regs_io2[reg] = inw(chip->io2_port + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; reg++)
-               chip->saved_regs_mpu[reg] = inw(chip->mpu_port + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++)
-               chip->saved_regs_synth[reg] = inw(chip->synth_port + reg * 2);
+
+       for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; ++reg)
+               chip->saved_regs_codec[reg] = inw(chip->codec_io + reg * 2);
+
+       /* manually store the one currently relevant write-only reg, too */
+       chip->saved_regs_codec[IDX_IO_6AH / 2] = chip->shadow_reg_codec_6AH;
+
+       for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg)
+               chip->saved_regs_game[reg] = inw(chip->game_io + reg * 2);
+       for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; ++reg)
+               chip->saved_regs_mpu[reg] = inw(chip->mpu_io + reg * 2);
+       for (reg = 0; reg < AZF_IO_SIZE_OPL3_PM / 2; ++reg)
+               chip->saved_regs_opl3[reg] = inw(chip->opl3_io + reg * 2);
 
        pci_disable_device(pci);
        pci_save_state(pci);
@@ -1927,7 +2348,7 @@ snd_azf3328_resume(struct pci_dev *pci)
 {
        struct snd_card *card = pci_get_drvdata(pci);
        struct snd_azf3328 *chip = card->private_data;
-       int reg;
+       unsigned reg;
 
        pci_set_power_state(pci, PCI_D0);
        pci_restore_state(pci);
@@ -1939,23 +2360,21 @@ snd_azf3328_resume(struct pci_dev *pci)
        }
        pci_set_master(pci);
 
-       for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++)
-               outw(chip->saved_regs_io2[reg], chip->io2_port + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; reg++)
-               outw(chip->saved_regs_mpu[reg], chip->mpu_port + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++)
-               outw(chip->saved_regs_synth[reg], chip->synth_port + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; reg++)
-               outw(chip->saved_regs_mixer[reg], chip->mixer_port + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; reg++)
-               outw(chip->saved_regs_codec[reg], chip->codec_port + reg * 2);
+       for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg)
+               outw(chip->saved_regs_game[reg], chip->game_io + reg * 2);
+       for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; ++reg)
+               outw(chip->saved_regs_mpu[reg], chip->mpu_io + reg * 2);
+       for (reg = 0; reg < AZF_IO_SIZE_OPL3_PM / 2; ++reg)
+               outw(chip->saved_regs_opl3[reg], chip->opl3_io + reg * 2);
+       for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg)
+               outw(chip->saved_regs_mixer[reg], chip->mixer_io + reg * 2);
+       for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; ++reg)
+               outw(chip->saved_regs_codec[reg], chip->codec_io + reg * 2);
 
        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
        return 0;
 }
-#endif
-
-
+#endif /* CONFIG_PM */
 
 
 static struct pci_driver driver = {
index 679fa992e2bc4db09f5e8a1066e55620295f5e1b..7e3e8942d0733f01fa3b9d5363878f2f9bf2f665 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef __SOUND_AZT3328_H
 #define __SOUND_AZT3328_H
 
-/* "PU" == "power-up value", as tested on PCI168 PCI rev. 10 */
+/* "PU" == "power-up value", as tested on PCI168 PCI rev. 10
+ * "WRITE_ONLY"  == register does not indicate actual bit values */
 
 /*** main I/O area port indices ***/
 /* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */
   #define SOUNDFORMAT_XTAL1            0x00
   #define SOUNDFORMAT_XTAL2            0x01
     /* all _SUSPECTED_ values are not used by Windows drivers, so we don't
-     * have any hard facts, only rough measurements */
+     * have any hard facts, only rough measurements.
+     * All we know is that the crystal used on the board has 24.576MHz,
+     * like many soundcards (which results in the frequencies below when
+     * using certain divider values selected by the values below) */
     #define SOUNDFORMAT_FREQ_SUSPECTED_4000    0x0c | SOUNDFORMAT_XTAL1
     #define SOUNDFORMAT_FREQ_SUSPECTED_4800    0x0a | SOUNDFORMAT_XTAL1
     #define SOUNDFORMAT_FREQ_5510              0x0c | SOUNDFORMAT_XTAL2
   #define SOUNDFORMAT_FLAG_16BIT       0x0010
   #define SOUNDFORMAT_FLAG_2CHANNELS   0x0020
 
+/* define frequency helpers, for maximum value safety */
+enum azf_freq_t {
+#define AZF_FREQ(rate) AZF_FREQ_##rate = rate
+  AZF_FREQ(4000),
+  AZF_FREQ(4800),
+  AZF_FREQ(5512),
+  AZF_FREQ(6620),
+  AZF_FREQ(8000),
+  AZF_FREQ(9600),
+  AZF_FREQ(11025),
+  AZF_FREQ(13240),
+  AZF_FREQ(16000),
+  AZF_FREQ(22050),
+  AZF_FREQ(32000),
+  AZF_FREQ(44100),
+  AZF_FREQ(48000),
+  AZF_FREQ(66200),
+#undef AZF_FREQ
+} AZF_FREQUENCIES;
+
 /** recording area (see also: playback bit flag definitions) **/
 #define IDX_IO_REC_FLAGS       0x20 /* ??, PU:0x0000 */
 #define IDX_IO_REC_IRQTYPE     0x22 /* ??, PU:0x0000 */
 
 /** DirectX timer, main interrupt area (FIXME: and something else?) **/ 
 #define IDX_IO_TIMER_VALUE     0x60 /* found this timer area by pure luck :-) */
-  #define TIMER_VALUE_MASK             0x000fffffUL /* timer countdown value; triggers IRQ when timer is finished */
-  #define TIMER_ENABLE_COUNTDOWN       0x01000000UL /* activate the timer countdown */
-  #define TIMER_ENABLE_IRQ             0x02000000UL /* trigger timer IRQ on zero transition */
-  #define TIMER_ACK_IRQ                        0x04000000UL /* being set in IRQ handler in case port 0x00 (hmm, not port 0x64!?!?) had 0x0020 set upon IRQ handler */
+  /* timer countdown value; triggers IRQ when timer is finished */
+  #define TIMER_VALUE_MASK             0x000fffffUL
+  /* activate timer countdown */
+  #define TIMER_COUNTDOWN_ENABLE       0x01000000UL
+  /* trigger timer IRQ on zero transition */
+  #define TIMER_IRQ_ENABLE             0x02000000UL
+  /* being set in IRQ handler in case port 0x00 (hmm, not port 0x64!?!?)
+   * had 0x0020 set upon IRQ handler */
+  #define TIMER_IRQ_ACK                        0x04000000UL
 #define IDX_IO_IRQSTATUS        0x64
-  #define IRQ_PLAYBACK                 0x0001
-  #define IRQ_RECORDING                        0x0002
-  #define IRQ_MPU401                   0x0010
-  #define IRQ_TIMER                    0x0020 /* DirectX timer */
-  #define IRQ_UNKNOWN1                 0x0040 /* probably unused, or possibly I2S port? or gameport IRQ? */
-  #define IRQ_UNKNOWN2                 0x0080 /* probably unused, or possibly I2S port? or gameport IRQ? */
+  /* some IRQ bit in here might also be used to signal a power-management timer
+   * timeout, to request shutdown of the chip (e.g. AD1815JS has such a thing).
+   * Some OPL3 hardware (e.g. in LM4560) has some special timer hardware which
+   * can trigger an OPL3 timer IRQ, so maybe there's such a thing as well... */
+
+  #define IRQ_PLAYBACK 0x0001
+  #define IRQ_RECORDING        0x0002
+  #define IRQ_UNKNOWN1 0x0004 /* most probably I2S port */
+  #define IRQ_GAMEPORT 0x0008 /* Interrupt of Digital(ly) Enhanced Game Port */
+  #define IRQ_MPU401   0x0010
+  #define IRQ_TIMER    0x0020 /* DirectX timer */
+  #define IRQ_UNKNOWN2 0x0040 /* probably unused, or possibly I2S port? */
+  #define IRQ_UNKNOWN3 0x0080 /* probably unused, or possibly I2S port? */
 #define IDX_IO_66H             0x66    /* writing 0xffff returns 0x0000 */
-#define IDX_IO_SOME_VALUE      0x68    /* this is set to e.g. 0x3ff or 0x300, and writable; maybe some buffer limit, but I couldn't find out more, PU:0x00ff */
-#define IDX_IO_6AH             0x6A    /* this WORD can be set to have bits 0x0028 activated (FIXME: correct??); actually inhibits PCM playback!!! maybe power management?? */
-  #define IO_6A_PAUSE_PLAYBACK         0x0200 /* bit 9; sure, this pauses playback, but what the heck is this really about?? */
-#define IDX_IO_6CH             0x6C
-#define IDX_IO_6EH             0x6E    /* writing 0xffff returns 0x83fe */
-/* further I/O indices not saved/restored, so probably not used */
+  /* this is set to e.g. 0x3ff or 0x300, and writable;
+   * maybe some buffer limit, but I couldn't find out more, PU:0x00ff: */
+#define IDX_IO_SOME_VALUE      0x68
+  #define IO_68_RANDOM_TOGGLE1 0x0100  /* toggles randomly */
+  #define IO_68_RANDOM_TOGGLE2 0x0200  /* toggles randomly */
+  /* umm, nope, behaviour of these bits changes depending on what we wrote
+   * to 0x6b!!
+   * And they change upon playback/stop, too:
+   * Writing a value to 0x68 will display this exact value during playback,
+   * too but when stopped it can fall back to a rather different
+   * seemingly random value). Hmm, possibly this is a register which
+   * has a remote shadow which needs proper device supply which only exists
+   * in case playback is active? Or is this driver-induced?
+   */
+
+/* this WORD can be set to have bits 0x0028 activated (FIXME: correct??);
+ * actually inhibits PCM playback!!! maybe power management??: */
+#define IDX_IO_6AH             0x6A /* WRITE_ONLY! */
+  /* bit 5: enabling this will activate permanent counting of bytes 2/3
+   * at gameport I/O (0xb402/3) (equal values each) and cause
+   * gameport legacy I/O at 0x0200 to be _DISABLED_!
+   * Is this Digital Enhanced Game Port Enable??? Or maybe it's Testmode
+   * for Enhanced Digital Gameport (see 4D Wave DX card): */
+  #define IO_6A_SOMETHING1_GAMEPORT    0x0020
+  /* bit 8; sure, this _pauses_ playback (later resumes at same spot!),
+   * but what the heck is this really about??: */
+  #define IO_6A_PAUSE_PLAYBACK_BIT8    0x0100
+  /* bit 9; sure, this _pauses_ playback (later resumes at same spot!),
+   * but what the heck is this really about??: */
+  #define IO_6A_PAUSE_PLAYBACK_BIT9    0x0200
+       /* BIT8 and BIT9 are _NOT_ able to affect OPL3 MIDI playback,
+        * thus it suggests influence on PCM only!!
+        * However OTOH there seems to be no bit anywhere around here
+        * which is able to disable OPL3... */
+  /* bit 10: enabling this actually changes values at legacy gameport
+   * I/O address (0x200); is this enabling of the Digital Enhanced Game Port???
+   * Or maybe this simply switches off the NE558 circuit, since enabling this
+   * still lets us evaluate button states, but not axis states */
+  #define IO_6A_SOMETHING2_GAMEPORT      0x0400
+       /* writing 0x0300: causes quite some crackling during
+        * PC activity such as switching windows (PCI traffic??
+        * --> FIFO/timing settings???) */
+       /* writing 0x0100 plus/or 0x0200 inhibits playback */
+       /* since the Windows .INF file has Flag_Enable_JoyStick and
+        * Flag_Enable_SB_DOS_Emulation directly together, it stands to reason
+        * that some other bit in this same register might be responsible
+        * for SB DOS Emulation activation (note that the file did NOT define
+        * a switch for OPL3!) */
+#define IDX_IO_6CH             0x6C    /* unknown; fully read-writable */
+#define IDX_IO_6EH             0x6E
+       /* writing 0xffff returns 0x83fe (or 0x03fe only).
+        * writing 0x83 (and only 0x83!!) to 0x6f will cause 0x6c to switch
+        * from 0000 to ffff. */
 
+/* further I/O indices not saved/restored and not readable after writing,
+ * so probably not used */
 
-/*** I/O 2 area port indices ***/
+
+/*** Gameport area port indices ***/
 /* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ 
-#define AZF_IO_SIZE_IO2                0x08
-#define AZF_IO_SIZE_IO2_PM     0x06
+#define AZF_IO_SIZE_GAME               0x08
+#define AZF_IO_SIZE_GAME_PM    0x06
+
+enum {
+       AZF_GAME_LEGACY_IO_PORT = 0x200
+} AZF_GAME_CONFIGS;
+
+#define IDX_GAME_LEGACY_COMPATIBLE     0x00
+       /* in some operation mode, writing anything to this port
+        * triggers an interrupt:
+        * yup, that's in case IDX_GAME_01H has one of the
+        * axis measurement bits enabled
+        * (and of course one needs to have GAME_HWCFG_IRQ_ENABLE, too) */
+
+#define IDX_GAME_AXES_CONFIG            0x01
+       /* NOTE: layout of this register awfully similar (read: "identical??")
+        * to AD1815JS.pdf (p.29) */
+
+  /* enables axis 1 (X axis) measurement: */
+  #define GAME_AXES_ENABLE_1           0x01
+  /* enables axis 2 (Y axis) measurement: */
+  #define GAME_AXES_ENABLE_2           0x02
+  /* enables axis 3 (X axis) measurement: */
+  #define GAME_AXES_ENABLE_3           0x04
+  /* enables axis 4 (Y axis) measurement: */
+  #define GAME_AXES_ENABLE_4           0x08
+  /* selects the current axis to read the measured value of
+   * (at IDX_GAME_AXIS_VALUE):
+   * 00 = axis 1, 01 = axis 2, 10 = axis 3, 11 = axis 4: */
+  #define GAME_AXES_READ_MASK          0x30
+  /* enable to have the latch continuously accept ADC values
+   * (and continuously cause interrupts in case interrupts are enabled);
+   * AD1815JS.pdf says it's ~16ms interval there: */
+  #define GAME_AXES_LATCH_ENABLE       0x40
+  /* joystick data (measured axes) ready for reading: */
+  #define GAME_AXES_SAMPLING_READY     0x80
+
+  /* NOTE: other card specs (SiS960 and others!) state that the
+   * game position latches should be frozen when reading and be freed
+   * (== reset?) after reading!!!
+   * Freezing most likely means disabling 0x40 (GAME_AXES_LATCH_ENABLE),
+   *  but how to free the value? */
+  /* An internet search for "gameport latch ADC" should provide some insight
+   * into how to program such a gameport system. */
+
+  /* writing 0xf0 to 01H once reset both counters to 0, in some special mode!?
+   * yup, in case 6AH 0x20 is not enabled
+   * (and 0x40 is sufficient, 0xf0 is not needed) */
+
+#define IDX_GAME_AXIS_VALUE    0x02
+       /* R: value of currently configured axis (word value!);
+        * W: trigger axis measurement */
+
+#define IDX_GAME_HWCONFIG      0x04
+       /* note: bits 4 to 7 are never set (== 0) when reading!
+        * --> reserved bits? */
+  /* enables IRQ notification upon axes measurement ready: */
+  #define GAME_HWCFG_IRQ_ENABLE                        0x01
+  /* these bits choose a different frequency for the
+   *  internal ADC counter increment.
+   * hmm, seems to be a combo of bits:
+   * 00 --> standard frequency
+   * 10 --> 1/2
+   * 01 --> 1/20
+   * 11 --> 1/200: */
+  #define GAME_HWCFG_ADC_COUNTER_FREQ_MASK     0x06
 
-#define IDX_IO2_LEGACY_ADDR    0x04
-  #define LEGACY_SOMETHING             0x01 /* OPL3?? */
-  #define LEGACY_JOY                   0x08
+  /* enable gameport legacy I/O address (0x200)
+   * I was unable to locate any configurability for a different address: */
+  #define GAME_HWCFG_LEGACY_ADDRESS_ENABLE     0x08
 
+/*** MPU401 ***/
 #define AZF_IO_SIZE_MPU                0x04
 #define AZF_IO_SIZE_MPU_PM     0x04
 
-#define AZF_IO_SIZE_SYNTH      0x08
-#define AZF_IO_SIZE_SYNTH_PM   0x06
+/*** OPL3 synth ***/
+#define AZF_IO_SIZE_OPL3       0x08
+#define AZF_IO_SIZE_OPL3_PM    0x06
+/* hmm, given that a standard OPL3 has 4 registers only,
+ * there might be some enhanced functionality lurking at the end
+ * (especially since register 0x04 has a "non-empty" value 0xfe) */
 
 /*** mixer I/O area port indices ***/
 /* (only 0x22 of 0x40 bytes saved/restored by Windows driver)
index ecbe79b67e437c0d94018e67e1a15f12984a2dbd..2f8b28add27687cfb63815836a72a06e1050eb92 100644 (file)
@@ -249,6 +249,11 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
           .name   = "MSI K8N Diamond MB [SB0438]",
           .gpio_type = 2,
           .i2c_adc = 1 } ,
+        /* Another MSI K8N Diamond MB, which has apprently a different SSID */
+        { .serial = 0x10091102,
+          .name   = "MSI K8N Diamond MB",
+          .gpio_type = 2,
+          .i2c_adc = 1 } ,
         /* Shuttle XPC SD31P which has an onboard Creative Labs
          * Sound Blaster Live! 24-bit EAX
          * high-definition 7.1 audio processor".
index 548c9cc81af5f5c05967ac2eae2d6c9d5db51ab9..2f283ea6ad9af4cd9762c0a5bb7fc116e4e79798 100644 (file)
@@ -1528,6 +1528,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .ca0151_chip = 1,
         .spk71 = 1,
         .spdif_bug = 1,
+        .invert_shared_spdif = 1,      /* digital/analog switch swapped */
         .adc_1361t = 1,  /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */
         .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .revision = 0x04,
index fd221209abcb221f6db0dcf323476b8620e40331..f34bbfb705f5f7c870d50012aa17e7c7b57b93ee 100644 (file)
@@ -1578,6 +1578,10 @@ static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
                ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
        else
                ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
+       if (emu->card_capabilities->invert_shared_spdif)
+               ucontrol->value.integer.value[0] =
+                       !ucontrol->value.integer.value[0];
+               
        return 0;
 }
 
@@ -1586,15 +1590,18 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
 {
        unsigned long flags;
        struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
-       unsigned int reg, val;
+       unsigned int reg, val, sw;
        int change = 0;
 
+       sw = ucontrol->value.integer.value[0];
+       if (emu->card_capabilities->invert_shared_spdif)
+               sw = !sw;
        spin_lock_irqsave(&emu->reg_lock, flags);
        if ( emu->card_capabilities->i2c_adc) {
                /* Do nothing for Audigy 2 ZS Notebook */
        } else if (emu->audigy) {
                reg = inl(emu->port + A_IOCFG);
-               val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
+               val = sw ? A_IOCFG_GPOUT0 : 0;
                change = (reg & A_IOCFG_GPOUT0) != val;
                if (change) {
                        reg &= ~A_IOCFG_GPOUT0;
@@ -1603,7 +1610,7 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
                }
        }
        reg = inl(emu->port + HCFG);
-       val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
+       val = sw ? HCFG_GPOUT0 : 0;
        change |= (reg & HCFG_GPOUT0) != val;
        if (change) {
                reg &= ~HCFG_GPOUT0;
index 916c1dbcd53cf919f6a420b86f893a676115302e..7d379f5131fbf61d4ab527a51bac881592c96fff 100644 (file)
@@ -437,43 +437,49 @@ static void get_single_page_range(struct snd_util_memhdr *hdr,
        *last_page_ret = last_page;
 }
 
+/* release allocated pages */
+static void __synth_free_pages(struct snd_emu10k1 *emu, int first_page,
+                              int last_page)
+{
+       int page;
+
+       for (page = first_page; page <= last_page; page++) {
+               free_page((unsigned long)emu->page_ptr_table[page]);
+               emu->page_addr_table[page] = 0;
+               emu->page_ptr_table[page] = NULL;
+       }
+}
+
 /*
  * allocate kernel pages
  */
 static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
 {
        int page, first_page, last_page;
-       struct snd_dma_buffer dmab;
 
        emu10k1_memblk_init(blk);
        get_single_page_range(emu->memhdr, blk, &first_page, &last_page);
        /* allocate kernel pages */
        for (page = first_page; page <= last_page; page++) {
-               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci),
-                                       PAGE_SIZE, &dmab) < 0)
-                       goto __fail;
-               if (! is_valid_page(emu, dmab.addr)) {
-                       snd_dma_free_pages(&dmab);
-                       goto __fail;
+               /* first try to allocate from <4GB zone */
+               struct page *p = alloc_page(GFP_KERNEL | GFP_DMA32 |
+                                           __GFP_NOWARN);
+               if (!p || (page_to_pfn(p) & ~(emu->dma_mask >> PAGE_SHIFT))) {
+                       if (p)
+                               __free_page(p);
+                       /* try to allocate from <16MB zone */
+                       p = alloc_page(GFP_ATOMIC | GFP_DMA |
+                                      __GFP_NORETRY | /* no OOM-killer */
+                                      __GFP_NOWARN);
+               }
+               if (!p) {
+                       __synth_free_pages(emu, first_page, page - 1);
+                       return -ENOMEM;
                }
-               emu->page_addr_table[page] = dmab.addr;
-               emu->page_ptr_table[page] = dmab.area;
+               emu->page_addr_table[page] = page_to_phys(p);
+               emu->page_ptr_table[page] = page_address(p);
        }
        return 0;
-
-__fail:
-       /* release allocated pages */
-       last_page = page - 1;
-       for (page = first_page; page <= last_page; page++) {
-               dmab.area = emu->page_ptr_table[page];
-               dmab.addr = emu->page_addr_table[page];
-               dmab.bytes = PAGE_SIZE;
-               snd_dma_free_pages(&dmab);
-               emu->page_addr_table[page] = 0;
-               emu->page_ptr_table[page] = NULL;
-       }
-
-       return -ENOMEM;
 }
 
 /*
@@ -481,23 +487,10 @@ __fail:
  */
 static int synth_free_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
 {
-       int page, first_page, last_page;
-       struct snd_dma_buffer dmab;
+       int first_page, last_page;
 
        get_single_page_range(emu->memhdr, blk, &first_page, &last_page);
-       dmab.dev.type = SNDRV_DMA_TYPE_DEV;
-       dmab.dev.dev = snd_dma_pci_data(emu->pci);
-       for (page = first_page; page <= last_page; page++) {
-               if (emu->page_ptr_table[page] == NULL)
-                       continue;
-               dmab.area = emu->page_ptr_table[page];
-               dmab.addr = emu->page_addr_table[page];
-               dmab.bytes = PAGE_SIZE;
-               snd_dma_free_pages(&dmab);
-               emu->page_addr_table[page] = 0;
-               emu->page_ptr_table[page] = NULL;
-       }
-
+       __synth_free_pages(emu, first_page, last_page);
        return 0;
 }
 
index a6be6e3e8716026b8a8e129f5e7bc9d9ec31b37f..d2e1093f8e972306727255a46ffb7ce7d59ccf2e 100644 (file)
@@ -2335,7 +2335,7 @@ int snd_hda_check_board_config(struct hda_codec *codec,
        if (!tbl)
                return -1;
        if (tbl->value >= 0 && tbl->value < num_configs) {
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
                char tmp[10];
                const char *model = NULL;
                if (models)
index dcd390b2bbaad8b031c8a7fc49ca5aa91f0b6356..efc682888b3173242510a0705accba40b09ad1cd 100644 (file)
@@ -78,7 +78,7 @@ enum {
 #define AC_VERB_GET_BEEP_CONTROL               0x0f0a
 #define AC_VERB_GET_EAPD_BTLENABLE             0x0f0c
 #define AC_VERB_GET_DIGI_CONVERT_1             0x0f0d
-#define AC_VERB_GET_DIGI_CONVERT_2             0x0f0e
+#define AC_VERB_GET_DIGI_CONVERT_2             0x0f0e /* unused */
 #define AC_VERB_GET_VOLUME_KNOB_CONTROL                0x0f0f
 /* f10-f1a: GPIO */
 #define AC_VERB_GET_GPIO_DATA                  0x0f15
index 2177d9af533496a4583d943c6f648d241f9ef078..6e18a422d993efcf68a2bf4be92d534f96f30d25 100644 (file)
@@ -88,7 +88,7 @@ static int hda_hwdep_ioctl_compat(struct snd_hwdep *hw, struct file *file,
 
 static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
 {
-#ifndef CONFIG_SND_DEBUG_DETECT
+#ifndef CONFIG_SND_DEBUG_VERBOSE
        if (!capable(CAP_SYS_RAWIO))
                return -EACCES;
 #endif
index b3a618eb42cdf5b4a45bc861312b974b7ce00581..16715a68ba5e59c362b5ea3d3db252b4f022523d 100644 (file)
@@ -55,6 +55,7 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
 static char *model[SNDRV_CARDS];
 static int position_fix[SNDRV_CARDS];
+static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
 static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
 static int single_cmd;
 static int enable_msi;
@@ -69,7 +70,9 @@ module_param_array(model, charp, NULL, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 module_param_array(position_fix, int, NULL, 0444);
 MODULE_PARM_DESC(position_fix, "Fix DMA pointer "
-                "(0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size).");
+                "(0 = auto, 1 = none, 2 = POSBUF).");
+module_param_array(bdl_pos_adj, int, NULL, 0644);
+MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
 module_param_array(probe_mask, int, NULL, 0444);
 MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
 module_param(single_cmd, bool, 0444);
@@ -197,6 +200,10 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define ATIHDMI_NUM_CAPTURE    0
 #define ATIHDMI_NUM_PLAYBACK   1
 
+/* TERA has 4 playback and 3 capture */
+#define TERA_NUM_CAPTURE       3
+#define TERA_NUM_PLAYBACK      4
+
 /* this number is statically defined for simplicity */
 #define MAX_AZX_DEV            16
 
@@ -259,9 +266,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 /* position fix mode */
 enum {
        POS_FIX_AUTO,
-       POS_FIX_NONE,
+       POS_FIX_LPIB,
        POS_FIX_POSBUF,
-       POS_FIX_FIFO,
 };
 
 /* Defines for ATI HD Audio support in SB450 south bridge */
@@ -285,6 +291,7 @@ struct azx_dev {
        u32 *posbuf;            /* position buffer pointer */
 
        unsigned int bufsize;   /* size of the play buffer in bytes */
+       unsigned int period_bytes; /* size of the period in bytes */
        unsigned int frags;     /* number for period in the play buffer */
        unsigned int fifo_size; /* FIFO size */
 
@@ -301,11 +308,11 @@ struct azx_dev {
                                         */
        unsigned char stream_tag;       /* assigned stream */
        unsigned char index;            /* stream index */
-       /* for sanity check of position buffer */
-       unsigned int period_intr;
 
        unsigned int opened :1;
        unsigned int running :1;
+       unsigned int irq_pending :1;
+       unsigned int irq_ignore :1;
 };
 
 /* CORB/RIRB */
@@ -323,6 +330,7 @@ struct azx_rb {
 struct azx {
        struct snd_card *card;
        struct pci_dev *pci;
+       int dev_index;
 
        /* chip type specific */
        int driver_type;
@@ -366,9 +374,13 @@ struct azx {
        unsigned int single_cmd :1;
        unsigned int polling_mode :1;
        unsigned int msi :1;
+       unsigned int irq_pending_warned :1;
 
        /* for debugging */
        unsigned int last_cmd;  /* last issued command (to sync) */
+
+       /* for pending irqs */
+       struct work_struct irq_pending_work;
 };
 
 /* driver types */
@@ -381,6 +393,7 @@ enum {
        AZX_DRIVER_SIS,
        AZX_DRIVER_ULI,
        AZX_DRIVER_NVIDIA,
+       AZX_DRIVER_TERA,
 };
 
 static char *driver_short_names[] __devinitdata = {
@@ -392,6 +405,7 @@ static char *driver_short_names[] __devinitdata = {
        [AZX_DRIVER_SIS] = "HDA SIS966",
        [AZX_DRIVER_ULI] = "HDA ULI M5461",
        [AZX_DRIVER_NVIDIA] = "HDA NVidia",
+       [AZX_DRIVER_TERA] = "HDA Teradici", 
 };
 
 /*
@@ -426,11 +440,6 @@ static char *driver_short_names[] __devinitdata = {
 /* for pcm support */
 #define get_azx_dev(substream) (substream->runtime->private_data)
 
-/* Get the upper 32bit of the given dma_addr_t
- * Compiler should optimize and eliminate the code if dma_addr_t is 32bit
- */
-#define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0)
-
 static int azx_acquire_irq(struct azx *chip, int do_disconnect);
 
 /*
@@ -461,7 +470,7 @@ static void azx_init_cmd_io(struct azx *chip)
        chip->corb.addr = chip->rb.addr;
        chip->corb.buf = (u32 *)chip->rb.area;
        azx_writel(chip, CORBLBASE, (u32)chip->corb.addr);
-       azx_writel(chip, CORBUBASE, upper_32bit(chip->corb.addr));
+       azx_writel(chip, CORBUBASE, upper_32_bits(chip->corb.addr));
 
        /* set the corb size to 256 entries (ULI requires explicitly) */
        azx_writeb(chip, CORBSIZE, 0x02);
@@ -476,7 +485,7 @@ static void azx_init_cmd_io(struct azx *chip)
        chip->rirb.addr = chip->rb.addr + 2048;
        chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
        azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr);
-       azx_writel(chip, RIRBUBASE, upper_32bit(chip->rirb.addr));
+       azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr));
 
        /* set the rirb size to 256 entries (ULI requires explicitly) */
        azx_writeb(chip, RIRBSIZE, 0x02);
@@ -847,7 +856,7 @@ static void azx_init_chip(struct azx *chip)
 
        /* program the position buffer */
        azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
-       azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
+       azx_writel(chip, DPUBASE, upper_32_bits(chip->posbuf.addr));
 
        chip->initialized = 1;
 }
@@ -908,6 +917,8 @@ static void azx_init_pci(struct azx *chip)
 }
 
 
+static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
+
 /*
  * interrupt handler
  */
@@ -930,11 +941,23 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
                azx_dev = &chip->azx_dev[i];
                if (status & azx_dev->sd_int_sta_mask) {
                        azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
-                       if (azx_dev->substream && azx_dev->running) {
-                               azx_dev->period_intr++;
+                       if (!azx_dev->substream || !azx_dev->running)
+                               continue;
+                       /* ignore the first dummy IRQ (due to pos_adj) */
+                       if (azx_dev->irq_ignore) {
+                               azx_dev->irq_ignore = 0;
+                               continue;
+                       }
+                       /* check whether this IRQ is really acceptable */
+                       if (azx_position_ok(chip, azx_dev)) {
+                               azx_dev->irq_pending = 0;
                                spin_unlock(&chip->reg_lock);
                                snd_pcm_period_elapsed(azx_dev->substream);
                                spin_lock(&chip->reg_lock);
+                       } else {
+                               /* bogus IRQ, process it later */
+                               azx_dev->irq_pending = 1;
+                               schedule_work(&chip->irq_pending_work);
                        }
                }
        }
@@ -958,60 +981,108 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
 }
 
 
+/*
+ * set up a BDL entry
+ */
+static int setup_bdle(struct snd_pcm_substream *substream,
+                     struct azx_dev *azx_dev, u32 **bdlp,
+                     int ofs, int size, int with_ioc)
+{
+       struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
+       u32 *bdl = *bdlp;
+
+       while (size > 0) {
+               dma_addr_t addr;
+               int chunk;
+
+               if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES)
+                       return -EINVAL;
+
+               addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs);
+               /* program the address field of the BDL entry */
+               bdl[0] = cpu_to_le32((u32)addr);
+               bdl[1] = cpu_to_le32(upper_32_bits(addr));
+               /* program the size field of the BDL entry */
+               chunk = PAGE_SIZE - (ofs % PAGE_SIZE);
+               if (size < chunk)
+                       chunk = size;
+               bdl[2] = cpu_to_le32(chunk);
+               /* program the IOC to enable interrupt
+                * only when the whole fragment is processed
+                */
+               size -= chunk;
+               bdl[3] = (size || !with_ioc) ? 0 : cpu_to_le32(0x01);
+               bdl += 4;
+               azx_dev->frags++;
+               ofs += chunk;
+       }
+       *bdlp = bdl;
+       return ofs;
+}
+
 /*
  * set up BDL entries
  */
-static int azx_setup_periods(struct snd_pcm_substream *substream,
+static int azx_setup_periods(struct azx *chip,
+                            struct snd_pcm_substream *substream,
                             struct azx_dev *azx_dev)
 {
-       struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
        u32 *bdl;
        int i, ofs, periods, period_bytes;
+       int pos_adj;
 
        /* reset BDL address */
        azx_sd_writel(azx_dev, SD_BDLPL, 0);
        azx_sd_writel(azx_dev, SD_BDLPU, 0);
 
        period_bytes = snd_pcm_lib_period_bytes(substream);
+       azx_dev->period_bytes = period_bytes;
        periods = azx_dev->bufsize / period_bytes;
 
        /* program the initial BDL entries */
        bdl = (u32 *)azx_dev->bdl.area;
        ofs = 0;
        azx_dev->frags = 0;
-       for (i = 0; i < periods; i++) {
-               int size, rest;
-               if (i >= AZX_MAX_BDL_ENTRIES) {
-                       snd_printk(KERN_ERR "Too many BDL entries: "
-                                  "buffer=%d, period=%d\n",
-                                  azx_dev->bufsize, period_bytes);
-                       /* reset */
-                       azx_sd_writel(azx_dev, SD_BDLPL, 0);
-                       azx_sd_writel(azx_dev, SD_BDLPU, 0);
-                       return -EINVAL;
+       azx_dev->irq_ignore = 0;
+       pos_adj = bdl_pos_adj[chip->dev_index];
+       if (pos_adj > 0) {
+               struct snd_pcm_runtime *runtime = substream->runtime;
+               pos_adj = (pos_adj * runtime->rate + 47999) / 48000;
+               if (!pos_adj)
+                       pos_adj = 1;
+               pos_adj = frames_to_bytes(runtime, pos_adj);
+               if (pos_adj >= period_bytes) {
+                       snd_printk(KERN_WARNING "Too big adjustment %d\n",
+                                  bdl_pos_adj[chip->dev_index]);
+                       pos_adj = 0;
+               } else {
+                       ofs = setup_bdle(substream, azx_dev,
+                                        &bdl, ofs, pos_adj, 1);
+                       if (ofs < 0)
+                               goto error;
+                       azx_dev->irq_ignore = 1;
                }
-               rest = period_bytes;
-               do {
-                       dma_addr_t addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs);
-                       /* program the address field of the BDL entry */
-                       bdl[0] = cpu_to_le32((u32)addr);
-                       bdl[1] = cpu_to_le32(upper_32bit(addr));
-                       /* program the size field of the BDL entry */
-                       size = PAGE_SIZE - (ofs % PAGE_SIZE);
-                       if (rest < size)
-                               size = rest;
-                       bdl[2] = cpu_to_le32(size);
-                       /* program the IOC to enable interrupt
-                        * only when the whole fragment is processed
-                        */
-                       rest -= size;
-                       bdl[3] = rest ? 0 : cpu_to_le32(0x01);
-                       bdl += 4;
-                       azx_dev->frags++;
-                       ofs += size;
-               } while (rest > 0);
+       } else
+               pos_adj = 0;
+       for (i = 0; i < periods; i++) {
+               if (i == periods - 1 && pos_adj)
+                       ofs = setup_bdle(substream, azx_dev, &bdl, ofs,
+                                        period_bytes - pos_adj, 0);
+               else
+                       ofs = setup_bdle(substream, azx_dev, &bdl, ofs,
+                                        period_bytes, 1);
+               if (ofs < 0)
+                       goto error;
        }
        return 0;
+
+ error:
+       snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n",
+                  azx_dev->bufsize, period_bytes);
+       /* reset */
+       azx_sd_writel(azx_dev, SD_BDLPL, 0);
+       azx_sd_writel(azx_dev, SD_BDLPU, 0);
+       return -EINVAL;
 }
 
 /*
@@ -1062,7 +1133,7 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
        /* lower BDL address */
        azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr);
        /* upper BDL address */
-       azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl.addr));
+       azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr));
 
        /* enable the position buffer */
        if (chip->position_fix == POS_FIX_POSBUF ||
@@ -1085,7 +1156,7 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
  */
 
 static unsigned int azx_max_codecs[] __devinitdata = {
-       [AZX_DRIVER_ICH] = 3,
+       [AZX_DRIVER_ICH] = 4,           /* Some ICH9 boards use SD3 */
        [AZX_DRIVER_SCH] = 3,
        [AZX_DRIVER_ATI] = 4,
        [AZX_DRIVER_ATIHDMI] = 4,
@@ -1093,6 +1164,7 @@ static unsigned int azx_max_codecs[] __devinitdata = {
        [AZX_DRIVER_SIS] = 3,           /* FIXME: correct? */
        [AZX_DRIVER_ULI] = 3,           /* FIXME: correct? */
        [AZX_DRIVER_NVIDIA] = 3,        /* FIXME: correct? */
+       [AZX_DRIVER_TERA] = 1,
 };
 
 static int __devinit azx_codec_create(struct azx *chip, const char *model,
@@ -1316,7 +1388,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
 
        snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
                    azx_dev->bufsize, azx_dev->format_val);
-       if (azx_setup_periods(substream, azx_dev) < 0)
+       if (azx_setup_periods(chip, substream, azx_dev) < 0)
                return -EINVAL;
        azx_setup_controller(chip, azx_dev);
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -1421,35 +1493,113 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        return 0;
 }
 
-static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
+static unsigned int azx_get_position(struct azx *chip,
+                                    struct azx_dev *azx_dev)
 {
-       struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
-       struct azx *chip = apcm->chip;
-       struct azx_dev *azx_dev = get_azx_dev(substream);
        unsigned int pos;
 
        if (chip->position_fix == POS_FIX_POSBUF ||
            chip->position_fix == POS_FIX_AUTO) {
                /* use the position buffer */
                pos = le32_to_cpu(*azx_dev->posbuf);
-               if (chip->position_fix == POS_FIX_AUTO &&
-                   azx_dev->period_intr == 1 && !pos) {
-                       printk(KERN_WARNING
-                              "hda-intel: Invalid position buffer, "
-                              "using LPIB read method instead.\n");
-                       chip->position_fix = POS_FIX_NONE;
-                       goto read_lpib;
-               }
        } else {
-       read_lpib:
                /* read LPIB */
                pos = azx_sd_readl(azx_dev, SD_LPIB);
-               if (chip->position_fix == POS_FIX_FIFO)
-                       pos += azx_dev->fifo_size;
        }
        if (pos >= azx_dev->bufsize)
                pos = 0;
-       return bytes_to_frames(substream->runtime, pos);
+       return pos;
+}
+
+static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
+{
+       struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+       struct azx *chip = apcm->chip;
+       struct azx_dev *azx_dev = get_azx_dev(substream);
+       return bytes_to_frames(substream->runtime,
+                              azx_get_position(chip, azx_dev));
+}
+
+/*
+ * Check whether the current DMA position is acceptable for updating
+ * periods.  Returns non-zero if it's OK.
+ *
+ * Many HD-audio controllers appear pretty inaccurate about
+ * the update-IRQ timing.  The IRQ is issued before actually the
+ * data is processed.  So, we need to process it afterwords in a
+ * workqueue.
+ */
+static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
+{
+       unsigned int pos;
+
+       pos = azx_get_position(chip, azx_dev);
+       if (chip->position_fix == POS_FIX_AUTO) {
+               if (!pos) {
+                       printk(KERN_WARNING
+                              "hda-intel: Invalid position buffer, "
+                              "using LPIB read method instead.\n");
+                       chip->position_fix = POS_FIX_LPIB;
+                       pos = azx_get_position(chip, azx_dev);
+               } else
+                       chip->position_fix = POS_FIX_POSBUF;
+       }
+
+       if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2)
+               return 0; /* NG - it's below the period boundary */
+       return 1; /* OK, it's fine */
+}
+
+/*
+ * The work for pending PCM period updates.
+ */
+static void azx_irq_pending_work(struct work_struct *work)
+{
+       struct azx *chip = container_of(work, struct azx, irq_pending_work);
+       int i, pending;
+
+       if (!chip->irq_pending_warned) {
+               printk(KERN_WARNING
+                      "hda-intel: IRQ timing workaround is activated "
+                      "for card #%d. Suggest a bigger bdl_pos_adj.\n",
+                      chip->card->number);
+               chip->irq_pending_warned = 1;
+       }
+
+       for (;;) {
+               pending = 0;
+               spin_lock_irq(&chip->reg_lock);
+               for (i = 0; i < chip->num_streams; i++) {
+                       struct azx_dev *azx_dev = &chip->azx_dev[i];
+                       if (!azx_dev->irq_pending ||
+                           !azx_dev->substream ||
+                           !azx_dev->running)
+                               continue;
+                       if (azx_position_ok(chip, azx_dev)) {
+                               azx_dev->irq_pending = 0;
+                               spin_unlock(&chip->reg_lock);
+                               snd_pcm_period_elapsed(azx_dev->substream);
+                               spin_lock(&chip->reg_lock);
+                       } else
+                               pending++;
+               }
+               spin_unlock_irq(&chip->reg_lock);
+               if (!pending)
+                       return;
+               cond_resched();
+       }
+}
+
+/* clear irq_pending flags and assure no on-going workq */
+static void azx_clear_irq_pending(struct azx *chip)
+{
+       int i;
+
+       spin_lock_irq(&chip->reg_lock);
+       for (i = 0; i < chip->num_streams; i++)
+               chip->azx_dev[i].irq_pending = 0;
+       spin_unlock_irq(&chip->reg_lock);
+       flush_scheduled_work();
 }
 
 static struct snd_pcm_ops azx_pcm_ops = {
@@ -1676,6 +1826,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
        int i;
 
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+       azx_clear_irq_pending(chip);
        for (i = 0; i < AZX_MAX_PCMS; i++)
                snd_pcm_suspend_all(chip->pcm[i]);
        if (chip->initialized)
@@ -1732,6 +1883,7 @@ static int azx_free(struct azx *chip)
        int i;
 
        if (chip->initialized) {
+               azx_clear_irq_pending(chip);
                for (i = 0; i < chip->num_streams; i++)
                        azx_stream_stop(chip, &chip->azx_dev[i]);
                azx_stop_chip(chip);
@@ -1770,9 +1922,9 @@ static int azx_dev_free(struct snd_device *device)
  * white/black-listing for position_fix
  */
 static struct snd_pci_quirk position_fix_list[] __devinitdata = {
-       SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE),
-       SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_NONE),
-       SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_NONE),
+       SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
        {}
 };
 
@@ -1857,12 +2009,25 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        chip->irq = -1;
        chip->driver_type = driver_type;
        chip->msi = enable_msi;
+       chip->dev_index = dev;
+       INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
 
        chip->position_fix = check_position_fix(chip, position_fix[dev]);
        check_probe_mask(chip, dev);
 
        chip->single_cmd = single_cmd;
 
+       if (bdl_pos_adj[dev] < 0) {
+               switch (chip->driver_type) {
+               case AZX_DRIVER_ICH:
+                       bdl_pos_adj[dev] = 1;
+                       break;
+               default:
+                       bdl_pos_adj[dev] = 32;
+                       break;
+               }
+       }
+
 #if BITS_PER_LONG != 64
        /* Fix up base address on ULI M5461 */
        if (chip->driver_type == AZX_DRIVER_ULI) {
@@ -2089,6 +2254,7 @@ static struct pci_device_id azx_ids[] = {
        { PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH },
        { PCI_DEVICE(0x8086, 0x269a), .driver_data = AZX_DRIVER_ICH },
        { PCI_DEVICE(0x8086, 0x284b), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x2911), .driver_data = AZX_DRIVER_ICH },
        { PCI_DEVICE(0x8086, 0x293e), .driver_data = AZX_DRIVER_ICH },
        { PCI_DEVICE(0x8086, 0x293f), .driver_data = AZX_DRIVER_ICH },
        { PCI_DEVICE(0x8086, 0x3a3e), .driver_data = AZX_DRIVER_ICH },
@@ -2141,6 +2307,8 @@ static struct pci_device_id azx_ids[] = {
        { PCI_DEVICE(0x10de, 0x0bd5), .driver_data = AZX_DRIVER_NVIDIA },
        { PCI_DEVICE(0x10de, 0x0bd6), .driver_data = AZX_DRIVER_NVIDIA },
        { PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA },
+       /* Teradici */
+       { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);
index 5633f77f8f3b74885f36ff33dec5481771096871..1e5aff5c48d16910074503907775e6d17eac5d66 100644 (file)
@@ -366,8 +366,6 @@ static void print_digital_conv(struct snd_info_buffer *buffer,
 {
        unsigned int digi1 = snd_hda_codec_read(codec, nid, 0,
                                                AC_VERB_GET_DIGI_CONVERT_1, 0);
-       unsigned int digi2 = snd_hda_codec_read(codec, nid, 0,
-                                               AC_VERB_GET_DIGI_CONVERT_2, 0);
        snd_iprintf(buffer, "  Digital:");
        if (digi1 & AC_DIG1_ENABLE)
                snd_iprintf(buffer, " Enabled");
@@ -386,7 +384,8 @@ static void print_digital_conv(struct snd_info_buffer *buffer,
        if (digi1 & AC_DIG1_LEVEL)
                snd_iprintf(buffer, " GenLevel");
        snd_iprintf(buffer, "\n");
-       snd_iprintf(buffer, "  Digital category: 0x%x\n", digi2 & AC_DIG2_CC);
+       snd_iprintf(buffer, "  Digital category: 0x%x\n",
+                   (digi1 >> 8) & AC_DIG2_CC);
 }
 
 static const char *get_pwr_state(u32 state)
index a99e86d742782ae14d2123c87696f8428bebd54c..e8003d99f0bfe3bb071d761a9a84922dd7d8bd07 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/mutex.h>
 
 #include <sound/core.h>
 #include "hda_codec.h"
@@ -64,7 +63,6 @@ struct ad198x_spec {
        /* PCM information */
        struct hda_pcm pcm_rec[3];      /* used in alc_build_pcms() */
 
-       struct mutex amp_mutex; /* PCM volume/mute control mutex */
        unsigned int spdif_route;
 
        /* dynamic controls, init_verbs and input_mux */
@@ -1618,6 +1616,7 @@ static const char *ad1981_models[AD1981_MODELS] = {
 
 static struct snd_pci_quirk ad1981_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
+       SND_PCI_QUIRK(0x1014, 0x05b7, "Lenovo Z60m", AD1981_THINKPAD),
        /* All HP models */
        SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP),
        SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba U205", AD1981_TOSHIBA),
@@ -2623,7 +2622,7 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
 {
        struct ad198x_spec *spec = codec->spec;
        hda_nid_t nid;
-       int idx, err;
+       int i, idx, err;
        char name[32];
 
        if (! pin)
@@ -2631,16 +2630,26 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
 
        idx = ad1988_pin_idx(pin);
        nid = ad1988_idx_to_dac(codec, idx);
-       /* specify the DAC as the extra output */
-       if (! spec->multiout.hp_nid)
-               spec->multiout.hp_nid = nid;
-       else
-               spec->multiout.extra_out_nid[0] = nid;
-       /* control HP volume/switch on the output mixer amp */
-       sprintf(name, "%s Playback Volume", pfx);
-       if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
-                              HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
-               return err;
+       /* check whether the corresponding DAC was already taken */
+       for (i = 0; i < spec->autocfg.line_outs; i++) {
+               hda_nid_t pin = spec->autocfg.line_out_pins[i];
+               hda_nid_t dac = ad1988_idx_to_dac(codec, ad1988_pin_idx(pin));
+               if (dac == nid)
+                       break;
+       }
+       if (i >= spec->autocfg.line_outs) {
+               /* specify the DAC as the extra output */
+               if (!spec->multiout.hp_nid)
+                       spec->multiout.hp_nid = nid;
+               else
+                       spec->multiout.extra_out_nid[0] = nid;
+               /* control HP volume/switch on the output mixer amp */
+               sprintf(name, "%s Playback Volume", pfx);
+               err = add_control(spec, AD_CTL_WIDGET_VOL, name,
+                                 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
+               if (err < 0)
+                       return err;
+       }
        nid = ad1988_mixer_nids[idx];
        sprintf(name, "%s Playback Switch", pfx);
        if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
@@ -3177,7 +3186,6 @@ static int patch_ad1884(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
-       mutex_init(&spec->amp_mutex);
        codec->spec = spec;
 
        spec->multiout.max_channels = 2;
@@ -3847,7 +3855,6 @@ static int patch_ad1884a(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
-       mutex_init(&spec->amp_mutex);
        codec->spec = spec;
 
        spec->multiout.max_channels = 2;
@@ -4152,7 +4159,6 @@ static int patch_ad1882(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
-       mutex_init(&spec->amp_mutex);
        codec->spec = spec;
 
        spec->multiout.max_channels = 6;
index 36fd852600352244c17e10f6b49c72e284840ea0..7c1eb23f0cec09ae31901058b11222b1ddeca6e4 100644 (file)
@@ -82,7 +82,6 @@ struct conexant_spec {
        /* PCM information */
        struct hda_pcm pcm_rec[2];      /* used in build_pcms() */
 
-       struct mutex amp_mutex; /* PCM volume/mute control mutex */
        unsigned int spdif_route;
 
        /* dynamic controls, init_verbs and input_mux */
@@ -687,7 +686,7 @@ static struct snd_kcontrol_new cxt5045_mixers_hp530[] = {
 
 static struct hda_verb cxt5045_init_verbs[] = {
        /* Line in, Mic */
-       {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+       {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
        /* HP, Amp  */
        {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
@@ -907,10 +906,12 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV9533EG", CXT5045_LAPTOP_HPSENSE),
        SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530),
        SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP_HPSENSE),
+       SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE),
        SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
        SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
        SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE),
-       SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505", CXT5045_LAPTOP_HPSENSE),
+       SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505",
+                     CXT5045_LAPTOP_HPMICSENSE),
        SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE),
        SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE),
        SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE),
@@ -928,7 +929,6 @@ static int patch_cxt5045(struct hda_codec *codec)
        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (!spec)
                return -ENOMEM;
-       mutex_init(&spec->amp_mutex);
        codec->spec = spec;
 
        spec->multiout.max_channels = 2;
@@ -963,6 +963,7 @@ static int patch_cxt5045(struct hda_codec *codec)
                codec->patch_ops.init = cxt5045_init;
                break;
        case CXT5045_LAPTOP_MICSENSE:
+               codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
                spec->input_mux = &cxt5045_capture_source;
                spec->num_init_verbs = 2;
                spec->init_verbs[1] = cxt5045_mic_sense_init_verbs;
@@ -1007,15 +1008,19 @@ static int patch_cxt5045(struct hda_codec *codec)
 #endif 
        }
 
-       /*
-        * Fix max PCM level to 0 dB
-        * (originall it has 0x2b steps with 0dB offset 0x14)
-        */
-       snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
-                                 (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
-                                 (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) |
-                                 (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
-                                 (1 << AC_AMPCAP_MUTE_SHIFT));
+       switch (codec->subsystem_id >> 16) {
+       case 0x103c:
+               /* HP laptop has a really bad sound over 0dB on NID 0x17.
+                * Fix max PCM level to 0 dB
+                * (originall it has 0x2b steps with 0dB offset 0x14)
+                */
+               snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
+                                         (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
+                                         (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+                                         (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+                                         (1 << AC_AMPCAP_MUTE_SHIFT));
+               break;
+       }
 
        return 0;
 }
@@ -1477,7 +1482,6 @@ static int patch_cxt5047(struct hda_codec *codec)
        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (!spec)
                return -ENOMEM;
-       mutex_init(&spec->amp_mutex);
        codec->spec = spec;
 
        spec->multiout.max_channels = 2;
@@ -1736,7 +1740,6 @@ static int patch_cxt5051(struct hda_codec *codec)
        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (!spec)
                return -ENOMEM;
-       mutex_init(&spec->amp_mutex);
        codec->spec = spec;
 
        codec->patch_ops = conexant_patch_ops;
index b0a2a262ece2f0101f8f885c0637ab37fd6e0ae6..2807bc840d26973f695d6be66c55b6bb5ac58717 100644 (file)
@@ -163,6 +163,10 @@ enum {
        ALC662_LENOVO_101E,
        ALC662_ASUS_EEEPC_P701,
        ALC662_ASUS_EEEPC_EP20,
+       ALC663_ASUS_M51VA,
+       ALC663_ASUS_G71V,
+       ALC663_ASUS_H13,
+       ALC663_ASUS_G50V,
        ALC662_AUTO,
        ALC662_MODEL_LAST,
 };
@@ -205,6 +209,7 @@ enum {
        ALC883_MITAC,
        ALC883_CLEVO_M720,
        ALC883_FUJITSU_PI2515,
+       ALC883_3ST_6ch_INTEL,
        ALC883_AUTO,
        ALC883_MODEL_LAST,
 };
@@ -280,6 +285,10 @@ struct alc_spec {
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        struct hda_loopback_check loopback;
 #endif
+
+       /* for PLL fix */
+       hda_nid_t pll_nid;
+       unsigned int pll_coef_idx, pll_coef_bit;
 };
 
 /*
@@ -747,6 +756,38 @@ static struct hda_verb alc_gpio3_init_verbs[] = {
        { }
 };
 
+/*
+ * Fix hardware PLL issue
+ * On some codecs, the analog PLL gating control must be off while
+ * the default value is 1.
+ */
+static void alc_fix_pll(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       unsigned int val;
+
+       if (!spec->pll_nid)
+               return;
+       snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
+                           spec->pll_coef_idx);
+       val = snd_hda_codec_read(codec, spec->pll_nid, 0,
+                                AC_VERB_GET_PROC_COEF, 0);
+       snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
+                           spec->pll_coef_idx);
+       snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
+                           val & ~(1 << spec->pll_coef_bit));
+}
+
+static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
+                            unsigned int coef_idx, unsigned int coef_bit)
+{
+       struct alc_spec *spec = codec->spec;
+       spec->pll_nid = nid;
+       spec->pll_coef_idx = coef_idx;
+       spec->pll_coef_bit = coef_bit;
+       alc_fix_pll(codec);
+}
+
 static void alc_sku_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -776,6 +817,24 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
        alc_sku_automute(codec);
 }
 
+/* additional initialization for ALC888 variants */
+static void alc888_coef_init(struct hda_codec *codec)
+{
+       unsigned int tmp;
+
+       snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
+       tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
+       snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
+       if ((tmp & 0xf0) == 2)
+               /* alc888S-VC */
+               snd_hda_codec_read(codec, 0x20, 0,
+                                  AC_VERB_SET_PROC_COEF, 0x830);
+        else
+                /* alc888-VB */
+                snd_hda_codec_read(codec, 0x20, 0,
+                                   AC_VERB_SET_PROC_COEF, 0x3030);
+}
+
 /* 32-bit subsystem ID for BIOS loading in HD Audio codec.
  *     31 ~ 16 :       Manufacture ID
  *     15 ~ 8  :       SKU ID
@@ -851,8 +910,10 @@ do_sku:
                case 0x10ec0267:
                case 0x10ec0268:
                case 0x10ec0269:
+               case 0x10ec0660:
+               case 0x10ec0662:
+               case 0x10ec0663:
                case 0x10ec0862:
-               case 0x10ec0662:        
                case 0x10ec0889:
                        snd_hda_codec_write(codec, 0x14, 0,
                                            AC_VERB_SET_EAPD_BTLENABLE, 2);
@@ -877,7 +938,6 @@ do_sku:
                case 0x10ec0882:
                case 0x10ec0883:
                case 0x10ec0885:
-               case 0x10ec0888:
                case 0x10ec0889:
                        snd_hda_codec_write(codec, 0x20, 0,
                                            AC_VERB_SET_COEF_INDEX, 7);
@@ -889,6 +949,9 @@ do_sku:
                                            AC_VERB_SET_PROC_COEF,
                                            tmp | 0x2010);
                        break;
+               case 0x10ec0888:
+                       alc888_coef_init(codec);
+                       break;
                case 0x10ec0267:
                case 0x10ec0268:
                        snd_hda_codec_write(codec, 0x20, 0,
@@ -2373,6 +2436,8 @@ static int alc_init(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
        unsigned int i;
 
+       alc_fix_pll(codec);
+
        for (i = 0; i < spec->num_init_verbs; i++)
                snd_hda_sequence_write(codec, spec->init_verbs[i]);
 
@@ -3009,6 +3074,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
        SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
        SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
+       SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
        SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL),
        SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
        SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
@@ -5101,7 +5167,7 @@ static struct snd_pci_quirk alc260_cfg_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
        SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_HP_3013),
        SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
-       SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP),
+       SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013),
        SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_3013),
        SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
        SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
@@ -6127,6 +6193,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
        SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
        SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
+       SND_PCI_QUIRK(0x106b, 0x00a0, "Apple iMac 24''", ALC885_IMAC24),
        SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
        SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8  */
        SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
@@ -6353,7 +6420,9 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec)
                        continue;
                vref = PIN_IN;
                if (1 /*i <= AUTO_PIN_FRONT_MIC*/) {
-                       if (snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) &
+                       unsigned int pincap;
+                       pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+                       if ((pincap >> AC_PINCAP_VREF_SHIFT) &
                            AC_PINCAP_VREF_80)
                                vref = PIN_VREF80;
                }
@@ -6450,8 +6519,9 @@ static int patch_alc882(struct hda_codec *codec)
                case 0x106b1000: /* iMac 24 */
                        board_config = ALC885_IMAC24;
                        break;
-               case 0x106b00a1: /* Macbook */
+               case 0x106b00a1: /* Macbook (might be wrong - PCI SSID?) */
                case 0x106b2c00: /* Macbook Pro rev3 */
+               case 0x106b3600: /* Macbook 3.1 */
                        board_config = ALC885_MBP3;
                        break;
                default:
@@ -6485,14 +6555,20 @@ static int patch_alc882(struct hda_codec *codec)
        if (board_config != ALC882_AUTO)
                setup_preset(spec, &alc882_presets[board_config]);
 
-       spec->stream_name_analog = "ALC882 Analog";
+       if (codec->vendor_id == 0x10ec0885) {
+               spec->stream_name_analog = "ALC885 Analog";
+               spec->stream_name_digital = "ALC885 Digital";
+       } else {
+               spec->stream_name_analog = "ALC882 Analog";
+               spec->stream_name_digital = "ALC882 Digital";
+       }
+
        spec->stream_analog_playback = &alc882_pcm_analog_playback;
        spec->stream_analog_capture = &alc882_pcm_analog_capture;
        /* FIXME: setup DAC5 */
        /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
        spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
 
-       spec->stream_name_digital = "ALC882 Digital";
        spec->stream_digital_playback = &alc882_pcm_digital_playback;
        spec->stream_digital_capture = &alc882_pcm_digital_capture;
 
@@ -6569,6 +6645,16 @@ static struct hda_input_mux alc883_capture_source = {
        },
 };
 
+static struct hda_input_mux alc883_3stack_6ch_intel = {
+       .num_items = 4,
+       .items = {
+               { "Mic", 0x1 },
+               { "Front Mic", 0x0 },
+               { "Line", 0x2 },
+               { "CD", 0x4 },
+       },
+};
+
 static struct hda_input_mux alc883_lenovo_101e_capture_source = {
        .num_items = 2,
        .items = {
@@ -6649,6 +6735,48 @@ static struct hda_channel_mode alc883_3ST_6ch_modes[3] = {
        { 6, alc883_3ST_ch6_init },
 };
 
+/*
+ * 2ch mode
+ */
+static struct hda_verb alc883_3ST_ch2_intel_init[] = {
+       { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+       { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+       { } /* end */
+};
+
+/*
+ * 4ch mode
+ */
+static struct hda_verb alc883_3ST_ch4_intel_init[] = {
+       { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+       { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+       { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+       { } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static struct hda_verb alc883_3ST_ch6_intel_init[] = {
+       { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+       { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+       { 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
+       { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+       { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+       { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+       { } /* end */
+};
+
+static struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
+       { 2, alc883_3ST_ch2_intel_init },
+       { 4, alc883_3ST_ch4_intel_init },
+       { 6, alc883_3ST_ch6_intel_init },
+};
+
 /*
  * 6ch mode
  */
@@ -6881,15 +7009,54 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
        { } /* end */
 };
 
+static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
+                             HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+       HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Boost", 0x19, 0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Front Mic Boost", 0x18, 0, HDA_INPUT),
+       HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+       HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+       HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               /* .name = "Capture Source", */
+               .name = "Input Source",
+               .count = 2,
+               .info = alc883_mux_enum_info,
+               .get = alc883_mux_enum_get,
+               .put = alc883_mux_enum_put,
+       },
+       { } /* end */
+};
+
 static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
        HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
        HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
-       HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+       HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
        HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
        HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
@@ -7729,6 +7896,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
        [ALC883_MITAC]          = "mitac",
        [ALC883_CLEVO_M720]     = "clevo-m720",
        [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
+       [ALC883_3ST_6ch_INTEL]  = "3stack-6ch-intel",
        [ALC883_AUTO]           = "auto",
 };
 
@@ -7786,6 +7954,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
        SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2),
        SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
        SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
+       SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
+       SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
        SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
        {}
 };
@@ -7824,6 +7994,18 @@ static struct alc_config_preset alc883_presets[] = {
                .need_dac_fix = 1,
                .input_mux = &alc883_capture_source,
        },
+       [ALC883_3ST_6ch_INTEL] = {
+               .mixers = { alc883_3ST_6ch_intel_mixer, alc883_chmode_mixer },
+               .init_verbs = { alc883_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc883_dac_nids),
+               .dac_nids = alc883_dac_nids,
+               .dig_out_nid = ALC883_DIGOUT_NID,
+               .dig_in_nid = ALC883_DIGIN_NID,
+               .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
+               .channel_mode = alc883_3ST_6ch_intel_modes,
+               .need_dac_fix = 1,
+               .input_mux = &alc883_3stack_6ch_intel,
+       },
        [ALC883_6ST_DIG] = {
                .mixers = { alc883_base_mixer, alc883_chmode_mixer },
                .init_verbs = { alc883_init_verbs },
@@ -8145,6 +8327,8 @@ static int patch_alc883(struct hda_codec *codec)
 
        codec->spec = spec;
 
+       alc_fix_pll_init(codec, 0x20, 0x0a, 10);
+
        board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST,
                                                  alc883_models,
                                                  alc883_cfg_tbl);
@@ -8171,12 +8355,25 @@ static int patch_alc883(struct hda_codec *codec)
        if (board_config != ALC883_AUTO)
                setup_preset(spec, &alc883_presets[board_config]);
 
-       spec->stream_name_analog = "ALC883 Analog";
+       switch (codec->vendor_id) {
+       case 0x10ec0888:
+               spec->stream_name_analog = "ALC888 Analog";
+               spec->stream_name_digital = "ALC888 Digital";
+               break;
+       case 0x10ec0889:
+               spec->stream_name_analog = "ALC889 Analog";
+               spec->stream_name_digital = "ALC889 Digital";
+               break;
+       default:
+               spec->stream_name_analog = "ALC883 Analog";
+               spec->stream_name_digital = "ALC883 Digital";
+               break;
+       }
+
        spec->stream_analog_playback = &alc883_pcm_analog_playback;
        spec->stream_analog_capture = &alc883_pcm_analog_capture;
        spec->stream_analog_alt_capture = &alc883_pcm_analog_alt_capture;
 
-       spec->stream_name_digital = "ALC883 Digital";
        spec->stream_digital_playback = &alc883_pcm_digital_playback;
        spec->stream_digital_capture = &alc883_pcm_digital_capture;
 
@@ -8189,6 +8386,9 @@ static int patch_alc883(struct hda_codec *codec)
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC883_AUTO)
                spec->init_hook = alc883_auto_init;
+       else if (codec->vendor_id == 0x10ec0888)
+               spec->init_hook = alc888_coef_init;
+
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc883_loopbacks;
@@ -9522,6 +9722,8 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
        SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
        SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD),
        SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
+       SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
+                     ALC262_SONY_ASSAMD),
        SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
        SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
        SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA),
@@ -9729,6 +9931,8 @@ static int patch_alc262(struct hda_codec *codec)
        }
 #endif
 
+       alc_fix_pll_init(codec, 0x20, 0x0a, 10);
+
        board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
                                                  alc262_models,
                                                  alc262_cfg_tbl);
@@ -10674,12 +10878,18 @@ static int patch_alc268(struct hda_codec *codec)
        if (board_config != ALC268_AUTO)
                setup_preset(spec, &alc268_presets[board_config]);
 
-       spec->stream_name_analog = "ALC268 Analog";
+       if (codec->vendor_id == 0x10ec0267) {
+               spec->stream_name_analog = "ALC267 Analog";
+               spec->stream_name_digital = "ALC267 Digital";
+       } else {
+               spec->stream_name_analog = "ALC268 Analog";
+               spec->stream_name_digital = "ALC268 Digital";
+       }
+
        spec->stream_analog_playback = &alc268_pcm_analog_playback;
        spec->stream_analog_capture = &alc268_pcm_analog_capture;
        spec->stream_analog_alt_capture = &alc268_pcm_analog_alt_capture;
 
-       spec->stream_name_digital = "ALC268 Digital";
        spec->stream_digital_playback = &alc268_pcm_digital_playback;
 
        if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
@@ -11033,6 +11243,8 @@ static int patch_alc269(struct hda_codec *codec)
 
        codec->spec = spec;
 
+       alc_fix_pll_init(codec, 0x20, 0x04, 15);
+
        board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
                                                  alc269_models,
                                                  alc269_cfg_tbl);
@@ -12631,6 +12843,12 @@ static struct hda_verb alc861vd_eapd_verbs[] = {
        { }
 };
 
+static struct hda_verb alc660vd_eapd_verbs[] = {
+       {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+       { }
+};
+
 static struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -12786,6 +13004,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
        SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
        SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
+       SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 N200", ALC861VD_LENOVO),
        SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
        {}
 };
@@ -13168,11 +13387,19 @@ static int patch_alc861vd(struct hda_codec *codec)
        if (board_config != ALC861VD_AUTO)
                setup_preset(spec, &alc861vd_presets[board_config]);
 
-       spec->stream_name_analog = "ALC861VD Analog";
+       if (codec->vendor_id == 0x10ec0660) {
+               spec->stream_name_analog = "ALC660-VD Analog";
+               spec->stream_name_digital = "ALC660-VD Digital";
+               /* always turn on EAPD */
+               spec->init_verbs[spec->num_init_verbs++] = alc660vd_eapd_verbs;
+       } else {
+               spec->stream_name_analog = "ALC861VD Analog";
+               spec->stream_name_digital = "ALC861VD Digital";
+       }
+
        spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
        spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
 
-       spec->stream_name_digital = "ALC861VD Digital";
        spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
        spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
 
@@ -13251,6 +13478,23 @@ static struct hda_input_mux alc662_eeepc_capture_source = {
        },
 };
 
+static struct hda_input_mux alc663_capture_source = {
+       .num_items = 3,
+       .items = {
+               { "Mic", 0x0 },
+               { "Front Mic", 0x1 },
+               { "Line", 0x2 },
+       },
+};
+
+static struct hda_input_mux alc663_m51va_capture_source = {
+       .num_items = 2,
+       .items = {
+               { "Ext-Mic", 0x0 },
+               { "D-Mic", 0x9 },
+       },
+};
+
 #define alc662_mux_enum_info alc_mux_enum_info
 #define alc662_mux_enum_get alc_mux_enum_get
 #define alc662_mux_enum_put alc882_mux_enum_put
@@ -13431,6 +13675,44 @@ static struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
        { } /* end */
 };
 
+static struct snd_kcontrol_new alc663_m51va_mixer[] = {
+       HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("DMic Playback Switch", 0x23, 0x9, HDA_INPUT),
+       { } /* end */
+};
+
+static struct snd_kcontrol_new alc663_g71v_mixer[] = {
+       HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+       { } /* end */
+};
+
+static struct snd_kcontrol_new alc663_g50v_mixer[] = {
+       HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+       HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("i-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("i-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+       { } /* end */
+};
+
 static struct snd_kcontrol_new alc662_chmode_mixer[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -13501,6 +13783,11 @@ static struct hda_verb alc662_init_verbs[] = {
        {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
        {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
        {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+       /* always trun on EAPD */
+       {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
+
        { }
 };
 
@@ -13571,6 +13858,43 @@ static struct hda_verb alc662_auto_init_verbs[] = {
        { }
 };
 
+static struct hda_verb alc663_m51va_init_verbs[] = {
+       {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x21, AC_VERB_SET_CONNECT_SEL, 0x00},  /* Headphone */
+
+       {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
+
+       {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+       {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {}
+};
+
+static struct hda_verb alc663_g71v_init_verbs[] = {
+       {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       /* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
+       /* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
+
+       {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x21, AC_VERB_SET_CONNECT_SEL, 0x00},  /* Headphone */
+
+       {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
+       {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_MIC_EVENT},
+       {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
+       {}
+};
+
+static struct hda_verb alc663_g50v_init_verbs[] = {
+       {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x21, AC_VERB_SET_CONNECT_SEL, 0x00},  /* Headphone */
+
+       {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
+       {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       {}
+};
+
 /* capture mixer elements */
 static struct snd_kcontrol_new alc662_capture_mixer[] = {
        HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
@@ -13692,6 +14016,125 @@ static void alc662_eeepc_ep20_inithook(struct hda_codec *codec)
        alc662_eeepc_ep20_automute(codec);
 }
 
+static void alc663_m51va_speaker_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+       unsigned char bits;
+
+       present = snd_hda_codec_read(codec, 0x21, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0)
+               & AC_PINSENSE_PRESENCE;
+       bits = present ? HDA_AMP_MUTE : 0;
+       snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, bits);
+}
+
+static void alc663_m51va_mic_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+
+       present = snd_hda_codec_read(codec, 0x18, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0)
+               & AC_PINSENSE_PRESENCE;
+       snd_hda_codec_write_cache(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
+       snd_hda_codec_write_cache(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           0x7000 | (0x00 << 8) | (present ? 0 : 0x80));
+       snd_hda_codec_write_cache(codec, 0x22, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           0x7000 | (0x09 << 8) | (present ? 0x80 : 0));
+       snd_hda_codec_write_cache(codec, 0x23, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+                           0x7000 | (0x09 << 8) | (present ? 0x80 : 0));
+}
+
+static void alc663_m51va_unsol_event(struct hda_codec *codec,
+                                          unsigned int res)
+{
+       switch (res >> 26) {
+       case ALC880_HP_EVENT:
+               alc663_m51va_speaker_automute(codec);
+               break;
+       case ALC880_MIC_EVENT:
+               alc663_m51va_mic_automute(codec);
+               break;
+       }
+}
+
+static void alc663_m51va_inithook(struct hda_codec *codec)
+{
+       alc663_m51va_speaker_automute(codec);
+       alc663_m51va_mic_automute(codec);
+}
+
+static void alc663_g71v_hp_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+       unsigned char bits;
+
+       present = snd_hda_codec_read(codec, 0x21, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0)
+               & AC_PINSENSE_PRESENCE;
+       bits = present ? HDA_AMP_MUTE : 0;
+       snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, bits);
+       snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, bits);
+}
+
+static void alc663_g71v_front_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+       unsigned char bits;
+
+       present = snd_hda_codec_read(codec, 0x15, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0)
+               & AC_PINSENSE_PRESENCE;
+       bits = present ? HDA_AMP_MUTE : 0;
+       snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, bits);
+}
+
+static void alc663_g71v_unsol_event(struct hda_codec *codec,
+                                          unsigned int res)
+{
+       switch (res >> 26) {
+       case ALC880_HP_EVENT:
+               alc663_g71v_hp_automute(codec);
+               break;
+       case ALC880_FRONT_EVENT:
+               alc663_g71v_front_automute(codec);
+               break;
+       case ALC880_MIC_EVENT:
+               alc662_eeepc_mic_automute(codec);
+               break;
+       }
+}
+
+static void alc663_g71v_inithook(struct hda_codec *codec)
+{
+       alc663_g71v_front_automute(codec);
+       alc663_g71v_hp_automute(codec);
+       alc662_eeepc_mic_automute(codec);
+}
+
+static void alc663_g50v_unsol_event(struct hda_codec *codec,
+                                          unsigned int res)
+{
+       switch (res >> 26) {
+       case ALC880_HP_EVENT:
+               alc663_m51va_speaker_automute(codec);
+               break;
+       case ALC880_MIC_EVENT:
+               alc662_eeepc_mic_automute(codec);
+               break;
+       }
+}
+
+static void alc663_g50v_inithook(struct hda_codec *codec)
+{
+       alc663_m51va_speaker_automute(codec);
+       alc662_eeepc_mic_automute(codec);
+}
+
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 #define alc662_loopbacks       alc880_loopbacks
 #endif
@@ -13714,14 +14157,24 @@ static const char *alc662_models[ALC662_MODEL_LAST] = {
        [ALC662_LENOVO_101E]    = "lenovo-101e",
        [ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
        [ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
+       [ALC663_ASUS_M51VA] = "m51va",
+       [ALC663_ASUS_G71V] = "g71v",
+       [ALC663_ASUS_H13] = "h13",
+       [ALC663_ASUS_G50V] = "g50v",
        [ALC662_AUTO]           = "auto",
 };
 
 static struct snd_pci_quirk alc662_cfg_tbl[] = {
+       SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS G71V", ALC663_ASUS_G71V),
+       SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
+       SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS M51VA", ALC663_ASUS_G50V),
        SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
        SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
        SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
+       SND_PCI_QUIRK(0x1854, 0x2000, "ASUS H13-2000", ALC663_ASUS_H13),
+       SND_PCI_QUIRK(0x1854, 0x2001, "ASUS H13-2001", ALC663_ASUS_H13),
+       SND_PCI_QUIRK(0x1854, 0x2002, "ASUS H13-2002", ALC663_ASUS_H13),
        {}
 };
 
@@ -13809,7 +14262,53 @@ static struct alc_config_preset alc662_presets[] = {
                .unsol_event = alc662_eeepc_ep20_unsol_event,
                .init_hook = alc662_eeepc_ep20_inithook,
        },
-
+       [ALC663_ASUS_M51VA] = {
+               .mixers = { alc663_m51va_mixer, alc662_capture_mixer},
+               .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+               .dac_nids = alc662_dac_nids,
+               .dig_out_nid = ALC662_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+               .channel_mode = alc662_3ST_2ch_modes,
+               .input_mux = &alc663_m51va_capture_source,
+               .unsol_event = alc663_m51va_unsol_event,
+               .init_hook = alc663_m51va_inithook,
+       },
+       [ALC663_ASUS_G71V] = {
+               .mixers = { alc663_g71v_mixer, alc662_capture_mixer},
+               .init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+               .dac_nids = alc662_dac_nids,
+               .dig_out_nid = ALC662_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+               .channel_mode = alc662_3ST_2ch_modes,
+               .input_mux = &alc662_eeepc_capture_source,
+               .unsol_event = alc663_g71v_unsol_event,
+               .init_hook = alc663_g71v_inithook,
+       },
+       [ALC663_ASUS_H13] = {
+               .mixers = { alc663_m51va_mixer, alc662_capture_mixer},
+               .init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+               .dac_nids = alc662_dac_nids,
+               .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+               .channel_mode = alc662_3ST_2ch_modes,
+               .input_mux = &alc663_m51va_capture_source,
+               .unsol_event = alc663_m51va_unsol_event,
+               .init_hook = alc663_m51va_inithook,
+       },
+       [ALC663_ASUS_G50V] = {
+               .mixers = { alc663_g50v_mixer, alc662_capture_mixer},
+               .init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc662_dac_nids),
+               .dac_nids = alc662_dac_nids,
+               .dig_out_nid = ALC662_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+               .channel_mode = alc662_3ST_6ch_modes,
+               .input_mux = &alc663_capture_source,
+               .unsol_event = alc663_g50v_unsol_event,
+               .init_hook = alc663_g50v_inithook,
+       },
 };
 
 
@@ -14082,6 +14581,8 @@ static int patch_alc662(struct hda_codec *codec)
 
        codec->spec = spec;
 
+       alc_fix_pll_init(codec, 0x20, 0x04, 15);
+
        board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
                                                  alc662_models,
                                                  alc662_cfg_tbl);
@@ -14108,11 +14609,17 @@ static int patch_alc662(struct hda_codec *codec)
        if (board_config != ALC662_AUTO)
                setup_preset(spec, &alc662_presets[board_config]);
 
-       spec->stream_name_analog = "ALC662 Analog";
+       if (codec->vendor_id == 0x10ec0663) {
+               spec->stream_name_analog = "ALC663 Analog";
+               spec->stream_name_digital = "ALC663 Digital";
+       } else {
+               spec->stream_name_analog = "ALC662 Analog";
+               spec->stream_name_digital = "ALC662 Digital";
+       }
+
        spec->stream_analog_playback = &alc662_pcm_analog_playback;
        spec->stream_analog_capture = &alc662_pcm_analog_capture;
 
-       spec->stream_name_digital = "ALC662 Digital";
        spec->stream_digital_playback = &alc662_pcm_digital_playback;
        spec->stream_digital_capture = &alc662_pcm_digital_capture;
 
@@ -14151,6 +14658,7 @@ struct hda_codec_preset snd_hda_preset_realtek[] = {
          .patch = patch_alc883 },
        { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
          .patch = patch_alc662 },
+       { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
        { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
        { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
        { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
index a4f44a00bae8eb548708a0dd8903cf0bf652bbb3..08cb77f51880a31265c46cf66691715cfbf5dd55 100644 (file)
@@ -636,21 +636,28 @@ static struct hda_verb stac92hd71bxx_core_init[] = {
        { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 };
 
+#define HD_DISABLE_PORTF 3
 static struct hda_verb stac92hd71bxx_analog_core_init[] = {
+       /* start of config #1 */
+
+       /* connect port 0f to audio mixer */
+       { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2},
+       { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Speaker */
+       /* unmute right and left channels for node 0x0f */
+       { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       /* start of config #2 */
+
        /* set master volume and direct control */
        { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
        /* connect headphone jack to dac1 */
        { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
-       /* connect ports 0d and 0f to audio mixer */
+       /* connect port 0d to audio mixer */
        { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x2},
-       { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2},
-       { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Speaker */
        /* unmute dac0 input in audio mixer */
        { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
-       /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */
+       /* unmute right and left channels for nodes 0x0a, 0xd */
        { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        {}
 };
 
@@ -818,6 +825,9 @@ static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = {
        HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT),
        HDA_CODEC_VOLUME_IDX("Capture Mux Volume", 0x1, 0x1b, 0x0, HDA_OUTPUT),
 
+       HDA_CODEC_VOLUME("PC Beep Volume", 0x17, 0x2, HDA_INPUT),
+       HDA_CODEC_MUTE("PC Beep Switch", 0x17, 0x2, HDA_INPUT),
+
        HDA_CODEC_MUTE("Analog Loopback 1", 0x17, 0x3, HDA_INPUT),
        HDA_CODEC_MUTE("Analog Loopback 2", 0x17, 0x4, HDA_INPUT),
        { } /* end */
@@ -1317,13 +1327,13 @@ static unsigned int ref92hd71bxx_pin_configs[10] = {
        0x90a000f0, 0x01452050,
 };
 
-static unsigned int dell_m4_1_pin_configs[13] = {
+static unsigned int dell_m4_1_pin_configs[10] = {
        0x0421101f, 0x04a11221, 0x40f000f0, 0x90170110,
        0x23a1902e, 0x23014250, 0x40f000f0, 0x90a000f0,
        0x40f000f0, 0x4f0000f0,
 };
 
-static unsigned int dell_m4_2_pin_configs[13] = {
+static unsigned int dell_m4_2_pin_configs[10] = {
        0x0421101f, 0x04a11221, 0x90a70330, 0x90170110,
        0x23a1902e, 0x23014250, 0x40f000f0, 0x40f000f0,
        0x40f000f0, 0x044413b0,
@@ -1754,12 +1764,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
                      "unknown Dell", STAC_9205_DELL_M42),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f8,
                      "Dell Precision", STAC_9205_DELL_M43),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c,
-                         "Dell Precision", STAC_9205_DELL_M43),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f9,
                      "Dell Precision", STAC_9205_DELL_M43),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b,
-                     "Dell Precision", STAC_9205_DELL_M43),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fa,
                      "Dell Precision", STAC_9205_DELL_M43),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc,
@@ -1770,18 +1776,14 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = {
                      "Dell Precision", STAC_9205_DELL_M43),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01ff,
                      "Dell Precision M4300", STAC_9205_DELL_M43),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206,
-                     "Dell Precision", STAC_9205_DELL_M43),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f1,
-                     "Dell Inspiron", STAC_9205_DELL_M44),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f2,
-                     "Dell Inspiron", STAC_9205_DELL_M44),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fc,
-                     "Dell Inspiron", STAC_9205_DELL_M44),
-       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01fd,
-                     "Dell Inspiron", STAC_9205_DELL_M44),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0204,
                      "unknown Dell", STAC_9205_DELL_M42),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0206,
+                     "Dell Precision", STAC_9205_DELL_M43),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021b,
+                     "Dell Precision", STAC_9205_DELL_M43),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021c,
+                     "Dell Precision", STAC_9205_DELL_M43),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x021f,
                      "Dell Inspiron", STAC_9205_DELL_M44),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228,
@@ -3103,13 +3105,16 @@ static int stac92xx_init(struct hda_codec *codec)
                                        0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
                int def_conf = snd_hda_codec_read(codec, spec->pwr_nids[i],
                                        0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+               def_conf = get_defcfg_connect(def_conf);
                /* outputs are only ports capable of power management
                 * any attempts on powering down a input port cause the
                 * referenced VREF to act quirky.
                 */
                if (pinctl & AC_PINCTL_IN_EN)
                        continue;
-               if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED)
+               /* skip any ports that don't have jacks since presence
+                * detection is useless */
+               if (def_conf && def_conf != AC_JACK_PORT_FIXED)
                        continue;
                enable_pin_detect(codec, spec->pwr_nids[i], event | i);
                codec->patch_ops.unsol_event(codec, (event | i) << 26);
@@ -3614,6 +3619,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
 
        codec->spec = spec;
        spec->num_pins = ARRAY_SIZE(stac92hd71bxx_pin_nids);
+       spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
        spec->pin_nids = stac92hd71bxx_pin_nids;
        spec->board_config = snd_hda_check_board_config(codec,
                                                        STAC_92HD71BXX_MODELS,
@@ -3642,6 +3648,19 @@ again:
                spec->mixer = stac92hd71bxx_mixer;
                spec->init = stac92hd71bxx_core_init;
                break;
+       case 0x111d7608: /* 5 Port with Analog Mixer */
+               /* no output amps */
+               spec->num_pwrs = 0;
+               spec->mixer = stac92hd71bxx_analog_mixer;
+
+               /* disable VSW */
+               spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
+               stac92xx_set_config_reg(codec, 0xf, 0x40f000f0);
+               break;
+       case 0x111d7603: /* 6 Port with Analog Mixer */
+               /* no output amps */
+               spec->num_pwrs = 0;
+               /* fallthru */
        default:
                spec->mixer = stac92hd71bxx_analog_mixer;
                spec->init = stac92hd71bxx_analog_core_init;
@@ -3653,22 +3672,19 @@ again:
        /* GPIO0 High = EAPD */
        spec->gpio_mask = 0x01;
        spec->gpio_dir = 0x01;
-       spec->gpio_mask = 0x01;
        spec->gpio_data = 0x01;
 
        spec->mux_nids = stac92hd71bxx_mux_nids;
        spec->adc_nids = stac92hd71bxx_adc_nids;
        spec->dmic_nids = stac92hd71bxx_dmic_nids;
        spec->dmux_nids = stac92hd71bxx_dmux_nids;
+       spec->pwr_nids = stac92hd71bxx_pwr_nids;
 
        spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids);
        spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids);
        spec->num_dmics = STAC92HD71BXX_NUM_DMICS;
        spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids);
 
-       spec->num_pwrs = ARRAY_SIZE(stac92hd71bxx_pwr_nids);
-       spec->pwr_nids = stac92hd71bxx_pwr_nids;
-
        spec->multiout.num_dacs = 1;
        spec->multiout.hp_nid = 0x11;
        spec->multiout.dac_nids = stac92hd71bxx_dac_nids;
@@ -4306,10 +4322,11 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = {
        { .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 },
        { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 },
        { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 },
+       { .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx},
+       { .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx},
        { .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx },
        { .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx },
        { .id = 0x111d7676, .name = "92HD73E1X5", .patch = patch_stac92hd73xx },
-       { .id = 0x111d7608, .name = "92HD71BXX", .patch = patch_stac92hd71bxx },
        { .id = 0x111d76b0, .name = "92HD71B8X", .patch = patch_stac92hd71bxx },
        { .id = 0x111d76b1, .name = "92HD71B8X", .patch = patch_stac92hd71bxx },
        { .id = 0x111d76b2, .name = "92HD71B7X", .patch = patch_stac92hd71bxx },
index 43b9e3e858be3d7a6297ab70b7bfd382cbf7fb08..a0c5e009bb4a23eaf4c4ddc97148ed34aea25f36 100644 (file)
@@ -93,9 +93,13 @@ enum {
 #define VT1724_REG_MPU_TXFIFO          0x0a    /*byte ro. number of bytes in TX fifo*/
 #define VT1724_REG_MPU_RXFIFO          0x0b    /*byte ro. number of bytes in RX fifo*/
 
-//are these 2 the wrong way around? they don't seem to be used yet anyway
-#define VT1724_REG_MPU_CTRL            0x0c    /* byte */
-#define VT1724_REG_MPU_DATA            0x0d    /* byte */
+#define VT1724_REG_MPU_DATA            0x0c    /* byte */
+#define VT1724_REG_MPU_CTRL            0x0d    /* byte */
+#define   VT1724_MPU_UART      0x01
+#define   VT1724_MPU_TX_EMPTY  0x02
+#define   VT1724_MPU_TX_FULL   0x04
+#define   VT1724_MPU_RX_EMPTY  0x08
+#define   VT1724_MPU_RX_FULL   0x10
 
 #define VT1724_REG_MPU_FIFO_WM 0x0e    /*byte set the high/low watermarks for RX/TX fifos*/
 #define   VT1724_MPU_RX_FIFO   0x20    //1=rx fifo watermark 0=tx fifo watermark
index 3208901c740e075166f95bc1b8d51406ab88ba56..762fbd7a750710dec0ede3ee426f20cc70668b2f 100644 (file)
@@ -333,6 +333,8 @@ struct snd_ice1712 {
        unsigned int has_spdif: 1;      /* VT1720/4 - has SPDIF I/O */
        unsigned int force_pdma4: 1;    /* VT1720/4 - PDMA4 as non-spdif */
        unsigned int force_rdma1: 1;    /* VT1720/4 - RDMA1 as non-spdif */
+       unsigned int midi_output: 1;    /* VT1720/4: MIDI output triggered */
+       unsigned int midi_input: 1;     /* VT1720/4: MIDI input triggered */
        unsigned int num_total_dacs;    /* total DACs */
        unsigned int num_total_adcs;    /* total ADCs */
        unsigned int cur_rate;          /* current rate */
index 67350901772ce986582ef19e0b8ce9dad738f9cb..e596d777d9dde630d12532c55a578937f8d5b2ee 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/mutex.h>
 #include <sound/core.h>
 #include <sound/info.h>
-#include <sound/mpu401.h>
+#include <sound/rawmidi.h>
 #include <sound/initval.h>
 
 #include <sound/asoundef.h>
@@ -223,30 +223,153 @@ static unsigned int snd_vt1724_get_gpio_data(struct snd_ice1712 *ice)
 }
 
 /*
- * MPU401 accessor
+ * MIDI
  */
-static unsigned char snd_vt1724_mpu401_read(struct snd_mpu401 *mpu,
-                                           unsigned long addr)
+
+static void vt1724_midi_clear_rx(struct snd_ice1712 *ice)
+{
+       unsigned int count;
+
+       for (count = inb(ICEREG1724(ice, MPU_RXFIFO)); count > 0; --count)
+               inb(ICEREG1724(ice, MPU_DATA));
+}
+
+static inline struct snd_rawmidi_substream *
+get_rawmidi_substream(struct snd_ice1712 *ice, unsigned int stream)
 {
-       /* fix status bits to the standard position */
-       /* only RX_EMPTY and TX_FULL are checked */
-       if (addr == MPU401C(mpu))
-               return (inb(addr) & 0x0c) << 4;
+       return list_first_entry(&ice->rmidi[0]->streams[stream].substreams,
+                               struct snd_rawmidi_substream, list);
+}
+
+static void vt1724_midi_write(struct snd_ice1712 *ice)
+{
+       struct snd_rawmidi_substream *s;
+       int count, i;
+       u8 buffer[32];
+
+       s = get_rawmidi_substream(ice, SNDRV_RAWMIDI_STREAM_OUTPUT);
+       count = 31 - inb(ICEREG1724(ice, MPU_TXFIFO));
+       if (count > 0) {
+               count = snd_rawmidi_transmit(s, buffer, count);
+               for (i = 0; i < count; ++i)
+                       outb(buffer[i], ICEREG1724(ice, MPU_DATA));
+       }
+}
+
+static void vt1724_midi_read(struct snd_ice1712 *ice)
+{
+       struct snd_rawmidi_substream *s;
+       int count, i;
+       u8 buffer[32];
+
+       s = get_rawmidi_substream(ice, SNDRV_RAWMIDI_STREAM_INPUT);
+       count = inb(ICEREG1724(ice, MPU_RXFIFO));
+       if (count > 0) {
+               count = min(count, 32);
+               for (i = 0; i < count; ++i)
+                       buffer[i] = inb(ICEREG1724(ice, MPU_DATA));
+               snd_rawmidi_receive(s, buffer, count);
+       }
+}
+
+static void vt1724_enable_midi_irq(struct snd_rawmidi_substream *substream,
+                                  u8 flag, int enable)
+{
+       struct snd_ice1712 *ice = substream->rmidi->private_data;
+       u8 mask;
+
+       spin_lock_irq(&ice->reg_lock);
+       mask = inb(ICEREG1724(ice, IRQMASK));
+       if (enable)
+               mask &= ~flag;
        else
-               return inb(addr);
+               mask |= flag;
+       outb(mask, ICEREG1724(ice, IRQMASK));
+       spin_unlock_irq(&ice->reg_lock);
 }
 
-static void snd_vt1724_mpu401_write(struct snd_mpu401 *mpu,
-                                   unsigned char data, unsigned long addr)
+static int vt1724_midi_output_open(struct snd_rawmidi_substream *s)
 {
-       if (addr == MPU401C(mpu)) {
-               if (data == MPU401_ENTER_UART)
-                       outb(0x01, addr);
-               /* what else? */
-       } else
-               outb(data, addr);
+       vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 1);
+       return 0;
+}
+
+static int vt1724_midi_output_close(struct snd_rawmidi_substream *s)
+{
+       vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_TX, 0);
+       return 0;
 }
 
+static void vt1724_midi_output_trigger(struct snd_rawmidi_substream *s, int up)
+{
+       struct snd_ice1712 *ice = s->rmidi->private_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ice->reg_lock, flags);
+       if (up) {
+               ice->midi_output = 1;
+               vt1724_midi_write(ice);
+       } else {
+               ice->midi_output = 0;
+       }
+       spin_unlock_irqrestore(&ice->reg_lock, flags);
+}
+
+static void vt1724_midi_output_drain(struct snd_rawmidi_substream *s)
+{
+       struct snd_ice1712 *ice = s->rmidi->private_data;
+       unsigned long timeout;
+
+       /* 32 bytes should be transmitted in less than about 12 ms */
+       timeout = jiffies + msecs_to_jiffies(15);
+       do {
+               if (inb(ICEREG1724(ice, MPU_CTRL)) & VT1724_MPU_TX_EMPTY)
+                       break;
+               schedule_timeout_uninterruptible(1);
+       } while (time_after(timeout, jiffies));
+}
+
+static struct snd_rawmidi_ops vt1724_midi_output_ops = {
+       .open = vt1724_midi_output_open,
+       .close = vt1724_midi_output_close,
+       .trigger = vt1724_midi_output_trigger,
+       .drain = vt1724_midi_output_drain,
+};
+
+static int vt1724_midi_input_open(struct snd_rawmidi_substream *s)
+{
+       vt1724_midi_clear_rx(s->rmidi->private_data);
+       vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_RX, 1);
+       return 0;
+}
+
+static int vt1724_midi_input_close(struct snd_rawmidi_substream *s)
+{
+       vt1724_enable_midi_irq(s, VT1724_IRQ_MPU_RX, 0);
+       return 0;
+}
+
+static void vt1724_midi_input_trigger(struct snd_rawmidi_substream *s, int up)
+{
+       struct snd_ice1712 *ice = s->rmidi->private_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ice->reg_lock, flags);
+       if (up) {
+               ice->midi_input = 1;
+               vt1724_midi_read(ice);
+       } else {
+               ice->midi_input = 0;
+       }
+       spin_unlock_irqrestore(&ice->reg_lock, flags);
+}
+
+static struct snd_rawmidi_ops vt1724_midi_input_ops = {
+       .open = vt1724_midi_input_open,
+       .close = vt1724_midi_input_close,
+       .trigger = vt1724_midi_input_trigger,
+};
+
 
 /*
  *  Interrupt handler
@@ -278,13 +401,10 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
 #endif
                handled = 1;            
                if (status & VT1724_IRQ_MPU_TX) {
-                       if (ice->rmidi[0])
-                               snd_mpu401_uart_interrupt_tx(irq,
-                                       ice->rmidi[0]->private_data);
-                       else /* disable TX to be sure */
-                               outb(inb(ICEREG1724(ice, IRQMASK)) |
-                                    VT1724_IRQ_MPU_TX,
-                                    ICEREG1724(ice, IRQMASK));
+                       spin_lock(&ice->reg_lock);
+                       if (ice->midi_output)
+                               vt1724_midi_write(ice);
+                       spin_unlock(&ice->reg_lock);
                        /* Due to mysterical reasons, MPU_TX is always
                         * generated (and can't be cleared) when a PCM
                         * playback is going.  So let's ignore at the
@@ -293,13 +413,12 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
                        status_mask &= ~VT1724_IRQ_MPU_TX;
                }
                if (status & VT1724_IRQ_MPU_RX) {
-                       if (ice->rmidi[0])
-                               snd_mpu401_uart_interrupt(irq,
-                                       ice->rmidi[0]->private_data);
-                       else /* disable RX to be sure */
-                               outb(inb(ICEREG1724(ice, IRQMASK)) |
-                                    VT1724_IRQ_MPU_RX,
-                                    ICEREG1724(ice, IRQMASK));
+                       spin_lock(&ice->reg_lock);
+                       if (ice->midi_input)
+                               vt1724_midi_read(ice);
+                       else
+                               vt1724_midi_clear_rx(ice);
+                       spin_unlock(&ice->reg_lock);
                }
                /* ack MPU irq */
                outb(status, ICEREG1724(ice, IRQSTAT));
@@ -2425,28 +2544,30 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
 
        if (! c->no_mpu401) {
                if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
-                       struct snd_mpu401 *mpu;
-                       if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
-                                                      ICEREG1724(ice, MPU_CTRL),
-                                                      (MPU401_INFO_INTEGRATED |
-                                                       MPU401_INFO_NO_ACK |
-                                                       MPU401_INFO_TX_IRQ),
-                                                      ice->irq, 0,
-                                                      &ice->rmidi[0])) < 0) {
+                       struct snd_rawmidi *rmidi;
+
+                       err = snd_rawmidi_new(card, "MIDI", 0, 1, 1, &rmidi);
+                       if (err < 0) {
                                snd_card_free(card);
                                return err;
                        }
-                       mpu = ice->rmidi[0]->private_data;
-                       mpu->read = snd_vt1724_mpu401_read;
-                       mpu->write = snd_vt1724_mpu401_write;
-                       /* unmask MPU RX/TX irqs */
-                       outb(inb(ICEREG1724(ice, IRQMASK)) &
-                            ~(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX),
-                            ICEREG1724(ice, IRQMASK));
+                       ice->rmidi[0] = rmidi;
+                       rmidi->private_data = ice;
+                       strcpy(rmidi->name, "ICE1724 MIDI");
+                       rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+                                           SNDRV_RAWMIDI_INFO_INPUT |
+                                           SNDRV_RAWMIDI_INFO_DUPLEX;
+                       snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
+                                           &vt1724_midi_output_ops);
+                       snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+                                           &vt1724_midi_input_ops);
+
                        /* set watermarks */
                        outb(VT1724_MPU_RX_FIFO | 0x1,
                             ICEREG1724(ice, MPU_FIFO_WM));
                        outb(0x1, ICEREG1724(ice, MPU_FIFO_WM));
+                       /* set UART mode */
+                       outb(VT1724_MPU_UART, ICEREG1724(ice, MPU_CTRL));
                }
        }
 
index a536c59fbea1e4faed5155ce579ac0ac800e572b..f4788dee05c36efe80ec6117d66bb469afdeecaa 100644 (file)
@@ -2427,6 +2427,29 @@ snd_m3_amp_enable(struct snd_m3 *chip, int enable)
        outw(0xffff, io + GPIO_MASK);
 }
 
+static void
+snd_m3_hv_init(struct snd_m3 *chip)
+{
+       unsigned long io = chip->iobase;
+       u16 val = GPI_VOL_DOWN | GPI_VOL_UP;
+
+       if (!chip->is_omnibook)
+               return;
+
+       /*
+        * Volume buttons on some HP OmniBook laptops
+        * require some GPIO magic to work correctly.
+        */
+       outw(0xffff, io + GPIO_MASK);
+       outw(0x0000, io + GPIO_DATA);
+
+       outw(~val, io + GPIO_MASK);
+       outw(inw(io + GPIO_DIRECTION) & ~val, io + GPIO_DIRECTION);
+       outw(val, io + GPIO_MASK);
+
+       outw(0xffff, io + GPIO_MASK);
+}
+
 static int
 snd_m3_chip_init(struct snd_m3 *chip)
 {
@@ -2442,21 +2465,6 @@ snd_m3_chip_init(struct snd_m3 *chip)
               DISABLE_LEGACY);
        pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w);
 
-       if (chip->is_omnibook) {
-               /*
-                * Volume buttons on some HP OmniBook laptops don't work
-                * correctly. This makes them work for the most part.
-                *
-                * Volume up and down buttons on the laptop side work.
-                * Fn+cursor_up (volme up) works.
-                * Fn+cursor_down (volume down) doesn't work.
-                * Fn+F7 (mute) works acts as volume up.
-                */
-               outw(~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_MASK);
-               outw(inw(io + GPIO_DIRECTION) & ~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DIRECTION);
-               outw((GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DATA);
-               outw(0xffff, io + GPIO_MASK);
-       }
        pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n);
        n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD);
        n |= chip->hv_config;
@@ -2642,6 +2650,8 @@ static int m3_resume(struct pci_dev *pci)
        snd_m3_enable_ints(chip);
        snd_m3_amp_enable(chip, 1);
 
+       snd_m3_hv_init(chip);
+
        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
        return 0;
 }
@@ -2781,6 +2791,8 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
 
        snd_m3_amp_enable(chip, 1);
 
+       snd_m3_hv_init(chip);
+
        tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
 
        if (request_irq(pci->irq, snd_m3_interrupt, IRQF_SHARED,
index 7efb838d18a6b3e78c0b5ceedeccc85887187b2c..06d13e7171148d261fdeeccd21563da3ef59d577 100644 (file)
@@ -1302,8 +1302,8 @@ snd_nm256_mixer(struct nm256 *chip)
                .read = snd_nm256_ac97_read,
        };
 
-       chip->ac97_regs = kcalloc(sizeof(short),
-                                 ARRAY_SIZE(nm256_ac97_init_val), GFP_KERNEL);
+       chip->ac97_regs = kcalloc(ARRAY_SIZE(nm256_ac97_init_val),
+                                 sizeof(short), GFP_KERNEL);
        if (! chip->ac97_regs)
                return -ENOMEM;
 
index 090dd4354a2838fa2e818265270965c829460c34..7442460583dde0c68f92f40c965afe8cbb461272 100644 (file)
@@ -28,7 +28,7 @@
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("TempoTec HiFier driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
@@ -62,16 +62,28 @@ static void ak4396_write(struct oxygen *chip, u8 reg, u8 value)
                         AK4396_WRITE | (reg << 8) | value);
 }
 
-static void hifier_init(struct oxygen *chip)
+static void update_ak4396_volume(struct oxygen *chip)
+{
+       ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]);
+       ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]);
+}
+
+static void hifier_registers_init(struct oxygen *chip)
 {
        struct hifier_data *data = chip->model_data;
 
-       data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
        ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
        ak4396_write(chip, AK4396_CONTROL_2, data->ak4396_ctl2);
        ak4396_write(chip, AK4396_CONTROL_3, AK4396_PCM);
-       ak4396_write(chip, AK4396_LCH_ATT, 0);
-       ak4396_write(chip, AK4396_RCH_ATT, 0);
+       update_ak4396_volume(chip);
+}
+
+static void hifier_init(struct oxygen *chip)
+{
+       struct hifier_data *data = chip->model_data;
+
+       data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
+       hifier_registers_init(chip);
 
        snd_component_add(chip->card, "AK4396");
        snd_component_add(chip->card, "CS5340");
@@ -100,12 +112,6 @@ static void set_ak4396_params(struct oxygen *chip,
        ak4396_write(chip, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
 }
 
-static void update_ak4396_volume(struct oxygen *chip)
-{
-       ak4396_write(chip, AK4396_LCH_ATT, chip->dac_volume[0]);
-       ak4396_write(chip, AK4396_RCH_ATT, chip->dac_volume[1]);
-}
-
 static void update_ak4396_mute(struct oxygen *chip)
 {
        struct hifier_data *data = chip->model_data;
@@ -140,6 +146,7 @@ static const struct oxygen_model model_hifier = {
        .init = hifier_init,
        .control_filter = hifier_control_filter,
        .cleanup = hifier_cleanup,
+       .resume = hifier_registers_init,
        .set_dac_params = set_ak4396_params,
        .set_adc_params = set_cs5340_params,
        .update_dac_volume = update_ak4396_volume,
@@ -180,6 +187,10 @@ static struct pci_driver hifier_driver = {
        .id_table = hifier_ids,
        .probe = hifier_probe,
        .remove = __devexit_p(oxygen_pci_remove),
+#ifdef CONFIG_PM
+       .suspend = oxygen_pci_suspend,
+       .resume = oxygen_pci_resume,
+#endif
 };
 
 static int __init alsa_card_hifier_init(void)
index 63f185c1ed1ed899a0af6786d4092731a87f0c26..7c8ae31eb4685b857488e931a55efcd8f4e1826e 100644 (file)
@@ -43,7 +43,7 @@
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("C-Media CMI8788 driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8788}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
@@ -80,6 +80,7 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
 
 struct generic_data {
        u8 ak4396_ctl2;
+       u16 saved_wm8785_registers[2];
 };
 
 static void ak4396_write(struct oxygen *chip, unsigned int codec,
@@ -99,20 +100,35 @@ static void ak4396_write(struct oxygen *chip, unsigned int codec,
 
 static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value)
 {
+       struct generic_data *data = chip->model_data;
+
        oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
                         OXYGEN_SPI_DATA_LENGTH_2 |
                         OXYGEN_SPI_CLOCK_160 |
                         (3 << OXYGEN_SPI_CODEC_SHIFT) |
                         OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
                         (reg << 9) | value);
+       if (reg < ARRAY_SIZE(data->saved_wm8785_registers))
+               data->saved_wm8785_registers[reg] = value;
 }
 
-static void ak4396_init(struct oxygen *chip)
+static void update_ak4396_volume(struct oxygen *chip)
+{
+       unsigned int i;
+
+       for (i = 0; i < 4; ++i) {
+               ak4396_write(chip, i,
+                            AK4396_LCH_ATT, chip->dac_volume[i * 2]);
+               ak4396_write(chip, i,
+                            AK4396_RCH_ATT, chip->dac_volume[i * 2 + 1]);
+       }
+}
+
+static void ak4396_registers_init(struct oxygen *chip)
 {
        struct generic_data *data = chip->model_data;
        unsigned int i;
 
-       data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
        for (i = 0; i < 4; ++i) {
                ak4396_write(chip, i,
                             AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_RSTN);
@@ -120,9 +136,16 @@ static void ak4396_init(struct oxygen *chip)
                             AK4396_CONTROL_2, data->ak4396_ctl2);
                ak4396_write(chip, i,
                             AK4396_CONTROL_3, AK4396_PCM);
-               ak4396_write(chip, i, AK4396_LCH_ATT, 0);
-               ak4396_write(chip, i, AK4396_RCH_ATT, 0);
        }
+       update_ak4396_volume(chip);
+}
+
+static void ak4396_init(struct oxygen *chip)
+{
+       struct generic_data *data = chip->model_data;
+
+       data->ak4396_ctl2 = AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
+       ak4396_registers_init(chip);
        snd_component_add(chip->card, "AK4396");
 }
 
@@ -133,12 +156,23 @@ static void ak5385_init(struct oxygen *chip)
        snd_component_add(chip->card, "AK5385");
 }
 
-static void wm8785_init(struct oxygen *chip)
+static void wm8785_registers_init(struct oxygen *chip)
 {
+       struct generic_data *data = chip->model_data;
+
        wm8785_write(chip, WM8785_R7, 0);
-       wm8785_write(chip, WM8785_R0, WM8785_MCR_SLAVE |
-                    WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST);
-       wm8785_write(chip, WM8785_R1, WM8785_WL_24);
+       wm8785_write(chip, WM8785_R0, data->saved_wm8785_registers[0]);
+       wm8785_write(chip, WM8785_R1, data->saved_wm8785_registers[1]);
+}
+
+static void wm8785_init(struct oxygen *chip)
+{
+       struct generic_data *data = chip->model_data;
+
+       data->saved_wm8785_registers[0] = WM8785_MCR_SLAVE |
+               WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST;
+       data->saved_wm8785_registers[1] = WM8785_WL_24;
+       wm8785_registers_init(chip);
        snd_component_add(chip->card, "WM8785");
 }
 
@@ -158,6 +192,12 @@ static void generic_cleanup(struct oxygen *chip)
 {
 }
 
+static void generic_resume(struct oxygen *chip)
+{
+       ak4396_registers_init(chip);
+       wm8785_registers_init(chip);
+}
+
 static void set_ak4396_params(struct oxygen *chip,
                              struct snd_pcm_hw_params *params)
 {
@@ -183,18 +223,6 @@ static void set_ak4396_params(struct oxygen *chip,
        }
 }
 
-static void update_ak4396_volume(struct oxygen *chip)
-{
-       unsigned int i;
-
-       for (i = 0; i < 4; ++i) {
-               ak4396_write(chip, i,
-                            AK4396_LCH_ATT, chip->dac_volume[i * 2]);
-               ak4396_write(chip, i,
-                            AK4396_RCH_ATT, chip->dac_volume[i * 2 + 1]);
-       }
-}
-
 static void update_ak4396_mute(struct oxygen *chip)
 {
        struct generic_data *data = chip->model_data;
@@ -256,6 +284,7 @@ static const struct oxygen_model model_generic = {
        .owner = THIS_MODULE,
        .init = generic_init,
        .cleanup = generic_cleanup,
+       .resume = generic_resume,
        .set_dac_params = set_ak4396_params,
        .set_adc_params = set_wm8785_params,
        .update_dac_volume = update_ak4396_volume,
@@ -283,6 +312,7 @@ static const struct oxygen_model model_meridian = {
        .owner = THIS_MODULE,
        .init = meridian_init,
        .cleanup = generic_cleanup,
+       .resume = ak4396_registers_init,
        .set_dac_params = set_ak4396_params,
        .set_adc_params = set_ak5385_params,
        .update_dac_volume = update_ak4396_volume,
@@ -331,6 +361,10 @@ static struct pci_driver oxygen_driver = {
        .id_table = oxygen_ids,
        .probe = generic_oxygen_probe,
        .remove = __devexit_p(oxygen_pci_remove),
+#ifdef CONFIG_PM
+       .suspend = oxygen_pci_suspend,
+       .resume = oxygen_pci_resume,
+#endif
 };
 
 static int __init alsa_card_oxygen_init(void)
index a71c6e059260543c08b172f4fd71e3bdd0f5eef8..74a6448800747acb0de19ce4eb70db51a4c67f7c 100644 (file)
@@ -16,6 +16,8 @@
 #define PCM_AC97       5
 #define PCM_COUNT      6
 
+#define OXYGEN_IO_SIZE 0x100
+
 /* model-specific configuration of outputs/inputs */
 #define PLAYBACK_0_TO_I2S      0x001
 #define PLAYBACK_1_TO_SPDIF    0x004
@@ -78,6 +80,12 @@ struct oxygen {
        struct work_struct spdif_input_bits_work;
        struct work_struct gpio_work;
        wait_queue_head_t ac97_waitqueue;
+       union {
+               u8 _8[OXYGEN_IO_SIZE];
+               __le16 _16[OXYGEN_IO_SIZE / 2];
+               __le32 _32[OXYGEN_IO_SIZE / 4];
+       } saved_registers;
+       u16 saved_ac97_registers[2][0x40];
 };
 
 struct oxygen_model {
@@ -89,6 +97,8 @@ struct oxygen_model {
        int (*control_filter)(struct snd_kcontrol_new *template);
        int (*mixer_init)(struct oxygen *chip);
        void (*cleanup)(struct oxygen *chip);
+       void (*suspend)(struct oxygen *chip);
+       void (*resume)(struct oxygen *chip);
        void (*pcm_hardware_filter)(unsigned int channel,
                                    struct snd_pcm_hardware *hardware);
        void (*set_dac_params)(struct oxygen *chip,
@@ -117,6 +127,10 @@ struct oxygen_model {
 int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
                     const struct oxygen_model *model);
 void oxygen_pci_remove(struct pci_dev *pci);
+#ifdef CONFIG_PM
+int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state);
+int oxygen_pci_resume(struct pci_dev *pci);
+#endif
 
 /* oxygen_mixer.c */
 
index 5569606ee87ff22bfb0ac9b9a15e9635e7bd4ed4..83f135f80df44439f62aed9f0b2e3b72d76172a8 100644 (file)
@@ -44,18 +44,21 @@ EXPORT_SYMBOL(oxygen_read32);
 void oxygen_write8(struct oxygen *chip, unsigned int reg, u8 value)
 {
        outb(value, chip->addr + reg);
+       chip->saved_registers._8[reg] = value;
 }
 EXPORT_SYMBOL(oxygen_write8);
 
 void oxygen_write16(struct oxygen *chip, unsigned int reg, u16 value)
 {
        outw(value, chip->addr + reg);
+       chip->saved_registers._16[reg / 2] = cpu_to_le16(value);
 }
 EXPORT_SYMBOL(oxygen_write16);
 
 void oxygen_write32(struct oxygen *chip, unsigned int reg, u32 value)
 {
        outl(value, chip->addr + reg);
+       chip->saved_registers._32[reg / 4] = cpu_to_le32(value);
 }
 EXPORT_SYMBOL(oxygen_write32);
 
@@ -63,7 +66,10 @@ void oxygen_write8_masked(struct oxygen *chip, unsigned int reg,
                          u8 value, u8 mask)
 {
        u8 tmp = inb(chip->addr + reg);
-       outb((tmp & ~mask) | (value & mask), chip->addr + reg);
+       tmp &= ~mask;
+       tmp |= value & mask;
+       outb(tmp, chip->addr + reg);
+       chip->saved_registers._8[reg] = tmp;
 }
 EXPORT_SYMBOL(oxygen_write8_masked);
 
@@ -71,7 +77,10 @@ void oxygen_write16_masked(struct oxygen *chip, unsigned int reg,
                           u16 value, u16 mask)
 {
        u16 tmp = inw(chip->addr + reg);
-       outw((tmp & ~mask) | (value & mask), chip->addr + reg);
+       tmp &= ~mask;
+       tmp |= value & mask;
+       outw(tmp, chip->addr + reg);
+       chip->saved_registers._16[reg / 2] = cpu_to_le16(tmp);
 }
 EXPORT_SYMBOL(oxygen_write16_masked);
 
@@ -79,7 +88,10 @@ void oxygen_write32_masked(struct oxygen *chip, unsigned int reg,
                           u32 value, u32 mask)
 {
        u32 tmp = inl(chip->addr + reg);
-       outl((tmp & ~mask) | (value & mask), chip->addr + reg);
+       tmp &= ~mask;
+       tmp |= value & mask;
+       outl(tmp, chip->addr + reg);
+       chip->saved_registers._32[reg / 4] = cpu_to_le32(tmp);
 }
 EXPORT_SYMBOL(oxygen_write32_masked);
 
@@ -128,8 +140,10 @@ void oxygen_write_ac97(struct oxygen *chip, unsigned int codec,
                oxygen_write32(chip, OXYGEN_AC97_REGS, reg);
                /* require two "completed" writes, just to be sure */
                if (oxygen_ac97_wait(chip, OXYGEN_AC97_INT_WRITE_DONE) >= 0 &&
-                   ++succeeded >= 2)
+                   ++succeeded >= 2) {
+                       chip->saved_ac97_registers[codec][index / 2] = data;
                        return;
+               }
        }
        snd_printk(KERN_ERR "AC'97 write timeout\n");
 }
index 897697d43506d2354b2ffc954f58232d97b3c556..22f37851045e9639032b55960abcd3edb88c973e 100644 (file)
@@ -32,7 +32,7 @@
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("C-Media CMI8788 helper library");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 
 
 static irqreturn_t oxygen_interrupt(int dummy, void *dev_id)
@@ -173,7 +173,7 @@ static void oxygen_proc_read(struct snd_info_entry *entry,
        int i, j;
 
        snd_iprintf(buffer, "CMI8788\n\n");
-       for (i = 0; i < 0x100; i += 0x10) {
+       for (i = 0; i < OXYGEN_IO_SIZE; i += 0x10) {
                snd_iprintf(buffer, "%02x:", i);
                for (j = 0; j < 0x10; ++j)
                        snd_iprintf(buffer, " %02x", oxygen_read8(chip, i + j));
@@ -314,6 +314,10 @@ static void oxygen_init(struct oxygen *chip)
                                    OXYGEN_SPDIF_LOCK_MASK |
                                    OXYGEN_SPDIF_RATE_MASK);
        oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits);
+       oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
+                      OXYGEN_2WIRE_LENGTH_8 |
+                      OXYGEN_2WIRE_INTERRUPT_MASK |
+                      OXYGEN_2WIRE_SPEED_STANDARD);
        oxygen_clear_bits8(chip, OXYGEN_MPU401_CONTROL, OXYGEN_MPU401_LOOPBACK);
        oxygen_write8(chip, OXYGEN_GPI_INTERRUPT_MASK, 0);
        oxygen_write16(chip, OXYGEN_GPIO_INTERRUPT_MASK, 0);
@@ -455,7 +459,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
        }
 
        if (!(pci_resource_flags(pci, 0) & IORESOURCE_IO) ||
-           pci_resource_len(pci, 0) < 0x100) {
+           pci_resource_len(pci, 0) < OXYGEN_IO_SIZE) {
                snd_printk(KERN_ERR "invalid PCI I/O range\n");
                err = -ENXIO;
                goto err_pci_regions;
@@ -534,3 +538,99 @@ void oxygen_pci_remove(struct pci_dev *pci)
        pci_set_drvdata(pci, NULL);
 }
 EXPORT_SYMBOL(oxygen_pci_remove);
+
+#ifdef CONFIG_PM
+int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state)
+{
+       struct snd_card *card = pci_get_drvdata(pci);
+       struct oxygen *chip = card->private_data;
+       unsigned int i, saved_interrupt_mask;
+
+       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+
+       for (i = 0; i < PCM_COUNT; ++i)
+               if (chip->streams[i])
+                       snd_pcm_suspend(chip->streams[i]);
+
+       if (chip->model->suspend)
+               chip->model->suspend(chip);
+
+       spin_lock_irq(&chip->reg_lock);
+       saved_interrupt_mask = chip->interrupt_mask;
+       chip->interrupt_mask = 0;
+       oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
+       oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
+       spin_unlock_irq(&chip->reg_lock);
+
+       synchronize_irq(chip->irq);
+       flush_scheduled_work();
+       chip->interrupt_mask = saved_interrupt_mask;
+
+       pci_disable_device(pci);
+       pci_save_state(pci);
+       pci_set_power_state(pci, pci_choose_state(pci, state));
+       return 0;
+}
+EXPORT_SYMBOL(oxygen_pci_suspend);
+
+static const u32 registers_to_restore[OXYGEN_IO_SIZE / 32] = {
+       0xffffffff, 0x00ff077f, 0x00011d08, 0x007f00ff,
+       0x00300000, 0x00000fe4, 0x0ff7001f, 0x00000000
+};
+static const u32 ac97_registers_to_restore[2][0x40 / 32] = {
+       { 0x18284fa2, 0x03060000 },
+       { 0x00007fa6, 0x00200000 }
+};
+
+static inline int is_bit_set(const u32 *bitmap, unsigned int bit)
+{
+       return bitmap[bit / 32] & (1 << (bit & 31));
+}
+
+static void oxygen_restore_ac97(struct oxygen *chip, unsigned int codec)
+{
+       unsigned int i;
+
+       oxygen_write_ac97(chip, codec, AC97_RESET, 0);
+       msleep(1);
+       for (i = 1; i < 0x40; ++i)
+               if (is_bit_set(ac97_registers_to_restore[codec], i))
+                       oxygen_write_ac97(chip, codec, i * 2,
+                                         chip->saved_ac97_registers[codec][i]);
+}
+
+int oxygen_pci_resume(struct pci_dev *pci)
+{
+       struct snd_card *card = pci_get_drvdata(pci);
+       struct oxygen *chip = card->private_data;
+       unsigned int i;
+
+       pci_set_power_state(pci, PCI_D0);
+       pci_restore_state(pci);
+       if (pci_enable_device(pci) < 0) {
+               snd_printk(KERN_ERR "cannot reenable device");
+               snd_card_disconnect(card);
+               return -EIO;
+       }
+       pci_set_master(pci);
+
+       oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
+       oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
+       for (i = 0; i < OXYGEN_IO_SIZE; ++i)
+               if (is_bit_set(registers_to_restore, i))
+                       oxygen_write8(chip, i, chip->saved_registers._8[i]);
+       if (chip->has_ac97_0)
+               oxygen_restore_ac97(chip, 0);
+       if (chip->has_ac97_1)
+               oxygen_restore_ac97(chip, 1);
+
+       if (chip->model->resume)
+               chip->model->resume(chip);
+
+       oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask);
+
+       snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+       return 0;
+}
+EXPORT_SYMBOL(oxygen_pci_resume);
+#endif /* CONFIG_PM */
index b17c405e069df5349daceba5db00416de012eb1b..c4ad65a3406fd61ea6bcb016d8b979def759691a 100644 (file)
 #include <sound/pcm_params.h>
 #include "oxygen.h"
 
+/* most DMA channels have a 16-bit counter for 32-bit words */
+#define BUFFER_BYTES_MAX               ((1 << 16) * 4)
+/* the multichannel DMA channel has a 24-bit counter */
+#define BUFFER_BYTES_MAX_MULTICH       ((1 << 24) * 4)
+
+#define PERIOD_BYTES_MIN               64
+
+#define DEFAULT_BUFFER_BYTES           (BUFFER_BYTES_MAX / 2)
+#define DEFAULT_BUFFER_BYTES_MULTICH   (1024 * 1024)
+
 static const struct snd_pcm_hardware oxygen_stereo_hardware = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_MMAP_VALID |
@@ -44,11 +54,11 @@ static const struct snd_pcm_hardware oxygen_stereo_hardware = {
        .rate_max = 192000,
        .channels_min = 2,
        .channels_max = 2,
-       .buffer_bytes_max = 256 * 1024,
-       .period_bytes_min = 128,
-       .period_bytes_max = 128 * 1024,
+       .buffer_bytes_max = BUFFER_BYTES_MAX,
+       .period_bytes_min = PERIOD_BYTES_MIN,
+       .period_bytes_max = BUFFER_BYTES_MAX / 2,
        .periods_min = 2,
-       .periods_max = 2048,
+       .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
 };
 static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
        .info = SNDRV_PCM_INFO_MMAP |
@@ -70,11 +80,11 @@ static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
        .rate_max = 192000,
        .channels_min = 2,
        .channels_max = 8,
-       .buffer_bytes_max = 2048 * 1024,
-       .period_bytes_min = 128,
-       .period_bytes_max = 256 * 1024,
+       .buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH,
+       .period_bytes_min = PERIOD_BYTES_MIN,
+       .period_bytes_max = BUFFER_BYTES_MAX_MULTICH / 2,
        .periods_min = 2,
-       .periods_max = 16384,
+       .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN,
 };
 static const struct snd_pcm_hardware oxygen_ac97_hardware = {
        .info = SNDRV_PCM_INFO_MMAP |
@@ -88,11 +98,11 @@ static const struct snd_pcm_hardware oxygen_ac97_hardware = {
        .rate_max = 48000,
        .channels_min = 2,
        .channels_max = 2,
-       .buffer_bytes_max = 256 * 1024,
-       .period_bytes_min = 128,
-       .period_bytes_max = 128 * 1024,
+       .buffer_bytes_max = BUFFER_BYTES_MAX,
+       .period_bytes_min = PERIOD_BYTES_MIN,
+       .period_bytes_max = BUFFER_BYTES_MAX / 2,
        .periods_min = 2,
-       .periods_max = 2048,
+       .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
 };
 
 static const struct snd_pcm_hardware *const oxygen_hardware[PCM_COUNT] = {
@@ -155,6 +165,12 @@ static int oxygen_open(struct snd_pcm_substream *substream,
                if (err < 0)
                        return err;
        }
+       if (channel == PCM_MULTICH) {
+               err = snd_pcm_hw_constraint_minmax
+                       (runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 0, 8192000);
+               if (err < 0)
+                       return err;
+       }
        snd_pcm_set_sync(substream);
        chip->streams[channel] = substream;
 
@@ -517,6 +533,7 @@ static int oxygen_trigger(struct snd_pcm_substream *substream, int cmd)
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
                pausing = 0;
                break;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -663,12 +680,14 @@ int oxygen_pcm_init(struct oxygen *chip)
                        snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
                                                      SNDRV_DMA_TYPE_DEV,
                                                      snd_dma_pci_data(chip->pci),
-                                                     512 * 1024, 2048 * 1024);
+                                                     DEFAULT_BUFFER_BYTES_MULTICH,
+                                                     BUFFER_BYTES_MAX_MULTICH);
                if (ins)
                        snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
                                                      SNDRV_DMA_TYPE_DEV,
                                                      snd_dma_pci_data(chip->pci),
-                                                     128 * 1024, 256 * 1024);
+                                                     DEFAULT_BUFFER_BYTES,
+                                                     BUFFER_BYTES_MAX);
        }
 
        outs = !!(chip->model->pcm_dev_cfg & PLAYBACK_1_TO_SPDIF);
@@ -688,7 +707,8 @@ int oxygen_pcm_init(struct oxygen *chip)
                strcpy(pcm->name, "Digital");
                snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
                                                      snd_dma_pci_data(chip->pci),
-                                                     128 * 1024, 256 * 1024);
+                                                     DEFAULT_BUFFER_BYTES,
+                                                     BUFFER_BYTES_MAX);
        }
 
        if (chip->has_ac97_1) {
@@ -718,7 +738,8 @@ int oxygen_pcm_init(struct oxygen *chip)
                strcpy(pcm->name, outs ? "Front Panel" : "Analog 2");
                snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
                                                      snd_dma_pci_data(chip->pci),
-                                                     128 * 1024, 256 * 1024);
+                                                     DEFAULT_BUFFER_BYTES,
+                                                     BUFFER_BYTES_MAX);
        }
        return 0;
 }
index 7f84fa5deca2864473c00d60ff07ed602235204c..9a2c16bf94e0479ab359640808f829e1950b7d09 100644 (file)
@@ -79,7 +79,7 @@
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("Asus AVx00 driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 MODULE_SUPPORTED_DEVICE("{{Asus,AV100},{Asus,AV200}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
@@ -132,6 +132,9 @@ struct xonar_data {
        u8 ext_power_int_reg;
        u8 ext_power_bit;
        u8 has_power;
+       u8 pcm1796_oversampling;
+       u8 cs4398_fm;
+       u8 cs4362a_fm;
 };
 
 static void pcm1796_write(struct oxygen *chip, unsigned int codec,
@@ -159,6 +162,14 @@ static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value)
        oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value);
 }
 
+static void xonar_enable_output(struct oxygen *chip)
+{
+       struct xonar_data *data = chip->model_data;
+
+       msleep(data->anti_pop_delay);
+       oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
+}
+
 static void xonar_common_init(struct oxygen *chip)
 {
        struct xonar_data *data = chip->model_data;
@@ -170,32 +181,59 @@ static void xonar_common_init(struct oxygen *chip)
                data->has_power = !!(oxygen_read8(chip, data->ext_power_reg)
                                     & data->ext_power_bit);
        }
-       oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK);
+       oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
+                         GPIO_CS53x1_M_MASK | data->output_enable_bit);
        oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
                              GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK);
        oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC);
-       msleep(data->anti_pop_delay);
-       oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, data->output_enable_bit);
-       oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit);
+       xonar_enable_output(chip);
 }
 
-static void xonar_d2_init(struct oxygen *chip)
+static void update_pcm1796_volume(struct oxygen *chip)
 {
-       struct xonar_data *data = chip->model_data;
        unsigned int i;
 
-       data->anti_pop_delay = 300;
-       data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
+       for (i = 0; i < 4; ++i) {
+               pcm1796_write(chip, i, 16, chip->dac_volume[i * 2]);
+               pcm1796_write(chip, i, 17, chip->dac_volume[i * 2 + 1]);
+       }
+}
+
+static void update_pcm1796_mute(struct oxygen *chip)
+{
+       unsigned int i;
+       u8 value;
+
+       value = PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD;
+       if (chip->dac_mute)
+               value |= PCM1796_MUTE;
+       for (i = 0; i < 4; ++i)
+               pcm1796_write(chip, i, 18, value);
+}
+
+static void pcm1796_init(struct oxygen *chip)
+{
+       struct xonar_data *data = chip->model_data;
+       unsigned int i;
 
        for (i = 0; i < 4; ++i) {
-               pcm1796_write(chip, i, 18, PCM1796_MUTE | PCM1796_DMF_DISABLED |
-                             PCM1796_FMT_24_LJUST | PCM1796_ATLD);
                pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1);
-               pcm1796_write(chip, i, 20, PCM1796_OS_64);
+               pcm1796_write(chip, i, 20, data->pcm1796_oversampling);
                pcm1796_write(chip, i, 21, 0);
-               pcm1796_write(chip, i, 16, 0x0f); /* set ATL/ATR after ATLD */
-               pcm1796_write(chip, i, 17, 0x0f);
        }
+       update_pcm1796_mute(chip); /* set ATLD before ATL/ATR */
+       update_pcm1796_volume(chip);
+}
+
+static void xonar_d2_init(struct oxygen *chip)
+{
+       struct xonar_data *data = chip->model_data;
+
+       data->anti_pop_delay = 300;
+       data->output_enable_bit = GPIO_D2_OUTPUT_ENABLE;
+       data->pcm1796_oversampling = PCM1796_OS_64;
+
+       pcm1796_init(chip);
 
        oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT);
        oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D2_ALT);
@@ -217,31 +255,47 @@ static void xonar_d2x_init(struct oxygen *chip)
        xonar_d2_init(chip);
 }
 
-static void xonar_dx_init(struct oxygen *chip)
+static void update_cs4362a_volumes(struct oxygen *chip)
 {
-       struct xonar_data *data = chip->model_data;
+       u8 mute;
 
-       data->anti_pop_delay = 800;
-       data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
-       data->ext_power_reg = OXYGEN_GPI_DATA;
-       data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
-       data->ext_power_bit = GPI_DX_EXT_POWER;
+       mute = chip->dac_mute ? CS4362A_MUTE : 0;
+       cs4362a_write(chip, 7, (127 - chip->dac_volume[2]) | mute);
+       cs4362a_write(chip, 8, (127 - chip->dac_volume[3]) | mute);
+       cs4362a_write(chip, 10, (127 - chip->dac_volume[4]) | mute);
+       cs4362a_write(chip, 11, (127 - chip->dac_volume[5]) | mute);
+       cs4362a_write(chip, 13, (127 - chip->dac_volume[6]) | mute);
+       cs4362a_write(chip, 14, (127 - chip->dac_volume[7]) | mute);
+}
 
-       oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
-                      OXYGEN_2WIRE_LENGTH_8 |
-                      OXYGEN_2WIRE_INTERRUPT_MASK |
-                      OXYGEN_2WIRE_SPEED_FAST);
+static void update_cs43xx_volume(struct oxygen *chip)
+{
+       cs4398_write(chip, 5, (127 - chip->dac_volume[0]) * 2);
+       cs4398_write(chip, 6, (127 - chip->dac_volume[1]) * 2);
+       update_cs4362a_volumes(chip);
+}
+
+static void update_cs43xx_mute(struct oxygen *chip)
+{
+       u8 reg;
+
+       reg = CS4398_MUTEP_LOW | CS4398_PAMUTE;
+       if (chip->dac_mute)
+               reg |= CS4398_MUTE_B | CS4398_MUTE_A;
+       cs4398_write(chip, 4, reg);
+       update_cs4362a_volumes(chip);
+}
+
+static void cs43xx_init(struct oxygen *chip)
+{
+       struct xonar_data *data = chip->model_data;
 
        /* set CPEN (control port mode) and power down */
        cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN);
        cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN);
        /* configure */
-       cs4398_write(chip, 2, CS4398_FM_SINGLE |
-                    CS4398_DEM_NONE | CS4398_DIF_LJUST);
+       cs4398_write(chip, 2, data->cs4398_fm);
        cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L);
-       cs4398_write(chip, 4, CS4398_MUTEP_LOW | CS4398_PAMUTE);
-       cs4398_write(chip, 5, 0xfe);
-       cs4398_write(chip, 6, 0xfe);
        cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP |
                     CS4398_ZERO_CROSS | CS4398_SOFT_RAMP);
        cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST);
@@ -249,21 +303,35 @@ static void xonar_dx_init(struct oxygen *chip)
                      CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP);
        cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE);
        cs4362a_write(chip, 0x05, 0);
-       cs4362a_write(chip, 0x06, CS4362A_FM_SINGLE |
-                     CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
-       cs4362a_write(chip, 0x07, 0x7f | CS4362A_MUTE);
-       cs4362a_write(chip, 0x08, 0x7f | CS4362A_MUTE);
-       cs4362a_write(chip, 0x09, CS4362A_FM_SINGLE |
-                     CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
-       cs4362a_write(chip, 0x0a, 0x7f | CS4362A_MUTE);
-       cs4362a_write(chip, 0x0b, 0x7f | CS4362A_MUTE);
-       cs4362a_write(chip, 0x0c, CS4362A_FM_SINGLE |
-                     CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L);
-       cs4362a_write(chip, 0x0d, 0x7f | CS4362A_MUTE);
-       cs4362a_write(chip, 0x0e, 0x7f | CS4362A_MUTE);
+       cs4362a_write(chip, 0x06, data->cs4362a_fm);
+       cs4362a_write(chip, 0x09, data->cs4362a_fm);
+       cs4362a_write(chip, 0x0c, data->cs4362a_fm);
+       update_cs43xx_volume(chip);
+       update_cs43xx_mute(chip);
        /* clear power down */
        cs4398_write(chip, 8, CS4398_CPEN);
        cs4362a_write(chip, 0x01, CS4362A_CPEN);
+}
+
+static void xonar_dx_init(struct oxygen *chip)
+{
+       struct xonar_data *data = chip->model_data;
+
+       data->anti_pop_delay = 800;
+       data->output_enable_bit = GPIO_DX_OUTPUT_ENABLE;
+       data->ext_power_reg = OXYGEN_GPI_DATA;
+       data->ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
+       data->ext_power_bit = GPI_DX_EXT_POWER;
+       data->cs4398_fm = CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST;
+       data->cs4362a_fm = CS4362A_FM_SINGLE |
+               CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
+
+       oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS,
+                      OXYGEN_2WIRE_LENGTH_8 |
+                      OXYGEN_2WIRE_INTERRUPT_MASK |
+                      OXYGEN_2WIRE_SPEED_FAST);
+
+       cs43xx_init(chip);
 
        oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
                          GPIO_DX_FRONT_PANEL | GPIO_DX_INPUT_ROUTE);
@@ -291,37 +359,28 @@ static void xonar_dx_cleanup(struct oxygen *chip)
        oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
 }
 
-static void set_pcm1796_params(struct oxygen *chip,
-                              struct snd_pcm_hw_params *params)
+static void xonar_d2_resume(struct oxygen *chip)
 {
-       unsigned int i;
-       u8 value;
-
-       value = params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64;
-       for (i = 0; i < 4; ++i)
-               pcm1796_write(chip, i, 20, value);
+       pcm1796_init(chip);
+       xonar_enable_output(chip);
 }
 
-static void update_pcm1796_volume(struct oxygen *chip)
+static void xonar_dx_resume(struct oxygen *chip)
 {
-       unsigned int i;
-
-       for (i = 0; i < 4; ++i) {
-               pcm1796_write(chip, i, 16, chip->dac_volume[i * 2]);
-               pcm1796_write(chip, i, 17, chip->dac_volume[i * 2 + 1]);
-       }
+       cs43xx_init(chip);
+       xonar_enable_output(chip);
 }
 
-static void update_pcm1796_mute(struct oxygen *chip)
+static void set_pcm1796_params(struct oxygen *chip,
+                              struct snd_pcm_hw_params *params)
 {
+       struct xonar_data *data = chip->model_data;
        unsigned int i;
-       u8 value;
 
-       value = PCM1796_FMT_24_LJUST | PCM1796_ATLD;
-       if (chip->dac_mute)
-               value |= PCM1796_MUTE;
+       data->pcm1796_oversampling =
+               params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64;
        for (i = 0; i < 4; ++i)
-               pcm1796_write(chip, i, 18, value);
+               pcm1796_write(chip, i, 20, data->pcm1796_oversampling);
 }
 
 static void set_cs53x1_params(struct oxygen *chip,
@@ -342,55 +401,24 @@ static void set_cs53x1_params(struct oxygen *chip,
 static void set_cs43xx_params(struct oxygen *chip,
                              struct snd_pcm_hw_params *params)
 {
-       u8 fm_cs4398, fm_cs4362a;
+       struct xonar_data *data = chip->model_data;
 
-       fm_cs4398 = CS4398_DEM_NONE | CS4398_DIF_LJUST;
-       fm_cs4362a = CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
+       data->cs4398_fm = CS4398_DEM_NONE | CS4398_DIF_LJUST;
+       data->cs4362a_fm = CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
        if (params_rate(params) <= 50000) {
-               fm_cs4398 |= CS4398_FM_SINGLE;
-               fm_cs4362a |= CS4362A_FM_SINGLE;
+               data->cs4398_fm |= CS4398_FM_SINGLE;
+               data->cs4362a_fm |= CS4362A_FM_SINGLE;
        } else if (params_rate(params) <= 100000) {
-               fm_cs4398 |= CS4398_FM_DOUBLE;
-               fm_cs4362a |= CS4362A_FM_DOUBLE;
+               data->cs4398_fm |= CS4398_FM_DOUBLE;
+               data->cs4362a_fm |= CS4362A_FM_DOUBLE;
        } else {
-               fm_cs4398 |= CS4398_FM_QUAD;
-               fm_cs4362a |= CS4362A_FM_QUAD;
+               data->cs4398_fm |= CS4398_FM_QUAD;
+               data->cs4362a_fm |= CS4362A_FM_QUAD;
        }
-       cs4398_write(chip, 2, fm_cs4398);
-       cs4362a_write(chip, 0x06, fm_cs4362a);
-       cs4362a_write(chip, 0x09, fm_cs4362a);
-       cs4362a_write(chip, 0x0c, fm_cs4362a);
-}
-
-static void update_cs4362a_volumes(struct oxygen *chip)
-{
-       u8 mute;
-
-       mute = chip->dac_mute ? CS4362A_MUTE : 0;
-       cs4362a_write(chip, 7, (127 - chip->dac_volume[2]) | mute);
-       cs4362a_write(chip, 8, (127 - chip->dac_volume[3]) | mute);
-       cs4362a_write(chip, 10, (127 - chip->dac_volume[4]) | mute);
-       cs4362a_write(chip, 11, (127 - chip->dac_volume[5]) | mute);
-       cs4362a_write(chip, 13, (127 - chip->dac_volume[6]) | mute);
-       cs4362a_write(chip, 14, (127 - chip->dac_volume[7]) | mute);
-}
-
-static void update_cs43xx_volume(struct oxygen *chip)
-{
-       cs4398_write(chip, 5, (127 - chip->dac_volume[0]) * 2);
-       cs4398_write(chip, 6, (127 - chip->dac_volume[1]) * 2);
-       update_cs4362a_volumes(chip);
-}
-
-static void update_cs43xx_mute(struct oxygen *chip)
-{
-       u8 reg;
-
-       reg = CS4398_MUTEP_LOW | CS4398_PAMUTE;
-       if (chip->dac_mute)
-               reg |= CS4398_MUTE_B | CS4398_MUTE_A;
-       cs4398_write(chip, 4, reg);
-       update_cs4362a_volumes(chip);
+       cs4398_write(chip, 2, data->cs4398_fm);
+       cs4362a_write(chip, 0x06, data->cs4362a_fm);
+       cs4362a_write(chip, 0x09, data->cs4362a_fm);
+       cs4362a_write(chip, 0x0c, data->cs4362a_fm);
 }
 
 static void xonar_gpio_changed(struct oxygen *chip)
@@ -535,6 +563,8 @@ static const struct oxygen_model xonar_models[] = {
                .control_filter = xonar_d2_control_filter,
                .mixer_init = xonar_mixer_init,
                .cleanup = xonar_cleanup,
+               .suspend = xonar_cleanup,
+               .resume = xonar_d2_resume,
                .set_dac_params = set_pcm1796_params,
                .set_adc_params = set_cs53x1_params,
                .update_dac_volume = update_pcm1796_volume,
@@ -563,6 +593,8 @@ static const struct oxygen_model xonar_models[] = {
                .control_filter = xonar_d2_control_filter,
                .mixer_init = xonar_mixer_init,
                .cleanup = xonar_cleanup,
+               .suspend = xonar_cleanup,
+               .resume = xonar_d2_resume,
                .set_dac_params = set_pcm1796_params,
                .set_adc_params = set_cs53x1_params,
                .update_dac_volume = update_pcm1796_volume,
@@ -592,6 +624,8 @@ static const struct oxygen_model xonar_models[] = {
                .control_filter = xonar_dx_control_filter,
                .mixer_init = xonar_dx_mixer_init,
                .cleanup = xonar_dx_cleanup,
+               .suspend = xonar_dx_cleanup,
+               .resume = xonar_dx_resume,
                .set_dac_params = set_cs43xx_params,
                .set_adc_params = set_cs53x1_params,
                .update_dac_volume = update_cs43xx_volume,
@@ -636,6 +670,10 @@ static struct pci_driver xonar_driver = {
        .id_table = xonar_ids,
        .probe = xonar_probe,
        .remove = __devexit_p(oxygen_pci_remove),
+#ifdef CONFIG_PM
+       .suspend = oxygen_pci_suspend,
+       .resume = oxygen_pci_resume,
+#endif
 };
 
 static int __init alsa_card_xonar_init(void)
index 7fdcdc8c6b6478bbce2fff1c3f784ed90fb51a37..2c7e25336795d6bfb6588019069ff77947163e61 100644 (file)
@@ -516,7 +516,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
        int capture_mask = 0;
        int playback_mask = 0;
 
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
        struct timeval my_tv1, my_tv2;
        do_gettimeofday(&my_tv1);
 #endif
@@ -623,7 +623,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
 
        mutex_unlock(&mgr->setup_mutex);
 
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
        do_gettimeofday(&my_tv2);
        snd_printdd("***TRIGGER TASKLET*** TIME = %ld (err = %x)\n",
                    (long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
index 78aa81feaa4a9edfccb8fde5444b580d3afbb1a6..abe5c59b72dfbe5366c5932911408e0848a1e0ed 100644 (file)
@@ -473,7 +473,7 @@ static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = {
 [CMD_AUDIO_LEVEL_ADJUST] =             { 0xc22000, 0, RMH_SSIZE_FIXED },
 };
 
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
 static char* cmd_names[] = {
 [CMD_VERSION] =                                "CMD_VERSION",
 [CMD_SUPPORTED] =                      "CMD_SUPPORTED",
@@ -549,7 +549,7 @@ static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
                                }
                        }
                }
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
                if (rmh->cmd_idx < CMD_LAST_INDEX)
                        snd_printdd("    stat[%d]=%x\n", i, data);
 #endif
@@ -597,7 +597,7 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
                data |= 0x008000;       /* MASK_MORE_THAN_1_WORD_COMMAND */
        else
                data &= 0xff7fff;       /* MASK_1_WORD_COMMAND */
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
        if (rmh->cmd_idx < CMD_LAST_INDEX)
                snd_printdd("MSG cmd[0]=%x (%s)\n", data, cmd_names[rmh->cmd_idx]);
 #endif
@@ -624,7 +624,7 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
                for (i=1; i < rmh->cmd_len; i++) {
                        /* send other words */
                        data = rmh->cmd[i];
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
                        if (rmh->cmd_idx < CMD_LAST_INDEX)
                                snd_printdd("    cmd[%d]=%x\n", i, data);
 #endif
@@ -847,7 +847,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_m
        int state, i, err;
        int audio_mask;
 
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
        struct timeval my_tv1, my_tv2;
        do_gettimeofday(&my_tv1);
 #endif
@@ -894,7 +894,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_m
                if (err)
                        return err;
        }
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
        do_gettimeofday(&my_tv2);
        snd_printdd("***SET PIPE STATE*** TIME = %ld (err = %x)\n",
                    (long)(my_tv2.tv_usec - my_tv1.tv_usec), err);
@@ -951,7 +951,7 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err,
                                  enum pcxhr_async_err_src err_src, int pipe,
                                  int is_capture)
 {
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
        static char* err_src_name[] = {
                [PCXHR_ERR_PIPE]        = "Pipe",
                [PCXHR_ERR_STREAM]      = "Stream",
@@ -1169,7 +1169,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
                                    mgr->dsp_time_last, dsp_time_new);
                        mgr->dsp_time_err++;
                }
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
                if (dsp_time_diff == 0)
                        snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n", dsp_time_new);
                else if (dsp_time_diff >= (2*PCXHR_GRANULARITY))
@@ -1208,7 +1208,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
                mgr->src_it_dsp = reg;
                tasklet_hi_schedule(&mgr->msg_taskq);
        }
-#ifdef CONFIG_SND_DEBUG_DETECT
+#ifdef CONFIG_SND_DEBUG_VERBOSE
        if (reg & PCXHR_FATAL_DSP_ERR)
                snd_printdd("FATAL DSP ERROR : %x\n", reg);
 #endif
index bbcee2c09ae42e15085cc91d0bcb1625b50118dd..a69b4206c69e205f9a88726f63182f75b36491ee 100644 (file)
@@ -1590,7 +1590,10 @@ static int snd_trident_trigger(struct snd_pcm_substream *substream,
        if (spdif_flag) {
                if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
                        outl(trident->spdif_pcm_bits, TRID_REG(trident, NX_SPCSTATUS));
-                       outb(trident->spdif_pcm_ctrl, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
+                       val = trident->spdif_pcm_ctrl;
+                       if (!go)
+                               val &= ~(0x28);
+                       outb(val, TRID_REG(trident, NX_SPCTRL_SPCSO + 3));
                } else {
                        outl(trident->spdif_pcm_bits, TRID_REG(trident, SI_SPDIF_CS));
                        val = inl(TRID_REG(trident, SI_SERIAL_INTF_CTRL)) | SPDIF_EN;
index df9b487fa17e7ca582e1eaae362656ca591e6620..3fd7f1b29b0f57840192aff0e4a97294134c0a5b 100644 (file)
@@ -310,181 +310,3 @@ int snd_trident_free_pages(struct snd_trident *trident,
        mutex_unlock(&hdr->block_mutex);
        return 0;
 }
-
-
-/*----------------------------------------------------------------
- * memory allocation using multiple pages (for synth)
- *----------------------------------------------------------------
- * Unlike the DMA allocation above, non-contiguous pages are
- * assigned to TLB.
- *----------------------------------------------------------------*/
-
-/*
- */
-static int synth_alloc_pages(struct snd_trident *hw, struct snd_util_memblk *blk);
-static int synth_free_pages(struct snd_trident *hw, struct snd_util_memblk *blk);
-
-/*
- * allocate a synth sample area
- */
-struct snd_util_memblk *
-snd_trident_synth_alloc(struct snd_trident *hw, unsigned int size)
-{
-       struct snd_util_memblk *blk;
-       struct snd_util_memhdr *hdr = hw->tlb.memhdr; 
-
-       mutex_lock(&hdr->block_mutex);
-       blk = __snd_util_mem_alloc(hdr, size);
-       if (blk == NULL) {
-               mutex_unlock(&hdr->block_mutex);
-               return NULL;
-       }
-       if (synth_alloc_pages(hw, blk)) {
-               __snd_util_mem_free(hdr, blk);
-               mutex_unlock(&hdr->block_mutex);
-               return NULL;
-       }
-       mutex_unlock(&hdr->block_mutex);
-       return blk;
-}
-
-EXPORT_SYMBOL(snd_trident_synth_alloc);
-
-/*
- * free a synth sample area
- */
-int
-snd_trident_synth_free(struct snd_trident *hw, struct snd_util_memblk *blk)
-{
-       struct snd_util_memhdr *hdr = hw->tlb.memhdr; 
-
-       mutex_lock(&hdr->block_mutex);
-       synth_free_pages(hw, blk);
-        __snd_util_mem_free(hdr, blk);
-       mutex_unlock(&hdr->block_mutex);
-       return 0;
-}
-
-EXPORT_SYMBOL(snd_trident_synth_free);
-
-/*
- * reset TLB entry and free kernel page
- */
-static void clear_tlb(struct snd_trident *trident, int page)
-{
-       void *ptr = page_to_ptr(trident, page);
-       dma_addr_t addr = page_to_addr(trident, page);
-       set_silent_tlb(trident, page);
-       if (ptr) {
-               struct snd_dma_buffer dmab;
-               dmab.dev.type = SNDRV_DMA_TYPE_DEV;
-               dmab.dev.dev = snd_dma_pci_data(trident->pci);
-               dmab.area = ptr;
-               dmab.addr = addr;
-               dmab.bytes = ALIGN_PAGE_SIZE;
-               snd_dma_free_pages(&dmab);
-       }
-}
-
-/* check new allocation range */
-static void get_single_page_range(struct snd_util_memhdr *hdr,
-                                 struct snd_util_memblk *blk,
-                                 int *first_page_ret, int *last_page_ret)
-{
-       struct list_head *p;
-       struct snd_util_memblk *q;
-       int first_page, last_page;
-       first_page = firstpg(blk);
-       if ((p = blk->list.prev) != &hdr->block) {
-               q = list_entry(p, struct snd_util_memblk, list);
-               if (lastpg(q) == first_page)
-                       first_page++;  /* first page was already allocated */
-       }
-       last_page = lastpg(blk);
-       if ((p = blk->list.next) != &hdr->block) {
-               q = list_entry(p, struct snd_util_memblk, list);
-               if (firstpg(q) == last_page)
-                       last_page--; /* last page was already allocated */
-       }
-       *first_page_ret = first_page;
-       *last_page_ret = last_page;
-}
-
-/*
- * allocate kernel pages and assign them to TLB
- */
-static int synth_alloc_pages(struct snd_trident *hw, struct snd_util_memblk *blk)
-{
-       int page, first_page, last_page;
-       struct snd_dma_buffer dmab;
-
-       firstpg(blk) = get_aligned_page(blk->offset);
-       lastpg(blk) = get_aligned_page(blk->offset + blk->size - 1);
-       get_single_page_range(hw->tlb.memhdr, blk, &first_page, &last_page);
-
-       /* allocate a kernel page for each Trident page -
-        * fortunately Trident page size and kernel PAGE_SIZE is identical!
-        */
-       for (page = first_page; page <= last_page; page++) {
-               if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(hw->pci),
-                                       ALIGN_PAGE_SIZE, &dmab) < 0)
-                       goto __fail;
-               if (! is_valid_page(dmab.addr)) {
-                       snd_dma_free_pages(&dmab);
-                       goto __fail;
-               }
-               set_tlb_bus(hw, page, (unsigned long)dmab.area, dmab.addr);
-       }
-       return 0;
-
-__fail:
-       /* release allocated pages */
-       last_page = page - 1;
-       for (page = first_page; page <= last_page; page++)
-               clear_tlb(hw, page);
-
-       return -ENOMEM;
-}
-
-/*
- * free pages
- */
-static int synth_free_pages(struct snd_trident *trident, struct snd_util_memblk *blk)
-{
-       int page, first_page, last_page;
-
-       get_single_page_range(trident->tlb.memhdr, blk, &first_page, &last_page);
-       for (page = first_page; page <= last_page; page++)
-               clear_tlb(trident, page);
-
-       return 0;
-}
-
-/*
- * copy_from_user(blk + offset, data, size)
- */
-int snd_trident_synth_copy_from_user(struct snd_trident *trident,
-                                    struct snd_util_memblk *blk,
-                                    int offset, const char __user *data, int size)
-{
-       int page, nextofs, end_offset, temp, temp1;
-
-       offset += blk->offset;
-       end_offset = offset + size;
-       page = get_aligned_page(offset) + 1;
-       do {
-               nextofs = aligned_page_offset(page);
-               temp = nextofs - offset;
-               temp1 = end_offset - offset;
-               if (temp1 < temp)
-                       temp = temp1;
-               if (copy_from_user(offset_ptr(trident, offset), data, temp))
-                       return -EFAULT;
-               offset = nextofs;
-               data += temp;
-               page++;
-       } while (offset < end_offset);
-       return 0;
-}
-
-EXPORT_SYMBOL(snd_trident_synth_copy_from_user);
index b585cc3e4c472eea6434e89d9ed463038f6a61c9..6781be9e3078ac702364770f407fbc4458486882 100644 (file)
@@ -1756,6 +1756,12 @@ static struct ac97_quirk ac97_quirks[] = {
                .name = "ECS L7VMM2",
                .type = AC97_TUNE_HP_ONLY
        },
+       {
+               .subvendor = 0x1019,
+               .subdevice = 0x1841,
+               .name = "ECS K7VTA3",
+               .type = AC97_TUNE_HP_ONLY
+       },
        {
                .subvendor = 0x1849,
                .subdevice = 0x3059,
index 29b3056c51098b708aaa6e860af148a011bae098..7129df5f315b32d01384560e1e2b0103c0e685f9 100644 (file)
@@ -2205,6 +2205,7 @@ static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip)
        for (reg = 0x80; reg < 0xc0; reg += 4)
                snd_ymfpci_writel(chip, reg, 0);
        snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff);
+       snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0x3fff3fff);
        snd_ymfpci_writel(chip, YDSXGR_ZVOUTVOL, 0x3fff3fff);
        snd_ymfpci_writel(chip, YDSXGR_SPDIFOUTVOL, 0x3fff3fff);
        snd_ymfpci_writel(chip, YDSXGR_NATIVEADCINVOL, 0x3fff3fff);
@@ -2324,6 +2325,7 @@ int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state)
                chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]);
        chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE);
        snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
+       snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
        snd_ymfpci_disable_dsp(chip);
        pci_disable_device(pci);
        pci_save_state(pci);
index c9fa1a2bc58b852e3e4680589d6c1b1b71f6145b..7fbb190adf6d1a256b59f4b0d442e9fa0a4e1011 100644 (file)
@@ -1,11 +1,16 @@
 # ALSA PCMCIA drivers
 
-menu "PCMCIA devices"
-       depends on SND!=n && PCMCIA
+menuconfig SND_PCMCIA
+       bool "PCMCIA sound devices"
+       depends on PCMCIA
+       default y
+       help
+         Support for sound devices connected via the PCMCIA bus.
+
+if SND_PCMCIA && PCMCIA
 
 config SND_VXPOCKET
        tristate "Digigram VXpocket"
-       depends on SND && PCMCIA
        select SND_VX_LIB
        help
          Say Y here to include support for Digigram VXpocket and
@@ -16,7 +21,6 @@ config SND_VXPOCKET
 
 config SND_PDAUDIOCF
        tristate "Sound Core PDAudioCF"
-       depends on SND && PCMCIA
        select SND_PCM
        help
          Say Y here to include support for Sound Core PDAudioCF
@@ -25,4 +29,5 @@ config SND_PDAUDIOCF
          To compile this driver as a module, choose M here: the module
          will be called snd-pdaudiocf.
 
-endmenu
+endif  # SND_PCMCIA
+
index 157b0b539f39d33cfc3b8f7bce35b1c288649bd6..99bf2a65a6f5ce82260b2f7d0f8fdbf56b804c7f 100644 (file)
@@ -151,7 +151,7 @@ static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware *
        unsigned int i;
        int c;
        int regCSUER, regRUER;
-       unsigned char *image;
+       const unsigned char *image;
        unsigned char data;
 
        /* Switch to programmation mode */
index cacb0b1368833d6d2055ee0bffdba03db273dec1..777de2b171781b78eca1a347238efc6a585624b5 100644 (file)
@@ -1,17 +1,17 @@
 # ALSA PowerMac drivers
 
-menu "ALSA PowerMac devices"
-       depends on SND!=n && PPC
-
-comment "ALSA PowerMac requires I2C"
-       depends on SND && I2C=n
+menuconfig SND_PPC
+       bool "PowerPC sound devices"
+       depends on PPC64 || PPC32
+       default y
+       help
+         Support for sound devices specific to PowerPC architectures.
 
-comment "ALSA PowerMac requires INPUT"
-       depends on SND && INPUT=n
+if SND_PPC
 
 config SND_POWERMAC
        tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)"
-       depends on SND && I2C && INPUT && PPC_PMAC
+       depends on I2C && INPUT && PPC_PMAC
        select SND_PCM
        help
          Say Y here to include support for the integrated sound device.
@@ -32,14 +32,9 @@ config SND_POWERMAC_AUTO_DRC
          Note that you can turn on/off DRC manually even without this
          option.
 
-endmenu
-
-menu "ALSA PowerPC devices"
-       depends on SND!=n && ( PPC64 || PPC32 )
-
 config SND_PS3
        tristate "PS3 Audio support"
-       depends on SND && PS3_PS3AV
+       depends on PS3_PS3AV
        select SND_PCM
        default m
        help
@@ -52,4 +47,5 @@ config SND_PS3_DEFAULT_START_DELAY
        int "Startup delay time in ms"
        depends on SND_PS3
        default "2000"
-endmenu
+
+endif  # SND_PPC
index ca9452901a50517e139f1e7784e327659b0bff48..8a5b29031933a09f1a9d1ef047ee2a1db93364c4 100644 (file)
@@ -249,9 +249,7 @@ int __init snd_pmac_daca_init(struct snd_pmac *chip)
        int i, err;
        struct pmac_daca *mix;
 
-#ifdef CONFIG_KMOD
        request_module("i2c-powermac");
-#endif /* CONFIG_KMOD */
 
        mix = kzalloc(sizeof(*mix), GFP_KERNEL);
        if (! mix)
index 3f8d7164cef9438407b3f00128739438f92069b7..009df8dd37a8483a10987b948ecd3329dd1e556c 100644 (file)
@@ -1350,9 +1350,7 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip)
        struct device_node *tas_node, *np;
        char *chipname;
 
-#ifdef CONFIG_KMOD
        request_module("i2c-powermac");
-#endif /* CONFIG_KMOD */
 
        mix = kzalloc(sizeof(*mix), GFP_KERNEL);
        if (! mix)
index b7e08ef22a940ef2d567c9c06c0d6816b8f33c1a..cfc1439858029e32956906947ecdf2755299059d 100644 (file)
@@ -1,14 +1,22 @@
 # ALSA SH drivers
 
-menu "SUPERH devices"
-       depends on SND!=n && SUPERH
+menuconfig SND_SUPERH
+       bool "SUPERH sound devices"
+       depends on SUPERH
+       default y
+       help
+         Support for sound devices specific to SUPERH architectures.
+         Drivers that are implemented on ASoC can be found in
+         "ALSA for SoC audio support" section.
+
+if SND_SUPERH
 
 config SND_AICA
        tristate "Dreamcast Yamaha AICA sound"
-       depends on SH_DREAMCAST && SND
+       depends on SH_DREAMCAST
        select SND_PCM
        help
          ALSA Sound driver for the SEGA Dreamcast console.
 
-endmenu
+endif  # SND_SUPERH
 
index 18f28ac4bfe82997733df97c1c1eaaf05dc41adb..f743530add8f2bf8a9b58a345ec515b62e3a056b 100644 (file)
@@ -2,15 +2,8 @@
 # SoC audio configuration
 #
 
-menu "System on Chip audio support"
-       depends on SND!=n
-
-config SND_SOC_AC97_BUS
-       bool
-
-config SND_SOC
+menuconfig SND_SOC
        tristate "ALSA for SoC audio support"
-       depends on SND
        select SND_PCM
        ---help---
 
@@ -23,8 +16,15 @@ config SND_SOC
          This ASoC audio support can also be built as a module.  If so, the module
          will be called snd-soc-core.
 
+if SND_SOC
+
+config SND_SOC_AC97_BUS
+       bool
+
 # All the supported Soc's
+source "sound/soc/at32/Kconfig"
 source "sound/soc/at91/Kconfig"
+source "sound/soc/au1x/Kconfig"
 source "sound/soc/pxa/Kconfig"
 source "sound/soc/s3c24xx/Kconfig"
 source "sound/soc/sh/Kconfig"
@@ -35,4 +35,5 @@ source "sound/soc/omap/Kconfig"
 # Supported codecs
 source "sound/soc/codecs/Kconfig"
 
-endmenu
+endif  # SND_SOC
+
index 782db2127108fd26c19a0bb6bf2ee378cbd4d0ac..933a66d30804950b96b1e185285880bf204d673f 100644 (file)
@@ -1,4 +1,5 @@
 snd-soc-core-objs := soc-core.o soc-dapm.o
 
 obj-$(CONFIG_SND_SOC)  += snd-soc-core.o
-obj-$(CONFIG_SND_SOC)  += codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/ omap/
+obj-$(CONFIG_SND_SOC)  += codecs/ at32/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/
+obj-$(CONFIG_SND_SOC)  += omap/ au1x/
diff --git a/sound/soc/at32/Kconfig b/sound/soc/at32/Kconfig
new file mode 100644 (file)
index 0000000..b0765e8
--- /dev/null
@@ -0,0 +1,34 @@
+config SND_AT32_SOC
+        tristate "SoC Audio for the Atmel AT32 System-on-a-Chip"
+        depends on AVR32 && SND_SOC
+        help
+          Say Y or M if you want to add support for codecs attached to 
+          the AT32 SSC interface.  You will also need to
+          to select the audio interfaces to support below.
+
+
+config SND_AT32_SOC_SSC
+        tristate
+
+
+
+config SND_AT32_SOC_PLAYPAQ
+        tristate "SoC Audio support for PlayPaq with WM8510"
+        depends on SND_AT32_SOC && BOARD_PLAYPAQ
+        select SND_AT32_SOC_SSC
+        select SND_SOC_WM8510
+        help
+          Say Y or M here if you want to add support for SoC audio
+          on the LRS PlayPaq.
+
+
+
+config SND_AT32_SOC_PLAYPAQ_SLAVE
+        bool "Run CODEC on PlayPaq in slave mode"
+        depends on SND_AT32_SOC_PLAYPAQ
+        default n
+        help
+          Say Y if you want to run with the AT32 SSC generating the BCLK
+          and FRAME signals on the PlayPaq.  Unless you want to play
+          with the AT32 as the SSC master, you probably want to say N here,
+          as this will give you better sound quality.
diff --git a/sound/soc/at32/Makefile b/sound/soc/at32/Makefile
new file mode 100644 (file)
index 0000000..c03e55e
--- /dev/null
@@ -0,0 +1,11 @@
+# AT32 Platform Support
+snd-soc-at32-objs := at32-pcm.o
+snd-soc-at32-ssc-objs := at32-ssc.o
+
+obj-$(CONFIG_SND_AT32_SOC) += snd-soc-at32.o
+obj-$(CONFIG_SND_AT32_SOC_SSC) += snd-soc-at32-ssc.o
+
+# AT32 Machine Support
+snd-soc-playpaq-objs := playpaq_wm8510.o
+
+obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
diff --git a/sound/soc/at32/at32-pcm.c b/sound/soc/at32/at32-pcm.c
new file mode 100644 (file)
index 0000000..435f1da
--- /dev/null
@@ -0,0 +1,491 @@
+/* sound/soc/at32/at32-pcm.c
+ * ASoC PCM interface for Atmel AT32 SoC
+ *
+ * Copyright (C) 2008 Long Range Systems
+ *    Geoffrey Wossum <gwossum@acm.org>
+ *
+ * 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.
+ *
+ * Note that this is basically a port of the sound/soc/at91-pcm.c to
+ * the AVR32 kernel.  Thanks to Frank Mandarino for that code.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/atmel_pdc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "at32-pcm.h"
+
+
+
+/*--------------------------------------------------------------------------*\
+ * Hardware definition
+\*--------------------------------------------------------------------------*/
+/* TODO: These values were taken from the AT91 platform driver, check
+ *      them against real values for AT32
+ */
+static const struct snd_pcm_hardware at32_pcm_hardware = {
+       .info = (SNDRV_PCM_INFO_MMAP |
+                SNDRV_PCM_INFO_MMAP_VALID |
+                SNDRV_PCM_INFO_INTERLEAVED |
+                SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                SNDRV_PCM_INFO_PAUSE),
+
+       .formats = SNDRV_PCM_FMTBIT_S16,
+       .period_bytes_min = 32,
+       .period_bytes_max = 8192,       /* 512 frames * 16 bytes / frame */
+       .periods_min = 2,
+       .periods_max = 1024,
+       .buffer_bytes_max = 32 * 1024,
+};
+
+
+
+/*--------------------------------------------------------------------------*\
+ * Data types
+\*--------------------------------------------------------------------------*/
+struct at32_runtime_data {
+       struct at32_pcm_dma_params *params;
+       dma_addr_t dma_buffer;  /* physical address of DMA buffer */
+       dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
+       size_t period_size;
+
+       dma_addr_t period_ptr;  /* physical address of next period */
+       int periods;            /* period index of period_ptr */
+
+       /* Save PDC registers (for power management) */
+       u32 pdc_xpr_save;
+       u32 pdc_xcr_save;
+       u32 pdc_xnpr_save;
+       u32 pdc_xncr_save;
+};
+
+
+
+/*--------------------------------------------------------------------------*\
+ * Helper functions
+\*--------------------------------------------------------------------------*/
+static int at32_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+       struct snd_dma_buffer *dmabuf = &substream->dma_buffer;
+       size_t size = at32_pcm_hardware.buffer_bytes_max;
+
+       dmabuf->dev.type = SNDRV_DMA_TYPE_DEV;
+       dmabuf->dev.dev = pcm->card->dev;
+       dmabuf->private_data = NULL;
+       dmabuf->area = dma_alloc_coherent(pcm->card->dev, size,
+                                         &dmabuf->addr, GFP_KERNEL);
+       pr_debug("at32_pcm: preallocate_dma_buffer: "
+                "area=%p, addr=%p, size=%ld\n",
+                (void *)dmabuf->area, (void *)dmabuf->addr, size);
+
+       if (!dmabuf->area)
+               return -ENOMEM;
+
+       dmabuf->bytes = size;
+       return 0;
+}
+
+
+
+/*--------------------------------------------------------------------------*\
+ * ISR
+\*--------------------------------------------------------------------------*/
+static void at32_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *rtd = substream->runtime;
+       struct at32_runtime_data *prtd = rtd->private_data;
+       struct at32_pcm_dma_params *params = prtd->params;
+       static int count;
+
+       count++;
+       if (ssc_sr & params->mask->ssc_endbuf) {
+               pr_warning("at32-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
+                          substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+                          "underrun" : "overrun", params->name, ssc_sr, count);
+
+               /* re-start the PDC */
+               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                          params->mask->pdc_disable);
+               prtd->period_ptr += prtd->period_size;
+               if (prtd->period_ptr >= prtd->dma_buffer_end)
+                       prtd->period_ptr = prtd->dma_buffer;
+
+
+               ssc_writex(params->ssc->regs, params->pdc->xpr,
+                          prtd->period_ptr);
+               ssc_writex(params->ssc->regs, params->pdc->xcr,
+                          prtd->period_size / params->pdc_xfer_size);
+               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                          params->mask->pdc_enable);
+       }
+
+
+       if (ssc_sr & params->mask->ssc_endx) {
+               /* Load the PDC next pointer and counter registers */
+               prtd->period_ptr += prtd->period_size;
+               if (prtd->period_ptr >= prtd->dma_buffer_end)
+                       prtd->period_ptr = prtd->dma_buffer;
+               ssc_writex(params->ssc->regs, params->pdc->xnpr,
+                          prtd->period_ptr);
+               ssc_writex(params->ssc->regs, params->pdc->xncr,
+                          prtd->period_size / params->pdc_xfer_size);
+       }
+
+
+       snd_pcm_period_elapsed(substream);
+}
+
+
+
+/*--------------------------------------------------------------------------*\
+ * PCM operations
+\*--------------------------------------------------------------------------*/
+static int at32_pcm_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *params)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct at32_runtime_data *prtd = runtime->private_data;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+       /* this may get called several times by oss emulation
+        * with different params
+        */
+       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+       runtime->dma_bytes = params_buffer_bytes(params);
+
+       prtd->params = rtd->dai->cpu_dai->dma_data;
+       prtd->params->dma_intr_handler = at32_pcm_dma_irq;
+
+       prtd->dma_buffer = runtime->dma_addr;
+       prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
+       prtd->period_size = params_period_bytes(params);
+
+       pr_debug("hw_params: DMA for %s initialized "
+                "(dma_bytes=%ld, period_size=%ld)\n",
+                prtd->params->name, runtime->dma_bytes, prtd->period_size);
+
+       return 0;
+}
+
+
+
+static int at32_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       struct at32_runtime_data *prtd = substream->runtime->private_data;
+       struct at32_pcm_dma_params *params = prtd->params;
+
+       if (params != NULL) {
+               ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+                          params->mask->pdc_disable);
+               prtd->params->dma_intr_handler = NULL;
+       }
+
+       return 0;
+}
+
+
+
+static int at32_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct at32_runtime_data *prtd = substream->runtime->private_data;
+       struct at32_pcm_dma_params *params = prtd->params;
+
+       ssc_writex(params->ssc->regs, SSC_IDR,
+                  params->mask->ssc_endx | params->mask->ssc_endbuf);
+       ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                  params->mask->pdc_disable);
+
+       return 0;
+}
+
+
+static int at32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_pcm_runtime *rtd = substream->runtime;
+       struct at32_runtime_data *prtd = rtd->private_data;
+       struct at32_pcm_dma_params *params = prtd->params;
+       int ret = 0;
+
+       pr_debug("at32_pcm_trigger: buffer_size = %ld, "
+                "dma_area = %p, dma_bytes = %ld\n",
+                rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               prtd->period_ptr = prtd->dma_buffer;
+
+               ssc_writex(params->ssc->regs, params->pdc->xpr,
+                          prtd->period_ptr);
+               ssc_writex(params->ssc->regs, params->pdc->xcr,
+                          prtd->period_size / params->pdc_xfer_size);
+
+               prtd->period_ptr += prtd->period_size;
+               ssc_writex(params->ssc->regs, params->pdc->xnpr,
+                          prtd->period_ptr);
+               ssc_writex(params->ssc->regs, params->pdc->xncr,
+                          prtd->period_size / params->pdc_xfer_size);
+
+               pr_debug("trigger: period_ptr=%lx, xpr=%x, "
+                        "xcr=%d, xnpr=%x, xncr=%d\n",
+                        (unsigned long)prtd->period_ptr,
+                        ssc_readx(params->ssc->regs, params->pdc->xpr),
+                        ssc_readx(params->ssc->regs, params->pdc->xcr),
+                        ssc_readx(params->ssc->regs, params->pdc->xnpr),
+                        ssc_readx(params->ssc->regs, params->pdc->xncr));
+
+               ssc_writex(params->ssc->regs, SSC_IER,
+                          params->mask->ssc_endx | params->mask->ssc_endbuf);
+               ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+                          params->mask->pdc_enable);
+
+               pr_debug("sr=%x, imr=%x\n",
+                        ssc_readx(params->ssc->regs, SSC_SR),
+                        ssc_readx(params->ssc->regs, SSC_IER));
+               break;          /* SNDRV_PCM_TRIGGER_START */
+
+
+
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                          params->mask->pdc_disable);
+               break;
+
+
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+                          params->mask->pdc_enable);
+               break;
+
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+
+
+static snd_pcm_uframes_t at32_pcm_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct at32_runtime_data *prtd = runtime->private_data;
+       struct at32_pcm_dma_params *params = prtd->params;
+       dma_addr_t ptr;
+       snd_pcm_uframes_t x;
+
+       ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
+       x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
+
+       if (x == runtime->buffer_size)
+               x = 0;
+
+       return x;
+}
+
+
+
+static int at32_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct at32_runtime_data *prtd;
+       int ret = 0;
+
+       snd_soc_set_runtime_hwparams(substream, &at32_pcm_hardware);
+
+       /* ensure that buffer size is a multiple of period size */
+       ret = snd_pcm_hw_constraint_integer(runtime,
+                                           SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret < 0)
+               goto out;
+
+       prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
+       if (prtd == NULL) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       runtime->private_data = prtd;
+
+
+out:
+       return ret;
+}
+
+
+
+static int at32_pcm_close(struct snd_pcm_substream *substream)
+{
+       struct at32_runtime_data *prtd = substream->runtime->private_data;
+
+       kfree(prtd);
+       return 0;
+}
+
+
+static int at32_pcm_mmap(struct snd_pcm_substream *substream,
+                        struct vm_area_struct *vma)
+{
+       return remap_pfn_range(vma, vma->vm_start,
+                              substream->dma_buffer.addr >> PAGE_SHIFT,
+                              vma->vm_end - vma->vm_start, vma->vm_page_prot);
+}
+
+
+
+static struct snd_pcm_ops at32_pcm_ops = {
+       .open = at32_pcm_open,
+       .close = at32_pcm_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = at32_pcm_hw_params,
+       .hw_free = at32_pcm_hw_free,
+       .prepare = at32_pcm_prepare,
+       .trigger = at32_pcm_trigger,
+       .pointer = at32_pcm_pointer,
+       .mmap = at32_pcm_mmap,
+};
+
+
+
+/*--------------------------------------------------------------------------*\
+ * ASoC platform driver
+\*--------------------------------------------------------------------------*/
+static u64 at32_pcm_dmamask = 0xffffffff;
+
+static int at32_pcm_new(struct snd_card *card,
+                       struct snd_soc_dai *dai,
+                       struct snd_pcm *pcm)
+{
+       int ret = 0;
+
+       if (!card->dev->dma_mask)
+               card->dev->dma_mask = &at32_pcm_dmamask;
+       if (!card->dev->coherent_dma_mask)
+               card->dev->coherent_dma_mask = 0xffffffff;
+
+       if (dai->playback.channels_min) {
+               ret = at32_pcm_preallocate_dma_buffer(
+                         pcm, SNDRV_PCM_STREAM_PLAYBACK);
+               if (ret)
+                       goto out;
+       }
+
+       if (dai->capture.channels_min) {
+               pr_debug("at32-pcm: Allocating PCM capture DMA buffer\n");
+               ret = at32_pcm_preallocate_dma_buffer(
+                         pcm, SNDRV_PCM_STREAM_CAPTURE);
+               if (ret)
+                       goto out;
+       }
+
+
+out:
+       return ret;
+}
+
+
+
+static void at32_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+       struct snd_pcm_substream *substream;
+       struct snd_dma_buffer *buf;
+       int stream;
+
+       for (stream = 0; stream < 2; stream++) {
+               substream = pcm->streams[stream].substream;
+               if (substream == NULL)
+                       continue;
+
+               buf = &substream->dma_buffer;
+               if (!buf->area)
+                       continue;
+               dma_free_coherent(pcm->card->dev, buf->bytes,
+                                 buf->area, buf->addr);
+               buf->area = NULL;
+       }
+}
+
+
+
+#ifdef CONFIG_PM
+static int at32_pcm_suspend(struct platform_device *pdev,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_pcm_runtime *runtime = dai->runtime;
+       struct at32_runtime_data *prtd;
+       struct at32_pcm_dma_params *params;
+
+       if (runtime == NULL)
+               return 0;
+       prtd = runtime->private_data;
+       params = prtd->params;
+
+       /* Disable the PDC and save the PDC registers */
+       ssc_writex(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
+
+       prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
+       prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
+       prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
+       prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
+
+       return 0;
+}
+
+
+
+static int at32_pcm_resume(struct platform_device *pdev,
+                          struct snd_soc_dai *dai)
+{
+       struct snd_pcm_runtime *runtime = dai->runtime;
+       struct at32_runtime_data *prtd;
+       struct at32_pcm_dma_params *params;
+
+       if (runtime == NULL)
+               return 0;
+       prtd = runtime->private_data;
+       params = prtd->params;
+
+       /* Restore the PDC registers and enable the PDC */
+       ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
+       ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
+       ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
+       ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
+
+       ssc_writex(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
+       return 0;
+}
+#else /* CONFIG_PM */
+#  define at32_pcm_suspend     NULL
+#  define at32_pcm_resume      NULL
+#endif /* CONFIG_PM */
+
+
+
+struct snd_soc_platform at32_soc_platform = {
+       .name = "at32-audio",
+       .pcm_ops = &at32_pcm_ops,
+       .pcm_new = at32_pcm_new,
+       .pcm_free = at32_pcm_free_dma_buffers,
+       .suspend = at32_pcm_suspend,
+       .resume = at32_pcm_resume,
+};
+EXPORT_SYMBOL_GPL(at32_soc_platform);
+
+
+
+MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
+MODULE_DESCRIPTION("Atmel AT32 PCM module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/at32/at32-pcm.h b/sound/soc/at32/at32-pcm.h
new file mode 100644 (file)
index 0000000..2a52430
--- /dev/null
@@ -0,0 +1,79 @@
+/* sound/soc/at32/at32-pcm.h
+ * ASoC PCM interface for Atmel AT32 SoC
+ *
+ * Copyright (C) 2008 Long Range Systems
+ *    Geoffrey Wossum <gwossum@acm.org>
+ *
+ * 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 __SOUND_SOC_AT32_AT32_PCM_H
+#define __SOUND_SOC_AT32_AT32_PCM_H __FILE__
+
+#include <linux/atmel-ssc.h>
+
+
+/*
+ * Registers and status bits that are required by the PCM driver
+ * TODO: Is ptcr really used?
+ */
+struct at32_pdc_regs {
+       u32 xpr;                /* PDC RX/TX pointer */
+       u32 xcr;                /* PDC RX/TX counter */
+       u32 xnpr;               /* PDC next RX/TX pointer */
+       u32 xncr;               /* PDC next RX/TX counter */
+       u32 ptcr;               /* PDC transfer control */
+};
+
+
+
+/*
+ * SSC mask info
+ */
+struct at32_ssc_mask {
+       u32 ssc_enable;         /* SSC RX/TX enable */
+       u32 ssc_disable;        /* SSC RX/TX disable */
+       u32 ssc_endx;           /* SSC ENDTX or ENDRX */
+       u32 ssc_endbuf;         /* SSC TXBUFF or RXBUFF */
+       u32 pdc_enable;         /* PDC RX/TX enable */
+       u32 pdc_disable;        /* PDC RX/TX disable */
+};
+
+
+
+/*
+ * This structure, shared between the PCM driver and the interface,
+ * contains all information required by the PCM driver to perform the
+ * PDC DMA operation.  All fields except dma_intr_handler() are initialized
+ * by the interface.  The dms_intr_handler() pointer is set by the PCM
+ * driver and called by the interface SSC interrupt handler if it is
+ * non-NULL.
+ */
+struct at32_pcm_dma_params {
+       char *name;             /* stream identifier */
+       int pdc_xfer_size;      /* PDC counter increment in bytes */
+       struct ssc_device *ssc; /* SSC device for stream */
+       struct at32_pdc_regs *pdc;      /* PDC register info */
+       struct at32_ssc_mask *mask;     /* SSC mask info */
+       struct snd_pcm_substream *substream;
+       void (*dma_intr_handler) (u32, struct snd_pcm_substream *);
+};
+
+
+
+/*
+ * The AT32 ASoC platform driver
+ */
+extern struct snd_soc_platform at32_soc_platform;
+
+
+
+/*
+ * SSC register access (since ssc_writel() / ssc_readl() require literal name)
+ */
+#define ssc_readx(base, reg)            (__raw_readl((base) + (reg)))
+#define ssc_writex(base, reg, value)    __raw_writel((value), (base) + (reg))
+
+#endif /* __SOUND_SOC_AT32_AT32_PCM_H */
diff --git a/sound/soc/at32/at32-ssc.c b/sound/soc/at32/at32-ssc.c
new file mode 100644 (file)
index 0000000..4ef6492
--- /dev/null
@@ -0,0 +1,849 @@
+/* sound/soc/at32/at32-ssc.c
+ * ASoC platform driver for AT32 using SSC as DAI
+ *
+ * Copyright (C) 2008 Long Range Systems
+ *    Geoffrey Wossum <gwossum@acm.org>
+ *
+ * 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.
+ *
+ * Note that this is basically a port of the sound/soc/at91-ssc.c to
+ * the AVR32 kernel.  Thanks to Frank Mandarino for that code.
+ */
+
+/* #define DEBUG */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/atmel_pdc.h>
+#include <linux/atmel-ssc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "at32-pcm.h"
+#include "at32-ssc.h"
+
+
+
+/*-------------------------------------------------------------------------*\
+ * Constants
+\*-------------------------------------------------------------------------*/
+#define NUM_SSC_DEVICES                3
+
+/*
+ * SSC direction masks
+ */
+#define SSC_DIR_MASK_UNUSED    0
+#define SSC_DIR_MASK_PLAYBACK  1
+#define SSC_DIR_MASK_CAPTURE   2
+
+/*
+ * SSC register values that Atmel left out of <linux/atmel-ssc.h>.  These
+ * are expected to be used with SSC_BF
+ */
+/* START bit field values */
+#define SSC_START_CONTINUOUS   0
+#define SSC_START_TX_RX                1
+#define SSC_START_LOW_RF       2
+#define SSC_START_HIGH_RF      3
+#define SSC_START_FALLING_RF   4
+#define SSC_START_RISING_RF    5
+#define SSC_START_LEVEL_RF     6
+#define SSC_START_EDGE_RF      7
+#define SSS_START_COMPARE_0    8
+
+/* CKI bit field values */
+#define SSC_CKI_FALLING                0
+#define SSC_CKI_RISING         1
+
+/* CKO bit field values */
+#define SSC_CKO_NONE           0
+#define SSC_CKO_CONTINUOUS     1
+#define SSC_CKO_TRANSFER       2
+
+/* CKS bit field values */
+#define SSC_CKS_DIV            0
+#define SSC_CKS_CLOCK          1
+#define SSC_CKS_PIN            2
+
+/* FSEDGE bit field values */
+#define SSC_FSEDGE_POSITIVE    0
+#define SSC_FSEDGE_NEGATIVE    1
+
+/* FSOS bit field values */
+#define SSC_FSOS_NONE          0
+#define SSC_FSOS_NEGATIVE      1
+#define SSC_FSOS_POSITIVE      2
+#define SSC_FSOS_LOW           3
+#define SSC_FSOS_HIGH          4
+#define SSC_FSOS_TOGGLE                5
+
+#define START_DELAY            1
+
+
+
+/*-------------------------------------------------------------------------*\
+ * Module data
+\*-------------------------------------------------------------------------*/
+/*
+ * SSC PDC registered required by the PCM DMA engine
+ */
+static struct at32_pdc_regs pdc_tx_reg = {
+       .xpr = SSC_PDC_TPR,
+       .xcr = SSC_PDC_TCR,
+       .xnpr = SSC_PDC_TNPR,
+       .xncr = SSC_PDC_TNCR,
+};
+
+
+
+static struct at32_pdc_regs pdc_rx_reg = {
+       .xpr = SSC_PDC_RPR,
+       .xcr = SSC_PDC_RCR,
+       .xnpr = SSC_PDC_RNPR,
+       .xncr = SSC_PDC_RNCR,
+};
+
+
+
+/*
+ * SSC and PDC status bits for transmit and receive
+ */
+static struct at32_ssc_mask ssc_tx_mask = {
+       .ssc_enable = SSC_BIT(CR_TXEN),
+       .ssc_disable = SSC_BIT(CR_TXDIS),
+       .ssc_endx = SSC_BIT(SR_ENDTX),
+       .ssc_endbuf = SSC_BIT(SR_TXBUFE),
+       .pdc_enable = SSC_BIT(PDC_PTCR_TXTEN),
+       .pdc_disable = SSC_BIT(PDC_PTCR_TXTDIS),
+};
+
+
+
+static struct at32_ssc_mask ssc_rx_mask = {
+       .ssc_enable = SSC_BIT(CR_RXEN),
+       .ssc_disable = SSC_BIT(CR_RXDIS),
+       .ssc_endx = SSC_BIT(SR_ENDRX),
+       .ssc_endbuf = SSC_BIT(SR_RXBUFF),
+       .pdc_enable = SSC_BIT(PDC_PTCR_RXTEN),
+       .pdc_disable = SSC_BIT(PDC_PTCR_RXTDIS),
+};
+
+
+
+/*
+ * DMA parameters for each SSC
+ */
+static struct at32_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
+       {
+        {
+         .name = "SSC0 PCM out",
+         .pdc = &pdc_tx_reg,
+         .mask = &ssc_tx_mask,
+         },
+        {
+         .name = "SSC0 PCM in",
+         .pdc = &pdc_rx_reg,
+         .mask = &ssc_rx_mask,
+         },
+        },
+       {
+        {
+         .name = "SSC1 PCM out",
+         .pdc = &pdc_tx_reg,
+         .mask = &ssc_tx_mask,
+         },
+        {
+         .name = "SSC1 PCM in",
+         .pdc = &pdc_rx_reg,
+         .mask = &ssc_rx_mask,
+         },
+        },
+       {
+        {
+         .name = "SSC2 PCM out",
+         .pdc = &pdc_tx_reg,
+         .mask = &ssc_tx_mask,
+         },
+        {
+         .name = "SSC2 PCM in",
+         .pdc = &pdc_rx_reg,
+         .mask = &ssc_rx_mask,
+         },
+        },
+};
+
+
+
+static struct at32_ssc_info ssc_info[NUM_SSC_DEVICES] = {
+       {
+        .name = "ssc0",
+        .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
+        .dir_mask = SSC_DIR_MASK_UNUSED,
+        .initialized = 0,
+        },
+       {
+        .name = "ssc1",
+        .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
+        .dir_mask = SSC_DIR_MASK_UNUSED,
+        .initialized = 0,
+        },
+       {
+        .name = "ssc2",
+        .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
+        .dir_mask = SSC_DIR_MASK_UNUSED,
+        .initialized = 0,
+        },
+};
+
+
+
+
+/*-------------------------------------------------------------------------*\
+ * ISR
+\*-------------------------------------------------------------------------*/
+/*
+ * SSC interrupt handler.  Passes PDC interrupts to the DMA interrupt
+ * handler in the PCM driver.
+ */
+static irqreturn_t at32_ssc_interrupt(int irq, void *dev_id)
+{
+       struct at32_ssc_info *ssc_p = dev_id;
+       struct at32_pcm_dma_params *dma_params;
+       u32 ssc_sr;
+       u32 ssc_substream_mask;
+       int i;
+
+       ssc_sr = (ssc_readl(ssc_p->ssc->regs, SR) &
+                 ssc_readl(ssc_p->ssc->regs, IMR));
+
+       /*
+        * Loop through substreams attached to this SSC.  If a DMA-related
+        * interrupt occured on that substream, call the DMA interrupt
+        * handler function, if one has been registered in the dma_param
+        * structure by the PCM driver.
+        */
+       for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
+               dma_params = ssc_p->dma_params[i];
+
+               if ((dma_params != NULL) &&
+                   (dma_params->dma_intr_handler != NULL)) {
+                       ssc_substream_mask = (dma_params->mask->ssc_endx |
+                                             dma_params->mask->ssc_endbuf);
+                       if (ssc_sr & ssc_substream_mask) {
+                               dma_params->dma_intr_handler(ssc_sr,
+                                                            dma_params->
+                                                            substream);
+                       }
+               }
+       }
+
+
+       return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*\
+ * DAI functions
+\*-------------------------------------------------------------------------*/
+/*
+ * Startup.  Only that one substream allowed in each direction.
+ */
+static int at32_ssc_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+       int dir_mask;
+
+       dir_mask = ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+                   SSC_DIR_MASK_PLAYBACK : SSC_DIR_MASK_CAPTURE);
+
+       spin_lock_irq(&ssc_p->lock);
+       if (ssc_p->dir_mask & dir_mask) {
+               spin_unlock_irq(&ssc_p->lock);
+               return -EBUSY;
+       }
+       ssc_p->dir_mask |= dir_mask;
+       spin_unlock_irq(&ssc_p->lock);
+
+       return 0;
+}
+
+
+
+/*
+ * Shutdown.  Clear DMA parameters and shutdown the SSC if there
+ * are no other substreams open.
+ */
+static void at32_ssc_shutdown(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+       struct at32_pcm_dma_params *dma_params;
+       int dir_mask;
+
+       dma_params = ssc_p->dma_params[substream->stream];
+
+       if (dma_params != NULL) {
+               ssc_writel(dma_params->ssc->regs, CR,
+                          dma_params->mask->ssc_disable);
+               pr_debug("%s disabled SSC_SR=0x%08x\n",
+                        (substream->stream ? "receiver" : "transmit"),
+                        ssc_readl(ssc_p->ssc->regs, SR));
+
+               dma_params->ssc = NULL;
+               dma_params->substream = NULL;
+               ssc_p->dma_params[substream->stream] = NULL;
+       }
+
+
+       dir_mask = 1 << substream->stream;
+       spin_lock_irq(&ssc_p->lock);
+       ssc_p->dir_mask &= ~dir_mask;
+       if (!ssc_p->dir_mask) {
+               /* Shutdown the SSC clock */
+               pr_debug("at32-ssc: Stopping user %d clock\n",
+                        ssc_p->ssc->user);
+               clk_disable(ssc_p->ssc->clk);
+
+               if (ssc_p->initialized) {
+                       free_irq(ssc_p->ssc->irq, ssc_p);
+                       ssc_p->initialized = 0;
+               }
+
+               /* Reset the SSC */
+               ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
+
+               /* clear the SSC dividers */
+               ssc_p->cmr_div = 0;
+               ssc_p->tcmr_period = 0;
+               ssc_p->rcmr_period = 0;
+       }
+       spin_unlock_irq(&ssc_p->lock);
+}
+
+
+
+/*
+ * Set the SSC system clock rate
+ */
+static int at32_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+                                  int clk_id, unsigned int freq, int dir)
+{
+       /* TODO: What the heck do I do here? */
+       return 0;
+}
+
+
+
+/*
+ * Record DAI format for use by hw_params()
+ */
+static int at32_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+                               unsigned int fmt)
+{
+       struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+
+       ssc_p->daifmt = fmt;
+       return 0;
+}
+
+
+
+/*
+ * Record SSC clock dividers for use in hw_params()
+ */
+static int at32_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
+                                  int div_id, int div)
+{
+       struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+
+       switch (div_id) {
+       case AT32_SSC_CMR_DIV:
+               /*
+                * The same master clock divider is used for both
+                * transmit and receive, so if a value has already
+                * been set, it must match this value
+                */
+               if (ssc_p->cmr_div == 0)
+                       ssc_p->cmr_div = div;
+               else if (div != ssc_p->cmr_div)
+                       return -EBUSY;
+               break;
+
+       case AT32_SSC_TCMR_PERIOD:
+               ssc_p->tcmr_period = div;
+               break;
+
+       case AT32_SSC_RCMR_PERIOD:
+               ssc_p->rcmr_period = div;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
+
+/*
+ * Configure the SSC
+ */
+static int at32_ssc_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       int id = rtd->dai->cpu_dai->id;
+       struct at32_ssc_info *ssc_p = &ssc_info[id];
+       struct at32_pcm_dma_params *dma_params;
+       int channels, bits;
+       u32 tfmr, rfmr, tcmr, rcmr;
+       int start_event;
+       int ret;
+
+
+       /*
+        * Currently, there is only one set of dma_params for each direction.
+        * If more are added, this code will have to be changed to select
+        * the proper set
+        */
+       dma_params = &ssc_dma_params[id][substream->stream];
+       dma_params->ssc = ssc_p->ssc;
+       dma_params->substream = substream;
+
+       ssc_p->dma_params[substream->stream] = dma_params;
+
+
+       /*
+        * The cpu_dai->dma_data field is only used to communicate the
+        * appropriate DMA parameters to the PCM driver's hw_params()
+        * function.  It should not be used for other purposes as it
+        * is common to all substreams.
+        */
+       rtd->dai->cpu_dai->dma_data = dma_params;
+
+       channels = params_channels(params);
+
+
+       /*
+        * Determine sample size in bits and the PDC increment
+        */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S8:
+               bits = 8;
+               dma_params->pdc_xfer_size = 1;
+               break;
+
+       case SNDRV_PCM_FORMAT_S16:
+               bits = 16;
+               dma_params->pdc_xfer_size = 2;
+               break;
+
+       case SNDRV_PCM_FORMAT_S24:
+               bits = 24;
+               dma_params->pdc_xfer_size = 4;
+               break;
+
+       case SNDRV_PCM_FORMAT_S32:
+               bits = 32;
+               dma_params->pdc_xfer_size = 4;
+               break;
+
+       default:
+               pr_warning("at32-ssc: Unsupported PCM format %d",
+                          params_format(params));
+               return -EINVAL;
+       }
+       pr_debug("at32-ssc: bits = %d, pdc_xfer_size = %d, channels = %d\n",
+                bits, dma_params->pdc_xfer_size, channels);
+
+
+       /*
+        * The SSC only supports up to 16-bit samples in I2S format, due
+        * to the size of the Frame Mode Register FSLEN field.
+        */
+       if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
+               if (bits > 16) {
+                       pr_warning("at32-ssc: "
+                                  "sample size %d is too large for I2S\n",
+                                  bits);
+                       return -EINVAL;
+               }
+
+
+       /*
+        * Compute the SSC register settings
+        */
+       switch (ssc_p->daifmt & (SND_SOC_DAIFMT_FORMAT_MASK |
+                                SND_SOC_DAIFMT_MASTER_MASK)) {
+       case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
+               /*
+                * I2S format, SSC provides BCLK and LRS clocks.
+                *
+                * The SSC transmit and receive clocks are generated from the
+                * MCK divider, and the BCLK signal is output on the SSC TK line
+                */
+               pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME master\n");
+               rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
+                       SSC_BF(RCMR_STTDLY, START_DELAY) |
+                       SSC_BF(RCMR_START, SSC_START_FALLING_RF) |
+                       SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
+                       SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
+                       SSC_BF(RCMR_CKS, SSC_CKS_DIV));
+
+               rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
+                       SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) |
+                       SSC_BF(RFMR_FSLEN, bits - 1) |
+                       SSC_BF(RFMR_DATNB, channels - 1) |
+                       SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
+
+               tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
+                       SSC_BF(TCMR_STTDLY, START_DELAY) |
+                       SSC_BF(TCMR_START, SSC_START_FALLING_RF) |
+                       SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
+                       SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
+                       SSC_BF(TCMR_CKS, SSC_CKS_DIV));
+
+               tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
+                       SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) |
+                       SSC_BF(TFMR_FSLEN, bits - 1) |
+                       SSC_BF(TFMR_DATNB, channels - 1) | SSC_BIT(TFMR_MSBF) |
+                       SSC_BF(TFMR_DATLEN, bits - 1));
+               break;
+
+
+       case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
+               /*
+                * I2S format, CODEC supplies BCLK and LRC clock.
+                *
+                * The SSC transmit clock is obtained from the BCLK signal
+                * on the TK line, and the SSC receive clock is generated from
+                * the transmit clock.
+                *
+                * For single channel data, one sample is transferred on the
+                * falling edge of the LRC clock.  For two channel data, one
+                * sample is transferred on both edges of the LRC clock.
+                */
+               pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME slave\n");
+               start_event = ((channels == 1) ?
+                              SSC_START_FALLING_RF : SSC_START_EDGE_RF);
+
+               rcmr = (SSC_BF(RCMR_STTDLY, START_DELAY) |
+                       SSC_BF(RCMR_START, start_event) |
+                       SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
+                       SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
+                       SSC_BF(RCMR_CKS, SSC_CKS_CLOCK));
+
+               rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
+                       SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) |
+                       SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
+
+               tcmr = (SSC_BF(TCMR_STTDLY, START_DELAY) |
+                       SSC_BF(TCMR_START, start_event) |
+                       SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
+                       SSC_BF(TCMR_CKO, SSC_CKO_NONE) |
+                       SSC_BF(TCMR_CKS, SSC_CKS_PIN));
+
+               tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
+                       SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) |
+                       SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
+               break;
+
+
+       case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
+               /*
+                * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
+                *
+                * The SSC transmit and receive clocks are generated from the
+                * MCK divider, and the BCLK signal is output on the SSC TK line
+                */
+               pr_debug("at32-ssc: SSC mode is DSP A BCLK / FRAME master\n");
+               rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
+                       SSC_BF(RCMR_STTDLY, 1) |
+                       SSC_BF(RCMR_START, SSC_START_RISING_RF) |
+                       SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
+                       SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
+                       SSC_BF(RCMR_CKS, SSC_CKS_DIV));
+
+               rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
+                       SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) |
+                       SSC_BF(RFMR_DATNB, channels - 1) |
+                       SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
+
+               tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
+                       SSC_BF(TCMR_STTDLY, 1) |
+                       SSC_BF(TCMR_START, SSC_START_RISING_RF) |
+                       SSC_BF(TCMR_CKI, SSC_CKI_RISING) |
+                       SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
+                       SSC_BF(TCMR_CKS, SSC_CKS_DIV));
+
+               tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
+                       SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) |
+                       SSC_BF(TFMR_DATNB, channels - 1) |
+                       SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
+               break;
+
+
+       case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
+       default:
+               pr_warning("at32-ssc: unsupported DAI format 0x%x\n",
+                          ssc_p->daifmt);
+               return -EINVAL;
+               break;
+       }
+       pr_debug("at32-ssc: RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
+                rcmr, rfmr, tcmr, tfmr);
+
+
+       if (!ssc_p->initialized) {
+               /* enable peripheral clock */
+               pr_debug("at32-ssc: Starting clock\n");
+               clk_enable(ssc_p->ssc->clk);
+
+               /* Reset the SSC and its PDC registers */
+               ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
+
+               ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
+               ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
+               ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
+               ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
+
+               ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
+               ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
+               ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
+               ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
+
+               ret = request_irq(ssc_p->ssc->irq, at32_ssc_interrupt, 0,
+                                 ssc_p->name, ssc_p);
+               if (ret < 0) {
+                       pr_warning("at32-ssc: request irq failed (%d)\n", ret);
+                       pr_debug("at32-ssc: Stopping clock\n");
+                       clk_disable(ssc_p->ssc->clk);
+                       return ret;
+               }
+
+               ssc_p->initialized = 1;
+       }
+
+       /* Set SSC clock mode register */
+       ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
+
+       /* set receive clock mode and format */
+       ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
+       ssc_writel(ssc_p->ssc->regs, RFMR, rfmr);
+
+       /* set transmit clock mode and format */
+       ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
+       ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
+
+       pr_debug("at32-ssc: SSC initialized\n");
+       return 0;
+}
+
+
+
+static int at32_ssc_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+       struct at32_pcm_dma_params *dma_params;
+
+       dma_params = ssc_p->dma_params[substream->stream];
+
+       ssc_writel(dma_params->ssc->regs, CR, dma_params->mask->ssc_enable);
+
+       return 0;
+}
+
+
+
+#ifdef CONFIG_PM
+static int at32_ssc_suspend(struct platform_device *pdev,
+                           struct snd_soc_dai *cpu_dai)
+{
+       struct at32_ssc_info *ssc_p;
+
+       if (!cpu_dai->active)
+               return 0;
+
+       ssc_p = &ssc_info[cpu_dai->id];
+
+       /* Save the status register before disabling transmit and receive */
+       ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
+       ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS));
+
+       /* Save the current interrupt mask, then disable unmasked interrupts */
+       ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR);
+       ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr);
+
+       ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR);
+       ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR);
+       ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR);
+       ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR);
+       ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR);
+
+       return 0;
+}
+
+
+
+static int at32_ssc_resume(struct platform_device *pdev,
+                          struct snd_soc_dai *cpu_dai)
+{
+       struct at32_ssc_info *ssc_p;
+       u32 cr;
+
+       if (!cpu_dai->active)
+               return 0;
+
+       ssc_p = &ssc_info[cpu_dai->id];
+
+       /* restore SSC register settings */
+       ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
+       ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr);
+       ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr);
+       ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr);
+       ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr);
+
+       /* re-enable interrupts */
+       ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr);
+
+       /* Re-enable recieve and transmit as appropriate */
+       cr = 0;
+       cr |=
+           (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0;
+       cr |=
+           (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0;
+       ssc_writel(ssc_p->ssc->regs, CR, cr);
+
+       return 0;
+}
+#else /* CONFIG_PM */
+#  define at32_ssc_suspend     NULL
+#  define at32_ssc_resume      NULL
+#endif /* CONFIG_PM */
+
+
+#define AT32_SSC_RATES \
+    (SNDRV_PCM_RATE_8000  | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
+     SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+     SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+
+
+#define AT32_SSC_FORMATS \
+    (SNDRV_PCM_FMTBIT_S8  | SNDRV_PCM_FMTBIT_S16 | \
+     SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_S32)
+
+
+struct snd_soc_dai at32_ssc_dai[NUM_SSC_DEVICES] = {
+       {
+        .name = "at32-ssc0",
+        .id = 0,
+        .type = SND_SOC_DAI_PCM,
+        .suspend = at32_ssc_suspend,
+        .resume = at32_ssc_resume,
+        .playback = {
+                     .channels_min = 1,
+                     .channels_max = 2,
+                     .rates = AT32_SSC_RATES,
+                     .formats = AT32_SSC_FORMATS,
+                     },
+        .capture = {
+                    .channels_min = 1,
+                    .channels_max = 2,
+                    .rates = AT32_SSC_RATES,
+                    .formats = AT32_SSC_FORMATS,
+                    },
+        .ops = {
+                .startup = at32_ssc_startup,
+                .shutdown = at32_ssc_shutdown,
+                .prepare = at32_ssc_prepare,
+                .hw_params = at32_ssc_hw_params,
+                },
+        .dai_ops = {
+                    .set_sysclk = at32_ssc_set_dai_sysclk,
+                    .set_fmt = at32_ssc_set_dai_fmt,
+                    .set_clkdiv = at32_ssc_set_dai_clkdiv,
+                    },
+        .private_data = &ssc_info[0],
+        },
+       {
+        .name = "at32-ssc1",
+        .id = 1,
+        .type = SND_SOC_DAI_PCM,
+        .suspend = at32_ssc_suspend,
+        .resume = at32_ssc_resume,
+        .playback = {
+                     .channels_min = 1,
+                     .channels_max = 2,
+                     .rates = AT32_SSC_RATES,
+                     .formats = AT32_SSC_FORMATS,
+                     },
+        .capture = {
+                    .channels_min = 1,
+                    .channels_max = 2,
+                    .rates = AT32_SSC_RATES,
+                    .formats = AT32_SSC_FORMATS,
+                    },
+        .ops = {
+                .startup = at32_ssc_startup,
+                .shutdown = at32_ssc_shutdown,
+                .prepare = at32_ssc_prepare,
+                .hw_params = at32_ssc_hw_params,
+                },
+        .dai_ops = {
+                    .set_sysclk = at32_ssc_set_dai_sysclk,
+                    .set_fmt = at32_ssc_set_dai_fmt,
+                    .set_clkdiv = at32_ssc_set_dai_clkdiv,
+                    },
+        .private_data = &ssc_info[1],
+        },
+       {
+        .name = "at32-ssc2",
+        .id = 2,
+        .type = SND_SOC_DAI_PCM,
+        .suspend = at32_ssc_suspend,
+        .resume = at32_ssc_resume,
+        .playback = {
+                     .channels_min = 1,
+                     .channels_max = 2,
+                     .rates = AT32_SSC_RATES,
+                     .formats = AT32_SSC_FORMATS,
+                     },
+        .capture = {
+                    .channels_min = 1,
+                    .channels_max = 2,
+                    .rates = AT32_SSC_RATES,
+                    .formats = AT32_SSC_FORMATS,
+                    },
+        .ops = {
+                .startup = at32_ssc_startup,
+                .shutdown = at32_ssc_shutdown,
+                .prepare = at32_ssc_prepare,
+                .hw_params = at32_ssc_hw_params,
+                },
+        .dai_ops = {
+                    .set_sysclk = at32_ssc_set_dai_sysclk,
+                    .set_fmt = at32_ssc_set_dai_fmt,
+                    .set_clkdiv = at32_ssc_set_dai_clkdiv,
+                    },
+        .private_data = &ssc_info[2],
+        },
+};
+EXPORT_SYMBOL_GPL(at32_ssc_dai);
+
+
+MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
+MODULE_DESCRIPTION("AT32 SSC ASoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/at32/at32-ssc.h b/sound/soc/at32/at32-ssc.h
new file mode 100644 (file)
index 0000000..3c052db
--- /dev/null
@@ -0,0 +1,59 @@
+/* sound/soc/at32/at32-ssc.h
+ * ASoC SSC interface for Atmel AT32 SoC
+ *
+ * Copyright (C) 2008 Long Range Systems
+ *    Geoffrey Wossum <gwossum@acm.org>
+ *
+ * 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 __SOUND_SOC_AT32_AT32_SSC_H
+#define __SOUND_SOC_AT32_AT32_SSC_H __FILE__
+
+#include <linux/types.h>
+#include <linux/atmel-ssc.h>
+
+#include "at32-pcm.h"
+
+
+
+struct at32_ssc_state {
+       u32 ssc_cmr;
+       u32 ssc_rcmr;
+       u32 ssc_rfmr;
+       u32 ssc_tcmr;
+       u32 ssc_tfmr;
+       u32 ssc_sr;
+       u32 ssc_imr;
+};
+
+
+
+struct at32_ssc_info {
+       char *name;
+       struct ssc_device *ssc;
+       spinlock_t lock;        /* lock for dir_mask */
+       unsigned short dir_mask;        /* 0=unused, 1=playback, 2=capture */
+       unsigned short initialized;     /* true if SSC has been initialized */
+       unsigned short daifmt;
+       unsigned short cmr_div;
+       unsigned short tcmr_period;
+       unsigned short rcmr_period;
+       struct at32_pcm_dma_params *dma_params[2];
+       struct at32_ssc_state ssc_state;
+};
+
+
+/* SSC divider ids */
+#define AT32_SSC_CMR_DIV        0      /* MCK divider for BCLK */
+#define AT32_SSC_TCMR_PERIOD    1      /* BCLK divider for transmit FS */
+#define AT32_SSC_RCMR_PERIOD    2      /* BCLK divider for receive FS */
+
+
+extern struct snd_soc_dai at32_ssc_dai[];
+
+
+
+#endif /* __SOUND_SOC_AT32_AT32_SSC_H */
diff --git a/sound/soc/at32/playpaq_wm8510.c b/sound/soc/at32/playpaq_wm8510.c
new file mode 100644 (file)
index 0000000..fee5f8e
--- /dev/null
@@ -0,0 +1,522 @@
+/* sound/soc/at32/playpaq_wm8510.c
+ * ASoC machine driver for PlayPaq using WM8510 codec
+ *
+ * Copyright (C) 2008 Long Range Systems
+ *    Geoffrey Wossum <gwossum@acm.org>
+ *
+ * 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.
+ *
+ * This code is largely inspired by sound/soc/at91/eti_b1_wm8731.c
+ *
+ * NOTE: If you don't have the AT32 enhanced portmux configured (which
+ * isn't currently in the mainline or Atmel patched kernel), you will
+ * need to set the MCLK pin (PA30) to peripheral A in your board initialization
+ * code.  Something like:
+ *     at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0);
+ *
+ */
+
+/* #define DEBUG */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/arch/at32ap700x.h>
+#include <asm/arch/portmux.h>
+
+#include "../codecs/wm8510.h"
+#include "at32-pcm.h"
+#include "at32-ssc.h"
+
+
+/*-------------------------------------------------------------------------*\
+ * constants
+\*-------------------------------------------------------------------------*/
+#define MCLK_PIN               GPIO_PIN_PA(30)
+#define MCLK_PERIPH            GPIO_PERIPH_A
+
+
+/*-------------------------------------------------------------------------*\
+ * data types
+\*-------------------------------------------------------------------------*/
+/* SSC clocking data */
+struct ssc_clock_data {
+       /* CMR div */
+       unsigned int cmr_div;
+
+       /* Frame period (as needed by xCMR.PERIOD) */
+       unsigned int period;
+
+       /* The SSC clock rate these settings where calculated for */
+       unsigned long ssc_rate;
+};
+
+
+/*-------------------------------------------------------------------------*\
+ * module data
+\*-------------------------------------------------------------------------*/
+static struct clk *_gclk0;
+static struct clk *_pll0;
+
+#define CODEC_CLK (_gclk0)
+
+
+/*-------------------------------------------------------------------------*\
+ * Sound SOC operations
+\*-------------------------------------------------------------------------*/
+#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
+static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock(
+       struct snd_pcm_hw_params *params,
+       struct snd_soc_dai *cpu_dai)
+{
+       struct at32_ssc_info *ssc_p = cpu_dai->private_data;
+       struct ssc_device *ssc = ssc_p->ssc;
+       struct ssc_clock_data cd;
+       unsigned int rate, width_bits, channels;
+       unsigned int bitrate, ssc_div;
+       unsigned actual_rate;
+
+
+       /*
+        * Figure out required bitrate
+        */
+       rate = params_rate(params);
+       channels = params_channels(params);
+       width_bits = snd_pcm_format_physical_width(params_format(params));
+       bitrate = rate * width_bits * channels;
+
+
+       /*
+        * Figure out required SSC divider and period for required bitrate
+        */
+       cd.ssc_rate = clk_get_rate(ssc->clk);
+       ssc_div = cd.ssc_rate / bitrate;
+       cd.cmr_div = ssc_div / 2;
+       if (ssc_div & 1) {
+               /* round cmr_div up */
+               cd.cmr_div++;
+       }
+       cd.period = width_bits - 1;
+
+
+       /*
+        * Find actual rate, compare to requested rate
+        */
+       actual_rate = (cd.ssc_rate / (cd.cmr_div * 2)) / (2 * (cd.period + 1));
+       pr_debug("playpaq_wm8510: Request rate = %d, actual rate = %d\n",
+                rate, actual_rate);
+
+
+       return cd;
+}
+#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
+
+
+
+static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream,
+                                   struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct at32_ssc_info *ssc_p = cpu_dai->private_data;
+       struct ssc_device *ssc = ssc_p->ssc;
+       unsigned int pll_out = 0, bclk = 0, mclk_div = 0;
+       int ret;
+
+
+       /* Due to difficulties with getting the correct clocks from the AT32's
+        * PLL0, we're going to let the CODEC be in charge of all the clocks
+        */
+#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
+       const unsigned int fmt = (SND_SOC_DAIFMT_I2S |
+                                 SND_SOC_DAIFMT_NB_NF |
+                                 SND_SOC_DAIFMT_CBM_CFM);
+#else
+       struct ssc_clock_data cd;
+       const unsigned int fmt = (SND_SOC_DAIFMT_I2S |
+                                 SND_SOC_DAIFMT_NB_NF |
+                                 SND_SOC_DAIFMT_CBS_CFS);
+#endif
+
+       if (ssc == NULL) {
+               pr_warning("playpaq_wm8510_hw_params: ssc is NULL!\n");
+               return -EINVAL;
+       }
+
+
+       /*
+        * Figure out PLL and BCLK dividers for WM8510
+        */
+       switch (params_rate(params)) {
+       case 48000:
+               pll_out = 12288000;
+               mclk_div = WM8510_MCLKDIV_1;
+               bclk = WM8510_BCLKDIV_8;
+               break;
+
+       case 44100:
+               pll_out = 11289600;
+               mclk_div = WM8510_MCLKDIV_1;
+               bclk = WM8510_BCLKDIV_8;
+               break;
+
+       case 22050:
+               pll_out = 11289600;
+               mclk_div = WM8510_MCLKDIV_2;
+               bclk = WM8510_BCLKDIV_8;
+               break;
+
+       case 16000:
+               pll_out = 12288000;
+               mclk_div = WM8510_MCLKDIV_3;
+               bclk = WM8510_BCLKDIV_8;
+               break;
+
+       case 11025:
+               pll_out = 11289600;
+               mclk_div = WM8510_MCLKDIV_4;
+               bclk = WM8510_BCLKDIV_8;
+               break;
+
+       case 8000:
+               pll_out = 12288000;
+               mclk_div = WM8510_MCLKDIV_6;
+               bclk = WM8510_BCLKDIV_8;
+               break;
+
+       default:
+               pr_warning("playpaq_wm8510: Unsupported sample rate %d\n",
+                          params_rate(params));
+               return -EINVAL;
+       }
+
+
+       /*
+        * set CPU and CODEC DAI configuration
+        */
+       ret = snd_soc_dai_set_fmt(codec_dai, fmt);
+       if (ret < 0) {
+               pr_warning("playpaq_wm8510: "
+                          "Failed to set CODEC DAI format (%d)\n",
+                          ret);
+               return ret;
+       }
+       ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
+       if (ret < 0) {
+               pr_warning("playpaq_wm8510: "
+                          "Failed to set CPU DAI format (%d)\n",
+                          ret);
+               return ret;
+       }
+
+
+       /*
+        * Set CPU clock configuration
+        */
+#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
+       cd = playpaq_wm8510_calc_ssc_clock(params, cpu_dai);
+       pr_debug("playpaq_wm8510: cmr_div = %d, period = %d\n",
+                cd.cmr_div, cd.period);
+       ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_CMR_DIV, cd.cmr_div);
+       if (ret < 0) {
+               pr_warning("playpaq_wm8510: Failed to set CPU CMR_DIV (%d)\n",
+                          ret);
+               return ret;
+       }
+       ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_TCMR_PERIOD,
+                                         cd.period);
+       if (ret < 0) {
+               pr_warning("playpaq_wm8510: "
+                          "Failed to set CPU transmit period (%d)\n",
+                          ret);
+               return ret;
+       }
+#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
+
+
+       /*
+        * Set CODEC clock configuration
+        */
+       pr_debug("playpaq_wm8510: "
+                "pll_in = %ld, pll_out = %u, bclk = %x, mclk = %x\n",
+                clk_get_rate(CODEC_CLK), pll_out, bclk, mclk_div);
+
+
+#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
+       ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_BCLKDIV, bclk);
+       if (ret < 0) {
+               pr_warning
+                   ("playpaq_wm8510: Failed to set CODEC DAI BCLKDIV (%d)\n",
+                    ret);
+               return ret;
+       }
+#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
+
+
+       ret = snd_soc_dai_set_pll(codec_dai, 0,
+                                        clk_get_rate(CODEC_CLK), pll_out);
+       if (ret < 0) {
+               pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n",
+                          ret);
+               return ret;
+       }
+
+
+       ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_MCLKDIV, mclk_div);
+       if (ret < 0) {
+               pr_warning("playpaq_wm8510: Failed to set CODEC MCLKDIV (%d)\n",
+                          ret);
+               return ret;
+       }
+
+
+       return 0;
+}
+
+
+
+static struct snd_soc_ops playpaq_wm8510_ops = {
+       .hw_params = playpaq_wm8510_hw_params,
+};
+
+
+
+static const struct snd_soc_dapm_widget playpaq_dapm_widgets[] = {
+       SND_SOC_DAPM_MIC("Int Mic", NULL),
+       SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+
+
+static const char *intercon[][3] = {
+       /* speaker connected to SPKOUT */
+       {"Ext Spk", NULL, "SPKOUTP"},
+       {"Ext Spk", NULL, "SPKOUTN"},
+
+       {"Mic Bias", NULL, "Int Mic"},
+       {"MICN", NULL, "Mic Bias"},
+       {"MICP", NULL, "Mic Bias"},
+
+       /* Terminator */
+       {NULL, NULL, NULL},
+};
+
+
+
+static int playpaq_wm8510_init(struct snd_soc_codec *codec)
+{
+       int i;
+
+       /*
+        * Add DAPM widgets
+        */
+       for (i = 0; i < ARRAY_SIZE(playpaq_dapm_widgets); i++)
+               snd_soc_dapm_new_control(codec, &playpaq_dapm_widgets[i]);
+
+
+
+       /*
+        * Setup audio path interconnects
+        */
+       for (i = 0; intercon[i][0] != NULL; i++) {
+               snd_soc_dapm_connect_input(codec,
+                                          intercon[i][0],
+                                          intercon[i][1], intercon[i][2]);
+       }
+
+
+       /* always connected pins */
+       snd_soc_dapm_enable_pin(codec, "Int Mic");
+       snd_soc_dapm_enable_pin(codec, "Ext Spk");
+       snd_soc_dapm_sync(codec);
+
+
+
+       /* Make CSB show PLL rate */
+       snd_soc_dai_set_clkdiv(codec->dai, WM8510_OPCLKDIV,
+                                      WM8510_OPCLKDIV_1 | 4);
+
+       return 0;
+}
+
+
+
+static struct snd_soc_dai_link playpaq_wm8510_dai = {
+       .name = "WM8510",
+       .stream_name = "WM8510 PCM",
+       .cpu_dai = &at32_ssc_dai[0],
+       .codec_dai = &wm8510_dai,
+       .init = playpaq_wm8510_init,
+       .ops = &playpaq_wm8510_ops,
+};
+
+
+
+static struct snd_soc_machine snd_soc_machine_playpaq = {
+       .name = "LRS_PlayPaq_WM8510",
+       .dai_link = &playpaq_wm8510_dai,
+       .num_links = 1,
+};
+
+
+
+static struct wm8510_setup_data playpaq_wm8510_setup = {
+       .i2c_address = 0x1a,
+};
+
+
+
+static struct snd_soc_device playpaq_wm8510_snd_devdata = {
+       .machine = &snd_soc_machine_playpaq,
+       .platform = &at32_soc_platform,
+       .codec_dev = &soc_codec_dev_wm8510,
+       .codec_data = &playpaq_wm8510_setup,
+};
+
+static struct platform_device *playpaq_snd_device;
+
+
+static int __init playpaq_asoc_init(void)
+{
+       int ret = 0;
+       struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data;
+       struct ssc_device *ssc = NULL;
+
+
+       /*
+        * Request SSC device
+        */
+       ssc = ssc_request(0);
+       if (IS_ERR(ssc)) {
+               ret = PTR_ERR(ssc);
+               ssc = NULL;
+               goto err_ssc;
+       }
+       ssc_p->ssc = ssc;
+
+
+       /*
+        * Configure MCLK for WM8510
+        */
+       _gclk0 = clk_get(NULL, "gclk0");
+       if (IS_ERR(_gclk0)) {
+               _gclk0 = NULL;
+               goto err_gclk0;
+       }
+       _pll0 = clk_get(NULL, "pll0");
+       if (IS_ERR(_pll0)) {
+               _pll0 = NULL;
+               goto err_pll0;
+       }
+       if (clk_set_parent(_gclk0, _pll0)) {
+               pr_warning("snd-soc-playpaq: "
+                          "Failed to set PLL0 as parent for DAC clock\n");
+               goto err_set_clk;
+       }
+       clk_set_rate(CODEC_CLK, 12000000);
+       clk_enable(CODEC_CLK);
+
+#if defined CONFIG_AT32_ENHANCED_PORTMUX
+       at32_select_periph(MCLK_PIN, MCLK_PERIPH, 0);
+#endif
+
+
+       /*
+        * Create and register platform device
+        */
+       playpaq_snd_device = platform_device_alloc("soc-audio", 0);
+       if (playpaq_snd_device == NULL) {
+               ret = -ENOMEM;
+               goto err_device_alloc;
+       }
+
+       platform_set_drvdata(playpaq_snd_device, &playpaq_wm8510_snd_devdata);
+       playpaq_wm8510_snd_devdata.dev = &playpaq_snd_device->dev;
+
+       ret = platform_device_add(playpaq_snd_device);
+       if (ret) {
+               pr_warning("playpaq_wm8510: platform_device_add failed (%d)\n",
+                          ret);
+               goto err_device_add;
+       }
+
+       return 0;
+
+
+err_device_add:
+       if (playpaq_snd_device != NULL) {
+               platform_device_put(playpaq_snd_device);
+               playpaq_snd_device = NULL;
+       }
+err_device_alloc:
+err_set_clk:
+       if (_pll0 != NULL) {
+               clk_put(_pll0);
+               _pll0 = NULL;
+       }
+err_pll0:
+       if (_gclk0 != NULL) {
+               clk_put(_gclk0);
+               _gclk0 = NULL;
+       }
+err_gclk0:
+       if (ssc != NULL) {
+               ssc_free(ssc);
+               ssc = NULL;
+       }
+err_ssc:
+       return ret;
+}
+
+
+static void __exit playpaq_asoc_exit(void)
+{
+       struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data;
+       struct ssc_device *ssc;
+
+       if (ssc_p != NULL) {
+               ssc = ssc_p->ssc;
+               if (ssc != NULL)
+                       ssc_free(ssc);
+               ssc_p->ssc = NULL;
+       }
+
+       if (_gclk0 != NULL) {
+               clk_put(_gclk0);
+               _gclk0 = NULL;
+       }
+       if (_pll0 != NULL) {
+               clk_put(_pll0);
+               _pll0 = NULL;
+       }
+
+#if defined CONFIG_AT32_ENHANCED_PORTMUX
+       at32_free_pin(MCLK_PIN);
+#endif
+
+       platform_device_unregister(playpaq_snd_device);
+       playpaq_snd_device = NULL;
+}
+
+module_init(playpaq_asoc_init);
+module_exit(playpaq_asoc_exit);
+
+MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
+MODULE_DESCRIPTION("ASoC machine driver for LRS PlayPaq");
+MODULE_LICENSE("GPL");
index 5cb93fd3a4071d477cd38bab269b2bbfe2fda50d..905186502e0009039efc81919022b9d4ffe44a54 100644 (file)
@@ -1,6 +1,6 @@
 config SND_AT91_SOC
        tristate "SoC Audio for the Atmel AT91 System-on-Chip"
-       depends on ARCH_AT91 && SND_SOC
+       depends on ARCH_AT91
        help
          Say Y or M if you want to add support for codecs attached to
          the AT91 SSC interface. You will also need
index ccac6bd2889c0f56589f2234aa899aeb42b42ff0..d47492b2b6e5db1494e466de57da06248cbc2ac0 100644 (file)
@@ -318,7 +318,7 @@ static int at91_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
 static u64 at91_pcm_dmamask = 0xffffffff;
 
 static int at91_pcm_new(struct snd_card *card,
-       struct snd_soc_codec_dai *dai, struct snd_pcm *pcm)
+       struct snd_soc_dai *dai, struct snd_pcm *pcm)
 {
        int ret = 0;
 
@@ -367,7 +367,7 @@ static void at91_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 #ifdef CONFIG_PM
 static int at91_pcm_suspend(struct platform_device *pdev,
-       struct snd_soc_cpu_dai *dai)
+       struct snd_soc_dai *dai)
 {
        struct snd_pcm_runtime *runtime = dai->runtime;
        struct at91_runtime_data *prtd;
@@ -392,7 +392,7 @@ static int at91_pcm_suspend(struct platform_device *pdev,
 }
 
 static int at91_pcm_resume(struct platform_device *pdev,
-       struct snd_soc_cpu_dai *dai)
+       struct snd_soc_dai *dai)
 {
        struct snd_pcm_runtime *runtime = dai->runtime;
        struct at91_runtime_data *prtd;
index bc35d00a38f86b89778bd86953a165d4075dfef2..c3625b665c5a027ee0ed06f7f8f6582da3a026a2 100644 (file)
@@ -281,7 +281,7 @@ static void at91_ssc_shutdown(struct snd_pcm_substream *substream)
 /*
  * Record the SSC system clock rate.
  */
-static int at91_ssc_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+static int at91_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                int clk_id, unsigned int freq, int dir)
 {
        /*
@@ -303,7 +303,7 @@ static int at91_ssc_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
 /*
  * Record the DAI format for use in hw_params().
  */
-static int at91_ssc_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
+static int at91_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
        struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
@@ -315,7 +315,7 @@ static int at91_ssc_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
 /*
  * Record SSC clock dividers for use in hw_params().
  */
-static int at91_ssc_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
+static int at91_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
        int div_id, int div)
 {
        struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
@@ -634,7 +634,7 @@ static int at91_ssc_prepare(struct snd_pcm_substream *substream)
 
 #ifdef CONFIG_PM
 static int at91_ssc_suspend(struct platform_device *pdev,
-       struct snd_soc_cpu_dai *cpu_dai)
+       struct snd_soc_dai *cpu_dai)
 {
        struct at91_ssc_info *ssc_p;
 
@@ -662,7 +662,7 @@ static int at91_ssc_suspend(struct platform_device *pdev,
 }
 
 static int at91_ssc_resume(struct platform_device *pdev,
-       struct snd_soc_cpu_dai *cpu_dai)
+       struct snd_soc_dai *cpu_dai)
 {
        struct at91_ssc_info *ssc_p;
 
@@ -700,7 +700,7 @@ static int at91_ssc_resume(struct platform_device *pdev,
 #define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_S16_LE |\
                          SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-struct snd_soc_cpu_dai at91_ssc_dai[NUM_SSC_DEVICES] = {
+struct snd_soc_dai at91_ssc_dai[NUM_SSC_DEVICES] = {
        {       .name = "at91-ssc0",
                .id = 0,
                .type = SND_SOC_DAI_PCM,
index b188f973df9fea1d0554bf36b26b4ad913649674..6b7bf382d06f78ddbaf2435c35f32a330b66f534 100644 (file)
@@ -21,7 +21,7 @@
 #define AT91SSC_TCMR_PERIOD    1 /* BCLK divider for transmit FS */
 #define AT91SSC_RCMR_PERIOD    2 /* BCLK divider for receive FS */
 
-extern struct snd_soc_cpu_dai at91_ssc_dai[];
+extern struct snd_soc_dai at91_ssc_dai[];
 
 #endif /* _AT91_SSC_H */
 
index 1347dcf3f80b822a300e522d93abbdd2e6ea3202..d532de954241d6bda834fb9df868f411f4bf0df6 100644 (file)
@@ -53,18 +53,18 @@ static struct clk *pllb_clk;
 static int eti_b1_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        int ret;
 
        /* cpu clock is the AT91 master clock sent to the SSC */
-       ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, AT91_SYSCLK_MCK,
+       ret = snd_soc_dai_set_sysclk(cpu_dai, AT91_SYSCLK_MCK,
                60000000, SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
 
        /* codec system clock is supplied by PCK1, set to 12MHz */
-       ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK,
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
                12000000, SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
@@ -87,8 +87,8 @@ static int eti_b1_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        int ret;
 
 #ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
@@ -96,13 +96,13 @@ static int eti_b1_hw_params(struct snd_pcm_substream *substream,
        int cmr_div, period;
 
        /* set codec DAI configuration */
-       ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
        if (ret < 0)
                return ret;
 
        /* set cpu DAI configuration */
-       ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
        if (ret < 0)
                return ret;
@@ -141,17 +141,17 @@ static int eti_b1_hw_params(struct snd_pcm_substream *substream,
        }
 
        /* set the MCK divider for BCLK */
-       ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div);
+       ret = snd_soc_dai_set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div);
        if (ret < 0)
                return ret;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                /* set the BCLK divider for DACLRC */
-               ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai,
+               ret = snd_soc_dai_set_clkdiv(cpu_dai,
                                                AT91SSC_TCMR_PERIOD, period);
        } else {
                /* set the BCLK divider for ADCLRC */
-               ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai,
+               ret = snd_soc_dai_set_clkdiv(cpu_dai,
                                                AT91SSC_RCMR_PERIOD, period);
        }
        if (ret < 0)
@@ -163,13 +163,13 @@ static int eti_b1_hw_params(struct snd_pcm_substream *substream,
         */
 
        /* set codec DAI configuration */
-       ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
        if (ret < 0)
                return ret;
 
        /* set cpu DAI configuration */
-       ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
        if (ret < 0)
                return ret;
@@ -191,7 +191,7 @@ static const struct snd_soc_dapm_widget eti_b1_dapm_widgets[] = {
        SND_SOC_DAPM_SPK("Ext Spk", NULL),
 };
 
-static const char *intercon[][3] = {
+static const struct snd_soc_dapm_route intercon[] = {
 
        /* speaker connected to LHPOUT */
        {"Ext Spk", NULL, "LHPOUT"},
@@ -199,9 +199,6 @@ static const char *intercon[][3] = {
        /* mic is connected to Mic Jack, with WM8731 Mic Bias */
        {"MICIN", NULL, "Mic Bias"},
        {"Mic Bias", NULL, "Int Mic"},
-
-       /* terminator */
-       {NULL, NULL, NULL},
 };
 
 /*
@@ -209,30 +206,24 @@ static const char *intercon[][3] = {
  */
 static int eti_b1_wm8731_init(struct snd_soc_codec *codec)
 {
-       int i;
-
        DBG("eti_b1_wm8731_init() called\n");
 
        /* Add specific widgets */
-       for(i = 0; i < ARRAY_SIZE(eti_b1_dapm_widgets); i++) {
-               snd_soc_dapm_new_control(codec, &eti_b1_dapm_widgets[i]);
-       }
+       snd_soc_dapm_new_controls(codec, eti_b1_dapm_widgets,
+                                 ARRAY_SIZE(eti_b1_dapm_widgets));
 
        /* Set up specific audio path interconnects */
-       for(i = 0; intercon[i][0] != NULL; i++) {
-               snd_soc_dapm_connect_input(codec, intercon[i][0],
-                       intercon[i][1], intercon[i][2]);
-       }
+       snd_soc_dapm_add_route(codec, intercon, ARRAY_SIZE(intercon));
 
        /* not connected */
-       snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
-       snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
+       snd_soc_dapm_disable_pin(codec, "RLINEIN");
+       snd_soc_dapm_disable_pin(codec, "LLINEIN");
 
        /* always connected */
-       snd_soc_dapm_set_endpoint(codec, "Int Mic", 1);
-       snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1);
+       snd_soc_dapm_enable_pin(codec, "Int Mic");
+       snd_soc_dapm_enable_pin(codec, "Ext Spk");
 
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
 
        return 0;
 }
diff --git a/sound/soc/au1x/Kconfig b/sound/soc/au1x/Kconfig
new file mode 100644 (file)
index 0000000..410a893
--- /dev/null
@@ -0,0 +1,32 @@
+##
+## Au1200/Au1550 PSC + DBDMA
+##
+config SND_SOC_AU1XPSC
+       tristate "SoC Audio for Au1200/Au1250/Au1550"
+       depends on SOC_AU1200 || SOC_AU1550
+       help
+         This option enables support for the Programmable Serial
+         Controllers in AC97 and I2S mode, and the Descriptor-Based DMA
+         Controller (DBDMA) as found on the Au1200/Au1250/Au1550 SoC.
+
+config SND_SOC_AU1XPSC_I2S
+       tristate
+
+config SND_SOC_AU1XPSC_AC97
+       tristate
+       select AC97_BUS
+       select SND_AC97_CODEC
+       select SND_SOC_AC97_BUS
+
+
+##
+## Boards
+##
+config SND_SOC_SAMPLE_PSC_AC97
+       tristate "Sample Au12x0/Au1550 PSC AC97 sound machine"
+       depends on SND_SOC_AU1XPSC
+       select SND_SOC_AU1XPSC_AC97
+       select SND_SOC_AC97_CODEC
+       help
+         This is a sample AC97 sound machine for use in Au12x0/Au1550
+         based systems which have audio on PSC1 (e.g. Db1200 demoboard).
diff --git a/sound/soc/au1x/Makefile b/sound/soc/au1x/Makefile
new file mode 100644 (file)
index 0000000..6c6950b
--- /dev/null
@@ -0,0 +1,13 @@
+# Au1200/Au1550 PSC audio
+snd-soc-au1xpsc-dbdma-objs := dbdma2.o
+snd-soc-au1xpsc-i2s-objs := psc-i2s.o
+snd-soc-au1xpsc-ac97-objs := psc-ac97.o
+
+obj-$(CONFIG_SND_SOC_AU1XPSC) += snd-soc-au1xpsc-dbdma.o
+obj-$(CONFIG_SND_SOC_AU1XPSC_I2S) += snd-soc-au1xpsc-i2s.o
+obj-$(CONFIG_SND_SOC_AU1XPSC_AC97) += snd-soc-au1xpsc-ac97.o
+
+# Boards
+snd-soc-sample-ac97-objs := sample-ac97.o
+
+obj-$(CONFIG_SND_SOC_SAMPLE_PSC_AC97) += snd-soc-sample-ac97.o
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
new file mode 100644 (file)
index 0000000..1466d93
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * Au12x0/Au1550 PSC ALSA ASoC audio support.
+ *
+ * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
+ *     Manuel Lauss <mano@roarinelk.homelinux.net>
+ *
+ * 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.
+ *
+ * DMA glue for Au1x-PSC audio.
+ *
+ * NOTE: all of these drivers can only work with a SINGLE instance
+ *      of a PSC. Multiple independent audio devices are impossible
+ *      with ASoC v1.
+ */
+
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+#include <asm/mach-au1x00/au1xxx_psc.h>
+
+#include "psc.h"
+
+/*#define PCM_DEBUG*/
+
+#define MSG(x...)      printk(KERN_INFO "au1xpsc_pcm: " x)
+#ifdef PCM_DEBUG
+#define DBG            MSG
+#else
+#define DBG(x...)      do {} while (0)
+#endif
+
+struct au1xpsc_audio_dmadata {
+       /* DDMA control data */
+       unsigned int ddma_id;           /* DDMA direction ID for this PSC */
+       u32 ddma_chan;                  /* DDMA context */
+
+       /* PCM context (for irq handlers) */
+       struct snd_pcm_substream *substream;
+       unsigned long curr_period;      /* current segment DDMA is working on */
+       unsigned long q_period;         /* queue period(s) */
+       unsigned long dma_area;         /* address of queued DMA area */
+       unsigned long dma_area_s;       /* start address of DMA area */
+       unsigned long pos;              /* current byte position being played */
+       unsigned long periods;          /* number of SG segments in total */
+       unsigned long period_bytes;     /* size in bytes of one SG segment */
+
+       /* runtime data */
+       int msbits;
+};
+
+/* instance data. There can be only one, MacLeod!!!! */
+static struct au1xpsc_audio_dmadata *au1xpsc_audio_pcmdma[2];
+
+/*
+ * These settings are somewhat okay, at least on my machine audio plays
+ * almost skip-free. Especially the 64kB buffer seems to help a LOT.
+ */
+#define AU1XPSC_PERIOD_MIN_BYTES       1024
+#define AU1XPSC_BUFFER_MIN_BYTES       65536
+
+#define AU1XPSC_PCM_FMTS                                       \
+       (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_U8 |        \
+        SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |    \
+        SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE |    \
+        SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |    \
+        SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE |    \
+        0)
+
+/* PCM hardware DMA capabilities - platform specific */
+static const struct snd_pcm_hardware au1xpsc_pcm_hardware = {
+       .info             = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+                           SNDRV_PCM_INFO_INTERLEAVED,
+       .formats          = AU1XPSC_PCM_FMTS,
+       .period_bytes_min = AU1XPSC_PERIOD_MIN_BYTES,
+       .period_bytes_max = 4096 * 1024 - 1,
+       .periods_min      = 2,
+       .periods_max      = 4096,       /* 2 to as-much-as-you-like */
+       .buffer_bytes_max = 4096 * 1024 - 1,
+       .fifo_size        = 16,         /* fifo entries of AC97/I2S PSC */
+};
+
+static void au1x_pcm_queue_tx(struct au1xpsc_audio_dmadata *cd)
+{
+       au1xxx_dbdma_put_source_flags(cd->ddma_chan,
+                               (void *)phys_to_virt(cd->dma_area),
+                               cd->period_bytes, DDMA_FLAGS_IE);
+
+       /* update next-to-queue period */
+       ++cd->q_period;
+       cd->dma_area += cd->period_bytes;
+       if (cd->q_period >= cd->periods) {
+               cd->q_period = 0;
+               cd->dma_area = cd->dma_area_s;
+       }
+}
+
+static void au1x_pcm_queue_rx(struct au1xpsc_audio_dmadata *cd)
+{
+       au1xxx_dbdma_put_dest_flags(cd->ddma_chan,
+                               (void *)phys_to_virt(cd->dma_area),
+                               cd->period_bytes, DDMA_FLAGS_IE);
+
+       /* update next-to-queue period */
+       ++cd->q_period;
+       cd->dma_area += cd->period_bytes;
+       if (cd->q_period >= cd->periods) {
+               cd->q_period = 0;
+               cd->dma_area = cd->dma_area_s;
+       }
+}
+
+static void au1x_pcm_dmatx_cb(int irq, void *dev_id)
+{
+       struct au1xpsc_audio_dmadata *cd = dev_id;
+
+       cd->pos += cd->period_bytes;
+       if (++cd->curr_period >= cd->periods) {
+               cd->pos = 0;
+               cd->curr_period = 0;
+       }
+       snd_pcm_period_elapsed(cd->substream);
+       au1x_pcm_queue_tx(cd);
+}
+
+static void au1x_pcm_dmarx_cb(int irq, void *dev_id)
+{
+       struct au1xpsc_audio_dmadata *cd = dev_id;
+
+       cd->pos += cd->period_bytes;
+       if (++cd->curr_period >= cd->periods) {
+               cd->pos = 0;
+               cd->curr_period = 0;
+       }
+       snd_pcm_period_elapsed(cd->substream);
+       au1x_pcm_queue_rx(cd);
+}
+
+static void au1x_pcm_dbdma_free(struct au1xpsc_audio_dmadata *pcd)
+{
+       if (pcd->ddma_chan) {
+               au1xxx_dbdma_stop(pcd->ddma_chan);
+               au1xxx_dbdma_reset(pcd->ddma_chan);
+               au1xxx_dbdma_chan_free(pcd->ddma_chan);
+               pcd->ddma_chan = 0;
+               pcd->msbits = 0;
+       }
+}
+
+/* in case of missing DMA ring or changed TX-source / RX-dest bit widths,
+ * allocate (or reallocate) a 2-descriptor DMA ring with bit depth according
+ * to ALSA-supplied sample depth.  This is due to limitations in the dbdma api
+ * (cannot adjust source/dest widths of already allocated descriptor ring).
+ */
+static int au1x_pcm_dbdma_realloc(struct au1xpsc_audio_dmadata *pcd,
+                                int stype, int msbits)
+{
+       /* DMA only in 8/16/32 bit widths */
+       if (msbits == 24)
+               msbits = 32;
+
+       /* check current config: correct bits and descriptors allocated? */
+       if ((pcd->ddma_chan) && (msbits == pcd->msbits))
+               goto out;       /* all ok! */
+
+       au1x_pcm_dbdma_free(pcd);
+
+       if (stype == PCM_RX)
+               pcd->ddma_chan = au1xxx_dbdma_chan_alloc(pcd->ddma_id,
+                                       DSCR_CMD0_ALWAYS,
+                                       au1x_pcm_dmarx_cb, (void *)pcd);
+       else
+               pcd->ddma_chan = au1xxx_dbdma_chan_alloc(DSCR_CMD0_ALWAYS,
+                                       pcd->ddma_id,
+                                       au1x_pcm_dmatx_cb, (void *)pcd);
+
+       if (!pcd->ddma_chan)
+               return -ENOMEM;;
+
+       au1xxx_dbdma_set_devwidth(pcd->ddma_chan, msbits);
+       au1xxx_dbdma_ring_alloc(pcd->ddma_chan, 2);
+
+       pcd->msbits = msbits;
+
+       au1xxx_dbdma_stop(pcd->ddma_chan);
+       au1xxx_dbdma_reset(pcd->ddma_chan);
+
+out:
+       return 0;
+}
+
+static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
+                                struct snd_pcm_hw_params *params)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct au1xpsc_audio_dmadata *pcd;
+       int stype, ret;
+
+       ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+       if (ret < 0)
+               goto out;
+
+       stype = SUBSTREAM_TYPE(substream);
+       pcd = au1xpsc_audio_pcmdma[stype];
+
+       DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d "
+           "runtime->min_align %d\n",
+               (unsigned long)runtime->dma_area,
+               (unsigned long)runtime->dma_addr, runtime->dma_bytes,
+               runtime->min_align);
+
+       DBG("bits %d  frags %d  frag_bytes %d  is_rx %d\n", params->msbits,
+               params_periods(params), params_period_bytes(params), stype);
+
+       ret = au1x_pcm_dbdma_realloc(pcd, stype, params->msbits);
+       if (ret) {
+               MSG("DDMA channel (re)alloc failed!\n");
+               goto out;
+       }
+
+       pcd->substream = substream;
+       pcd->period_bytes = params_period_bytes(params);
+       pcd->periods = params_periods(params);
+       pcd->dma_area_s = pcd->dma_area = (unsigned long)runtime->dma_addr;
+       pcd->q_period = 0;
+       pcd->curr_period = 0;
+       pcd->pos = 0;
+
+       ret = 0;
+out:
+       return ret;
+}
+
+static int au1xpsc_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       snd_pcm_lib_free_pages(substream);
+       return 0;
+}
+
+static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct au1xpsc_audio_dmadata *pcd =
+                       au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)];
+
+       au1xxx_dbdma_reset(pcd->ddma_chan);
+
+       if (SUBSTREAM_TYPE(substream) == PCM_RX) {
+               au1x_pcm_queue_rx(pcd);
+               au1x_pcm_queue_rx(pcd);
+       } else {
+               au1x_pcm_queue_tx(pcd);
+               au1x_pcm_queue_tx(pcd);
+       }
+
+       return 0;
+}
+
+static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       u32 c = au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->ddma_chan;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+               au1xxx_dbdma_start(c);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               au1xxx_dbdma_stop(c);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static snd_pcm_uframes_t
+au1xpsc_pcm_pointer(struct snd_pcm_substream *substream)
+{
+       return bytes_to_frames(substream->runtime,
+               au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->pos);
+}
+
+static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
+{
+       snd_soc_set_runtime_hwparams(substream, &au1xpsc_pcm_hardware);
+       return 0;
+}
+
+static int au1xpsc_pcm_close(struct snd_pcm_substream *substream)
+{
+       au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]);
+       return 0;
+}
+
+struct snd_pcm_ops au1xpsc_pcm_ops = {
+       .open           = au1xpsc_pcm_open,
+       .close          = au1xpsc_pcm_close,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .hw_params      = au1xpsc_pcm_hw_params,
+       .hw_free        = au1xpsc_pcm_hw_free,
+       .prepare        = au1xpsc_pcm_prepare,
+       .trigger        = au1xpsc_pcm_trigger,
+       .pointer        = au1xpsc_pcm_pointer,
+};
+
+static void au1xpsc_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+       snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static int au1xpsc_pcm_new(struct snd_card *card,
+                          struct snd_soc_dai *dai,
+                          struct snd_pcm *pcm)
+{
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+               card->dev, AU1XPSC_BUFFER_MIN_BYTES, (4096 * 1024) - 1);
+
+       return 0;
+}
+
+static int au1xpsc_pcm_probe(struct platform_device *pdev)
+{
+       struct resource *r;
+       int ret;
+
+       if (au1xpsc_audio_pcmdma[PCM_TX] || au1xpsc_audio_pcmdma[PCM_RX])
+               return -EBUSY;
+
+       /* TX DMA */
+       au1xpsc_audio_pcmdma[PCM_TX]
+               = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
+       if (!au1xpsc_audio_pcmdma[PCM_TX])
+               return -ENOMEM;
+
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!r) {
+               ret = -ENODEV;
+               goto out1;
+       }
+       (au1xpsc_audio_pcmdma[PCM_TX])->ddma_id = r->start;
+
+       /* RX DMA */
+       au1xpsc_audio_pcmdma[PCM_RX]
+               = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
+       if (!au1xpsc_audio_pcmdma[PCM_RX])
+               return -ENOMEM;
+
+       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!r) {
+               ret = -ENODEV;
+               goto out2;
+       }
+       (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start;
+
+       return 0;
+
+out2:
+       kfree(au1xpsc_audio_pcmdma[PCM_RX]);
+       au1xpsc_audio_pcmdma[PCM_RX] = NULL;
+out1:
+       kfree(au1xpsc_audio_pcmdma[PCM_TX]);
+       au1xpsc_audio_pcmdma[PCM_TX] = NULL;
+       return ret;
+}
+
+static int au1xpsc_pcm_remove(struct platform_device *pdev)
+{
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               if (au1xpsc_audio_pcmdma[i]) {
+                       au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]);
+                       kfree(au1xpsc_audio_pcmdma[i]);
+                       au1xpsc_audio_pcmdma[i] = NULL;
+               }
+       }
+
+       return 0;
+}
+
+/* au1xpsc audio platform */
+struct snd_soc_platform au1xpsc_soc_platform = {
+       .name           = "au1xpsc-pcm-dbdma",
+       .probe          = au1xpsc_pcm_probe,
+       .remove         = au1xpsc_pcm_remove,
+       .pcm_ops        = &au1xpsc_pcm_ops,
+       .pcm_new        = au1xpsc_pcm_new,
+       .pcm_free       = au1xpsc_pcm_free_dma_buffers,
+};
+EXPORT_SYMBOL_GPL(au1xpsc_soc_platform);
+
+static int __init au1xpsc_audio_dbdma_init(void)
+{
+       au1xpsc_audio_pcmdma[PCM_TX] = NULL;
+       au1xpsc_audio_pcmdma[PCM_RX] = NULL;
+       return 0;
+}
+
+static void __exit au1xpsc_audio_dbdma_exit(void)
+{
+}
+
+module_init(au1xpsc_audio_dbdma_init);
+module_exit(au1xpsc_audio_dbdma_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver");
+MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
new file mode 100644 (file)
index 0000000..57facba
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+ * Au12x0/Au1550 PSC ALSA ASoC audio support.
+ *
+ * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
+ *     Manuel Lauss <mano@roarinelk.homelinux.net>
+ *
+ * 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.
+ *
+ * Au1xxx-PSC AC97 glue.
+ *
+ * NOTE: all of these drivers can only work with a SINGLE instance
+ *      of a PSC. Multiple independent audio devices are impossible
+ *      with ASoC v1.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/suspend.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_psc.h>
+
+#include "psc.h"
+
+#define AC97_DIR       \
+       (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
+
+#define AC97_RATES     \
+       SNDRV_PCM_RATE_8000_48000
+
+#define AC97_FMTS      \
+       (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3BE)
+
+#define AC97PCR_START(stype)   \
+       ((stype) == PCM_TX ? PSC_AC97PCR_TS : PSC_AC97PCR_RS)
+#define AC97PCR_STOP(stype)    \
+       ((stype) == PCM_TX ? PSC_AC97PCR_TP : PSC_AC97PCR_RP)
+#define AC97PCR_CLRFIFO(stype) \
+       ((stype) == PCM_TX ? PSC_AC97PCR_TC : PSC_AC97PCR_RC)
+
+/* instance data. There can be only one, MacLeod!!!! */
+static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;
+
+/* AC97 controller reads codec register */
+static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
+                                       unsigned short reg)
+{
+       /* FIXME */
+       struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
+       unsigned short data, tmo;
+
+       au_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg), AC97_CDC(pscdata));
+       au_sync();
+
+       tmo = 1000;
+       while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) && --tmo)
+               udelay(2);
+
+       if (!tmo)
+               data = 0xffff;
+       else
+               data = au_readl(AC97_CDC(pscdata)) & 0xffff;
+
+       au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
+       au_sync();
+
+       return data;
+}
+
+/* AC97 controller writes to codec register */
+static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+                               unsigned short val)
+{
+       /* FIXME */
+       struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
+       unsigned int tmo;
+
+       au_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff), AC97_CDC(pscdata));
+       au_sync();
+       tmo = 1000;
+       while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) && --tmo)
+               au_sync();
+
+       au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
+       au_sync();
+}
+
+/* AC97 controller asserts a warm reset */
+static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)
+{
+       /* FIXME */
+       struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
+
+       au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));
+       au_sync();
+       msleep(10);
+       au_writel(0, AC97_RST(pscdata));
+       au_sync();
+}
+
+static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
+{
+       /* FIXME */
+       struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
+       int i;
+
+       /* disable PSC during cold reset */
+       au_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
+       au_sync();
+       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(pscdata));
+       au_sync();
+
+       /* issue cold reset */
+       au_writel(PSC_AC97RST_RST, AC97_RST(pscdata));
+       au_sync();
+       msleep(500);
+       au_writel(0, AC97_RST(pscdata));
+       au_sync();
+
+       /* enable PSC */
+       au_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
+       au_sync();
+
+       /* wait for PSC to indicate it's ready */
+       i = 100000;
+       while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i))
+               au_sync();
+
+       if (i == 0) {
+               printk(KERN_ERR "au1xpsc-ac97: PSC not ready!\n");
+               return;
+       }
+
+       /* enable the ac97 function */
+       au_writel(pscdata->cfg | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
+       au_sync();
+
+       /* wait for AC97 core to become ready */
+       i = 100000;
+       while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i))
+               au_sync();
+       if (i == 0)
+               printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n");
+}
+
+/* AC97 controller operations */
+struct snd_ac97_bus_ops soc_ac97_ops = {
+       .read           = au1xpsc_ac97_read,
+       .write          = au1xpsc_ac97_write,
+       .reset          = au1xpsc_ac97_cold_reset,
+       .warm_reset     = au1xpsc_ac97_warm_reset,
+};
+EXPORT_SYMBOL_GPL(soc_ac97_ops);
+
+static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
+                                 struct snd_pcm_hw_params *params)
+{
+       /* FIXME */
+       struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
+       unsigned long r, stat;
+       int chans, stype = SUBSTREAM_TYPE(substream);
+
+       chans = params_channels(params);
+
+       r = au_readl(AC97_CFG(pscdata));
+       stat = au_readl(AC97_STAT(pscdata));
+
+       /* already active? */
+       if (stat & (PSC_AC97STAT_TB | PSC_AC97STAT_RB)) {
+               /* reject parameters not currently set up */
+               if ((PSC_AC97CFG_GET_LEN(r) != params->msbits) ||
+                   (pscdata->rate != params_rate(params)))
+                       return -EINVAL;
+       } else {
+               /* disable AC97 device controller first */
+               au_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
+               au_sync();
+
+               /* set sample bitdepth: REG[24:21]=(BITS-2)/2 */
+               r &= ~PSC_AC97CFG_LEN_MASK;
+               r |= PSC_AC97CFG_SET_LEN(params->msbits);
+
+               /* channels: enable slots for front L/R channel */
+               if (stype == PCM_TX) {
+                       r &= ~PSC_AC97CFG_TXSLOT_MASK;
+                       r |= PSC_AC97CFG_TXSLOT_ENA(3);
+                       r |= PSC_AC97CFG_TXSLOT_ENA(4);
+               } else {
+                       r &= ~PSC_AC97CFG_RXSLOT_MASK;
+                       r |= PSC_AC97CFG_RXSLOT_ENA(3);
+                       r |= PSC_AC97CFG_RXSLOT_ENA(4);
+               }
+
+               /* finally enable the AC97 controller again */
+               au_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
+               au_sync();
+
+               pscdata->cfg = r;
+               pscdata->rate = params_rate(params);
+       }
+
+       return 0;
+}
+
+static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
+                               int cmd)
+{
+       /* FIXME */
+       struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
+       int ret, stype = SUBSTREAM_TYPE(substream);
+
+       ret = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+               au_writel(AC97PCR_START(stype), AC97_PCR(pscdata));
+               au_sync();
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               au_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata));
+               au_sync();
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static int au1xpsc_ac97_probe(struct platform_device *pdev,
+                             struct snd_soc_dai *dai)
+{
+       int ret;
+       struct resource *r;
+       unsigned long sel;
+
+       if (au1xpsc_ac97_workdata)
+               return -EBUSY;
+
+       au1xpsc_ac97_workdata =
+               kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
+       if (!au1xpsc_ac97_workdata)
+               return -ENOMEM;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r) {
+               ret = -ENODEV;
+               goto out0;
+       }
+
+       ret = -EBUSY;
+       au1xpsc_ac97_workdata->ioarea =
+               request_mem_region(r->start, r->end - r->start + 1,
+                                       "au1xpsc_ac97");
+       if (!au1xpsc_ac97_workdata->ioarea)
+               goto out0;
+
+       au1xpsc_ac97_workdata->mmio = ioremap(r->start, 0xffff);
+       if (!au1xpsc_ac97_workdata->mmio)
+               goto out1;
+
+       /* configuration: max dma trigger threshold, enable ac97 */
+        au1xpsc_ac97_workdata->cfg = PSC_AC97CFG_RT_FIFO8 |
+                                     PSC_AC97CFG_TT_FIFO8 |
+                                     PSC_AC97CFG_DE_ENABLE;
+
+       /* preserve PSC clock source set up by platform (dev.platform_data
+        * is already occupied by soc layer)
+        */
+       sel = au_readl(PSC_SEL(au1xpsc_ac97_workdata)) & PSC_SEL_CLK_MASK;
+       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata));
+       au_sync();
+       au_writel(0, PSC_SEL(au1xpsc_ac97_workdata));
+       au_sync();
+       au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(au1xpsc_ac97_workdata));
+       au_sync();
+       /* next up: cold reset.  Dont check for PSC-ready now since
+        * there may not be any codec clock yet.
+        */
+
+       return 0;
+
+out1:
+       release_resource(au1xpsc_ac97_workdata->ioarea);
+       kfree(au1xpsc_ac97_workdata->ioarea);
+out0:
+       kfree(au1xpsc_ac97_workdata);
+       au1xpsc_ac97_workdata = NULL;
+       return ret;
+}
+
+static void au1xpsc_ac97_remove(struct platform_device *pdev,
+                               struct snd_soc_dai *dai)
+{
+       /* disable PSC completely */
+       au_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
+       au_sync();
+       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata));
+       au_sync();
+
+       iounmap(au1xpsc_ac97_workdata->mmio);
+       release_resource(au1xpsc_ac97_workdata->ioarea);
+       kfree(au1xpsc_ac97_workdata->ioarea);
+       kfree(au1xpsc_ac97_workdata);
+       au1xpsc_ac97_workdata = NULL;
+}
+
+static int au1xpsc_ac97_suspend(struct platform_device *pdev,
+                               struct snd_soc_dai *dai)
+{
+       /* save interesting registers and disable PSC */
+       au1xpsc_ac97_workdata->pm[0] =
+                       au_readl(PSC_SEL(au1xpsc_ac97_workdata));
+
+       au_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
+       au_sync();
+       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata));
+       au_sync();
+
+       return 0;
+}
+
+static int au1xpsc_ac97_resume(struct platform_device *pdev,
+                              struct snd_soc_dai *dai)
+{
+       /* restore PSC clock config */
+       au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE,
+                       PSC_SEL(au1xpsc_ac97_workdata));
+       au_sync();
+
+       /* after this point the ac97 core will cold-reset the codec.
+        * During cold-reset the PSC is reinitialized and the last
+        * configuration set up in hw_params() is restored.
+        */
+       return 0;
+}
+
+struct snd_soc_dai au1xpsc_ac97_dai = {
+       .name                   = "au1xpsc_ac97",
+       .type                   = SND_SOC_DAI_AC97,
+       .probe                  = au1xpsc_ac97_probe,
+       .remove                 = au1xpsc_ac97_remove,
+       .suspend                = au1xpsc_ac97_suspend,
+       .resume                 = au1xpsc_ac97_resume,
+       .playback = {
+               .rates          = AC97_RATES,
+               .formats        = AC97_FMTS,
+               .channels_min   = 2,
+               .channels_max   = 2,
+       },
+       .capture = {
+               .rates          = AC97_RATES,
+               .formats        = AC97_FMTS,
+               .channels_min   = 2,
+               .channels_max   = 2,
+       },
+       .ops = {
+               .trigger        = au1xpsc_ac97_trigger,
+               .hw_params      = au1xpsc_ac97_hw_params,
+       },
+};
+EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
+
+static int __init au1xpsc_ac97_init(void)
+{
+       au1xpsc_ac97_workdata = NULL;
+       return 0;
+}
+
+static void __exit au1xpsc_ac97_exit(void)
+{
+}
+
+module_init(au1xpsc_ac97_init);
+module_exit(au1xpsc_ac97_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver");
+MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
new file mode 100644 (file)
index 0000000..ba4b5c1
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * Au12x0/Au1550 PSC ALSA ASoC audio support.
+ *
+ * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
+ *     Manuel Lauss <mano@roarinelk.homelinux.net>
+ *
+ * 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.
+ *
+ * Au1xxx-PSC I2S glue.
+ *
+ * NOTE: all of these drivers can only work with a SINGLE instance
+ *      of a PSC. Multiple independent audio devices are impossible
+ *      with ASoC v1.
+ * NOTE: so far only PSC slave mode (bit- and frameclock) is supported.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/suspend.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_psc.h>
+
+#include "psc.h"
+
+/* supported I2S DAI hardware formats */
+#define AU1XPSC_I2S_DAIFMT \
+       (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J |   \
+        SND_SOC_DAIFMT_NB_NF)
+
+/* supported I2S direction */
+#define AU1XPSC_I2S_DIR \
+       (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
+
+#define AU1XPSC_I2S_RATES \
+       SNDRV_PCM_RATE_8000_192000
+
+#define AU1XPSC_I2S_FMTS \
+       (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
+
+#define I2SSTAT_BUSY(stype)    \
+       ((stype) == PCM_TX ? PSC_I2SSTAT_TB : PSC_I2SSTAT_RB)
+#define I2SPCR_START(stype)    \
+       ((stype) == PCM_TX ? PSC_I2SPCR_TS : PSC_I2SPCR_RS)
+#define I2SPCR_STOP(stype)     \
+       ((stype) == PCM_TX ? PSC_I2SPCR_TP : PSC_I2SPCR_RP)
+#define I2SPCR_CLRFIFO(stype)  \
+       ((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC)
+
+
+/* instance data. There can be only one, MacLeod!!!! */
+static struct au1xpsc_audio_data *au1xpsc_i2s_workdata;
+
+static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
+                              unsigned int fmt)
+{
+       struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
+       unsigned long ct;
+       int ret;
+
+       ret = -EINVAL;
+
+       ct = pscdata->cfg;
+
+       ct &= ~(PSC_I2SCFG_XM | PSC_I2SCFG_MLJ);        /* left-justified */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               ct |= PSC_I2SCFG_XM;    /* enable I2S mode */
+               break;
+       case SND_SOC_DAIFMT_MSB:
+               break;
+       case SND_SOC_DAIFMT_LSB:
+               ct |= PSC_I2SCFG_MLJ;   /* LSB (right-) justified */
+               break;
+       default:
+               goto out;
+       }
+
+       ct &= ~(PSC_I2SCFG_BI | PSC_I2SCFG_WI);         /* IB-IF */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               ct |= PSC_I2SCFG_BI | PSC_I2SCFG_WI;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               ct |= PSC_I2SCFG_BI;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               ct |= PSC_I2SCFG_WI;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               break;
+       default:
+               goto out;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:    /* CODEC master */
+               ct |= PSC_I2SCFG_MS;    /* PSC I2S slave mode */
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:    /* CODEC slave */
+               ct &= ~PSC_I2SCFG_MS;   /* PSC I2S Master mode */
+               break;
+       default:
+               goto out;
+       }
+
+       pscdata->cfg = ct;
+       ret = 0;
+out:
+       return ret;
+}
+
+static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream,
+                                struct snd_pcm_hw_params *params)
+{
+       struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
+
+       int cfgbits;
+       unsigned long stat;
+
+       /* check if the PSC is already streaming data */
+       stat = au_readl(I2S_STAT(pscdata));
+       if (stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB)) {
+               /* reject parameters not currently set up in hardware */
+               cfgbits = au_readl(I2S_CFG(pscdata));
+               if ((PSC_I2SCFG_GET_LEN(cfgbits) != params->msbits) ||
+                   (params_rate(params) != pscdata->rate))
+                       return -EINVAL;
+       } else {
+               /* set sample bitdepth */
+               pscdata->cfg &= ~(0x1f << 4);
+               pscdata->cfg |= PSC_I2SCFG_SET_LEN(params->msbits);
+               /* remember current rate for other stream */
+               pscdata->rate = params_rate(params);
+       }
+       return 0;
+}
+
+/* Configure PSC late:  on my devel systems the codec  is I2S master and
+ * supplies the i2sbitclock __AND__ i2sMclk (!) to the PSC unit.  ASoC
+ * uses aggressive PM and  switches the codec off  when it is not in use
+ * which also means the PSC unit doesn't get any clocks and is therefore
+ * dead. That's why this chunk here gets called from the trigger callback
+ * because I can be reasonably certain the codec is driving the clocks.
+ */
+static int au1xpsc_i2s_configure(struct au1xpsc_audio_data *pscdata)
+{
+       unsigned long tmo;
+
+       /* bring PSC out of sleep, and configure I2S unit */
+       au_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
+       au_sync();
+
+       tmo = 1000000;
+       while (!(au_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_SR) && tmo)
+               tmo--;
+
+       if (!tmo)
+               goto psc_err;
+
+       au_writel(0, I2S_CFG(pscdata));
+       au_sync();
+       au_writel(pscdata->cfg | PSC_I2SCFG_DE_ENABLE, I2S_CFG(pscdata));
+       au_sync();
+
+       /* wait for I2S controller to become ready */
+       tmo = 1000000;
+       while (!(au_readl(I2S_STAT(pscdata)) & PSC_I2SSTAT_DR) && tmo)
+               tmo--;
+
+       if (tmo)
+               return 0;
+
+psc_err:
+       au_writel(0, I2S_CFG(pscdata));
+       au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
+       au_sync();
+       return -ETIMEDOUT;
+}
+
+static int au1xpsc_i2s_start(struct au1xpsc_audio_data *pscdata, int stype)
+{
+       unsigned long tmo, stat;
+       int ret;
+
+       ret = 0;
+
+       /* if both TX and RX are idle, configure the PSC  */
+       stat = au_readl(I2S_STAT(pscdata));
+       if (!(stat & (PSC_I2SSTAT_TB | PSC_I2SSTAT_RB))) {
+               ret = au1xpsc_i2s_configure(pscdata);
+               if (ret)
+                       goto out;
+       }
+
+       au_writel(I2SPCR_CLRFIFO(stype), I2S_PCR(pscdata));
+       au_sync();
+       au_writel(I2SPCR_START(stype), I2S_PCR(pscdata));
+       au_sync();
+
+       /* wait for start confirmation */
+       tmo = 1000000;
+       while (!(au_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
+               tmo--;
+
+       if (!tmo) {
+               au_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
+               au_sync();
+               ret = -ETIMEDOUT;
+       }
+out:
+       return ret;
+}
+
+static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype)
+{
+       unsigned long tmo, stat;
+
+       au_writel(I2SPCR_STOP(stype), I2S_PCR(pscdata));
+       au_sync();
+
+       /* wait for stop confirmation */
+       tmo = 1000000;
+       while ((au_readl(I2S_STAT(pscdata)) & I2SSTAT_BUSY(stype)) && tmo)
+               tmo--;
+
+       /* if both TX and RX are idle, disable PSC */
+       stat = au_readl(I2S_STAT(pscdata));
+       if (!(stat & (PSC_I2SSTAT_RB | PSC_I2SSTAT_RB))) {
+               au_writel(0, I2S_CFG(pscdata));
+               au_sync();
+               au_writel(PSC_CTRL_SUSPEND, PSC_CTRL(pscdata));
+               au_sync();
+       }
+       return 0;
+}
+
+static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
+       int ret, stype = SUBSTREAM_TYPE(substream);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+               ret = au1xpsc_i2s_start(pscdata, stype);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               ret = au1xpsc_i2s_stop(pscdata, stype);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static int au1xpsc_i2s_probe(struct platform_device *pdev,
+                            struct snd_soc_dai *dai)
+{
+       struct resource *r;
+       unsigned long sel;
+       int ret;
+
+       if (au1xpsc_i2s_workdata)
+               return -EBUSY;
+
+       au1xpsc_i2s_workdata =
+               kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
+       if (!au1xpsc_i2s_workdata)
+               return -ENOMEM;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r) {
+               ret = -ENODEV;
+               goto out0;
+       }
+
+       ret = -EBUSY;
+       au1xpsc_i2s_workdata->ioarea =
+               request_mem_region(r->start, r->end - r->start + 1,
+                                       "au1xpsc_i2s");
+       if (!au1xpsc_i2s_workdata->ioarea)
+               goto out0;
+
+       au1xpsc_i2s_workdata->mmio = ioremap(r->start, 0xffff);
+       if (!au1xpsc_i2s_workdata->mmio)
+               goto out1;
+
+       /* preserve PSC clock source set up by platform (dev.platform_data
+        * is already occupied by soc layer)
+        */
+       sel = au_readl(PSC_SEL(au1xpsc_i2s_workdata)) & PSC_SEL_CLK_MASK;
+       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata));
+       au_sync();
+       au_writel(PSC_SEL_PS_I2SMODE | sel, PSC_SEL(au1xpsc_i2s_workdata));
+       au_writel(0, I2S_CFG(au1xpsc_i2s_workdata));
+       au_sync();
+
+       /* preconfigure: set max rx/tx fifo depths */
+       au1xpsc_i2s_workdata->cfg |=
+                       PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8;
+
+       /* don't wait for I2S core to become ready now; clocks may not
+        * be running yet; depending on clock input for PSC a wait might
+        * time out.
+        */
+
+       return 0;
+
+out1:
+       release_resource(au1xpsc_i2s_workdata->ioarea);
+       kfree(au1xpsc_i2s_workdata->ioarea);
+out0:
+       kfree(au1xpsc_i2s_workdata);
+       au1xpsc_i2s_workdata = NULL;
+       return ret;
+}
+
+static void au1xpsc_i2s_remove(struct platform_device *pdev,
+                              struct snd_soc_dai *dai)
+{
+       au_writel(0, I2S_CFG(au1xpsc_i2s_workdata));
+       au_sync();
+       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata));
+       au_sync();
+
+       iounmap(au1xpsc_i2s_workdata->mmio);
+       release_resource(au1xpsc_i2s_workdata->ioarea);
+       kfree(au1xpsc_i2s_workdata->ioarea);
+       kfree(au1xpsc_i2s_workdata);
+       au1xpsc_i2s_workdata = NULL;
+}
+
+static int au1xpsc_i2s_suspend(struct platform_device *pdev,
+                              struct snd_soc_dai *cpu_dai)
+{
+       /* save interesting register and disable PSC */
+       au1xpsc_i2s_workdata->pm[0] =
+               au_readl(PSC_SEL(au1xpsc_i2s_workdata));
+
+       au_writel(0, I2S_CFG(au1xpsc_i2s_workdata));
+       au_sync();
+       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata));
+       au_sync();
+
+       return 0;
+}
+
+static int au1xpsc_i2s_resume(struct platform_device *pdev,
+                             struct snd_soc_dai *cpu_dai)
+{
+       /* select I2S mode and PSC clock */
+       au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata));
+       au_sync();
+       au_writel(0, PSC_SEL(au1xpsc_i2s_workdata));
+       au_sync();
+       au_writel(au1xpsc_i2s_workdata->pm[0],
+                       PSC_SEL(au1xpsc_i2s_workdata));
+       au_sync();
+
+       return 0;
+}
+
+struct snd_soc_dai au1xpsc_i2s_dai = {
+       .name                   = "au1xpsc_i2s",
+       .type                   = SND_SOC_DAI_I2S,
+       .probe                  = au1xpsc_i2s_probe,
+       .remove                 = au1xpsc_i2s_remove,
+       .suspend                = au1xpsc_i2s_suspend,
+       .resume                 = au1xpsc_i2s_resume,
+       .playback = {
+               .rates          = AU1XPSC_I2S_RATES,
+               .formats        = AU1XPSC_I2S_FMTS,
+               .channels_min   = 2,
+               .channels_max   = 8,    /* 2 without external help */
+       },
+       .capture = {
+               .rates          = AU1XPSC_I2S_RATES,
+               .formats        = AU1XPSC_I2S_FMTS,
+               .channels_min   = 2,
+               .channels_max   = 8,    /* 2 without external help */
+       },
+       .ops = {
+               .trigger        = au1xpsc_i2s_trigger,
+               .hw_params      = au1xpsc_i2s_hw_params,
+       },
+       .dai_ops = {
+               .set_fmt        = au1xpsc_i2s_set_fmt,
+       },
+};
+EXPORT_SYMBOL(au1xpsc_i2s_dai);
+
+static int __init au1xpsc_i2s_init(void)
+{
+       au1xpsc_i2s_workdata = NULL;
+       return 0;
+}
+
+static void __exit au1xpsc_i2s_exit(void)
+{
+}
+
+module_init(au1xpsc_i2s_init);
+module_exit(au1xpsc_i2s_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Au12x0/Au1550 PSC I2S ALSA ASoC audio driver");
+MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h
new file mode 100644 (file)
index 0000000..8fdb1a0
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Au12x0/Au1550 PSC ALSA ASoC audio support.
+ *
+ * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
+ *     Manuel Lauss <mano@roarinelk.homelinux.net>
+ *
+ * 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.
+ *
+ * NOTE: all of these drivers can only work with a SINGLE instance
+ *      of a PSC. Multiple independent audio devices are impossible
+ *      with ASoC v1.
+ */
+
+#ifndef _AU1X_PCM_H
+#define _AU1X_PCM_H
+
+extern struct snd_soc_dai au1xpsc_ac97_dai;
+extern struct snd_soc_dai au1xpsc_i2s_dai;
+extern struct snd_soc_platform au1xpsc_soc_platform;
+extern struct snd_ac97_bus_ops soc_ac97_ops;
+
+struct au1xpsc_audio_data {
+       void __iomem *mmio;
+
+       unsigned long cfg;
+       unsigned long rate;
+
+       unsigned long pm[2];
+       struct resource *ioarea;
+};
+
+#define PCM_TX 0
+#define PCM_RX 1
+
+#define SUBSTREAM_TYPE(substream) \
+       ((substream)->stream == SNDRV_PCM_STREAM_PLAYBACK ? PCM_TX : PCM_RX)
+
+/* easy access macros */
+#define PSC_CTRL(x)    ((unsigned long)((x)->mmio) + PSC_CTRL_OFFSET)
+#define PSC_SEL(x)     ((unsigned long)((x)->mmio) + PSC_SEL_OFFSET)
+#define I2S_STAT(x)    ((unsigned long)((x)->mmio) + PSC_I2SSTAT_OFFSET)
+#define I2S_CFG(x)     ((unsigned long)((x)->mmio) + PSC_I2SCFG_OFFSET)
+#define I2S_PCR(x)     ((unsigned long)((x)->mmio) + PSC_I2SPCR_OFFSET)
+#define AC97_CFG(x)    ((unsigned long)((x)->mmio) + PSC_AC97CFG_OFFSET)
+#define AC97_CDC(x)    ((unsigned long)((x)->mmio) + PSC_AC97CDC_OFFSET)
+#define AC97_EVNT(x)   ((unsigned long)((x)->mmio) + PSC_AC97EVNT_OFFSET)
+#define AC97_PCR(x)    ((unsigned long)((x)->mmio) + PSC_AC97PCR_OFFSET)
+#define AC97_RST(x)    ((unsigned long)((x)->mmio) + PSC_AC97RST_OFFSET)
+#define AC97_STAT(x)   ((unsigned long)((x)->mmio) + PSC_AC97STAT_OFFSET)
+
+#endif
diff --git a/sound/soc/au1x/sample-ac97.c b/sound/soc/au1x/sample-ac97.c
new file mode 100644 (file)
index 0000000..f75ae7f
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Sample Au12x0/Au1550 PSC AC97 sound machine.
+ *
+ * Copyright (c) 2007-2008 Manuel Lauss <mano@roarinelk.homelinux.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms outlined in the file COPYING at the root of this
+ *  source archive.
+ *
+ * This is a very generic AC97 sound machine driver for boards which
+ * have (AC97) audio at PSC1 (e.g. DB1200 demoboards).
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1xxx_psc.h>
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
+
+#include "../codecs/ac97.h"
+#include "psc.h"
+
+static int au1xpsc_sample_ac97_init(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_sync(codec);
+       return 0;
+}
+
+static struct snd_soc_dai_link au1xpsc_sample_ac97_dai = {
+       .name           = "AC97",
+       .stream_name    = "AC97 HiFi",
+       .cpu_dai        = &au1xpsc_ac97_dai,    /* see psc-ac97.c */
+       .codec_dai      = &ac97_dai,            /* see codecs/ac97.c */
+       .init           = au1xpsc_sample_ac97_init,
+       .ops            = NULL,
+};
+
+static struct snd_soc_machine au1xpsc_sample_ac97_machine = {
+       .name           = "Au1xxx PSC AC97 Audio",
+       .dai_link       = &au1xpsc_sample_ac97_dai,
+       .num_links      = 1,
+};
+
+static struct snd_soc_device au1xpsc_sample_ac97_devdata = {
+       .machine        = &au1xpsc_sample_ac97_machine,
+       .platform       = &au1xpsc_soc_platform, /* see dbdma2.c */
+       .codec_dev      = &soc_codec_dev_ac97,
+};
+
+static struct resource au1xpsc_psc1_res[] = {
+       [0] = {
+               .start  = CPHYSADDR(PSC1_BASE_ADDR),
+               .end    = CPHYSADDR(PSC1_BASE_ADDR) + 0x000fffff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+#ifdef CONFIG_SOC_AU1200
+               .start  = AU1200_PSC1_INT,
+               .end    = AU1200_PSC1_INT,
+#elif defined(CONFIG_SOC_AU1550)
+               .start  = AU1550_PSC1_INT,
+               .end    = AU1550_PSC1_INT,
+#endif
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               .start  = DSCR_CMD0_PSC1_TX,
+               .end    = DSCR_CMD0_PSC1_TX,
+               .flags  = IORESOURCE_DMA,
+       },
+       [3] = {
+               .start  = DSCR_CMD0_PSC1_RX,
+               .end    = DSCR_CMD0_PSC1_RX,
+               .flags  = IORESOURCE_DMA,
+       },
+};
+
+static struct platform_device *au1xpsc_sample_ac97_dev;
+
+static int __init au1xpsc_sample_ac97_load(void)
+{
+       int ret;
+
+#ifdef CONFIG_SOC_AU1200
+       unsigned long io;
+
+       /* modify sys_pinfunc for AC97 on PSC1 */
+       io = au_readl(SYS_PINFUNC);
+       io |= SYS_PINFUNC_P1C;
+       io &= ~(SYS_PINFUNC_P1A | SYS_PINFUNC_P1B);
+       au_writel(io, SYS_PINFUNC);
+       au_sync();
+#endif
+
+       ret = -ENOMEM;
+
+       /* setup PSC clock source for AC97 part: external clock provided
+        * by codec.  The psc-ac97.c driver depends on this setting!
+        */
+       au_writel(PSC_SEL_CLK_SERCLK, PSC1_BASE_ADDR + PSC_SEL_OFFSET);
+       au_sync();
+
+       au1xpsc_sample_ac97_dev = platform_device_alloc("soc-audio", -1);
+       if (!au1xpsc_sample_ac97_dev)
+               goto out;
+
+       au1xpsc_sample_ac97_dev->resource =
+               kmemdup(au1xpsc_psc1_res, sizeof(struct resource) *
+                       ARRAY_SIZE(au1xpsc_psc1_res), GFP_KERNEL);
+       au1xpsc_sample_ac97_dev->num_resources = ARRAY_SIZE(au1xpsc_psc1_res);
+       au1xpsc_sample_ac97_dev->id = 1;
+
+       platform_set_drvdata(au1xpsc_sample_ac97_dev,
+                            &au1xpsc_sample_ac97_devdata);
+       au1xpsc_sample_ac97_devdata.dev = &au1xpsc_sample_ac97_dev->dev;
+       ret = platform_device_add(au1xpsc_sample_ac97_dev);
+
+       if (ret) {
+               platform_device_put(au1xpsc_sample_ac97_dev);
+               au1xpsc_sample_ac97_dev = NULL;
+       }
+
+out:
+       return ret;
+}
+
+static void __exit au1xpsc_sample_ac97_exit(void)
+{
+       platform_device_unregister(au1xpsc_sample_ac97_dev);
+}
+
+module_init(au1xpsc_sample_ac97_load);
+module_exit(au1xpsc_sample_ac97_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Au1xxx PSC sample AC97 machine");
+MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
index 3903ab7dfa4a78ea2e3eebcbf8526f832b5ebdc4..1db04a28a53d46c7732401a2375ea904db158af6 100644 (file)
@@ -1,31 +1,37 @@
 config SND_SOC_AC97_CODEC
        tristate
-       depends on SND_SOC
+       select SND_AC97_CODEC
+
+config SND_SOC_AK4535
+       tristate
+
+config SND_SOC_UDA1380
+        tristate
+
+config SND_SOC_WM8510
+       tristate
 
 config SND_SOC_WM8731
        tristate
-       depends on SND_SOC
 
 config SND_SOC_WM8750
        tristate
-       depends on SND_SOC
 
 config SND_SOC_WM8753
        tristate
-       depends on SND_SOC
+
+config SND_SOC_WM8990
+       tristate
 
 config SND_SOC_WM9712
        tristate
-       depends on SND_SOC
 
 config SND_SOC_WM9713
        tristate
-       depends on SND_SOC
 
 # Cirrus Logic CS4270 Codec
 config SND_SOC_CS4270
        tristate
-       depends on SND_SOC
 
 # Cirrus Logic CS4270 Codec Hardware Mute Support
 # Select if you have external muting circuitry attached to your CS4270.
@@ -43,4 +49,4 @@ config SND_SOC_CS4270_VD33_ERRATA
 
 config SND_SOC_TLV320AIC3X
        tristate
-       depends on SND_SOC && I2C
+       depends on I2C
index 4e1314c9d3ecc44bd8228d383a3d9688bcf9dc45..d7b97abcf7291cea11e2ea29a3c687551f241b4f 100644 (file)
@@ -1,16 +1,24 @@
 snd-soc-ac97-objs := ac97.o
+snd-soc-ak4535-objs := ak4535.o
+snd-soc-uda1380-objs := uda1380.o
+snd-soc-wm8510-objs := wm8510.o
 snd-soc-wm8731-objs := wm8731.o
 snd-soc-wm8750-objs := wm8750.o
 snd-soc-wm8753-objs := wm8753.o
+snd-soc-wm8990-objs := wm8990.o
 snd-soc-wm9712-objs := wm9712.o
 snd-soc-wm9713-objs := wm9713.o
 snd-soc-cs4270-objs := cs4270.o
 snd-soc-tlv320aic3x-objs := tlv320aic3x.o
 
 obj-$(CONFIG_SND_SOC_AC97_CODEC)       += snd-soc-ac97.o
+obj-$(CONFIG_SND_SOC_AK4535)   += snd-soc-ak4535.o
+obj-$(CONFIG_SND_SOC_UDA1380)  += snd-soc-uda1380.o
+obj-$(CONFIG_SND_SOC_WM8510)   += snd-soc-wm8510.o
 obj-$(CONFIG_SND_SOC_WM8731)   += snd-soc-wm8731.o
 obj-$(CONFIG_SND_SOC_WM8750)   += snd-soc-wm8750.o
 obj-$(CONFIG_SND_SOC_WM8753)   += snd-soc-wm8753.o
+obj-$(CONFIG_SND_SOC_WM8990)   += snd-soc-wm8990.o
 obj-$(CONFIG_SND_SOC_WM9712)   += snd-soc-wm9712.o
 obj-$(CONFIG_SND_SOC_WM9713)   += snd-soc-wm9713.o
 obj-$(CONFIG_SND_SOC_CS4270)   += snd-soc-cs4270.o
index 2a1ffe39690887efcd9e5ea66628fca8e8d4d531..61fd96ca7bc782588e17655ebd8dd12887837e75 100644 (file)
@@ -10,9 +10,6 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  *
- *  Revision history
- *    17th Oct 2005   Initial version.
- *
  * Generic AC97 support.
  */
 
@@ -24,6 +21,7 @@
 #include <sound/ac97_codec.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
+#include "ac97.h"
 
 #define AC97_VERSION "0.6"
 
@@ -43,7 +41,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream)
                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
                SNDRV_PCM_RATE_48000)
 
-struct snd_soc_codec_dai ac97_dai = {
+struct snd_soc_dai ac97_dai = {
        .name = "AC97 HiFi",
        .type = SND_SOC_DAI_AC97,
        .playback = {
@@ -146,9 +144,34 @@ static int ac97_soc_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+       snd_ac97_suspend(socdev->codec->ac97);
+
+       return 0;
+}
+
+static int ac97_soc_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+       snd_ac97_resume(socdev->codec->ac97);
+
+       return 0;
+}
+#else
+#define ac97_soc_suspend NULL
+#define ac97_soc_resume NULL
+#endif
+
 struct snd_soc_codec_device soc_codec_dev_ac97 = {
        .probe =        ac97_soc_probe,
        .remove =       ac97_soc_remove,
+       .suspend =      ac97_soc_suspend,
+       .resume =       ac97_soc_resume,
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
 
index 2bf6d69fd0692c204f3a3126edf3eb34ef39249a..281aa42e2bbb95c055ed0a48270a3a83a46d991e 100644 (file)
@@ -14,6 +14,6 @@
 #define __LINUX_SND_SOC_AC97_H
 
 extern struct snd_soc_codec_device soc_codec_dev_ac97;
-extern struct snd_soc_codec_dai ac97_dai;
+extern struct snd_soc_dai ac97_dai;
 
 #endif
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
new file mode 100644 (file)
index 0000000..b26003c
--- /dev/null
@@ -0,0 +1,696 @@
+/*
+ * ak4535.c  --  AK4535 ALSA Soc Audio driver
+ *
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <richard@openedhand.com>
+ *
+ * Based on wm8753.c by Liam Girdwood
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include "ak4535.h"
+
+#define AUDIO_NAME "ak4535"
+#define AK4535_VERSION "0.3"
+
+struct snd_soc_codec_device soc_codec_dev_ak4535;
+
+/* codec private data */
+struct ak4535_priv {
+       unsigned int sysclk;
+};
+
+/*
+ * ak4535 register cache
+ */
+static const u16 ak4535_reg[AK4535_CACHEREGNUM] = {
+    0x0000, 0x0080, 0x0000, 0x0003,
+    0x0002, 0x0000, 0x0011, 0x0001,
+    0x0000, 0x0040, 0x0036, 0x0010,
+    0x0000, 0x0000, 0x0057, 0x0000,
+};
+
+/*
+ * read ak4535 register cache
+ */
+static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec,
+       unsigned int reg)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg >= AK4535_CACHEREGNUM)
+               return -1;
+       return cache[reg];
+}
+
+static inline unsigned int ak4535_read(struct snd_soc_codec *codec,
+       unsigned int reg)
+{
+       u8 data;
+       data = reg;
+
+       if (codec->hw_write(codec->control_data, &data, 1) != 1)
+               return -EIO;
+
+       if (codec->hw_read(codec->control_data, &data, 1) != 1)
+               return -EIO;
+
+       return data;
+};
+
+/*
+ * write ak4535 register cache
+ */
+static inline void ak4535_write_reg_cache(struct snd_soc_codec *codec,
+       u16 reg, unsigned int value)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg >= AK4535_CACHEREGNUM)
+               return;
+       cache[reg] = value;
+}
+
+/*
+ * write to the AK4535 register space
+ */
+static int ak4535_write(struct snd_soc_codec *codec, unsigned int reg,
+       unsigned int value)
+{
+       u8 data[2];
+
+       /* data is
+        *   D15..D8 AK4535 register offset
+        *   D7...D0 register data
+        */
+       data[0] = reg & 0xff;
+       data[1] = value & 0xff;
+
+       ak4535_write_reg_cache(codec, reg, value);
+       if (codec->hw_write(codec->control_data, data, 2) == 2)
+               return 0;
+       else
+               return -EIO;
+}
+
+static int ak4535_sync(struct snd_soc_codec *codec)
+{
+       u16 *cache = codec->reg_cache;
+       int i, r = 0;
+
+       for (i = 0; i < AK4535_CACHEREGNUM; i++)
+               r |= ak4535_write(codec, i, cache[i]);
+
+       return r;
+};
+
+static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"};
+static const char *ak4535_mono_out[] = {"(L + R)/2", "Hi-Z"};
+static const char *ak4535_hp_out[] = {"Stereo", "Mono"};
+static const char *ak4535_deemp[] = {"44.1kHz", "Off", "48kHz", "32kHz"};
+static const char *ak4535_mic_select[] = {"Internal", "External"};
+
+static const struct soc_enum ak4535_enum[] = {
+       SOC_ENUM_SINGLE(AK4535_SIG1, 7, 2, ak4535_mono_gain),
+       SOC_ENUM_SINGLE(AK4535_SIG1, 6, 2, ak4535_mono_out),
+       SOC_ENUM_SINGLE(AK4535_MODE2, 2, 2, ak4535_hp_out),
+       SOC_ENUM_SINGLE(AK4535_DAC, 0, 4, ak4535_deemp),
+       SOC_ENUM_SINGLE(AK4535_MIC, 1, 2, ak4535_mic_select),
+};
+
+static const struct snd_kcontrol_new ak4535_snd_controls[] = {
+       SOC_SINGLE("ALC2 Switch", AK4535_SIG1, 1, 1, 0),
+       SOC_ENUM("Mono 1 Output", ak4535_enum[1]),
+       SOC_ENUM("Mono 1 Gain", ak4535_enum[0]),
+       SOC_ENUM("Headphone Output", ak4535_enum[2]),
+       SOC_ENUM("Playback Deemphasis", ak4535_enum[3]),
+       SOC_SINGLE("Bass Volume", AK4535_DAC, 2, 3, 0),
+       SOC_SINGLE("Mic Boost (+20dB) Switch", AK4535_MIC, 0, 1, 0),
+       SOC_ENUM("Mic Select", ak4535_enum[4]),
+       SOC_SINGLE("ALC Operation Time", AK4535_TIMER, 0, 3, 0),
+       SOC_SINGLE("ALC Recovery Time", AK4535_TIMER, 2, 3, 0),
+       SOC_SINGLE("ALC ZC Time", AK4535_TIMER, 4, 3, 0),
+       SOC_SINGLE("ALC 1 Switch", AK4535_ALC1, 5, 1, 0),
+       SOC_SINGLE("ALC 2 Switch", AK4535_ALC1, 6, 1, 0),
+       SOC_SINGLE("ALC Volume", AK4535_ALC2, 0, 127, 0),
+       SOC_SINGLE("Capture Volume", AK4535_PGA, 0, 127, 0),
+       SOC_SINGLE("Left Playback Volume", AK4535_LATT, 0, 127, 1),
+       SOC_SINGLE("Right Playback Volume", AK4535_RATT, 0, 127, 1),
+       SOC_SINGLE("AUX Bypass Volume", AK4535_VOL, 0, 15, 0),
+       SOC_SINGLE("Mic Sidetone Volume", AK4535_VOL, 4, 7, 0),
+};
+
+/* add non dapm controls */
+static int ak4535_add_controls(struct snd_soc_codec *codec)
+{
+       int err, i;
+
+       for (i = 0; i < ARRAY_SIZE(ak4535_snd_controls); i++) {
+               err = snd_ctl_add(codec->card,
+                       snd_soc_cnew(&ak4535_snd_controls[i], codec, NULL));
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
+/* Mono 1 Mixer */
+static const struct snd_kcontrol_new ak4535_mono1_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG1, 4, 1, 0),
+       SOC_DAPM_SINGLE("Mono Playback Switch", AK4535_SIG1, 5, 1, 0),
+};
+
+/* Stereo Mixer */
+static const struct snd_kcontrol_new ak4535_stereo_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Mic Sidetone Switch", AK4535_SIG2, 4, 1, 0),
+       SOC_DAPM_SINGLE("Playback Switch", AK4535_SIG2, 7, 1, 0),
+       SOC_DAPM_SINGLE("Aux Bypass Switch", AK4535_SIG2, 5, 1, 0),
+};
+
+/* Input Mixer */
+static const struct snd_kcontrol_new ak4535_input_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Mic Capture Switch", AK4535_MIC, 2, 1, 0),
+       SOC_DAPM_SINGLE("Aux Capture Switch", AK4535_MIC, 5, 1, 0),
+};
+
+/* Input mux */
+static const struct snd_kcontrol_new ak4535_input_mux_control =
+       SOC_DAPM_ENUM("Input Select", ak4535_enum[4]);
+
+/* HP L switch */
+static const struct snd_kcontrol_new ak4535_hpl_control =
+       SOC_DAPM_SINGLE("Switch", AK4535_SIG2, 1, 1, 1);
+
+/* HP R switch */
+static const struct snd_kcontrol_new ak4535_hpr_control =
+       SOC_DAPM_SINGLE("Switch", AK4535_SIG2, 0, 1, 1);
+
+/* mono 2 switch */
+static const struct snd_kcontrol_new ak4535_mono2_control =
+       SOC_DAPM_SINGLE("Switch", AK4535_SIG1, 0, 1, 0);
+
+/* Line out switch */
+static const struct snd_kcontrol_new ak4535_line_control =
+       SOC_DAPM_SINGLE("Switch", AK4535_SIG2, 6, 1, 0);
+
+/* ak4535 dapm widgets */
+static const struct snd_soc_dapm_widget ak4535_dapm_widgets[] = {
+       SND_SOC_DAPM_MIXER("Stereo Mixer", SND_SOC_NOPM, 0, 0,
+               &ak4535_stereo_mixer_controls[0],
+               ARRAY_SIZE(ak4535_stereo_mixer_controls)),
+       SND_SOC_DAPM_MIXER("Mono1 Mixer", SND_SOC_NOPM, 0, 0,
+               &ak4535_mono1_mixer_controls[0],
+               ARRAY_SIZE(ak4535_mono1_mixer_controls)),
+       SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0,
+               &ak4535_input_mixer_controls[0],
+               ARRAY_SIZE(ak4535_input_mixer_controls)),
+       SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0,
+               &ak4535_input_mux_control),
+       SND_SOC_DAPM_DAC("DAC", "Playback", AK4535_PM2, 0, 0),
+       SND_SOC_DAPM_SWITCH("Mono 2 Enable", SND_SOC_NOPM, 0, 0,
+               &ak4535_mono2_control),
+       /* speaker powersave bit */
+       SND_SOC_DAPM_PGA("Speaker Enable", AK4535_MODE2, 0, 0, NULL, 0),
+       SND_SOC_DAPM_SWITCH("Line Out Enable", SND_SOC_NOPM, 0, 0,
+               &ak4535_line_control),
+       SND_SOC_DAPM_SWITCH("Left HP Enable", SND_SOC_NOPM, 0, 0,
+               &ak4535_hpl_control),
+       SND_SOC_DAPM_SWITCH("Right HP Enable", SND_SOC_NOPM, 0, 0,
+               &ak4535_hpr_control),
+       SND_SOC_DAPM_OUTPUT("LOUT"),
+       SND_SOC_DAPM_OUTPUT("HPL"),
+       SND_SOC_DAPM_OUTPUT("ROUT"),
+       SND_SOC_DAPM_OUTPUT("HPR"),
+       SND_SOC_DAPM_OUTPUT("SPP"),
+       SND_SOC_DAPM_OUTPUT("SPN"),
+       SND_SOC_DAPM_OUTPUT("MOUT1"),
+       SND_SOC_DAPM_OUTPUT("MOUT2"),
+       SND_SOC_DAPM_OUTPUT("MICOUT"),
+       SND_SOC_DAPM_ADC("ADC", "Capture", AK4535_PM1, 0, 0),
+       SND_SOC_DAPM_PGA("Spk Amp", AK4535_PM2, 3, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("HP R Amp", AK4535_PM2, 1, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("HP L Amp", AK4535_PM2, 2, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Mic", AK4535_PM1, 1, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Line Out", AK4535_PM1, 4, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Mono Out", AK4535_PM1, 3, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("AUX In", AK4535_PM1, 2, 0, NULL, 0),
+
+       SND_SOC_DAPM_MICBIAS("Mic Int Bias", AK4535_MIC, 3, 0),
+       SND_SOC_DAPM_MICBIAS("Mic Ext Bias", AK4535_MIC, 4, 0),
+       SND_SOC_DAPM_INPUT("MICIN"),
+       SND_SOC_DAPM_INPUT("MICEXT"),
+       SND_SOC_DAPM_INPUT("AUX"),
+       SND_SOC_DAPM_INPUT("MIN"),
+       SND_SOC_DAPM_INPUT("AIN"),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+       /*stereo mixer */
+       {"Stereo Mixer", "Playback Switch", "DAC"},
+       {"Stereo Mixer", "Mic Sidetone Switch", "Mic"},
+       {"Stereo Mixer", "Aux Bypass Switch", "AUX In"},
+
+       /* mono1 mixer */
+       {"Mono1 Mixer", "Mic Sidetone Switch", "Mic"},
+       {"Mono1 Mixer", "Mono Playback Switch", "DAC"},
+
+       /* Mic */
+       {"Mic", NULL, "AIN"},
+       {"Input Mux", "Internal", "Mic Int Bias"},
+       {"Input Mux", "External", "Mic Ext Bias"},
+       {"Mic Int Bias", NULL, "MICIN"},
+       {"Mic Ext Bias", NULL, "MICEXT"},
+       {"MICOUT", NULL, "Input Mux"},
+
+       /* line out */
+       {"LOUT", NULL, "Line Out Enable"},
+       {"ROUT", NULL, "Line Out Enable"},
+       {"Line Out Enable", "Switch", "Line Out"},
+       {"Line Out", NULL, "Stereo Mixer"},
+
+       /* mono1 out */
+       {"MOUT1", NULL, "Mono Out"},
+       {"Mono Out", NULL, "Mono1 Mixer"},
+
+       /* left HP */
+       {"HPL", NULL, "Left HP Enable"},
+       {"Left HP Enable", "Switch", "HP L Amp"},
+       {"HP L Amp", NULL, "Stereo Mixer"},
+
+       /* right HP */
+       {"HPR", NULL, "Right HP Enable"},
+       {"Right HP Enable", "Switch", "HP R Amp"},
+       {"HP R Amp", NULL, "Stereo Mixer"},
+
+       /* speaker */
+       {"SPP", NULL, "Speaker Enable"},
+       {"SPN", NULL, "Speaker Enable"},
+       {"Speaker Enable", "Switch", "Spk Amp"},
+       {"Spk Amp", NULL, "MIN"},
+
+       /* mono 2 */
+       {"MOUT2", NULL, "Mono 2 Enable"},
+       {"Mono 2 Enable", "Switch", "Stereo Mixer"},
+
+       /* Aux In */
+       {"Aux In", NULL, "AUX"},
+
+       /* ADC */
+       {"ADC", NULL, "Input Mixer"},
+       {"Input Mixer", "Mic Capture Switch", "Mic"},
+       {"Input Mixer", "Aux Capture Switch", "Aux In"},
+};
+
+static int ak4535_add_widgets(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, ak4535_dapm_widgets,
+                                 ARRAY_SIZE(ak4535_dapm_widgets));
+
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+       snd_soc_dapm_new_widgets(codec);
+       return 0;
+}
+
+static int ak4535_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+       int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct ak4535_priv *ak4535 = codec->private_data;
+
+       ak4535->sysclk = freq;
+       return 0;
+}
+
+static int ak4535_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       struct ak4535_priv *ak4535 = codec->private_data;
+       u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
+       int rate = params_rate(params), fs = 256;
+
+       if (rate)
+               fs = ak4535->sysclk / rate;
+
+       /* set fs */
+       switch (fs) {
+       case 1024:
+               mode2 |= (0x2 << 5);
+               break;
+       case 512:
+               mode2 |= (0x1 << 5);
+               break;
+       case 256:
+               break;
+       }
+
+       /* set rate */
+       ak4535_write(codec, AK4535_MODE2, mode2);
+       return 0;
+}
+
+static int ak4535_set_dai_fmt(struct snd_soc_dai *codec_dai,
+               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u8 mode1 = 0;
+
+       /* interface format */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               mode1 = 0x0002;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               mode1 = 0x0001;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* use 32 fs for BCLK to save power */
+       mode1 |= 0x4;
+
+       ak4535_write(codec, AK4535_MODE1, mode1);
+       return 0;
+}
+
+static int ak4535_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u16 mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
+       if (!mute)
+               ak4535_write(codec, AK4535_DAC, mute_reg);
+       else
+               ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
+       return 0;
+}
+
+static int ak4535_set_bias_level(struct snd_soc_codec *codec,
+       enum snd_soc_bias_level level)
+{
+       u16 i;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               ak4535_mute(codec->dai, 0);
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               ak4535_mute(codec->dai, 1);
+               break;
+       case SND_SOC_BIAS_STANDBY:
+               i = ak4535_read_reg_cache(codec, AK4535_PM1);
+               ak4535_write(codec, AK4535_PM1, i | 0x80);
+               i = ak4535_read_reg_cache(codec, AK4535_PM2);
+               ak4535_write(codec, AK4535_PM2, i & (~0x80));
+               break;
+       case SND_SOC_BIAS_OFF:
+               i = ak4535_read_reg_cache(codec, AK4535_PM1);
+               ak4535_write(codec, AK4535_PM1, i & (~0x80));
+               break;
+       }
+       codec->bias_level = level;
+       return 0;
+}
+
+#define AK4535_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+               SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
+               SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+
+struct snd_soc_dai ak4535_dai = {
+       .name = "AK4535",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = AK4535_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = AK4535_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .ops = {
+               .hw_params = ak4535_hw_params,
+       },
+       .dai_ops = {
+               .set_fmt = ak4535_set_dai_fmt,
+               .digital_mute = ak4535_mute,
+               .set_sysclk = ak4535_set_dai_sysclk,
+       },
+};
+EXPORT_SYMBOL_GPL(ak4535_dai);
+
+static int ak4535_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int ak4535_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+       ak4535_sync(codec);
+       ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       ak4535_set_bias_level(codec, codec->suspend_bias_level);
+       return 0;
+}
+
+/*
+ * initialise the AK4535 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int ak4535_init(struct snd_soc_device *socdev)
+{
+       struct snd_soc_codec *codec = socdev->codec;
+       int ret = 0;
+
+       codec->name = "AK4535";
+       codec->owner = THIS_MODULE;
+       codec->read = ak4535_read_reg_cache;
+       codec->write = ak4535_write;
+       codec->set_bias_level = ak4535_set_bias_level;
+       codec->dai = &ak4535_dai;
+       codec->num_dai = 1;
+       codec->reg_cache_size = ARRAY_SIZE(ak4535_reg);
+       codec->reg_cache = kmemdup(ak4535_reg, sizeof(ak4535_reg), GFP_KERNEL);
+
+       if (codec->reg_cache == NULL)
+               return -ENOMEM;
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               printk(KERN_ERR "ak4535: failed to create pcms\n");
+               goto pcm_err;
+       }
+
+       /* power on device */
+       ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       ak4535_add_controls(codec);
+       ak4535_add_widgets(codec);
+       ret = snd_soc_register_card(socdev);
+       if (ret < 0) {
+               printk(KERN_ERR "ak4535: failed to register card\n");
+               goto card_err;
+       }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       kfree(codec->reg_cache);
+
+       return ret;
+}
+
+static struct snd_soc_device *ak4535_socdev;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+#define I2C_DRIVERID_AK4535 0xfefe /* liam -  need a proper id */
+
+static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
+
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver ak4535_i2c_driver;
+static struct i2c_client client_template;
+
+/* If the i2c layer weren't so broken, we could pass this kind of data
+   around */
+static int ak4535_codec_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+       struct snd_soc_device *socdev = ak4535_socdev;
+       struct ak4535_setup_data *setup = socdev->codec_data;
+       struct snd_soc_codec *codec = socdev->codec;
+       struct i2c_client *i2c;
+       int ret;
+
+       if (addr != setup->i2c_address)
+               return -ENODEV;
+
+       client_template.adapter = adap;
+       client_template.addr = addr;
+
+       i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
+       if (i2c == NULL) {
+               kfree(codec);
+               return -ENOMEM;
+       }
+       i2c_set_clientdata(i2c, codec);
+       codec->control_data = i2c;
+
+       ret = i2c_attach_client(i2c);
+       if (ret < 0) {
+               printk(KERN_ERR "failed to attach codec at addr %x\n", addr);
+               goto err;
+       }
+
+       ret = ak4535_init(socdev);
+       if (ret < 0) {
+               printk(KERN_ERR "failed to initialise AK4535\n");
+               goto err;
+       }
+       return ret;
+
+err:
+       kfree(codec);
+       kfree(i2c);
+       return ret;
+}
+
+static int ak4535_i2c_detach(struct i2c_client *client)
+{
+       struct snd_soc_codec *codec = i2c_get_clientdata(client);
+       i2c_detach_client(client);
+       kfree(codec->reg_cache);
+       kfree(client);
+       return 0;
+}
+
+static int ak4535_i2c_attach(struct i2c_adapter *adap)
+{
+       return i2c_probe(adap, &addr_data, ak4535_codec_probe);
+}
+
+/* corgi i2c codec control layer */
+static struct i2c_driver ak4535_i2c_driver = {
+       .driver = {
+               .name = "AK4535 I2C Codec",
+               .owner = THIS_MODULE,
+       },
+       .id =             I2C_DRIVERID_AK4535,
+       .attach_adapter = ak4535_i2c_attach,
+       .detach_client =  ak4535_i2c_detach,
+       .command =        NULL,
+};
+
+static struct i2c_client client_template = {
+       .name =   "AK4535",
+       .driver = &ak4535_i2c_driver,
+};
+#endif
+
+static int ak4535_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct ak4535_setup_data *setup;
+       struct snd_soc_codec *codec;
+       struct ak4535_priv *ak4535;
+       int ret = 0;
+
+       printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
+
+       setup = socdev->codec_data;
+       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+       if (codec == NULL)
+               return -ENOMEM;
+
+       ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL);
+       if (ak4535 == NULL) {
+               kfree(codec);
+               return -ENOMEM;
+       }
+
+       codec->private_data = ak4535;
+       socdev->codec = codec;
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       ak4535_socdev = socdev;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       if (setup->i2c_address) {
+               normal_i2c[0] = setup->i2c_address;
+               codec->hw_write = (hw_write_t)i2c_master_send;
+               codec->hw_read = (hw_read_t)i2c_master_recv;
+               ret = i2c_add_driver(&ak4535_i2c_driver);
+               if (ret != 0)
+                       printk(KERN_ERR "can't add i2c driver");
+       }
+#else
+       /* Add other interfaces here */
+#endif
+       return ret;
+}
+
+/* power down chip */
+static int ak4535_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       if (codec->control_data)
+               ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&ak4535_i2c_driver);
+#endif
+       kfree(codec->private_data);
+       kfree(codec);
+
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_ak4535 = {
+       .probe =        ak4535_probe,
+       .remove =       ak4535_remove,
+       .suspend =      ak4535_suspend,
+       .resume =       ak4535_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535);
+
+MODULE_DESCRIPTION("Soc AK4535 driver");
+MODULE_AUTHOR("Richard Purdie");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h
new file mode 100644 (file)
index 0000000..e9fe30e
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * ak4535.h  --  AK4535 Soc Audio driver
+ *
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <richard@openedhand.com>
+ *
+ * Based on wm8753.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.
+ */
+
+#ifndef _AK4535_H
+#define _AK4535_H
+
+/* AK4535 register space */
+
+#define AK4535_PM1             0x0
+#define AK4535_PM2             0x1
+#define AK4535_SIG1            0x2
+#define AK4535_SIG2            0x3
+#define AK4535_MODE1           0x4
+#define AK4535_MODE2           0x5
+#define AK4535_DAC             0x6
+#define AK4535_MIC             0x7
+#define AK4535_TIMER           0x8
+#define AK4535_ALC1            0x9
+#define AK4535_ALC2            0xa
+#define AK4535_PGA             0xb
+#define AK4535_LATT            0xc
+#define AK4535_RATT            0xd
+#define AK4535_VOL             0xe
+#define AK4535_STATUS          0xf
+
+#define AK4535_CACHEREGNUM     0x10
+
+struct ak4535_setup_data {
+       unsigned short i2c_address;
+};
+
+extern struct snd_soc_dai ak4535_dai;
+extern struct snd_soc_codec_device soc_codec_dev_ak4535;
+
+#endif
index e73fcfd9f5cd41638acbc8d3ad5e30f532fe829f..9deb8c74fdfd3f1c07f5b1eaf518d4b8f145b5d6 100644 (file)
@@ -201,7 +201,7 @@ static struct {
  * driver what the input settings can be.  This would need to be implemented
  * for stand-alone mode to work.
  */
-static int cs4270_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
+static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,
                                 int clk_id, unsigned int freq, int dir)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -251,7 +251,7 @@ static int cs4270_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
  * data for playback only, but ASoC currently does not support different
  * formats for playback vs. record.
  */
-static int cs4270_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
                              unsigned int format)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -471,7 +471,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
  * board does not have the MUTEA or MUTEB pins connected to such circuitry,
  * then this function will do nothing.
  */
-static int cs4270_mute(struct snd_soc_codec_dai *dai, int mute)
+static int cs4270_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
        int reg6;
@@ -667,7 +667,7 @@ error:
 
 #endif /* USE_I2C*/
 
-struct snd_soc_codec_dai cs4270_dai = {
+struct snd_soc_dai cs4270_dai = {
        .name = "CS4270",
        .playback = {
                .stream_name = "Playback",
index 0ced49b7804db22f46719e4ee6957e7e96e908d1..adc6cd9667d4275b3a1035d15de5b5a9c04d0fbf 100644 (file)
@@ -16,7 +16,7 @@
  * The ASoC codec DAI structure for the CS4270.  Assign this structure to
  * the .codec_dai field of your machine driver's snd_soc_dai_link structure.
  */
-extern struct snd_soc_codec_dai cs4270_dai;
+extern struct snd_soc_dai cs4270_dai;
 
 /*
  * The ASoC codec device structure for the CS4270.  Assign this structure
index 09b1661b8a3a3930720947d91cf9a582b642cb0f..b1dce5f459db6d40663112ecb2e3f8eb13bb30a9 100644 (file)
@@ -29,7 +29,7 @@
  *  ---------------------------------------
  *
  *  Hence the machine layer should disable unsupported inputs/outputs by
- *  snd_soc_dapm_set_endpoint(codec, "MONO_LOUT", 0), etc.
+ *  snd_soc_dapm_disable_pin(codec, "MONO_LOUT"), etc.
  */
 
 #include <linux/module.h>
@@ -49,7 +49,7 @@
 #include "tlv320aic3x.h"
 
 #define AUDIO_NAME "aic3x"
-#define AIC3X_VERSION "0.1"
+#define AIC3X_VERSION "0.2"
 
 /* codec private data */
 struct aic3x_priv {
@@ -138,6 +138,20 @@ static int aic3x_write(struct snd_soc_codec *codec, unsigned int reg,
                return -EIO;
 }
 
+/*
+ * read from the aic3x register space
+ */
+static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
+                     u8 *value)
+{
+       *value = reg & 0xff;
+       if (codec->hw_read(codec->control_data, value, 1) != 1)
+               return -EIO;
+
+       aic3x_write_reg_cache(codec, reg, *value);
+       return 0;
+}
+
 #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
        .info = snd_soc_info_volsw, \
@@ -192,7 +206,7 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
                }
 
                if (found)
-                       snd_soc_dapm_sync_endpoints(widget->codec);
+                       snd_soc_dapm_sync(widget->codec);
        }
 
        ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
@@ -209,6 +223,8 @@ static const char *aic3x_right_hpcom_mux[] =
     { "differential of HPROUT", "constant VCM", "single-ended",
       "differential of HPLCOM", "external feedback" };
 static const char *aic3x_linein_mode_mux[] = { "single-ended", "differential" };
+static const char *aic3x_adc_hpf[] =
+    { "Disabled", "0.0045xFs", "0.0125xFs", "0.025xFs" };
 
 #define LDAC_ENUM      0
 #define RDAC_ENUM      1
@@ -218,6 +234,7 @@ static const char *aic3x_linein_mode_mux[] = { "single-ended", "differential" };
 #define LINE1R_ENUM    5
 #define LINE2L_ENUM    6
 #define LINE2R_ENUM    7
+#define ADC_HPF_ENUM   8
 
 static const struct soc_enum aic3x_enum[] = {
        SOC_ENUM_SINGLE(DAC_LINE_MUX, 6, 3, aic3x_left_dac_mux),
@@ -228,6 +245,7 @@ static const struct soc_enum aic3x_enum[] = {
        SOC_ENUM_SINGLE(LINE1R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux),
        SOC_ENUM_SINGLE(LINE2L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux),
        SOC_ENUM_SINGLE(LINE2R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux),
+       SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf),
 };
 
 static const struct snd_kcontrol_new aic3x_snd_controls[] = {
@@ -278,6 +296,8 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
        /* Input */
        SOC_DOUBLE_R("PGA Capture Volume", LADC_VOL, RADC_VOL, 0, 0x7f, 0),
        SOC_DOUBLE_R("PGA Capture Switch", LADC_VOL, RADC_VOL, 7, 0x01, 1),
+
+       SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]),
 };
 
 /* add non dapm controls */
@@ -441,11 +461,34 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0,
                         &aic3x_right_line2_mux_controls),
 
+       /*
+        * Not a real mic bias widget but similar function. This is for dynamic
+        * control of GPIO1 digital mic modulator clock output function when
+        * using digital mic.
+        */
+       SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "GPIO1 dmic modclk",
+                        AIC3X_GPIO1_REG, 4, 0xf,
+                        AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK,
+                        AIC3X_GPIO1_FUNC_DISABLED),
+
+       /*
+        * Also similar function like mic bias. Selects digital mic with
+        * configurable oversampling rate instead of ADC converter.
+        */
+       SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 128",
+                        AIC3X_ASD_INTF_CTRLA, 0, 3, 1, 0),
+       SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 64",
+                        AIC3X_ASD_INTF_CTRLA, 0, 3, 2, 0),
+       SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "DMic Rate 32",
+                        AIC3X_ASD_INTF_CTRLA, 0, 3, 3, 0),
+
        /* Mic Bias */
-       SND_SOC_DAPM_MICBIAS("Mic Bias 2V", MICBIAS_CTRL, 6, 0),
-       SND_SOC_DAPM_MICBIAS("Mic Bias 2.5V", MICBIAS_CTRL, 7, 0),
-       SND_SOC_DAPM_MICBIAS("Mic Bias AVDD", MICBIAS_CTRL, 6, 0),
-       SND_SOC_DAPM_MICBIAS("Mic Bias AVDD", MICBIAS_CTRL, 7, 0),
+       SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias 2V",
+                        MICBIAS_CTRL, 6, 3, 1, 0),
+       SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias 2.5V",
+                        MICBIAS_CTRL, 6, 3, 2, 0),
+       SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias AVDD",
+                        MICBIAS_CTRL, 6, 3, 3, 0),
 
        /* Left PGA to Left Output bypass */
        SND_SOC_DAPM_MIXER("Left PGA Bypass Mixer", SND_SOC_NOPM, 0, 0,
@@ -483,7 +526,7 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("LINE2R"),
 };
 
-static const char *intercon[][3] = {
+static const struct snd_soc_dapm_route intercon[] = {
        /* Left Output */
        {"Left DAC Mux", "DAC_L1", "Left DAC"},
        {"Left DAC Mux", "DAC_L2", "Left DAC"},
@@ -554,6 +597,7 @@ static const char *intercon[][3] = {
        {"Left PGA Mixer", "Mic3L Switch", "MIC3L"},
 
        {"Left ADC", NULL, "Left PGA Mixer"},
+       {"Left ADC", NULL, "GPIO1 dmic modclk"},
 
        /* Right Input */
        {"Right Line1R Mux", "single-ended", "LINE1R"},
@@ -567,6 +611,7 @@ static const char *intercon[][3] = {
        {"Right PGA Mixer", "Mic3R Switch", "MIC3R"},
 
        {"Right ADC", NULL, "Right PGA Mixer"},
+       {"Right ADC", NULL, "GPIO1 dmic modclk"},
 
        /* Left PGA Bypass */
        {"Left PGA Bypass Mixer", "Line Switch", "Left PGA Mixer"},
@@ -628,101 +673,27 @@ static const char *intercon[][3] = {
        {"Mono Out", NULL, "Right Line2 Bypass Mixer"},
        {"Right HP Out", NULL, "Right Line2 Bypass Mixer"},
 
-       /* terminator */
-       {NULL, NULL, NULL},
+       /*
+        * Logical path between digital mic enable and GPIO1 modulator clock
+        * output function
+        */
+       {"GPIO1 dmic modclk", NULL, "DMic Rate 128"},
+       {"GPIO1 dmic modclk", NULL, "DMic Rate 64"},
+       {"GPIO1 dmic modclk", NULL, "DMic Rate 32"},
 };
 
 static int aic3x_add_widgets(struct snd_soc_codec *codec)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(aic3x_dapm_widgets); i++)
-               snd_soc_dapm_new_control(codec, &aic3x_dapm_widgets[i]);
+       snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
+                                 ARRAY_SIZE(aic3x_dapm_widgets));
 
        /* set up audio path interconnects */
-       for (i = 0; intercon[i][0] != NULL; i++)
-               snd_soc_dapm_connect_input(codec, intercon[i][0],
-                                          intercon[i][1], intercon[i][2]);
+       snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
 
        snd_soc_dapm_new_widgets(codec);
        return 0;
 }
 
-struct aic3x_rate_divs {
-       u32 mclk;
-       u32 rate;
-       u32 fsref_reg;
-       u8 sr_reg:4;
-       u8 pllj_reg;
-       u16 plld_reg;
-};
-
-/* AIC3X codec mclk clock divider coefficients */
-static const struct aic3x_rate_divs aic3x_divs[] = {
-       /* 8k */
-       {12000000, 8000, 48000, 0xa, 16, 3840},
-       {19200000, 8000, 48000, 0xa, 10, 2400},
-       {22579200, 8000, 48000, 0xa, 8, 7075},
-       {33868800, 8000, 48000, 0xa, 5, 8049},
-       /* 11.025k */
-       {12000000, 11025, 44100, 0x6, 15, 528},
-       {19200000, 11025, 44100, 0x6, 9, 4080},
-       {22579200, 11025, 44100, 0x6, 8, 0},
-       {33868800, 11025, 44100, 0x6, 5, 3333},
-       /* 16k */
-       {12000000, 16000, 48000, 0x4, 16, 3840},
-       {19200000, 16000, 48000, 0x4, 10, 2400},
-       {22579200, 16000, 48000, 0x4, 8, 7075},
-       {33868800, 16000, 48000, 0x4, 5, 8049},
-       /* 22.05k */
-       {12000000, 22050, 44100, 0x2, 15, 528},
-       {19200000, 22050, 44100, 0x2, 9, 4080},
-       {22579200, 22050, 44100, 0x2, 8, 0},
-       {33868800, 22050, 44100, 0x2, 5, 3333},
-       /* 32k */
-       {12000000, 32000, 48000, 0x1, 16, 3840},
-       {19200000, 32000, 48000, 0x1, 10, 2400},
-       {22579200, 32000, 48000, 0x1, 8, 7075},
-       {33868800, 32000, 48000, 0x1, 5, 8049},
-       /* 44.1k */
-       {12000000, 44100, 44100, 0x0, 15, 528},
-       {19200000, 44100, 44100, 0x0, 9, 4080},
-       {22579200, 44100, 44100, 0x0, 8, 0},
-       {33868800, 44100, 44100, 0x0, 5, 3333},
-       /* 48k */
-       {12000000, 48000, 48000, 0x0, 16, 3840},
-       {19200000, 48000, 48000, 0x0, 10, 2400},
-       {22579200, 48000, 48000, 0x0, 8, 7075},
-       {33868800, 48000, 48000, 0x0, 5, 8049},
-       /* 64k */
-       {12000000, 64000, 96000, 0x1, 16, 3840},
-       {19200000, 64000, 96000, 0x1, 10, 2400},
-       {22579200, 64000, 96000, 0x1, 8, 7075},
-       {33868800, 64000, 96000, 0x1, 5, 8049},
-       /* 88.2k */
-       {12000000, 88200, 88200, 0x0, 15, 528},
-       {19200000, 88200, 88200, 0x0, 9, 4080},
-       {22579200, 88200, 88200, 0x0, 8, 0},
-       {33868800, 88200, 88200, 0x0, 5, 3333},
-       /* 96k */
-       {12000000, 96000, 96000, 0x0, 16, 3840},
-       {19200000, 96000, 96000, 0x0, 10, 2400},
-       {22579200, 96000, 96000, 0x0, 8, 7075},
-       {33868800, 96000, 96000, 0x0, 5, 8049},
-};
-
-static inline int aic3x_get_divs(int mclk, int rate)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(aic3x_divs); i++) {
-               if (aic3x_divs[i].rate == rate && aic3x_divs[i].mclk == mclk)
-                       return i;
-       }
-
-       return 0;
-}
-
 static int aic3x_hw_params(struct snd_pcm_substream *substream,
                           struct snd_pcm_hw_params *params)
 {
@@ -730,49 +701,107 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->codec;
        struct aic3x_priv *aic3x = codec->private_data;
-       int i;
-       u8 data, pll_p, pll_r, pll_j;
-       u16 pll_d;
-
-       i = aic3x_get_divs(aic3x->sysclk, params_rate(params));
+       int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
+       u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
+       u16 pll_d = 1;
 
-       /* Route Left DAC to left channel input and
-        * right DAC to right channel input */
-       data = (LDAC2LCH | RDAC2RCH);
-       switch (aic3x_divs[i].fsref_reg) {
-       case 44100:
-               data |= FSREF_44100;
+       /* select data word length */
+       data =
+           aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
                break;
-       case 48000:
-               data |= FSREF_48000;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               data |= (0x01 << 4);
                break;
-       case 88200:
-               data |= FSREF_44100 | DUAL_RATE_MODE;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               data |= (0x02 << 4);
                break;
-       case 96000:
-               data |= FSREF_48000 | DUAL_RATE_MODE;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               data |= (0x03 << 4);
                break;
        }
+       aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, data);
+
+       /* Fsref can be 44100 or 48000 */
+       fsref = (params_rate(params) % 11025 == 0) ? 44100 : 48000;
+
+       /* Try to find a value for Q which allows us to bypass the PLL and
+        * generate CODEC_CLK directly. */
+       for (pll_q = 2; pll_q < 18; pll_q++)
+               if (aic3x->sysclk / (128 * pll_q) == fsref) {
+                       bypass_pll = 1;
+                       break;
+               }
+
+       if (bypass_pll) {
+               pll_q &= 0xf;
+               aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
+               aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
+       } else
+               aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
+
+       /* Route Left DAC to left channel input and
+        * right DAC to right channel input */
+       data = (LDAC2LCH | RDAC2RCH);
+       data |= (fsref == 44100) ? FSREF_44100 : FSREF_48000;
+       if (params_rate(params) >= 64000)
+               data |= DUAL_RATE_MODE;
        aic3x_write(codec, AIC3X_CODEC_DATAPATH_REG, data);
 
        /* codec sample rate select */
-       data = aic3x_divs[i].sr_reg;
+       data = (fsref * 20) / params_rate(params);
+       if (params_rate(params) < 64000)
+               data /= 2;
+       data /= 5;
+       data -= 2;
        data |= (data << 4);
        aic3x_write(codec, AIC3X_SAMPLE_RATE_SEL_REG, data);
 
-       /* Use PLL for generation Fsref by equation:
-        * Fsref = (MCLK * K * R)/(2048 * P);
-        * Fix P = 2 and R = 1 and calculate K, if
-        * K = J.D, i.e. J - an interger portion of K and D is the fractional
-        * one with 4 digits of precision;
-        * Example:
-        * For MCLK = 22.5792 MHz and Fsref = 48kHz:
-        * Select P = 2, R= 1, K = 8.7074, which results in J = 8, D = 7074
+       if (bypass_pll)
+               return 0;
+
+       /* Use PLL
+        * find an apropriate setup for j, d, r and p by iterating over
+        * p and r - j and d are calculated for each fraction.
+        * Up to 128 values are probed, the closest one wins the game.
+        * The sysclk is divided by 1000 to prevent integer overflows.
         */
-       pll_p = 2;
-       pll_r = 1;
-       pll_j = aic3x_divs[i].pllj_reg;
-       pll_d = aic3x_divs[i].plld_reg;
+       codec_clk = (2048 * fsref) / (aic3x->sysclk / 1000);
+
+       for (r = 1; r <= 16; r++)
+               for (p = 1; p <= 8; p++) {
+                       int clk, tmp = (codec_clk * pll_r * 10) / pll_p;
+                       u8 j = tmp / 10000;
+                       u16 d = tmp % 10000;
+
+                       if (j > 63)
+                               continue;
+
+                       if (d != 0 && aic3x->sysclk < 10000000)
+                               continue;
+
+                       /* This is actually 1000 * ((j + (d/10000)) * r) / p
+                        * The term had to be converted to get rid of the
+                        * division by 10000 */
+                       clk = ((10000 * j * r) + (d * r)) / (10 * p);
+
+                       /* check whether this values get closer than the best
+                        * ones we had before */
+                       if (abs(codec_clk - clk) < abs(codec_clk - last_clk)) {
+                               pll_j = j; pll_d = d; pll_r = r; pll_p = p;
+                               last_clk = clk;
+                       }
+
+                       /* Early exit for exact matches */
+                       if (clk == codec_clk)
+                               break;
+               }
+
+       if (last_clk == 0) {
+               printk(KERN_ERR "%s(): unable to setup PLL\n", __func__);
+               return -EINVAL;
+       }
 
        data = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
        aic3x_write(codec, AIC3X_PLL_PROGA_REG, data | (pll_p << PLLP_SHIFT));
@@ -782,28 +811,10 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
        aic3x_write(codec, AIC3X_PLL_PROGD_REG,
                    (pll_d & 0x3F) << PLLD_LSB_SHIFT);
 
-       /* select data word length */
-       data =
-           aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
-               break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
-               data |= (0x01 << 4);
-               break;
-       case SNDRV_PCM_FORMAT_S24_LE:
-               data |= (0x02 << 4);
-               break;
-       case SNDRV_PCM_FORMAT_S32_LE:
-               data |= (0x03 << 4);
-               break;
-       }
-       aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, data);
-
        return 0;
 }
 
-static int aic3x_mute(struct snd_soc_codec_dai *dai, int mute)
+static int aic3x_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
        u8 ldac_reg = aic3x_read_reg_cache(codec, LDAC_VOL) & ~MUTE_ON;
@@ -820,31 +831,25 @@ static int aic3x_mute(struct snd_soc_codec_dai *dai, int mute)
        return 0;
 }
 
-static int aic3x_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
+static int aic3x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
                                int clk_id, unsigned int freq, int dir)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct aic3x_priv *aic3x = codec->private_data;
 
-       switch (freq) {
-       case 12000000:
-       case 19200000:
-       case 22579200:
-       case 33868800:
-               aic3x->sysclk = freq;
-               return 0;
-       }
-
-       return -EINVAL;
+       aic3x->sysclk = freq;
+       return 0;
 }
 
-static int aic3x_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
                             unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct aic3x_priv *aic3x = codec->private_data;
-       u8 iface_areg = 0;
-       u8 iface_breg = 0;
+       u8 iface_areg, iface_breg;
+
+       iface_areg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f;
+       iface_breg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f;
 
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -883,13 +888,14 @@ static int aic3x_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
        return 0;
 }
 
-static int aic3x_dapm_event(struct snd_soc_codec *codec, int event)
+static int aic3x_set_bias_level(struct snd_soc_codec *codec,
+                               enum snd_soc_bias_level level)
 {
        struct aic3x_priv *aic3x = codec->private_data;
        u8 reg;
 
-       switch (event) {
-       case SNDRV_CTL_POWER_D0:
+       switch (level) {
+       case SND_SOC_BIAS_ON:
                /* all power is driven by DAPM system */
                if (aic3x->master) {
                        /* enable pll */
@@ -898,10 +904,9 @@ static int aic3x_dapm_event(struct snd_soc_codec *codec, int event)
                                    reg | PLL_ENABLE);
                }
                break;
-       case SNDRV_CTL_POWER_D1:
-       case SNDRV_CTL_POWER_D2:
+       case SND_SOC_BIAS_PREPARE:
                break;
-       case SNDRV_CTL_POWER_D3hot:
+       case SND_SOC_BIAS_STANDBY:
                /*
                 * all power is driven by DAPM system,
                 * so output power is safe if bypass was set
@@ -913,7 +918,7 @@ static int aic3x_dapm_event(struct snd_soc_codec *codec, int event)
                                    reg & ~PLL_ENABLE);
                }
                break;
-       case SNDRV_CTL_POWER_D3cold:
+       case SND_SOC_BIAS_OFF:
                /* force all power off */
                reg = aic3x_read_reg_cache(codec, LINE1L_2_LADC_CTRL);
                aic3x_write(codec, LINE1L_2_LADC_CTRL, reg & ~LADC_PWR_ON);
@@ -949,16 +954,43 @@ static int aic3x_dapm_event(struct snd_soc_codec *codec, int event)
                }
                break;
        }
-       codec->dapm_state = event;
+       codec->bias_level = level;
 
        return 0;
 }
 
+void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state)
+{
+       u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
+       u8 bit = gpio ? 3: 0;
+       u8 val = aic3x_read_reg_cache(codec, reg) & ~(1 << bit);
+       aic3x_write(codec, reg, val | (!!state << bit));
+}
+EXPORT_SYMBOL_GPL(aic3x_set_gpio);
+
+int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
+{
+       u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
+       u8 val, bit = gpio ? 2: 1;
+
+       aic3x_read(codec, reg, &val);
+       return (val >> bit) & 1;
+}
+EXPORT_SYMBOL_GPL(aic3x_get_gpio);
+
+int aic3x_headset_detected(struct snd_soc_codec *codec)
+{
+       u8 val;
+       aic3x_read(codec, AIC3X_RT_IRQ_FLAGS_REG, &val);
+       return (val >> 2) & 1;
+}
+EXPORT_SYMBOL_GPL(aic3x_headset_detected);
+
 #define AIC3X_RATES    SNDRV_PCM_RATE_8000_96000
 #define AIC3X_FORMATS  (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
                         SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-struct snd_soc_codec_dai aic3x_dai = {
+struct snd_soc_dai aic3x_dai = {
        .name = "aic3x",
        .playback = {
                .stream_name = "Playback",
@@ -988,7 +1020,7 @@ static int aic3x_suspend(struct platform_device *pdev, pm_message_t state)
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_codec *codec = socdev->codec;
 
-       aic3x_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+       aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
@@ -1008,7 +1040,7 @@ static int aic3x_resume(struct platform_device *pdev)
                codec->hw_write(codec->control_data, data, 2);
        }
 
-       aic3x_dapm_event(codec, codec->suspend_dapm_state);
+       aic3x_set_bias_level(codec, codec->suspend_bias_level);
 
        return 0;
 }
@@ -1020,16 +1052,17 @@ static int aic3x_resume(struct platform_device *pdev)
 static int aic3x_init(struct snd_soc_device *socdev)
 {
        struct snd_soc_codec *codec = socdev->codec;
+       struct aic3x_setup_data *setup = socdev->codec_data;
        int reg, ret = 0;
 
        codec->name = "aic3x";
        codec->owner = THIS_MODULE;
        codec->read = aic3x_read_reg_cache;
        codec->write = aic3x_write;
-       codec->dapm_event = aic3x_dapm_event;
+       codec->set_bias_level = aic3x_set_bias_level;
        codec->dai = &aic3x_dai;
        codec->num_dai = 1;
-       codec->reg_cache_size = sizeof(aic3x_reg);
+       codec->reg_cache_size = ARRAY_SIZE(aic3x_reg);
        codec->reg_cache = kmemdup(aic3x_reg, sizeof(aic3x_reg), GFP_KERNEL);
        if (codec->reg_cache == NULL)
                return -ENOMEM;
@@ -1108,7 +1141,11 @@ static int aic3x_init(struct snd_soc_device *socdev)
        aic3x_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
 
        /* off, with power on */
-       aic3x_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+       aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       /* setup GPIO functions */
+       aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4);
+       aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4);
 
        aic3x_add_controls(codec);
        aic3x_add_widgets(codec);
@@ -1217,6 +1254,12 @@ static struct i2c_client client_template = {
        .name = "AIC3X",
        .driver = &aic3x_i2c_driver,
 };
+
+static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len)
+{
+       value[0] = i2c_smbus_read_byte_data(client, value[0]);
+       return (len == 1);
+}
 #endif
 
 static int aic3x_probe(struct platform_device *pdev)
@@ -1251,6 +1294,7 @@ static int aic3x_probe(struct platform_device *pdev)
        if (setup->i2c_address) {
                normal_i2c[0] = setup->i2c_address;
                codec->hw_write = (hw_write_t) i2c_master_send;
+               codec->hw_read = (hw_read_t) aic3x_i2c_read;
                ret = i2c_add_driver(&aic3x_i2c_driver);
                if (ret != 0)
                        printk(KERN_ERR "can't add i2c driver");
@@ -1268,7 +1312,7 @@ static int aic3x_remove(struct platform_device *pdev)
 
        /* power down chip */
        if (codec->control_data)
-               aic3x_dapm_event(codec, SNDRV_CTL_POWER_D3);
+               aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
index d0cdeeb629de5f0a12435f78b5fb2fbe4d4a9a7b..d76c079b86e7b52f148b3a35a49ff0ea2f9a7b8d 100644 (file)
@@ -37,6 +37,8 @@
 #define AIC3X_ASD_INTF_CTRLB           9
 /* Audio overflow status and PLL R value programming register */
 #define AIC3X_OVRF_STATUS_AND_PLLR_REG 11
+/* Audio codec digital filter control register */
+#define AIC3X_CODEC_DFILT_CTRL         12
 
 /* ADC PGA Gain control registers */
 #define LADC_VOL                       15
 #define DACR1_2_RLOPM_VOL              92
 #define LLOPM_CTRL                     86
 #define RLOPM_CTRL                     93
+/* GPIO/IRQ registers */
+#define AIC3X_STICKY_IRQ_FLAGS_REG     96
+#define AIC3X_RT_IRQ_FLAGS_REG         97
+#define AIC3X_GPIO1_REG                        98
+#define AIC3X_GPIO2_REG                        99
+#define AIC3X_GPIOA_REG                        100
+#define AIC3X_GPIOB_REG                        101
 /* Clock generation control register */
 #define AIC3X_CLKGEN_CTRL_REG          102
 
 
 /* PLL registers bitfields */
 #define PLLP_SHIFT             0
+#define PLLQ_SHIFT             3
 #define PLLR_SHIFT             0
 #define PLLJ_SHIFT             2
 #define PLLD_MSB_SHIFT         0
 #define PLLD_LSB_SHIFT         2
 
 /* Clock generation register bits */
+#define CODEC_CLKIN_PLLDIV     0
+#define CODEC_CLKIN_CLKDIV     1
 #define PLL_CLKIN_SHIFT                4
 #define MCLK_SOURCE            0x0
 #define PLL_CLKDIV_SHIFT       0
 /* Default input volume */
 #define DEFAULT_GAIN    0x20
 
+/* GPIO API */
+enum {
+       AIC3X_GPIO1_FUNC_DISABLED               = 0,
+       AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC      = 1,
+       AIC3X_GPIO1_FUNC_CLOCK_MUX              = 2,
+       AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2         = 3,
+       AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4         = 4,
+       AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8         = 5,
+       AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ      = 6,
+       AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ          = 7,
+       AIC3X_GPIO1_FUNC_INPUT                  = 8,
+       AIC3X_GPIO1_FUNC_OUTPUT                 = 9,
+       AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK     = 10,
+       AIC3X_GPIO1_FUNC_AUDIO_WORDCLK          = 11,
+       AIC3X_GPIO1_FUNC_BUTTON_IRQ             = 12,
+       AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ     = 13,
+       AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ   = 14,
+       AIC3X_GPIO1_FUNC_ALL_IRQ                = 16
+};
+
+enum {
+       AIC3X_GPIO2_FUNC_DISABLED               = 0,
+       AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ     = 2,
+       AIC3X_GPIO2_FUNC_INPUT                  = 3,
+       AIC3X_GPIO2_FUNC_OUTPUT                 = 4,
+       AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT      = 5,
+       AIC3X_GPIO2_FUNC_AUDIO_BITCLK           = 8,
+       AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9,
+       AIC3X_GPIO2_FUNC_ALL_IRQ                = 10,
+       AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11,
+       AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12,
+       AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ      = 13,
+       AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ          = 14,
+       AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ       = 15
+};
+
+void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
+int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
+int aic3x_headset_detected(struct snd_soc_codec *codec);
+
 struct aic3x_setup_data {
        unsigned short i2c_address;
+       unsigned int gpio_func[2];
 };
 
-extern struct snd_soc_codec_dai aic3x_dai;
+extern struct snd_soc_dai aic3x_dai;
 extern struct snd_soc_codec_device soc_codec_dev_aic3x;
 
 #endif /* _AIC3X_H */
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
new file mode 100644 (file)
index 0000000..a52d6d9
--- /dev/null
@@ -0,0 +1,852 @@
+/*
+ * uda1380.c - Philips UDA1380 ALSA SoC audio driver
+ *
+ * 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.
+ *
+ * Copyright (c) 2007 Philipp Zabel <philipp.zabel@gmail.com>
+ * Improved support for DAPM and audio routing/mixing capabilities,
+ * added TLV support.
+ *
+ * Modified by Richard Purdie <richard@openedhand.com> to fit into SoC
+ * codec model.
+ *
+ * Copyright (c) 2005 Giorgio Padrin <giorgio@mandarinlogiq.org>
+ * Copyright 2005 Openedhand Ltd.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/info.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+
+#include "uda1380.h"
+
+#define UDA1380_VERSION "0.6"
+#define AUDIO_NAME "uda1380"
+
+/*
+ * uda1380 register cache
+ */
+static const u16 uda1380_reg[UDA1380_CACHEREGNUM] = {
+       0x0502, 0x0000, 0x0000, 0x3f3f,
+       0x0202, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0000, 0xff00, 0x0000, 0x4800,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x8000, 0x0002, 0x0000,
+};
+
+/*
+ * read uda1380 register cache
+ */
+static inline unsigned int uda1380_read_reg_cache(struct snd_soc_codec *codec,
+       unsigned int reg)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg == UDA1380_RESET)
+               return 0;
+       if (reg >= UDA1380_CACHEREGNUM)
+               return -1;
+       return cache[reg];
+}
+
+/*
+ * write uda1380 register cache
+ */
+static inline void uda1380_write_reg_cache(struct snd_soc_codec *codec,
+       u16 reg, unsigned int value)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg >= UDA1380_CACHEREGNUM)
+               return;
+       cache[reg] = value;
+}
+
+/*
+ * write to the UDA1380 register space
+ */
+static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
+       unsigned int value)
+{
+       u8 data[3];
+
+       /* data is
+        *   data[0] is register offset
+        *   data[1] is MS byte
+        *   data[2] is LS byte
+        */
+       data[0] = reg;
+       data[1] = (value & 0xff00) >> 8;
+       data[2] = value & 0x00ff;
+
+       uda1380_write_reg_cache(codec, reg, value);
+
+       /* the interpolator & decimator regs must only be written when the
+        * codec DAI is active.
+        */
+       if (!codec->active && (reg >= UDA1380_MVOL))
+               return 0;
+       pr_debug("uda1380: hw write %x val %x\n", reg, value);
+       if (codec->hw_write(codec->control_data, data, 3) == 3) {
+               unsigned int val;
+               i2c_master_send(codec->control_data, data, 1);
+               i2c_master_recv(codec->control_data, data, 2);
+               val = (data[0]<<8) | data[1];
+               if (val != value) {
+                       pr_debug("uda1380: READ BACK VAL %x\n",
+                                       (data[0]<<8) | data[1]);
+                       return -EIO;
+               }
+               return 0;
+       } else
+               return -EIO;
+}
+
+#define uda1380_reset(c)       uda1380_write(c, UDA1380_RESET, 0)
+
+/* declarations of ALSA reg_elem_REAL controls */
+static const char *uda1380_deemp[] = {
+       "None",
+       "32kHz",
+       "44.1kHz",
+       "48kHz",
+       "96kHz",
+};
+static const char *uda1380_input_sel[] = {
+       "Line",
+       "Mic + Line R",
+       "Line L",
+       "Mic",
+};
+static const char *uda1380_output_sel[] = {
+       "DAC",
+       "Analog Mixer",
+};
+static const char *uda1380_spf_mode[] = {
+       "Flat",
+       "Minimum1",
+       "Minimum2",
+       "Maximum"
+};
+static const char *uda1380_capture_sel[] = {
+       "ADC",
+       "Digital Mixer"
+};
+static const char *uda1380_sel_ns[] = {
+       "3rd-order",
+       "5th-order"
+};
+static const char *uda1380_mix_control[] = {
+       "off",
+       "PCM only",
+       "before sound processing",
+       "after sound processing"
+};
+static const char *uda1380_sdet_setting[] = {
+       "3200",
+       "4800",
+       "9600",
+       "19200"
+};
+static const char *uda1380_os_setting[] = {
+       "single-speed",
+       "double-speed (no mixing)",
+       "quad-speed (no mixing)"
+};
+
+static const struct soc_enum uda1380_deemp_enum[] = {
+       SOC_ENUM_SINGLE(UDA1380_DEEMP, 8, 5, uda1380_deemp),
+       SOC_ENUM_SINGLE(UDA1380_DEEMP, 0, 5, uda1380_deemp),
+};
+static const struct soc_enum uda1380_input_sel_enum =
+       SOC_ENUM_SINGLE(UDA1380_ADC, 2, 4, uda1380_input_sel);          /* SEL_MIC, SEL_LNA */
+static const struct soc_enum uda1380_output_sel_enum =
+       SOC_ENUM_SINGLE(UDA1380_PM, 7, 2, uda1380_output_sel);          /* R02_EN_AVC */
+static const struct soc_enum uda1380_spf_enum =
+       SOC_ENUM_SINGLE(UDA1380_MODE, 14, 4, uda1380_spf_mode);         /* M */
+static const struct soc_enum uda1380_capture_sel_enum =
+       SOC_ENUM_SINGLE(UDA1380_IFACE, 6, 2, uda1380_capture_sel);      /* SEL_SOURCE */
+static const struct soc_enum uda1380_sel_ns_enum =
+       SOC_ENUM_SINGLE(UDA1380_MIXER, 14, 2, uda1380_sel_ns);          /* SEL_NS */
+static const struct soc_enum uda1380_mix_enum =
+       SOC_ENUM_SINGLE(UDA1380_MIXER, 12, 4, uda1380_mix_control);     /* MIX, MIX_POS */
+static const struct soc_enum uda1380_sdet_enum =
+       SOC_ENUM_SINGLE(UDA1380_MIXER, 4, 4, uda1380_sdet_setting);     /* SD_VALUE */
+static const struct soc_enum uda1380_os_enum =
+       SOC_ENUM_SINGLE(UDA1380_MIXER, 0, 3, uda1380_os_setting);       /* OS */
+
+/*
+ * from -48 dB in 1.5 dB steps (mute instead of -49.5 dB)
+ */
+static DECLARE_TLV_DB_SCALE(amix_tlv, -4950, 150, 1);
+
+/*
+ * from -78 dB in 1 dB steps (3 dB steps, really. LSB are ignored),
+ * from -66 dB in 0.5 dB steps (2 dB steps, really) and
+ * from -52 dB in 0.25 dB steps
+ */
+static const unsigned int mvol_tlv[] = {
+       TLV_DB_RANGE_HEAD(3),
+       0, 15, TLV_DB_SCALE_ITEM(-8200, 100, 1),
+       16, 43, TLV_DB_SCALE_ITEM(-6600, 50, 0),
+       44, 252, TLV_DB_SCALE_ITEM(-5200, 25, 0),
+};
+
+/*
+ * from -72 dB in 1.5 dB steps (6 dB steps really),
+ * from -66 dB in 0.75 dB steps (3 dB steps really),
+ * from -60 dB in 0.5 dB steps (2 dB steps really) and
+ * from -46 dB in 0.25 dB steps
+ */
+static const unsigned int vc_tlv[] = {
+       TLV_DB_RANGE_HEAD(4),
+       0, 7, TLV_DB_SCALE_ITEM(-7800, 150, 1),
+       8, 15, TLV_DB_SCALE_ITEM(-6600, 75, 0),
+       16, 43, TLV_DB_SCALE_ITEM(-6000, 50, 0),
+       44, 228, TLV_DB_SCALE_ITEM(-4600, 25, 0),
+};
+
+/* from 0 to 6 dB in 2 dB steps if SPF mode != flat */
+static DECLARE_TLV_DB_SCALE(tr_tlv, 0, 200, 0);
+
+/* from 0 to 24 dB in 2 dB steps, if SPF mode == maximum, otherwise cuts
+ * off at 18 dB max) */
+static DECLARE_TLV_DB_SCALE(bb_tlv, 0, 200, 0);
+
+/* from -63 to 24 dB in 0.5 dB steps (-128...48) */
+static DECLARE_TLV_DB_SCALE(dec_tlv, -6400, 50, 1);
+
+/* from 0 to 24 dB in 3 dB steps */
+static DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0);
+
+/* from 0 to 30 dB in 2 dB steps */
+static DECLARE_TLV_DB_SCALE(vga_tlv, 0, 200, 0);
+
+static const struct snd_kcontrol_new uda1380_snd_controls[] = {
+       SOC_DOUBLE_TLV("Analog Mixer Volume", UDA1380_AMIX, 0, 8, 44, 1, amix_tlv),     /* AVCR, AVCL */
+       SOC_DOUBLE_TLV("Master Playback Volume", UDA1380_MVOL, 0, 8, 252, 1, mvol_tlv), /* MVCL, MVCR */
+       SOC_SINGLE_TLV("ADC Playback Volume", UDA1380_MIXVOL, 8, 228, 1, vc_tlv),       /* VC2 */
+       SOC_SINGLE_TLV("PCM Playback Volume", UDA1380_MIXVOL, 0, 228, 1, vc_tlv),       /* VC1 */
+       SOC_ENUM("Sound Processing Filter", uda1380_spf_enum),                          /* M */
+       SOC_DOUBLE_TLV("Tone Control - Treble", UDA1380_MODE, 4, 12, 3, 0, tr_tlv),     /* TRL, TRR */
+       SOC_DOUBLE_TLV("Tone Control - Bass", UDA1380_MODE, 0, 8, 15, 0, bb_tlv),       /* BBL, BBR */
+/**/   SOC_SINGLE("Master Playback Switch", UDA1380_DEEMP, 14, 1, 1),          /* MTM */
+       SOC_SINGLE("ADC Playback Switch", UDA1380_DEEMP, 11, 1, 1),             /* MT2 from decimation filter */
+       SOC_ENUM("ADC Playback De-emphasis", uda1380_deemp_enum[0]),            /* DE2 */
+       SOC_SINGLE("PCM Playback Switch", UDA1380_DEEMP, 3, 1, 1),              /* MT1, from digital data input */
+       SOC_ENUM("PCM Playback De-emphasis", uda1380_deemp_enum[1]),            /* DE1 */
+       SOC_SINGLE("DAC Polarity inverting Switch", UDA1380_MIXER, 15, 1, 0),   /* DA_POL_INV */
+       SOC_ENUM("Noise Shaper", uda1380_sel_ns_enum),                          /* SEL_NS */
+       SOC_ENUM("Digital Mixer Signal Control", uda1380_mix_enum),             /* MIX_POS, MIX */
+       SOC_SINGLE("Silence Switch", UDA1380_MIXER, 7, 1, 0),                   /* SILENCE, force DAC output to silence */
+       SOC_SINGLE("Silence Detector Switch", UDA1380_MIXER, 6, 1, 0),          /* SDET_ON */
+       SOC_ENUM("Silence Detector Setting", uda1380_sdet_enum),                /* SD_VALUE */
+       SOC_ENUM("Oversampling Input", uda1380_os_enum),                        /* OS */
+       SOC_DOUBLE_S8_TLV("ADC Capture Volume", UDA1380_DEC, -128, 48, dec_tlv),        /* ML_DEC, MR_DEC */
+/**/   SOC_SINGLE("ADC Capture Switch", UDA1380_PGA, 15, 1, 1),                /* MT_ADC */
+       SOC_DOUBLE_TLV("Line Capture Volume", UDA1380_PGA, 0, 8, 8, 0, pga_tlv), /* PGA_GAINCTRLL, PGA_GAINCTRLR */
+       SOC_SINGLE("ADC Polarity inverting Switch", UDA1380_ADC, 12, 1, 0),     /* ADCPOL_INV */
+       SOC_SINGLE_TLV("Mic Capture Volume", UDA1380_ADC, 8, 15, 0, vga_tlv),   /* VGA_CTRL */
+       SOC_SINGLE("DC Filter Bypass Switch", UDA1380_ADC, 1, 1, 0),            /* SKIP_DCFIL (before decimator) */
+       SOC_SINGLE("DC Filter Enable Switch", UDA1380_ADC, 0, 1, 0),            /* EN_DCFIL (at output of decimator) */
+       SOC_SINGLE("AGC Timing", UDA1380_AGC, 8, 7, 0),                 /* TODO: enum, see table 62 */
+       SOC_SINGLE("AGC Target level", UDA1380_AGC, 2, 3, 1),                   /* AGC_LEVEL */
+       /* -5.5, -8, -11.5, -14 dBFS */
+       SOC_SINGLE("AGC Switch", UDA1380_AGC, 0, 1, 0),
+};
+
+/* add non dapm controls */
+static int uda1380_add_controls(struct snd_soc_codec *codec)
+{
+       int err, i;
+
+       for (i = 0; i < ARRAY_SIZE(uda1380_snd_controls); i++) {
+               err = snd_ctl_add(codec->card,
+                       snd_soc_cnew(&uda1380_snd_controls[i], codec, NULL));
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
+/* Input mux */
+static const struct snd_kcontrol_new uda1380_input_mux_control =
+       SOC_DAPM_ENUM("Route", uda1380_input_sel_enum);
+
+/* Output mux */
+static const struct snd_kcontrol_new uda1380_output_mux_control =
+       SOC_DAPM_ENUM("Route", uda1380_output_sel_enum);
+
+/* Capture mux */
+static const struct snd_kcontrol_new uda1380_capture_mux_control =
+       SOC_DAPM_ENUM("Route", uda1380_capture_sel_enum);
+
+
+static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
+       SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0,
+               &uda1380_input_mux_control),
+       SND_SOC_DAPM_MUX("Output Mux", SND_SOC_NOPM, 0, 0,
+               &uda1380_output_mux_control),
+       SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0,
+               &uda1380_capture_mux_control),
+       SND_SOC_DAPM_PGA("Left PGA", UDA1380_PM, 3, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Right PGA", UDA1380_PM, 1, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Mic LNA", UDA1380_PM, 4, 0, NULL, 0),
+       SND_SOC_DAPM_ADC("Left ADC", "Left Capture", UDA1380_PM, 2, 0),
+       SND_SOC_DAPM_ADC("Right ADC", "Right Capture", UDA1380_PM, 0, 0),
+       SND_SOC_DAPM_INPUT("VINM"),
+       SND_SOC_DAPM_INPUT("VINL"),
+       SND_SOC_DAPM_INPUT("VINR"),
+       SND_SOC_DAPM_MIXER("Analog Mixer", UDA1380_PM, 6, 0, NULL, 0),
+       SND_SOC_DAPM_OUTPUT("VOUTLHP"),
+       SND_SOC_DAPM_OUTPUT("VOUTRHP"),
+       SND_SOC_DAPM_OUTPUT("VOUTL"),
+       SND_SOC_DAPM_OUTPUT("VOUTR"),
+       SND_SOC_DAPM_DAC("DAC", "Playback", UDA1380_PM, 10, 0),
+       SND_SOC_DAPM_PGA("HeadPhone Driver", UDA1380_PM, 13, 0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+
+       /* output mux */
+       {"HeadPhone Driver", NULL, "Output Mux"},
+       {"VOUTR", NULL, "Output Mux"},
+       {"VOUTL", NULL, "Output Mux"},
+
+       {"Analog Mixer", NULL, "VINR"},
+       {"Analog Mixer", NULL, "VINL"},
+       {"Analog Mixer", NULL, "DAC"},
+
+       {"Output Mux", "DAC", "DAC"},
+       {"Output Mux", "Analog Mixer", "Analog Mixer"},
+
+       /* {"DAC", "Digital Mixer", "I2S" } */
+
+       /* headphone driver */
+       {"VOUTLHP", NULL, "HeadPhone Driver"},
+       {"VOUTRHP", NULL, "HeadPhone Driver"},
+
+       /* input mux */
+       {"Left ADC", NULL, "Input Mux"},
+       {"Input Mux", "Mic", "Mic LNA"},
+       {"Input Mux", "Mic + Line R", "Mic LNA"},
+       {"Input Mux", "Line L", "Left PGA"},
+       {"Input Mux", "Line", "Left PGA"},
+
+       /* right input */
+       {"Right ADC", "Mic + Line R", "Right PGA"},
+       {"Right ADC", "Line", "Right PGA"},
+
+       /* inputs */
+       {"Mic LNA", NULL, "VINM"},
+       {"Left PGA", NULL, "VINL"},
+       {"Right PGA", NULL, "VINR"},
+};
+
+static int uda1380_add_widgets(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, uda1380_dapm_widgets,
+                                 ARRAY_SIZE(uda1380_dapm_widgets));
+
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+       snd_soc_dapm_new_widgets(codec);
+       return 0;
+}
+
+static int uda1380_set_dai_fmt(struct snd_soc_dai *codec_dai,
+               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       int iface;
+
+       /* set up DAI based upon fmt */
+       iface = uda1380_read_reg_cache(codec, UDA1380_IFACE);
+       iface &= ~(R01_SFORI_MASK | R01_SIM | R01_SFORO_MASK);
+
+       /* FIXME: how to select I2S for DATAO and MSB for DATAI correctly? */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               iface |= R01_SFORI_I2S | R01_SFORO_I2S;
+               break;
+       case SND_SOC_DAIFMT_LSB:
+               iface |= R01_SFORI_LSB16 | R01_SFORO_I2S;
+               break;
+       case SND_SOC_DAIFMT_MSB:
+               iface |= R01_SFORI_MSB | R01_SFORO_I2S;
+       }
+
+       if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM)
+               iface |= R01_SIM;
+
+       uda1380_write(codec, UDA1380_IFACE, iface);
+
+       return 0;
+}
+
+/*
+ * Flush reg cache
+ * We can only write the interpolator and decimator registers
+ * when the DAI is being clocked by the CPU DAI. It's up to the
+ * machine and cpu DAI driver to do this before we are called.
+ */
+static int uda1380_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       int reg, reg_start, reg_end, clk;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               reg_start = UDA1380_MVOL;
+               reg_end = UDA1380_MIXER;
+       } else {
+               reg_start = UDA1380_DEC;
+               reg_end = UDA1380_AGC;
+       }
+
+       /* FIXME disable DAC_CLK */
+       clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
+       uda1380_write(codec, UDA1380_CLK, clk & ~R00_DAC_CLK);
+
+       for (reg = reg_start; reg <= reg_end; reg++) {
+               pr_debug("uda1380: flush reg %x val %x:", reg,
+                               uda1380_read_reg_cache(codec, reg));
+               uda1380_write(codec, reg, uda1380_read_reg_cache(codec, reg));
+       }
+
+       /* FIXME enable DAC_CLK */
+       uda1380_write(codec, UDA1380_CLK, clk | R00_DAC_CLK);
+
+       return 0;
+}
+
+static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
+
+       /* set WSPLL power and divider if running from this clock */
+       if (clk & R00_DAC_CLK) {
+               int rate = params_rate(params);
+               u16 pm = uda1380_read_reg_cache(codec, UDA1380_PM);
+               clk &= ~0x3; /* clear SEL_LOOP_DIV */
+               switch (rate) {
+               case 6250 ... 12500:
+                       clk |= 0x0;
+                       break;
+               case 12501 ... 25000:
+                       clk |= 0x1;
+                       break;
+               case 25001 ... 50000:
+                       clk |= 0x2;
+                       break;
+               case 50001 ... 100000:
+                       clk |= 0x3;
+                       break;
+               }
+               uda1380_write(codec, UDA1380_PM, R02_PON_PLL | pm);
+       }
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               clk |= R00_EN_DAC | R00_EN_INT;
+       else
+               clk |= R00_EN_ADC | R00_EN_DEC;
+
+       uda1380_write(codec, UDA1380_CLK, clk);
+       return 0;
+}
+
+static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
+
+       /* shut down WSPLL power if running from this clock */
+       if (clk & R00_DAC_CLK) {
+               u16 pm = uda1380_read_reg_cache(codec, UDA1380_PM);
+               uda1380_write(codec, UDA1380_PM, ~R02_PON_PLL & pm);
+       }
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               clk &= ~(R00_EN_DAC | R00_EN_INT);
+       else
+               clk &= ~(R00_EN_ADC | R00_EN_DEC);
+
+       uda1380_write(codec, UDA1380_CLK, clk);
+}
+
+static int uda1380_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 mute_reg = uda1380_read_reg_cache(codec, UDA1380_DEEMP) & ~R13_MTM;
+
+       /* FIXME: mute(codec,0) is called when the magician clock is already
+        * set to WSPLL, but for some unknown reason writing to interpolator
+        * registers works only when clocked by SYSCLK */
+       u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
+       uda1380_write(codec, UDA1380_CLK, ~R00_DAC_CLK & clk);
+       if (mute)
+               uda1380_write(codec, UDA1380_DEEMP, mute_reg | R13_MTM);
+       else
+               uda1380_write(codec, UDA1380_DEEMP, mute_reg);
+       uda1380_write(codec, UDA1380_CLK, clk);
+       return 0;
+}
+
+static int uda1380_set_bias_level(struct snd_soc_codec *codec,
+       enum snd_soc_bias_level level)
+{
+       int pm = uda1380_read_reg_cache(codec, UDA1380_PM);
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+       case SND_SOC_BIAS_PREPARE:
+               uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm);
+               break;
+       case SND_SOC_BIAS_STANDBY:
+               uda1380_write(codec, UDA1380_PM, R02_PON_BIAS);
+               break;
+       case SND_SOC_BIAS_OFF:
+               uda1380_write(codec, UDA1380_PM, 0x0);
+               break;
+       }
+       codec->bias_level = level;
+       return 0;
+}
+
+#define UDA1380_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+                      SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
+                      SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+
+struct snd_soc_dai uda1380_dai[] = {
+{
+       .name = "UDA1380",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = UDA1380_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = UDA1380_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .ops = {
+               .hw_params = uda1380_pcm_hw_params,
+               .shutdown = uda1380_pcm_shutdown,
+               .prepare = uda1380_pcm_prepare,
+       },
+       .dai_ops = {
+               .digital_mute = uda1380_mute,
+               .set_fmt = uda1380_set_dai_fmt,
+       },
+},
+{ /* playback only - dual interface */
+       .name = "UDA1380",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = UDA1380_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .ops = {
+               .hw_params = uda1380_pcm_hw_params,
+               .shutdown = uda1380_pcm_shutdown,
+               .prepare = uda1380_pcm_prepare,
+       },
+       .dai_ops = {
+               .digital_mute = uda1380_mute,
+               .set_fmt = uda1380_set_dai_fmt,
+       },
+},
+{ /* capture only - dual interface*/
+       .name = "UDA1380",
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = UDA1380_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .ops = {
+               .hw_params = uda1380_pcm_hw_params,
+               .shutdown = uda1380_pcm_shutdown,
+               .prepare = uda1380_pcm_prepare,
+       },
+       .dai_ops = {
+               .set_fmt = uda1380_set_dai_fmt,
+       },
+},
+};
+EXPORT_SYMBOL_GPL(uda1380_dai);
+
+static int uda1380_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int uda1380_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+       int i;
+       u8 data[2];
+       u16 *cache = codec->reg_cache;
+
+       /* Sync reg_cache with the hardware */
+       for (i = 0; i < ARRAY_SIZE(uda1380_reg); i++) {
+               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
+               data[1] = cache[i] & 0x00ff;
+               codec->hw_write(codec->control_data, data, 2);
+       }
+       uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       uda1380_set_bias_level(codec, codec->suspend_bias_level);
+       return 0;
+}
+
+/*
+ * initialise the UDA1380 driver
+ * register mixer and dsp interfaces with the kernel
+ */
+static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
+{
+       struct snd_soc_codec *codec = socdev->codec;
+       int ret = 0;
+
+       codec->name = "UDA1380";
+       codec->owner = THIS_MODULE;
+       codec->read = uda1380_read_reg_cache;
+       codec->write = uda1380_write;
+       codec->set_bias_level = uda1380_set_bias_level;
+       codec->dai = uda1380_dai;
+       codec->num_dai = ARRAY_SIZE(uda1380_dai);
+       codec->reg_cache = kmemdup(uda1380_reg, sizeof(uda1380_reg),
+                                  GFP_KERNEL);
+       if (codec->reg_cache == NULL)
+               return -ENOMEM;
+       codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
+       codec->reg_cache_step = 1;
+       uda1380_reset(codec);
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               pr_err("uda1380: failed to create pcms\n");
+               goto pcm_err;
+       }
+
+       /* power on device */
+       uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       /* set clock input */
+       switch (dac_clk) {
+       case UDA1380_DAC_CLK_SYSCLK:
+               uda1380_write(codec, UDA1380_CLK, 0);
+               break;
+       case UDA1380_DAC_CLK_WSPLL:
+               uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK);
+               break;
+       }
+
+       /* uda1380 init */
+       uda1380_add_controls(codec);
+       uda1380_add_widgets(codec);
+       ret = snd_soc_register_card(socdev);
+       if (ret < 0) {
+               pr_err("uda1380: failed to register card\n");
+               goto card_err;
+       }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       kfree(codec->reg_cache);
+       return ret;
+}
+
+static struct snd_soc_device *uda1380_socdev;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+#define I2C_DRIVERID_UDA1380 0xfefe /* liam -  need a proper id */
+
+static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
+
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver uda1380_i2c_driver;
+static struct i2c_client client_template;
+
+/* If the i2c layer weren't so broken, we could pass this kind of data
+   around */
+
+static int uda1380_codec_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+       struct snd_soc_device *socdev = uda1380_socdev;
+       struct uda1380_setup_data *setup = socdev->codec_data;
+       struct snd_soc_codec *codec = socdev->codec;
+       struct i2c_client *i2c;
+       int ret;
+
+       if (addr != setup->i2c_address)
+               return -ENODEV;
+
+       client_template.adapter = adap;
+       client_template.addr = addr;
+
+       i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
+       if (i2c == NULL) {
+               kfree(codec);
+               return -ENOMEM;
+       }
+       i2c_set_clientdata(i2c, codec);
+       codec->control_data = i2c;
+
+       ret = i2c_attach_client(i2c);
+       if (ret < 0) {
+               pr_err("uda1380: failed to attach codec at addr %x\n", addr);
+               goto err;
+       }
+
+       ret = uda1380_init(socdev, setup->dac_clk);
+       if (ret < 0) {
+               pr_err("uda1380: failed to initialise UDA1380\n");
+               goto err;
+       }
+       return ret;
+
+err:
+       kfree(codec);
+       kfree(i2c);
+       return ret;
+}
+
+static int uda1380_i2c_detach(struct i2c_client *client)
+{
+       struct snd_soc_codec *codec = i2c_get_clientdata(client);
+       i2c_detach_client(client);
+       kfree(codec->reg_cache);
+       kfree(client);
+       return 0;
+}
+
+static int uda1380_i2c_attach(struct i2c_adapter *adap)
+{
+       return i2c_probe(adap, &addr_data, uda1380_codec_probe);
+}
+
+static struct i2c_driver uda1380_i2c_driver = {
+       .driver = {
+               .name =  "UDA1380 I2C Codec",
+               .owner = THIS_MODULE,
+       },
+       .id =             I2C_DRIVERID_UDA1380,
+       .attach_adapter = uda1380_i2c_attach,
+       .detach_client =  uda1380_i2c_detach,
+       .command =        NULL,
+};
+
+static struct i2c_client client_template = {
+       .name =   "UDA1380",
+       .driver = &uda1380_i2c_driver,
+};
+#endif
+
+static int uda1380_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct uda1380_setup_data *setup;
+       struct snd_soc_codec *codec;
+       int ret = 0;
+
+       pr_info("UDA1380 Audio Codec %s", UDA1380_VERSION);
+
+       setup = socdev->codec_data;
+       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+       if (codec == NULL)
+               return -ENOMEM;
+
+       socdev->codec = codec;
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       uda1380_socdev = socdev;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       if (setup->i2c_address) {
+               normal_i2c[0] = setup->i2c_address;
+               codec->hw_write = (hw_write_t)i2c_master_send;
+               ret = i2c_add_driver(&uda1380_i2c_driver);
+               if (ret != 0)
+                       printk(KERN_ERR "can't add i2c driver");
+       }
+#else
+       /* Add other interfaces here */
+#endif
+       return ret;
+}
+
+/* power down chip */
+static int uda1380_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       if (codec->control_data)
+               uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&uda1380_i2c_driver);
+#endif
+       kfree(codec);
+
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_uda1380 = {
+       .probe =        uda1380_probe,
+       .remove =       uda1380_remove,
+       .suspend =      uda1380_suspend,
+       .resume =       uda1380_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
+
+MODULE_AUTHOR("Giorgio Padrin");
+MODULE_DESCRIPTION("Audio support for codec Philips UDA1380");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/uda1380.h b/sound/soc/codecs/uda1380.h
new file mode 100644 (file)
index 0000000..50c603e
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Audio support for Philips UDA1380
+ *
+ * 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.
+ *
+ * Copyright (c) 2005 Giorgio Padrin <giorgio@mandarinlogiq.org>
+ */
+
+#ifndef _UDA1380_H
+#define _UDA1380_H
+
+#define UDA1380_CLK    0x00
+#define UDA1380_IFACE  0x01
+#define UDA1380_PM     0x02
+#define UDA1380_AMIX   0x03
+#define UDA1380_HP     0x04
+#define UDA1380_MVOL   0x10
+#define UDA1380_MIXVOL 0x11
+#define UDA1380_MODE   0x12
+#define UDA1380_DEEMP  0x13
+#define UDA1380_MIXER  0x14
+#define UDA1380_INTSTAT        0x18
+#define UDA1380_DEC    0x20
+#define UDA1380_PGA    0x21
+#define UDA1380_ADC    0x22
+#define UDA1380_AGC    0x23
+#define UDA1380_DECSTAT        0x28
+#define UDA1380_RESET  0x7f
+
+#define UDA1380_CACHEREGNUM 0x24
+
+/* Register flags */
+#define R00_EN_ADC     0x0800
+#define R00_EN_DEC     0x0400
+#define R00_EN_DAC     0x0200
+#define R00_EN_INT     0x0100
+#define R00_DAC_CLK    0x0010
+#define R01_SFORI_I2S   0x0000
+#define R01_SFORI_LSB16 0x0100
+#define R01_SFORI_LSB18 0x0200
+#define R01_SFORI_LSB20 0x0300
+#define R01_SFORI_MSB   0x0500
+#define R01_SFORI_MASK  0x0700
+#define R01_SFORO_I2S   0x0000
+#define R01_SFORO_LSB16 0x0001
+#define R01_SFORO_LSB18 0x0002
+#define R01_SFORO_LSB20 0x0003
+#define R01_SFORO_LSB24 0x0004
+#define R01_SFORO_MSB   0x0005
+#define R01_SFORO_MASK  0x0007
+#define R01_SEL_SOURCE  0x0040
+#define R01_SIM                0x0010
+#define R02_PON_PLL    0x8000
+#define R02_PON_HP     0x2000
+#define R02_PON_DAC    0x0400
+#define R02_PON_BIAS   0x0100
+#define R02_EN_AVC     0x0080
+#define R02_PON_AVC    0x0040
+#define R02_PON_LNA    0x0010
+#define R02_PON_PGAL   0x0008
+#define R02_PON_ADCL   0x0004
+#define R02_PON_PGAR   0x0002
+#define R02_PON_ADCR   0x0001
+#define R13_MTM                0x4000
+#define R14_SILENCE    0x0080
+#define R14_SDET_ON    0x0040
+#define R21_MT_ADC     0x8000
+#define R22_SEL_LNA    0x0008
+#define R22_SEL_MIC    0x0004
+#define R22_SKIP_DCFIL 0x0002
+#define R23_AGC_EN     0x0001
+
+struct uda1380_setup_data {
+       unsigned short i2c_address;
+       int            dac_clk;
+#define UDA1380_DAC_CLK_SYSCLK 0
+#define UDA1380_DAC_CLK_WSPLL  1
+};
+
+#define UDA1380_DAI_DUPLEX     0 /* playback and capture on single DAI */
+#define UDA1380_DAI_PLAYBACK   1 /* playback DAI */
+#define UDA1380_DAI_CAPTURE    2 /* capture DAI */
+
+extern struct snd_soc_dai uda1380_dai[3];
+extern struct snd_soc_codec_device soc_codec_dev_uda1380;
+
+#endif /* _UDA1380_H */
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
new file mode 100644 (file)
index 0000000..67325fd
--- /dev/null
@@ -0,0 +1,817 @@
+/*
+ * wm8510.c  --  WM8510 ALSA Soc Audio driver
+ *
+ * Copyright 2006 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood <liam.girdwood@wolfsonmicro.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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include "wm8510.h"
+
+#define AUDIO_NAME "wm8510"
+#define WM8510_VERSION "0.6"
+
+struct snd_soc_codec_device soc_codec_dev_wm8510;
+
+/*
+ * wm8510 register cache
+ * We can't read the WM8510 register space when we are
+ * using 2 wire for device control, so we cache them instead.
+ */
+static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0050, 0x0000, 0x0140, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x00ff,
+       0x0000, 0x0000, 0x0100, 0x00ff,
+       0x0000, 0x0000, 0x012c, 0x002c,
+       0x002c, 0x002c, 0x002c, 0x0000,
+       0x0032, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0038, 0x000b, 0x0032, 0x0000,
+       0x0008, 0x000c, 0x0093, 0x00e9,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0003, 0x0010, 0x0000, 0x0000,
+       0x0000, 0x0002, 0x0001, 0x0000,
+       0x0000, 0x0000, 0x0039, 0x0000,
+       0x0001,
+};
+
+/*
+ * read wm8510 register cache
+ */
+static inline unsigned int wm8510_read_reg_cache(struct snd_soc_codec *codec,
+       unsigned int reg)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg == WM8510_RESET)
+               return 0;
+       if (reg >= WM8510_CACHEREGNUM)
+               return -1;
+       return cache[reg];
+}
+
+/*
+ * write wm8510 register cache
+ */
+static inline void wm8510_write_reg_cache(struct snd_soc_codec *codec,
+       u16 reg, unsigned int value)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg >= WM8510_CACHEREGNUM)
+               return;
+       cache[reg] = value;
+}
+
+/*
+ * write to the WM8510 register space
+ */
+static int wm8510_write(struct snd_soc_codec *codec, unsigned int reg,
+       unsigned int value)
+{
+       u8 data[2];
+
+       /* data is
+        *   D15..D9 WM8510 register offset
+        *   D8...D0 register data
+        */
+       data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+       data[1] = value & 0x00ff;
+
+       wm8510_write_reg_cache(codec, reg, value);
+       if (codec->hw_write(codec->control_data, data, 2) == 2)
+               return 0;
+       else
+               return -EIO;
+}
+
+#define wm8510_reset(c)        wm8510_write(c, WM8510_RESET, 0)
+
+static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" };
+static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
+static const char *wm8510_alc[] = { "ALC", "Limiter" };
+
+static const struct soc_enum wm8510_enum[] = {
+       SOC_ENUM_SINGLE(WM8510_COMP, 1, 4, wm8510_companding), /* adc */
+       SOC_ENUM_SINGLE(WM8510_COMP, 3, 4, wm8510_companding), /* dac */
+       SOC_ENUM_SINGLE(WM8510_DAC,  4, 4, wm8510_deemp),
+       SOC_ENUM_SINGLE(WM8510_ALC3,  8, 2, wm8510_alc),
+};
+
+static const struct snd_kcontrol_new wm8510_snd_controls[] = {
+
+SOC_SINGLE("Digital Loopback Switch", WM8510_COMP, 0, 1, 0),
+
+SOC_ENUM("DAC Companding", wm8510_enum[1]),
+SOC_ENUM("ADC Companding", wm8510_enum[0]),
+
+SOC_ENUM("Playback De-emphasis", wm8510_enum[2]),
+SOC_SINGLE("DAC Inversion Switch", WM8510_DAC, 0, 1, 0),
+
+SOC_SINGLE("Master Playback Volume", WM8510_DACVOL, 0, 127, 0),
+
+SOC_SINGLE("High Pass Filter Switch", WM8510_ADC, 8, 1, 0),
+SOC_SINGLE("High Pass Cut Off", WM8510_ADC, 4, 7, 0),
+SOC_SINGLE("ADC Inversion Switch", WM8510_COMP, 0, 1, 0),
+
+SOC_SINGLE("Capture Volume", WM8510_ADCVOL,  0, 127, 0),
+
+SOC_SINGLE("DAC Playback Limiter Switch", WM8510_DACLIM1,  8, 1, 0),
+SOC_SINGLE("DAC Playback Limiter Decay", WM8510_DACLIM1,  4, 15, 0),
+SOC_SINGLE("DAC Playback Limiter Attack", WM8510_DACLIM1,  0, 15, 0),
+
+SOC_SINGLE("DAC Playback Limiter Threshold", WM8510_DACLIM2,  4, 7, 0),
+SOC_SINGLE("DAC Playback Limiter Boost", WM8510_DACLIM2,  0, 15, 0),
+
+SOC_SINGLE("ALC Enable Switch", WM8510_ALC1,  8, 1, 0),
+SOC_SINGLE("ALC Capture Max Gain", WM8510_ALC1,  3, 7, 0),
+SOC_SINGLE("ALC Capture Min Gain", WM8510_ALC1,  0, 7, 0),
+
+SOC_SINGLE("ALC Capture ZC Switch", WM8510_ALC2,  8, 1, 0),
+SOC_SINGLE("ALC Capture Hold", WM8510_ALC2,  4, 7, 0),
+SOC_SINGLE("ALC Capture Target", WM8510_ALC2,  0, 15, 0),
+
+SOC_ENUM("ALC Capture Mode", wm8510_enum[3]),
+SOC_SINGLE("ALC Capture Decay", WM8510_ALC3,  4, 15, 0),
+SOC_SINGLE("ALC Capture Attack", WM8510_ALC3,  0, 15, 0),
+
+SOC_SINGLE("ALC Capture Noise Gate Switch", WM8510_NGATE,  3, 1, 0),
+SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8510_NGATE,  0, 7, 0),
+
+SOC_SINGLE("Capture PGA ZC Switch", WM8510_INPPGA,  7, 1, 0),
+SOC_SINGLE("Capture PGA Volume", WM8510_INPPGA,  0, 63, 0),
+
+SOC_SINGLE("Speaker Playback ZC Switch", WM8510_SPKVOL,  7, 1, 0),
+SOC_SINGLE("Speaker Playback Switch", WM8510_SPKVOL,  6, 1, 1),
+SOC_SINGLE("Speaker Playback Volume", WM8510_SPKVOL,  0, 63, 0),
+SOC_SINGLE("Speaker Boost", WM8510_OUTPUT, 2, 1, 0),
+
+SOC_SINGLE("Capture Boost(+20dB)", WM8510_ADCBOOST,  8, 1, 0),
+SOC_SINGLE("Mono Playback Switch", WM8510_MONOMIX, 6, 1, 1),
+};
+
+/* add non dapm controls */
+static int wm8510_add_controls(struct snd_soc_codec *codec)
+{
+       int err, i;
+
+       for (i = 0; i < ARRAY_SIZE(wm8510_snd_controls); i++) {
+               err = snd_ctl_add(codec->card,
+                               snd_soc_cnew(&wm8510_snd_controls[i], codec,
+                                       NULL));
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
+/* Speaker Output Mixer */
+static const struct snd_kcontrol_new wm8510_speaker_mixer_controls[] = {
+SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_SPKMIX, 1, 1, 0),
+SOC_DAPM_SINGLE("Aux Playback Switch", WM8510_SPKMIX, 5, 1, 0),
+SOC_DAPM_SINGLE("PCM Playback Switch", WM8510_SPKMIX, 0, 1, 0),
+};
+
+/* Mono Output Mixer */
+static const struct snd_kcontrol_new wm8510_mono_mixer_controls[] = {
+SOC_DAPM_SINGLE("Line Bypass Switch", WM8510_MONOMIX, 1, 1, 0),
+SOC_DAPM_SINGLE("Aux Playback Switch", WM8510_MONOMIX, 2, 1, 0),
+SOC_DAPM_SINGLE("PCM Playback Switch", WM8510_MONOMIX, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8510_boost_controls[] = {
+SOC_DAPM_SINGLE("Mic PGA Switch", WM8510_INPPGA,  6, 1, 0),
+SOC_DAPM_SINGLE("Aux Volume", WM8510_ADCBOOST, 0, 7, 0),
+SOC_DAPM_SINGLE("Mic Volume", WM8510_ADCBOOST, 4, 7, 0),
+};
+
+static const struct snd_kcontrol_new wm8510_micpga_controls[] = {
+SOC_DAPM_SINGLE("MICP Switch", WM8510_INPUT, 0, 1, 0),
+SOC_DAPM_SINGLE("MICN Switch", WM8510_INPUT, 1, 1, 0),
+SOC_DAPM_SINGLE("AUX Switch", WM8510_INPUT, 2, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget wm8510_dapm_widgets[] = {
+SND_SOC_DAPM_MIXER("Speaker Mixer", WM8510_POWER3, 2, 0,
+       &wm8510_speaker_mixer_controls[0],
+       ARRAY_SIZE(wm8510_speaker_mixer_controls)),
+SND_SOC_DAPM_MIXER("Mono Mixer", WM8510_POWER3, 3, 0,
+       &wm8510_mono_mixer_controls[0],
+       ARRAY_SIZE(wm8510_mono_mixer_controls)),
+SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8510_POWER3, 0, 0),
+SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8510_POWER2, 0, 0),
+SND_SOC_DAPM_PGA("Aux Input", WM8510_POWER1, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA("SpkN Out", WM8510_POWER3, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA("SpkP Out", WM8510_POWER3, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Mono Out", WM8510_POWER3, 7, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Mic PGA", WM8510_POWER2, 2, 0,
+                &wm8510_micpga_controls[0],
+                ARRAY_SIZE(wm8510_micpga_controls)),
+SND_SOC_DAPM_MIXER("Boost Mixer", WM8510_POWER2, 4, 0,
+       &wm8510_boost_controls[0],
+       ARRAY_SIZE(wm8510_boost_controls)),
+
+SND_SOC_DAPM_MICBIAS("Mic Bias", WM8510_POWER1, 4, 0),
+
+SND_SOC_DAPM_INPUT("MICN"),
+SND_SOC_DAPM_INPUT("MICP"),
+SND_SOC_DAPM_INPUT("AUX"),
+SND_SOC_DAPM_OUTPUT("MONOOUT"),
+SND_SOC_DAPM_OUTPUT("SPKOUTP"),
+SND_SOC_DAPM_OUTPUT("SPKOUTN"),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+       /* Mono output mixer */
+       {"Mono Mixer", "PCM Playback Switch", "DAC"},
+       {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
+       {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
+
+       /* Speaker output mixer */
+       {"Speaker Mixer", "PCM Playback Switch", "DAC"},
+       {"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
+       {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
+
+       /* Outputs */
+       {"Mono Out", NULL, "Mono Mixer"},
+       {"MONOOUT", NULL, "Mono Out"},
+       {"SpkN Out", NULL, "Speaker Mixer"},
+       {"SpkP Out", NULL, "Speaker Mixer"},
+       {"SPKOUTN", NULL, "SpkN Out"},
+       {"SPKOUTP", NULL, "SpkP Out"},
+
+       /* Microphone PGA */
+       {"Mic PGA", "MICN Switch", "MICN"},
+       {"Mic PGA", "MICP Switch", "MICP"},
+       { "Mic PGA", "AUX Switch", "Aux Input" },
+
+       /* Boost Mixer */
+       {"Boost Mixer", "Mic PGA Switch", "Mic PGA"},
+       {"Boost Mixer", "Mic Volume", "MICP"},
+       {"Boost Mixer", "Aux Volume", "Aux Input"},
+
+       {"ADC", NULL, "Boost Mixer"},
+};
+
+static int wm8510_add_widgets(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, wm8510_dapm_widgets,
+                                 ARRAY_SIZE(wm8510_dapm_widgets));
+
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+       snd_soc_dapm_new_widgets(codec);
+       return 0;
+}
+
+struct pll_ {
+       unsigned int pre_div:4; /* prescale - 1 */
+       unsigned int n:4;
+       unsigned int k;
+};
+
+static struct pll_ pll_div;
+
+/* The size in bits of the pll divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_PLL_SIZE ((1 << 24) * 10)
+
+static void pll_factors(unsigned int target, unsigned int source)
+{
+       unsigned long long Kpart;
+       unsigned int K, Ndiv, Nmod;
+
+       Ndiv = target / source;
+       if (Ndiv < 6) {
+               source >>= 1;
+               pll_div.pre_div = 1;
+               Ndiv = target / source;
+       } else
+               pll_div.pre_div = 0;
+
+       if ((Ndiv < 6) || (Ndiv > 12))
+               printk(KERN_WARNING
+                       "WM8510 N value %d outwith recommended range!d\n",
+                       Ndiv);
+
+       pll_div.n = Ndiv;
+       Nmod = target % source;
+       Kpart = FIXED_PLL_SIZE * (long long)Nmod;
+
+       do_div(Kpart, source);
+
+       K = Kpart & 0xFFFFFFFF;
+
+       /* Check if we need to round */
+       if ((K % 10) >= 5)
+               K += 5;
+
+       /* Move down to proper range now rounding is done */
+       K /= 10;
+
+       pll_div.k = K;
+}
+
+static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai,
+               int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 reg;
+
+       if (freq_in == 0 || freq_out == 0) {
+               /* Clock CODEC directly from MCLK */
+               reg = wm8510_read_reg_cache(codec, WM8510_CLOCK);
+               wm8510_write(codec, WM8510_CLOCK, reg & 0x0ff);
+
+               /* Turn off PLL */
+               reg = wm8510_read_reg_cache(codec, WM8510_POWER1);
+               wm8510_write(codec, WM8510_POWER1, reg & 0x1df);
+               return 0;
+       }
+
+       pll_factors(freq_out*8, freq_in);
+
+       wm8510_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n);
+       wm8510_write(codec, WM8510_PLLK1, pll_div.k >> 18);
+       wm8510_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff);
+       wm8510_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff);
+       reg = wm8510_read_reg_cache(codec, WM8510_POWER1);
+       wm8510_write(codec, WM8510_POWER1, reg | 0x020);
+
+       /* Run CODEC from PLL instead of MCLK */
+       reg = wm8510_read_reg_cache(codec, WM8510_CLOCK);
+       wm8510_write(codec, WM8510_CLOCK, reg | 0x100);
+
+       return 0;
+}
+
+/*
+ * Configure WM8510 clock dividers.
+ */
+static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
+               int div_id, int div)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 reg;
+
+       switch (div_id) {
+       case WM8510_OPCLKDIV:
+               reg = wm8510_read_reg_cache(codec, WM8510_GPIO) & 0x1cf;
+               wm8510_write(codec, WM8510_GPIO, reg | div);
+               break;
+       case WM8510_MCLKDIV:
+               reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1f;
+               wm8510_write(codec, WM8510_CLOCK, reg | div);
+               break;
+       case WM8510_ADCCLK:
+               reg = wm8510_read_reg_cache(codec, WM8510_ADC) & 0x1f7;
+               wm8510_write(codec, WM8510_ADC, reg | div);
+               break;
+       case WM8510_DACCLK:
+               reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0x1f7;
+               wm8510_write(codec, WM8510_DAC, reg | div);
+               break;
+       case WM8510_BCLKDIV:
+               reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1e3;
+               wm8510_write(codec, WM8510_CLOCK, reg | div);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
+               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 iface = 0;
+       u16 clk = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1fe;
+
+       /* set master/slave audio interface */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               clk |= 0x0001;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* interface format */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               iface |= 0x0010;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               iface |= 0x0008;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               iface |= 0x00018;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* clock inversion */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               iface |= 0x0180;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               iface |= 0x0100;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               iface |= 0x0080;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       wm8510_write(codec, WM8510_IFACE, iface);
+       wm8510_write(codec, WM8510_CLOCK, clk);
+       return 0;
+}
+
+static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f;
+       u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1;
+
+       /* bit size */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               iface |= 0x0020;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               iface |= 0x0040;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               iface |= 0x0060;
+               break;
+       }
+
+       /* filter coefficient */
+       switch (params_rate(params)) {
+       case SNDRV_PCM_RATE_8000:
+               adn |= 0x5 << 1;
+               break;
+       case SNDRV_PCM_RATE_11025:
+               adn |= 0x4 << 1;
+               break;
+       case SNDRV_PCM_RATE_16000:
+               adn |= 0x3 << 1;
+               break;
+       case SNDRV_PCM_RATE_22050:
+               adn |= 0x2 << 1;
+               break;
+       case SNDRV_PCM_RATE_32000:
+               adn |= 0x1 << 1;
+               break;
+       case SNDRV_PCM_RATE_44100:
+       case SNDRV_PCM_RATE_48000:
+               break;
+       }
+
+       wm8510_write(codec, WM8510_IFACE, iface);
+       wm8510_write(codec, WM8510_ADD, adn);
+       return 0;
+}
+
+static int wm8510_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u16 mute_reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0xffbf;
+
+       if (mute)
+               wm8510_write(codec, WM8510_DAC, mute_reg | 0x40);
+       else
+               wm8510_write(codec, WM8510_DAC, mute_reg);
+       return 0;
+}
+
+/* liam need to make this lower power with dapm */
+static int wm8510_set_bias_level(struct snd_soc_codec *codec,
+       enum snd_soc_bias_level level)
+{
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               wm8510_write(codec, WM8510_POWER1, 0x1ff);
+               wm8510_write(codec, WM8510_POWER2, 0x1ff);
+               wm8510_write(codec, WM8510_POWER3, 0x1ff);
+               break;
+       case SND_SOC_BIAS_PREPARE:
+       case SND_SOC_BIAS_STANDBY:
+               break;
+       case SND_SOC_BIAS_OFF:
+               /* everything off, dac mute, inactive */
+               wm8510_write(codec, WM8510_POWER1, 0x0);
+               wm8510_write(codec, WM8510_POWER2, 0x0);
+               wm8510_write(codec, WM8510_POWER3, 0x0);
+               break;
+       }
+       codec->bias_level = level;
+       return 0;
+}
+
+#define WM8510_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+               SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
+               SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+
+#define WM8510_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_dai wm8510_dai = {
+       .name = "WM8510 HiFi",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = WM8510_RATES,
+               .formats = WM8510_FORMATS,},
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = WM8510_RATES,
+               .formats = WM8510_FORMATS,},
+       .ops = {
+               .hw_params = wm8510_pcm_hw_params,
+       },
+       .dai_ops = {
+               .digital_mute = wm8510_mute,
+               .set_fmt = wm8510_set_dai_fmt,
+               .set_clkdiv = wm8510_set_dai_clkdiv,
+               .set_pll = wm8510_set_dai_pll,
+       },
+};
+EXPORT_SYMBOL_GPL(wm8510_dai);
+
+static int wm8510_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int wm8510_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+       int i;
+       u8 data[2];
+       u16 *cache = codec->reg_cache;
+
+       /* Sync reg_cache with the hardware */
+       for (i = 0; i < ARRAY_SIZE(wm8510_reg); i++) {
+               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
+               data[1] = cache[i] & 0x00ff;
+               codec->hw_write(codec->control_data, data, 2);
+       }
+       wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       wm8510_set_bias_level(codec, codec->suspend_bias_level);
+       return 0;
+}
+
+/*
+ * initialise the WM8510 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int wm8510_init(struct snd_soc_device *socdev)
+{
+       struct snd_soc_codec *codec = socdev->codec;
+       int ret = 0;
+
+       codec->name = "WM8510";
+       codec->owner = THIS_MODULE;
+       codec->read = wm8510_read_reg_cache;
+       codec->write = wm8510_write;
+       codec->set_bias_level = wm8510_set_bias_level;
+       codec->dai = &wm8510_dai;
+       codec->num_dai = 1;
+       codec->reg_cache_size = ARRAY_SIZE(wm8510_reg);
+       codec->reg_cache = kmemdup(wm8510_reg, sizeof(wm8510_reg), GFP_KERNEL);
+
+       if (codec->reg_cache == NULL)
+               return -ENOMEM;
+
+       wm8510_reset(codec);
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               printk(KERN_ERR "wm8510: failed to create pcms\n");
+               goto pcm_err;
+       }
+
+       /* power on device */
+       wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       wm8510_add_controls(codec);
+       wm8510_add_widgets(codec);
+       ret = snd_soc_register_card(socdev);
+       if (ret < 0) {
+               printk(KERN_ERR "wm8510: failed to register card\n");
+               goto card_err;
+       }
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       kfree(codec->reg_cache);
+       return ret;
+}
+
+static struct snd_soc_device *wm8510_socdev;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+/*
+ * WM8510 2 wire address is 0x1a
+ */
+#define I2C_DRIVERID_WM8510 0xfefe /* liam -  need a proper id */
+
+static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
+
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver wm8510_i2c_driver;
+static struct i2c_client client_template;
+
+/* If the i2c layer weren't so broken, we could pass this kind of data
+   around */
+
+static int wm8510_codec_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+       struct snd_soc_device *socdev = wm8510_socdev;
+       struct wm8510_setup_data *setup = socdev->codec_data;
+       struct snd_soc_codec *codec = socdev->codec;
+       struct i2c_client *i2c;
+       int ret;
+
+       if (addr != setup->i2c_address)
+               return -ENODEV;
+
+       client_template.adapter = adap;
+       client_template.addr = addr;
+
+       i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
+       if (i2c == NULL) {
+               kfree(codec);
+               return -ENOMEM;
+       }
+       i2c_set_clientdata(i2c, codec);
+       codec->control_data = i2c;
+
+       ret = i2c_attach_client(i2c);
+       if (ret < 0) {
+               pr_err("failed to attach codec at addr %x\n", addr);
+               goto err;
+       }
+
+       ret = wm8510_init(socdev);
+       if (ret < 0) {
+               pr_err("failed to initialise WM8510\n");
+               goto err;
+       }
+       return ret;
+
+err:
+       kfree(codec);
+       kfree(i2c);
+       return ret;
+}
+
+static int wm8510_i2c_detach(struct i2c_client *client)
+{
+       struct snd_soc_codec *codec = i2c_get_clientdata(client);
+       i2c_detach_client(client);
+       kfree(codec->reg_cache);
+       kfree(client);
+       return 0;
+}
+
+static int wm8510_i2c_attach(struct i2c_adapter *adap)
+{
+       return i2c_probe(adap, &addr_data, wm8510_codec_probe);
+}
+
+/* corgi i2c codec control layer */
+static struct i2c_driver wm8510_i2c_driver = {
+       .driver = {
+               .name = "WM8510 I2C Codec",
+               .owner = THIS_MODULE,
+       },
+       .id =             I2C_DRIVERID_WM8510,
+       .attach_adapter = wm8510_i2c_attach,
+       .detach_client =  wm8510_i2c_detach,
+       .command =        NULL,
+};
+
+static struct i2c_client client_template = {
+       .name =   "WM8510",
+       .driver = &wm8510_i2c_driver,
+};
+#endif
+
+static int wm8510_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct wm8510_setup_data *setup;
+       struct snd_soc_codec *codec;
+       int ret = 0;
+
+       pr_info("WM8510 Audio Codec %s", WM8510_VERSION);
+
+       setup = socdev->codec_data;
+       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+       if (codec == NULL)
+               return -ENOMEM;
+
+       socdev->codec = codec;
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       wm8510_socdev = socdev;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       if (setup->i2c_address) {
+               normal_i2c[0] = setup->i2c_address;
+               codec->hw_write = (hw_write_t)i2c_master_send;
+               ret = i2c_add_driver(&wm8510_i2c_driver);
+               if (ret != 0)
+                       printk(KERN_ERR "can't add i2c driver");
+       }
+#else
+       /* Add other interfaces here */
+#endif
+       return ret;
+}
+
+/* power down chip */
+static int wm8510_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       if (codec->control_data)
+               wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&wm8510_i2c_driver);
+#endif
+       kfree(codec);
+
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8510 = {
+       .probe =        wm8510_probe,
+       .remove =       wm8510_remove,
+       .suspend =      wm8510_suspend,
+       .resume =       wm8510_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510);
+
+MODULE_DESCRIPTION("ASoC WM8510 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8510.h b/sound/soc/codecs/wm8510.h
new file mode 100644 (file)
index 0000000..f5d2e42
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * wm8510.h  --  WM8510 Soc Audio driver
+ *
+ * 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 _WM8510_H
+#define _WM8510_H
+
+/* WM8510 register space */
+
+#define WM8510_RESET           0x0
+#define WM8510_POWER1          0x1
+#define WM8510_POWER2          0x2
+#define WM8510_POWER3          0x3
+#define WM8510_IFACE           0x4
+#define WM8510_COMP                    0x5
+#define WM8510_CLOCK           0x6
+#define WM8510_ADD                     0x7
+#define WM8510_GPIO                    0x8
+#define WM8510_DAC                     0xa
+#define WM8510_DACVOL          0xb
+#define WM8510_ADC                     0xe
+#define WM8510_ADCVOL          0xf
+#define WM8510_EQ1                     0x12
+#define WM8510_EQ2                     0x13
+#define WM8510_EQ3                     0x14
+#define WM8510_EQ4                     0x15
+#define WM8510_EQ5                     0x16
+#define WM8510_DACLIM1         0x18
+#define WM8510_DACLIM2         0x19
+#define WM8510_NOTCH1          0x1b
+#define WM8510_NOTCH2          0x1c
+#define WM8510_NOTCH3          0x1d
+#define WM8510_NOTCH4          0x1e
+#define WM8510_ALC1                    0x20
+#define WM8510_ALC2                    0x21
+#define WM8510_ALC3                    0x22
+#define WM8510_NGATE           0x23
+#define WM8510_PLLN                    0x24
+#define WM8510_PLLK1           0x25
+#define WM8510_PLLK2           0x26
+#define WM8510_PLLK3           0x27
+#define WM8510_ATTEN           0x28
+#define WM8510_INPUT           0x2c
+#define WM8510_INPPGA          0x2d
+#define WM8510_ADCBOOST                0x2f
+#define WM8510_OUTPUT          0x31
+#define WM8510_SPKMIX          0x32
+#define WM8510_SPKVOL          0x36
+#define WM8510_MONOMIX         0x38
+
+#define WM8510_CACHEREGNUM     57
+
+/* Clock divider Id's */
+#define WM8510_OPCLKDIV                0
+#define WM8510_MCLKDIV         1
+#define WM8510_ADCCLK          2
+#define WM8510_DACCLK          3
+#define WM8510_BCLKDIV         4
+
+/* DAC clock dividers */
+#define WM8510_DACCLK_F2       (1 << 3)
+#define WM8510_DACCLK_F4       (0 << 3)
+
+/* ADC clock dividers */
+#define WM8510_ADCCLK_F2       (1 << 3)
+#define WM8510_ADCCLK_F4       (0 << 3)
+
+/* PLL Out dividers */
+#define WM8510_OPCLKDIV_1      (0 << 4)
+#define WM8510_OPCLKDIV_2      (1 << 4)
+#define WM8510_OPCLKDIV_3      (2 << 4)
+#define WM8510_OPCLKDIV_4      (3 << 4)
+
+/* BCLK clock dividers */
+#define WM8510_BCLKDIV_1       (0 << 2)
+#define WM8510_BCLKDIV_2       (1 << 2)
+#define WM8510_BCLKDIV_4       (2 << 2)
+#define WM8510_BCLKDIV_8       (3 << 2)
+#define WM8510_BCLKDIV_16      (4 << 2)
+#define WM8510_BCLKDIV_32      (5 << 2)
+
+/* MCLK clock dividers */
+#define WM8510_MCLKDIV_1       (0 << 5)
+#define WM8510_MCLKDIV_1_5     (1 << 5)
+#define WM8510_MCLKDIV_2       (2 << 5)
+#define WM8510_MCLKDIV_3       (3 << 5)
+#define WM8510_MCLKDIV_4       (4 << 5)
+#define WM8510_MCLKDIV_6       (5 << 5)
+#define WM8510_MCLKDIV_8       (6 << 5)
+#define WM8510_MCLKDIV_12      (7 << 5)
+
+struct wm8510_setup_data {
+       unsigned short i2c_address;
+};
+
+extern struct snd_soc_dai wm8510_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8510;
+
+#endif
index 0cf9265fca8fb54ef9c66d1704a896738b60d227..369d39c3f745d9d441ff23d253afaa51dc36aefb 100644 (file)
 #define AUDIO_NAME "wm8731"
 #define WM8731_VERSION "0.13"
 
-/*
- * Debug
- */
-
-#define WM8731_DEBUG 0
-
-#ifdef WM8731_DEBUG
-#define dbg(format, arg...) \
-       printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
-#else
-#define dbg(format, arg...) do {} while (0)
-#endif
-#define err(format, arg...) \
-       printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
-#define info(format, arg...) \
-       printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
-#define warn(format, arg...) \
-       printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
-
 struct snd_soc_codec_device soc_codec_dev_wm8731;
 
 /* codec private data */
@@ -193,7 +174,7 @@ SND_SOC_DAPM_INPUT("RLINEIN"),
 SND_SOC_DAPM_INPUT("LLINEIN"),
 };
 
-static const char *intercon[][3] = {
+static const struct snd_soc_dapm_route intercon[] = {
        /* output mixer */
        {"Output Mixer", "Line Bypass Switch", "Line Input"},
        {"Output Mixer", "HiFi Playback Switch", "DAC"},
@@ -214,22 +195,14 @@ static const char *intercon[][3] = {
        {"Line Input", NULL, "LLINEIN"},
        {"Line Input", NULL, "RLINEIN"},
        {"Mic Bias", NULL, "MICIN"},
-
-       /* terminator */
-       {NULL, NULL, NULL},
 };
 
 static int wm8731_add_widgets(struct snd_soc_codec *codec)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
-               snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
+       snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
+                                 ARRAY_SIZE(wm8731_dapm_widgets));
 
-       /* set up audio path interconnects */
-       for (i = 0; intercon[i][0] != NULL; i++)
-               snd_soc_dapm_connect_input(codec, intercon[i][0],
-                       intercon[i][1], intercon[i][2]);
+       snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
 
        snd_soc_dapm_new_widgets(codec);
        return 0;
@@ -345,7 +318,7 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream)
        }
 }
 
-static int wm8731_mute(struct snd_soc_codec_dai *dai, int mute)
+static int wm8731_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
        u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7;
@@ -357,7 +330,7 @@ static int wm8731_mute(struct snd_soc_codec_dai *dai, int mute)
        return 0;
 }
 
-static int wm8731_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
+static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
                int clk_id, unsigned int freq, int dir)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -376,7 +349,7 @@ static int wm8731_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
 }
 
 
-static int wm8731_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -435,29 +408,29 @@ static int wm8731_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
        return 0;
 }
 
-static int wm8731_dapm_event(struct snd_soc_codec *codec, int event)
+static int wm8731_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
 {
        u16 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f;
 
-       switch (event) {
-       case SNDRV_CTL_POWER_D0: /* full On */
+       switch (level) {
+       case SND_SOC_BIAS_ON:
                /* vref/mid, osc on, dac unmute */
                wm8731_write(codec, WM8731_PWR, reg);
                break;
-       case SNDRV_CTL_POWER_D1: /* partial On */
-       case SNDRV_CTL_POWER_D2: /* partial On */
+       case SND_SOC_BIAS_PREPARE:
                break;
-       case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+       case SND_SOC_BIAS_STANDBY:
                /* everything off except vref/vmid, */
                wm8731_write(codec, WM8731_PWR, reg | 0x0040);
                break;
-       case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+       case SND_SOC_BIAS_OFF:
                /* everything off, dac mute, inactive */
                wm8731_write(codec, WM8731_ACTIVE, 0x0);
                wm8731_write(codec, WM8731_PWR, 0xffff);
                break;
        }
-       codec->dapm_state = event;
+       codec->bias_level = level;
        return 0;
 }
 
@@ -470,7 +443,7 @@ static int wm8731_dapm_event(struct snd_soc_codec *codec, int event)
 #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
 
-struct snd_soc_codec_dai wm8731_dai = {
+struct snd_soc_dai wm8731_dai = {
        .name = "WM8731",
        .playback = {
                .stream_name = "Playback",
@@ -503,7 +476,7 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
        struct snd_soc_codec *codec = socdev->codec;
 
        wm8731_write(codec, WM8731_ACTIVE, 0x0);
-       wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+       wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
@@ -521,8 +494,8 @@ static int wm8731_resume(struct platform_device *pdev)
                data[1] = cache[i] & 0x00ff;
                codec->hw_write(codec->control_data, data, 2);
        }
-       wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
-       wm8731_dapm_event(codec, codec->suspend_dapm_state);
+       wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       wm8731_set_bias_level(codec, codec->suspend_bias_level);
        return 0;
 }
 
@@ -539,10 +512,10 @@ static int wm8731_init(struct snd_soc_device *socdev)
        codec->owner = THIS_MODULE;
        codec->read = wm8731_read_reg_cache;
        codec->write = wm8731_write;
-       codec->dapm_event = wm8731_dapm_event;
+       codec->set_bias_level = wm8731_set_bias_level;
        codec->dai = &wm8731_dai;
        codec->num_dai = 1;
-       codec->reg_cache_size = sizeof(wm8731_reg);
+       codec->reg_cache_size = ARRAY_SIZE(wm8731_reg);
        codec->reg_cache = kmemdup(wm8731_reg, sizeof(wm8731_reg), GFP_KERNEL);
        if (codec->reg_cache == NULL)
                return -ENOMEM;
@@ -557,7 +530,7 @@ static int wm8731_init(struct snd_soc_device *socdev)
        }
 
        /* power on device */
-       wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+       wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* set the update bits */
        reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V);
@@ -632,13 +605,13 @@ static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind)
 
        ret = i2c_attach_client(i2c);
        if (ret < 0) {
-               err("failed to attach codec at addr %x\n", addr);
+               pr_err("failed to attach codec at addr %x\n", addr);
                goto err;
        }
 
        ret = wm8731_init(socdev);
        if (ret < 0) {
-               err("failed to initialise WM8731\n");
+               pr_err("failed to initialise WM8731\n");
                goto err;
        }
        return ret;
@@ -689,7 +662,7 @@ static int wm8731_probe(struct platform_device *pdev)
        struct wm8731_priv *wm8731;
        int ret = 0;
 
-       info("WM8731 Audio Codec %s", WM8731_VERSION);
+       pr_info("WM8731 Audio Codec %s", WM8731_VERSION);
 
        setup = socdev->codec_data;
        codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
@@ -730,7 +703,7 @@ static int wm8731_remove(struct platform_device *pdev)
        struct snd_soc_codec *codec = socdev->codec;
 
        if (codec->control_data)
-               wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+               wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
index 5bcab6a7afb4f8c2a760637383201944c87da565..99f2e3c60e3331c6802318b636ff709fc4796518 100644 (file)
@@ -38,7 +38,7 @@ struct wm8731_setup_data {
        unsigned short i2c_address;
 };
 
-extern struct snd_soc_codec_dai wm8731_dai;
+extern struct snd_soc_dai wm8731_dai;
 extern struct snd_soc_codec_device soc_codec_dev_wm8731;
 
 #endif
index 16cd5d4d5ad97108443d6bc1e51db727c282b5d4..e23cb09f0d1499ef76a1fd50790b14e4aef1500a 100644 (file)
 #define AUDIO_NAME "WM8750"
 #define WM8750_VERSION "0.12"
 
-/*
- * Debug
- */
-
-#define WM8750_DEBUG 0
-
-#ifdef WM8750_DEBUG
-#define dbg(format, arg...) \
-       printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
-#else
-#define dbg(format, arg...) do {} while (0)
-#endif
-#define err(format, arg...) \
-       printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
-#define info(format, arg...) \
-       printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
-#define warn(format, arg...) \
-       printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
-
 /* codec private data */
 struct wm8750_priv {
        unsigned int sysclk;
@@ -378,7 +359,7 @@ static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("RINPUT3"),
 };
 
-static const char *audio_map[][3] = {
+static const struct snd_soc_dapm_route audio_map[] = {
        /* left mixer */
        {"Left Mixer", "Playback Switch", "Left DAC"},
        {"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
@@ -470,22 +451,14 @@ static const char *audio_map[][3] = {
        /* ADC */
        {"Left ADC", NULL, "Left ADC Mux"},
        {"Right ADC", NULL, "Right ADC Mux"},
-
-       /* terminator */
-       {NULL, NULL, NULL},
 };
 
 static int wm8750_add_widgets(struct snd_soc_codec *codec)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++)
-               snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
+       snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
+                                 ARRAY_SIZE(wm8750_dapm_widgets));
 
-       /* set up audio path audio_mapnects */
-       for (i = 0; audio_map[i][0] != NULL; i++)
-               snd_soc_dapm_connect_input(codec, audio_map[i][0],
-                       audio_map[i][1], audio_map[i][2]);
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
 
        snd_soc_dapm_new_widgets(codec);
        return 0;
@@ -563,7 +536,7 @@ static inline int get_coeff(int mclk, int rate)
        return -EINVAL;
 }
 
-static int wm8750_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
+static int wm8750_set_dai_sysclk(struct snd_soc_dai *codec_dai,
                int clk_id, unsigned int freq, int dir)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -581,7 +554,7 @@ static int wm8750_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
        return -EINVAL;
 }
 
-static int wm8750_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -674,7 +647,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int wm8750_mute(struct snd_soc_codec_dai *dai, int mute)
+static int wm8750_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
        u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7;
@@ -686,29 +659,29 @@ static int wm8750_mute(struct snd_soc_codec_dai *dai, int mute)
        return 0;
 }
 
-static int wm8750_dapm_event(struct snd_soc_codec *codec, int event)
+static int wm8750_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
 {
        u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e;
 
-       switch (event) {
-       case SNDRV_CTL_POWER_D0: /* full On */
+       switch (level) {
+       case SND_SOC_BIAS_ON:
                /* set vmid to 50k and unmute dac */
                wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
                break;
-       case SNDRV_CTL_POWER_D1: /* partial On */
-       case SNDRV_CTL_POWER_D2: /* partial On */
+       case SND_SOC_BIAS_PREPARE:
                /* set vmid to 5k for quick power up */
                wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
                break;
-       case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+       case SND_SOC_BIAS_STANDBY:
                /* mute dac and set vmid to 500k, enable VREF */
                wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
                break;
-       case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+       case SND_SOC_BIAS_OFF:
                wm8750_write(codec, WM8750_PWR1, 0x0001);
                break;
        }
-       codec->dapm_state = event;
+       codec->bias_level = level;
        return 0;
 }
 
@@ -719,7 +692,7 @@ static int wm8750_dapm_event(struct snd_soc_codec *codec, int event)
 #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
        SNDRV_PCM_FMTBIT_S24_LE)
 
-struct snd_soc_codec_dai wm8750_dai = {
+struct snd_soc_dai wm8750_dai = {
        .name = "WM8750",
        .playback = {
                .stream_name = "Playback",
@@ -748,7 +721,7 @@ static void wm8750_work(struct work_struct *work)
 {
        struct snd_soc_codec *codec =
                container_of(work, struct snd_soc_codec, delayed_work.work);
-       wm8750_dapm_event(codec, codec->dapm_state);
+       wm8750_set_bias_level(codec, codec->bias_level);
 }
 
 static int wm8750_suspend(struct platform_device *pdev, pm_message_t state)
@@ -756,7 +729,7 @@ static int wm8750_suspend(struct platform_device *pdev, pm_message_t state)
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_codec *codec = socdev->codec;
 
-       wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+       wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
@@ -777,12 +750,12 @@ static int wm8750_resume(struct platform_device *pdev)
                codec->hw_write(codec->control_data, data, 2);
        }
 
-       wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+       wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* charge wm8750 caps */
-       if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) {
-               wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
-               codec->dapm_state = SNDRV_CTL_POWER_D0;
+       if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
+               wm8750_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
+               codec->bias_level = SND_SOC_BIAS_ON;
                schedule_delayed_work(&codec->delayed_work,
                                        msecs_to_jiffies(1000));
        }
@@ -803,10 +776,10 @@ static int wm8750_init(struct snd_soc_device *socdev)
        codec->owner = THIS_MODULE;
        codec->read = wm8750_read_reg_cache;
        codec->write = wm8750_write;
-       codec->dapm_event = wm8750_dapm_event;
+       codec->set_bias_level = wm8750_set_bias_level;
        codec->dai = &wm8750_dai;
        codec->num_dai = 1;
-       codec->reg_cache_size = sizeof(wm8750_reg);
+       codec->reg_cache_size = ARRAY_SIZE(wm8750_reg);
        codec->reg_cache = kmemdup(wm8750_reg, sizeof(wm8750_reg), GFP_KERNEL);
        if (codec->reg_cache == NULL)
                return -ENOMEM;
@@ -821,8 +794,8 @@ static int wm8750_init(struct snd_soc_device *socdev)
        }
 
        /* charge output caps */
-       wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
-       codec->dapm_state = SNDRV_CTL_POWER_D3hot;
+       wm8750_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
+       codec->bias_level = SND_SOC_BIAS_STANDBY;
        schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
 
        /* set the update bits */
@@ -904,13 +877,13 @@ static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind)
 
        ret = i2c_attach_client(i2c);
        if (ret < 0) {
-               err("failed to attach codec at addr %x\n", addr);
+               pr_err("failed to attach codec at addr %x\n", addr);
                goto err;
        }
 
        ret = wm8750_init(socdev);
        if (ret < 0) {
-       err("failed to initialise WM8750\n");
+               pr_err("failed to initialise WM8750\n");
                goto err;
        }
        return ret;
@@ -961,7 +934,7 @@ static int wm8750_probe(struct platform_device *pdev)
        struct wm8750_priv *wm8750;
        int ret = 0;
 
-       info("WM8750 Audio Codec %s", WM8750_VERSION);
+       pr_info("WM8750 Audio Codec %s", WM8750_VERSION);
        codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
        if (codec == NULL)
                return -ENOMEM;
@@ -1021,7 +994,7 @@ static int wm8750_remove(struct platform_device *pdev)
        struct snd_soc_codec *codec = socdev->codec;
 
        if (codec->control_data)
-               wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+               wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
        run_delayed_work(&codec->delayed_work);
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
index a97a54a6348ee492c7e2c4b7f0f35b7761ab8db0..8ef30e628b21963a35d10668747f7b76874a4192 100644 (file)
@@ -61,7 +61,7 @@ struct wm8750_setup_data {
        unsigned short i2c_address;
 };
 
-extern struct snd_soc_codec_dai wm8750_dai;
+extern struct snd_soc_dai wm8750_dai;
 extern struct snd_soc_codec_device soc_codec_dev_wm8750;
 
 #endif
index fb41826c4c4cdba27f39486eab75f888ff08cc99..8604809f0c362b75ee150ae0292663683baebf6f 100644 (file)
 #define AUDIO_NAME "wm8753"
 #define WM8753_VERSION "0.16"
 
-/*
- * Debug
- */
-
-#define WM8753_DEBUG 0
-
-#ifdef WM8753_DEBUG
-#define dbg(format, arg...) \
-       printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
-#else
-#define dbg(format, arg...) do {} while (0)
-#endif
-#define err(format, arg...) \
-       printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
-#define info(format, arg...) \
-       printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
-#define warn(format, arg...) \
-       printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
-
 static int caps_charge = 2000;
 module_param(caps_charge, int, 0);
 MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
@@ -260,28 +241,50 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
        return 1;
 }
 
-static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600);
+static const DECLARE_TLV_DB_SCALE(rec_mix_tlv, -1500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(mic_preamp_tlv, 1200, 600, 0);
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
+static const unsigned int out_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       /* 0000000 - 0101111 = "Analogue mute" */
+       0, 48, TLV_DB_SCALE_ITEM(-25500, 0, 0),
+       48, 127, TLV_DB_SCALE_ITEM(-7300, 100, 0),
+};
+static const DECLARE_TLV_DB_SCALE(mix_tlv, -1500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(voice_mix_tlv, -1200, 300, 0);
+static const DECLARE_TLV_DB_SCALE(pga_tlv, -1725, 75, 0);
 
 static const struct snd_kcontrol_new wm8753_snd_controls[] = {
-SOC_DOUBLE_R("PCM Volume", WM8753_LDAC, WM8753_RDAC, 0, 255, 0),
-
-SOC_DOUBLE_R("ADC Capture Volume", WM8753_LADC, WM8753_RADC, 0, 255, 0),
-
-SOC_DOUBLE_R("Headphone Playback Volume", WM8753_LOUT1V, WM8753_ROUT1V, 0, 127, 0),
-SOC_DOUBLE_R("Speaker Playback Volume", WM8753_LOUT2V, WM8753_ROUT2V, 0, 127, 0),
-
-SOC_SINGLE("Mono Playback Volume", WM8753_MOUTV, 0, 127, 0),
-
-SOC_DOUBLE_R("Bypass Playback Volume", WM8753_LOUTM1, WM8753_ROUTM1, 4, 7, 1),
-SOC_DOUBLE_R("Sidetone Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 4, 7, 1),
-SOC_DOUBLE_R("Voice Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 0, 7, 1),
-
-SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8753_LOUT1V, WM8753_ROUT1V, 7, 1, 0),
-SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7, 1, 0),
-
-SOC_SINGLE("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1),
-SOC_SINGLE("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1),
-SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 0, 7, 1),
+SOC_DOUBLE_R_TLV("PCM Volume", WM8753_LDAC, WM8753_RDAC, 0, 255, 0, dac_tlv),
+
+SOC_DOUBLE_R_TLV("ADC Capture Volume", WM8753_LADC, WM8753_RADC, 0, 255, 0,
+                adc_tlv),
+
+SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8753_LOUT1V, WM8753_ROUT1V,
+                0, 127, 0, out_tlv),
+SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8753_LOUT2V, WM8753_ROUT2V, 0,
+                127, 0, out_tlv),
+
+SOC_SINGLE_TLV("Mono Playback Volume", WM8753_MOUTV, 0, 127, 0, out_tlv),
+
+SOC_DOUBLE_R_TLV("Bypass Playback Volume", WM8753_LOUTM1, WM8753_ROUTM1, 4, 7,
+                1, mix_tlv),
+SOC_DOUBLE_R_TLV("Sidetone Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 4,
+                7, 1, mix_tlv),
+SOC_DOUBLE_R_TLV("Voice Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 0, 7,
+                1, voice_mix_tlv),
+
+SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8753_LOUT1V, WM8753_ROUT1V, 7,
+            1, 0),
+SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7,
+            1, 0),
+
+SOC_SINGLE_TLV("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1, mix_tlv),
+SOC_SINGLE_TLV("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1,
+              mix_tlv),
+SOC_SINGLE_TLV("Mono Voice Playback Volume", WM8753_MOUTM2, 0, 7, 1,
+              voice_mix_tlv),
 SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0),
 
 SOC_ENUM("Bass Boost", wm8753_enum[0]),
@@ -291,10 +294,13 @@ SOC_SINGLE("Bass Volume", WM8753_BASS, 0, 15, 1),
 SOC_SINGLE("Treble Volume", WM8753_TREBLE, 0, 15, 1),
 SOC_ENUM("Treble Cut-off", wm8753_enum[2]),
 
-SOC_DOUBLE_TLV("Sidetone Capture Volume", WM8753_RECMIX1, 0, 4, 7, 1, rec_mix_tlv),
-SOC_SINGLE_TLV("Voice Sidetone Capture Volume", WM8753_RECMIX2, 0, 7, 1, rec_mix_tlv),
+SOC_DOUBLE_TLV("Sidetone Capture Volume", WM8753_RECMIX1, 0, 4, 7, 1,
+              rec_mix_tlv),
+SOC_SINGLE_TLV("Voice Sidetone Capture Volume", WM8753_RECMIX2, 0, 7, 1,
+              rec_mix_tlv),
 
-SOC_DOUBLE_R("Capture Volume", WM8753_LINVOL, WM8753_RINVOL, 0, 63, 0),
+SOC_DOUBLE_R_TLV("Capture Volume", WM8753_LINVOL, WM8753_RINVOL, 0, 63, 0,
+                pga_tlv),
 SOC_DOUBLE_R("Capture ZC Switch", WM8753_LINVOL, WM8753_RINVOL, 6, 1, 0),
 SOC_DOUBLE_R("Capture Switch", WM8753_LINVOL, WM8753_RINVOL, 7, 1, 1),
 
@@ -326,8 +332,8 @@ SOC_ENUM("De-emphasis", wm8753_enum[8]),
 SOC_ENUM("Playback Mono Mix", wm8753_enum[9]),
 SOC_ENUM("Playback Phase", wm8753_enum[10]),
 
-SOC_SINGLE("Mic2 Capture Volume", WM8753_INCTL1, 7, 3, 0),
-SOC_SINGLE("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0),
+SOC_SINGLE_TLV("Mic2 Capture Volume", WM8753_INCTL1, 7, 3, 0, mic_preamp_tlv),
+SOC_SINGLE_TLV("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0, mic_preamp_tlv),
 
 SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai),
 
@@ -523,7 +529,7 @@ SND_SOC_DAPM_INPUT("MIC2"),
 SND_SOC_DAPM_VMID("VREF"),
 };
 
-static const char *audio_map[][3] = {
+static const struct snd_soc_dapm_route audio_map[] = {
        /* left mixer */
        {"Left Mixer", "Left Playback Switch", "Left DAC"},
        {"Left Mixer", "Voice Playback Switch", "Voice DAC"},
@@ -674,23 +680,14 @@ static const char *audio_map[][3] = {
 
        /* ACOP */
        {"ACOP", NULL, "ALC Mixer"},
-
-       /* terminator */
-       {NULL, NULL, NULL},
 };
 
 static int wm8753_add_widgets(struct snd_soc_codec *codec)
 {
-       int i;
+       snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
+                                 ARRAY_SIZE(wm8753_dapm_widgets));
 
-       for (i = 0; i < ARRAY_SIZE(wm8753_dapm_widgets); i++)
-               snd_soc_dapm_new_control(codec, &wm8753_dapm_widgets[i]);
-
-       /* set up the WM8753 audio map */
-       for (i = 0; audio_map[i][0] != NULL; i++) {
-               snd_soc_dapm_connect_input(codec, audio_map[i][0],
-                       audio_map[i][1], audio_map[i][2]);
-       }
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
 
        snd_soc_dapm_new_widgets(codec);
        return 0;
@@ -743,7 +740,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
        pll_div->k = K;
 }
 
-static int wm8753_set_dai_pll(struct snd_soc_codec_dai *codec_dai,
+static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai,
                int pll_id, unsigned int freq_in, unsigned int freq_out)
 {
        u16 reg, enable;
@@ -866,7 +863,7 @@ static int get_coeff(int mclk, int rate)
 /*
  * Clock after PLL and dividers
  */
-static int wm8753_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
+static int wm8753_set_dai_sysclk(struct snd_soc_dai *codec_dai,
                int clk_id, unsigned int freq, int dir)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -893,7 +890,7 @@ static int wm8753_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
 /*
  * Set's ADC and Voice DAC format.
  */
-static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -963,7 +960,7 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
 /*
  * Set's PCM dai fmt and BCLK.
  */
-static int wm8753_pcm_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -1029,7 +1026,7 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
        return 0;
 }
 
-static int wm8753_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
+static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
                int div_id, int div)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -1057,7 +1054,7 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
 /*
  * Set's HiFi DAC format.
  */
-static int wm8753_hdac_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -1090,7 +1087,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
 /*
  * Set's I2S DAI format.
  */
-static int wm8753_i2s_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -1198,7 +1195,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int wm8753_mode1v_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -1213,7 +1210,7 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
        return wm8753_pcm_set_dai_fmt(codec_dai, fmt);
 }
 
-static int wm8753_mode1h_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int wm8753_mode1h_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
@@ -1221,7 +1218,7 @@ static int wm8753_mode1h_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
        return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
 }
 
-static int wm8753_mode2_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -1236,7 +1233,7 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
        return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
 }
 
-static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -1253,7 +1250,7 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
        return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
 }
 
-static int wm8753_mute(struct snd_soc_codec_dai *dai, int mute)
+static int wm8753_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
        u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7;
@@ -1274,29 +1271,29 @@ static int wm8753_mute(struct snd_soc_codec_dai *dai, int mute)
        return 0;
 }
 
-static int wm8753_dapm_event(struct snd_soc_codec *codec, int event)
+static int wm8753_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
 {
        u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e;
 
-       switch (event) {
-       case SNDRV_CTL_POWER_D0: /* full On */
+       switch (level) {
+       case SND_SOC_BIAS_ON:
                /* set vmid to 50k and unmute dac */
                wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
                break;
-       case SNDRV_CTL_POWER_D1: /* partial On */
-       case SNDRV_CTL_POWER_D2: /* partial On */
+       case SND_SOC_BIAS_PREPARE:
                /* set vmid to 5k for quick power up */
                wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
                break;
-       case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+       case SND_SOC_BIAS_STANDBY:
                /* mute dac and set vmid to 500k, enable VREF */
                wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
                break;
-       case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+       case SND_SOC_BIAS_OFF:
                wm8753_write(codec, WM8753_PWR1, 0x0001);
                break;
        }
-       codec->dapm_state = event;
+       codec->bias_level = level;
        return 0;
 }
 
@@ -1319,7 +1316,7 @@ static int wm8753_dapm_event(struct snd_soc_codec *codec, int event)
  * 3. Voice disabled - HIFI over HIFI
  * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
  */
-static const struct snd_soc_codec_dai wm8753_all_dai[] = {
+static const struct snd_soc_dai wm8753_all_dai[] = {
 /* DAI HiFi mode 1 */
 {      .name = "WM8753 HiFi",
        .id = 1,
@@ -1459,7 +1456,7 @@ static const struct snd_soc_codec_dai wm8753_all_dai[] = {
 },
 };
 
-struct snd_soc_codec_dai wm8753_dai[2];
+struct snd_soc_dai wm8753_dai[2];
 EXPORT_SYMBOL_GPL(wm8753_dai);
 
 static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode)
@@ -1500,7 +1497,7 @@ static void wm8753_work(struct work_struct *work)
 {
        struct snd_soc_codec *codec =
                container_of(work, struct snd_soc_codec, delayed_work.work);
-       wm8753_dapm_event(codec, codec->dapm_state);
+       wm8753_set_bias_level(codec, codec->bias_level);
 }
 
 static int wm8753_suspend(struct platform_device *pdev, pm_message_t state)
@@ -1512,7 +1509,7 @@ static int wm8753_suspend(struct platform_device *pdev, pm_message_t state)
        if (!codec->card)
                return 0;
 
-       wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+       wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
@@ -1537,12 +1534,12 @@ static int wm8753_resume(struct platform_device *pdev)
                codec->hw_write(codec->control_data, data, 2);
        }
 
-       wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+       wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* charge wm8753 caps */
-       if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) {
-               wm8753_dapm_event(codec, SNDRV_CTL_POWER_D2);
-               codec->dapm_state = SNDRV_CTL_POWER_D0;
+       if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
+               wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
+               codec->bias_level = SND_SOC_BIAS_ON;
                schedule_delayed_work(&codec->delayed_work,
                        msecs_to_jiffies(caps_charge));
        }
@@ -1563,10 +1560,10 @@ static int wm8753_init(struct snd_soc_device *socdev)
        codec->owner = THIS_MODULE;
        codec->read = wm8753_read_reg_cache;
        codec->write = wm8753_write;
-       codec->dapm_event = wm8753_dapm_event;
+       codec->set_bias_level = wm8753_set_bias_level;
        codec->dai = wm8753_dai;
        codec->num_dai = 2;
-       codec->reg_cache_size = sizeof(wm8753_reg);
+       codec->reg_cache_size = ARRAY_SIZE(wm8753_reg);
        codec->reg_cache = kmemdup(wm8753_reg, sizeof(wm8753_reg), GFP_KERNEL);
 
        if (codec->reg_cache == NULL)
@@ -1584,8 +1581,8 @@ static int wm8753_init(struct snd_soc_device *socdev)
        }
 
        /* charge output caps */
-       wm8753_dapm_event(codec, SNDRV_CTL_POWER_D2);
-       codec->dapm_state = SNDRV_CTL_POWER_D3hot;
+       wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
+       codec->bias_level = SND_SOC_BIAS_STANDBY;
        schedule_delayed_work(&codec->delayed_work,
                msecs_to_jiffies(caps_charge));
 
@@ -1673,13 +1670,13 @@ static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind)
 
        ret = i2c_attach_client(i2c);
        if (ret < 0) {
-               err("failed to attach codec at addr %x\n", addr);
+               pr_err("failed to attach codec at addr %x\n", addr);
                goto err;
        }
 
        ret = wm8753_init(socdev);
        if (ret < 0) {
-               err("failed to initialise WM8753\n");
+               pr_err("failed to initialise WM8753\n");
                goto err;
        }
 
@@ -1731,7 +1728,7 @@ static int wm8753_probe(struct platform_device *pdev)
        struct wm8753_priv *wm8753;
        int ret = 0;
 
-       info("WM8753 Audio Codec %s", WM8753_VERSION);
+       pr_info("WM8753 Audio Codec %s", WM8753_VERSION);
 
        setup = socdev->codec_data;
        codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
@@ -1792,7 +1789,7 @@ static int wm8753_remove(struct platform_device *pdev)
        struct snd_soc_codec *codec = socdev->codec;
 
        if (codec->control_data)
-               wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+               wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
        run_delayed_work(&codec->delayed_work);
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
index 95e2a1f53169f6ee9fd5da0e9c1ed14c7af1581f..44f5f1ff0cc7080bfb920c0c5fbb345901896e8a 100644 (file)
@@ -120,7 +120,7 @@ struct wm8753_setup_data {
 #define WM8753_DAI_HIFI                0
 #define WM8753_DAI_VOICE               1
 
-extern struct snd_soc_codec_dai wm8753_dai[2];
+extern struct snd_soc_dai wm8753_dai[2];
 extern struct snd_soc_codec_device soc_codec_dev_wm8753;
 
 #endif
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
new file mode 100644 (file)
index 0000000..3ecce51
--- /dev/null
@@ -0,0 +1,1626 @@
+/*
+ * wm8990.c  --  WM8990 ALSA Soc Audio driver
+ *
+ * Copyright 2008 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         lg@opensource.wolfsonmicro.com or linux@wolfsonmicro.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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <asm/div64.h>
+
+#include "wm8990.h"
+
+#define AUDIO_NAME "wm8990"
+#define WM8990_VERSION "0.2"
+
+/* codec private data */
+struct wm8990_priv {
+       unsigned int sysclk;
+       unsigned int pcmclk;
+};
+
+/*
+ * wm8990 register cache.  Note that register 0 is not included in the
+ * cache.
+ */
+static const u16 wm8990_reg[] = {
+       0x8990,     /* R0  - Reset */
+       0x0000,     /* R1  - Power Management (1) */
+       0x6000,     /* R2  - Power Management (2) */
+       0x0000,     /* R3  - Power Management (3) */
+       0x4050,     /* R4  - Audio Interface (1) */
+       0x4000,     /* R5  - Audio Interface (2) */
+       0x01C8,     /* R6  - Clocking (1) */
+       0x0000,     /* R7  - Clocking (2) */
+       0x0040,     /* R8  - Audio Interface (3) */
+       0x0040,     /* R9  - Audio Interface (4) */
+       0x0004,     /* R10 - DAC CTRL */
+       0x00C0,     /* R11 - Left DAC Digital Volume */
+       0x00C0,     /* R12 - Right DAC Digital Volume */
+       0x0000,     /* R13 - Digital Side Tone */
+       0x0100,     /* R14 - ADC CTRL */
+       0x00C0,     /* R15 - Left ADC Digital Volume */
+       0x00C0,     /* R16 - Right ADC Digital Volume */
+       0x0000,     /* R17 */
+       0x0000,     /* R18 - GPIO CTRL 1 */
+       0x1000,     /* R19 - GPIO1 & GPIO2 */
+       0x1010,     /* R20 - GPIO3 & GPIO4 */
+       0x1010,     /* R21 - GPIO5 & GPIO6 */
+       0x8000,     /* R22 - GPIOCTRL 2 */
+       0x0800,     /* R23 - GPIO_POL */
+       0x008B,     /* R24 - Left Line Input 1&2 Volume */
+       0x008B,     /* R25 - Left Line Input 3&4 Volume */
+       0x008B,     /* R26 - Right Line Input 1&2 Volume */
+       0x008B,     /* R27 - Right Line Input 3&4 Volume */
+       0x0000,     /* R28 - Left Output Volume */
+       0x0000,     /* R29 - Right Output Volume */
+       0x0066,     /* R30 - Line Outputs Volume */
+       0x0022,     /* R31 - Out3/4 Volume */
+       0x0079,     /* R32 - Left OPGA Volume */
+       0x0079,     /* R33 - Right OPGA Volume */
+       0x0003,     /* R34 - Speaker Volume */
+       0x0003,     /* R35 - ClassD1 */
+       0x0000,     /* R36 */
+       0x0100,     /* R37 - ClassD3 */
+       0x0000,     /* R38 */
+       0x0000,     /* R39 - Input Mixer1 */
+       0x0000,     /* R40 - Input Mixer2 */
+       0x0000,     /* R41 - Input Mixer3 */
+       0x0000,     /* R42 - Input Mixer4 */
+       0x0000,     /* R43 - Input Mixer5 */
+       0x0000,     /* R44 - Input Mixer6 */
+       0x0000,     /* R45 - Output Mixer1 */
+       0x0000,     /* R46 - Output Mixer2 */
+       0x0000,     /* R47 - Output Mixer3 */
+       0x0000,     /* R48 - Output Mixer4 */
+       0x0000,     /* R49 - Output Mixer5 */
+       0x0000,     /* R50 - Output Mixer6 */
+       0x0180,     /* R51 - Out3/4 Mixer */
+       0x0000,     /* R52 - Line Mixer1 */
+       0x0000,     /* R53 - Line Mixer2 */
+       0x0000,     /* R54 - Speaker Mixer */
+       0x0000,     /* R55 - Additional Control */
+       0x0000,     /* R56 - AntiPOP1 */
+       0x0000,     /* R57 - AntiPOP2 */
+       0x0000,     /* R58 - MICBIAS */
+       0x0000,     /* R59 */
+       0x0008,     /* R60 - PLL1 */
+       0x0031,     /* R61 - PLL2 */
+       0x0026,     /* R62 - PLL3 */
+};
+
+/*
+ * read wm8990 register cache
+ */
+static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec,
+       unsigned int reg)
+{
+       u16 *cache = codec->reg_cache;
+       BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1);
+       return cache[reg];
+}
+
+/*
+ * write wm8990 register cache
+ */
+static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec,
+       unsigned int reg, unsigned int value)
+{
+       u16 *cache = codec->reg_cache;
+       BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1);
+
+       /* Reset register is uncached */
+       if (reg == 0)
+               return;
+
+       cache[reg] = value;
+}
+
+/*
+ * write to the wm8990 register space
+ */
+static int wm8990_write(struct snd_soc_codec *codec, unsigned int reg,
+       unsigned int value)
+{
+       u8 data[3];
+
+       data[0] = reg & 0xFF;
+       data[1] = (value >> 8) & 0xFF;
+       data[2] = value & 0xFF;
+
+       wm8990_write_reg_cache(codec, reg, value);
+
+       if (codec->hw_write(codec->control_data, data, 3) == 2)
+               return 0;
+       else
+               return -EIO;
+}
+
+#define wm8990_reset(c) wm8990_write(c, WM8990_RESET, 0)
+
+static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600);
+
+static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000);
+
+static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, 0, -2100);
+
+static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600);
+
+static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0);
+
+static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0);
+
+static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763);
+
+static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0);
+
+static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       int reg = kcontrol->private_value & 0xff;
+       int ret;
+       u16 val;
+
+       ret = snd_soc_put_volsw(kcontrol, ucontrol);
+       if (ret < 0)
+               return ret;
+
+       /* now hit the volume update bits (always bit 8) */
+       val = wm8990_read_reg_cache(codec, reg);
+       return wm8990_write(codec, reg, val | 0x0100);
+}
+
+#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
+        tlv_array) {\
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+                 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+       .tlv.p = (tlv_array), \
+       .info = snd_soc_info_volsw, \
+       .get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \
+       .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
+
+
+static const char *wm8990_digital_sidetone[] =
+       {"None", "Left ADC", "Right ADC", "Reserved"};
+
+static const struct soc_enum wm8990_left_digital_sidetone_enum =
+SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE,
+       WM8990_ADC_TO_DACL_SHIFT,
+       WM8990_ADC_TO_DACL_MASK,
+       wm8990_digital_sidetone);
+
+static const struct soc_enum wm8990_right_digital_sidetone_enum =
+SOC_ENUM_SINGLE(WM8990_DIGITAL_SIDE_TONE,
+       WM8990_ADC_TO_DACR_SHIFT,
+       WM8990_ADC_TO_DACR_MASK,
+       wm8990_digital_sidetone);
+
+static const char *wm8990_adcmode[] =
+       {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
+
+static const struct soc_enum wm8990_right_adcmode_enum =
+SOC_ENUM_SINGLE(WM8990_ADC_CTRL,
+       WM8990_ADC_HPF_CUT_SHIFT,
+       WM8990_ADC_HPF_CUT_MASK,
+       wm8990_adcmode);
+
+static const struct snd_kcontrol_new wm8990_snd_controls[] = {
+/* INMIXL */
+SOC_SINGLE("LIN12 PGA Boost", WM8990_INPUT_MIXER3, WM8990_L12MNBST_BIT, 1, 0),
+SOC_SINGLE("LIN34 PGA Boost", WM8990_INPUT_MIXER3, WM8990_L34MNBST_BIT, 1, 0),
+/* INMIXR */
+SOC_SINGLE("RIN12 PGA Boost", WM8990_INPUT_MIXER3, WM8990_R12MNBST_BIT, 1, 0),
+SOC_SINGLE("RIN34 PGA Boost", WM8990_INPUT_MIXER3, WM8990_R34MNBST_BIT, 1, 0),
+
+/* LOMIX */
+SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8990_OUTPUT_MIXER3,
+       WM8990_LLI3LOVOL_SHIFT, WM8990_LLI3LOVOL_MASK, 1, out_mix_tlv),
+SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER3,
+       WM8990_LR12LOVOL_SHIFT, WM8990_LR12LOVOL_MASK, 1, out_mix_tlv),
+SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER3,
+       WM8990_LL12LOVOL_SHIFT, WM8990_LL12LOVOL_MASK, 1, out_mix_tlv),
+SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8990_OUTPUT_MIXER5,
+       WM8990_LRI3LOVOL_SHIFT, WM8990_LRI3LOVOL_MASK, 1, out_mix_tlv),
+SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8990_OUTPUT_MIXER5,
+       WM8990_LRBLOVOL_SHIFT, WM8990_LRBLOVOL_MASK, 1, out_mix_tlv),
+SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8990_OUTPUT_MIXER5,
+       WM8990_LRBLOVOL_SHIFT, WM8990_LRBLOVOL_MASK, 1, out_mix_tlv),
+
+/* ROMIX */
+SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8990_OUTPUT_MIXER4,
+       WM8990_RRI3ROVOL_SHIFT, WM8990_RRI3ROVOL_MASK, 1, out_mix_tlv),
+SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER4,
+       WM8990_RL12ROVOL_SHIFT, WM8990_RL12ROVOL_MASK, 1, out_mix_tlv),
+SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8990_OUTPUT_MIXER4,
+       WM8990_RR12ROVOL_SHIFT, WM8990_RR12ROVOL_MASK, 1, out_mix_tlv),
+SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8990_OUTPUT_MIXER6,
+       WM8990_RLI3ROVOL_SHIFT, WM8990_RLI3ROVOL_MASK, 1, out_mix_tlv),
+SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8990_OUTPUT_MIXER6,
+       WM8990_RLBROVOL_SHIFT, WM8990_RLBROVOL_MASK, 1, out_mix_tlv),
+SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8990_OUTPUT_MIXER6,
+       WM8990_RRBROVOL_SHIFT, WM8990_RRBROVOL_MASK, 1, out_mix_tlv),
+
+/* LOUT */
+SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8990_LEFT_OUTPUT_VOLUME,
+       WM8990_LOUTVOL_SHIFT, WM8990_LOUTVOL_MASK, 0, out_pga_tlv),
+SOC_SINGLE("LOUT ZC", WM8990_LEFT_OUTPUT_VOLUME, WM8990_LOZC_BIT, 1, 0),
+
+/* ROUT */
+SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8990_RIGHT_OUTPUT_VOLUME,
+       WM8990_ROUTVOL_SHIFT, WM8990_ROUTVOL_MASK, 0, out_pga_tlv),
+SOC_SINGLE("ROUT ZC", WM8990_RIGHT_OUTPUT_VOLUME, WM8990_ROZC_BIT, 1, 0),
+
+/* LOPGA */
+SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8990_LEFT_OPGA_VOLUME,
+       WM8990_LOPGAVOL_SHIFT, WM8990_LOPGAVOL_MASK, 0, out_pga_tlv),
+SOC_SINGLE("LOPGA ZC Switch", WM8990_LEFT_OPGA_VOLUME,
+       WM8990_LOPGAZC_BIT, 1, 0),
+
+/* ROPGA */
+SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8990_RIGHT_OPGA_VOLUME,
+       WM8990_ROPGAVOL_SHIFT, WM8990_ROPGAVOL_MASK, 0, out_pga_tlv),
+SOC_SINGLE("ROPGA ZC Switch", WM8990_RIGHT_OPGA_VOLUME,
+       WM8990_ROPGAZC_BIT, 1, 0),
+
+SOC_SINGLE("LON Mute Switch", WM8990_LINE_OUTPUTS_VOLUME,
+       WM8990_LONMUTE_BIT, 1, 0),
+SOC_SINGLE("LOP Mute Switch", WM8990_LINE_OUTPUTS_VOLUME,
+       WM8990_LOPMUTE_BIT, 1, 0),
+SOC_SINGLE("LOP Attenuation Switch", WM8990_LINE_OUTPUTS_VOLUME,
+       WM8990_LOATTN_BIT, 1, 0),
+SOC_SINGLE("RON Mute Switch", WM8990_LINE_OUTPUTS_VOLUME,
+       WM8990_RONMUTE_BIT, 1, 0),
+SOC_SINGLE("ROP Mute Switch", WM8990_LINE_OUTPUTS_VOLUME,
+       WM8990_ROPMUTE_BIT, 1, 0),
+SOC_SINGLE("ROP Attenuation Switch", WM8990_LINE_OUTPUTS_VOLUME,
+       WM8990_ROATTN_BIT, 1, 0),
+
+SOC_SINGLE("OUT3 Mute Switch", WM8990_OUT3_4_VOLUME,
+       WM8990_OUT3MUTE_BIT, 1, 0),
+SOC_SINGLE("OUT3 Attenuation Switch", WM8990_OUT3_4_VOLUME,
+       WM8990_OUT3ATTN_BIT, 1, 0),
+
+SOC_SINGLE("OUT4 Mute Switch", WM8990_OUT3_4_VOLUME,
+       WM8990_OUT4MUTE_BIT, 1, 0),
+SOC_SINGLE("OUT4 Attenuation Switch", WM8990_OUT3_4_VOLUME,
+       WM8990_OUT4ATTN_BIT, 1, 0),
+
+SOC_SINGLE("Speaker Mode Switch", WM8990_CLASSD1,
+       WM8990_CDMODE_BIT, 1, 0),
+
+SOC_SINGLE("Speaker Output Attenuation Volume", WM8990_SPEAKER_VOLUME,
+       WM8990_SPKVOL_SHIFT, WM8990_SPKVOL_MASK, 0),
+SOC_SINGLE("Speaker DC Boost Volume", WM8990_CLASSD3,
+       WM8990_DCGAIN_SHIFT, WM8990_DCGAIN_MASK, 0),
+SOC_SINGLE("Speaker AC Boost Volume", WM8990_CLASSD3,
+       WM8990_ACGAIN_SHIFT, WM8990_ACGAIN_MASK, 0),
+
+SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume",
+       WM8990_LEFT_DAC_DIGITAL_VOLUME,
+       WM8990_DACL_VOL_SHIFT,
+       WM8990_DACL_VOL_MASK,
+       0,
+       out_dac_tlv),
+
+SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume",
+       WM8990_RIGHT_DAC_DIGITAL_VOLUME,
+       WM8990_DACR_VOL_SHIFT,
+       WM8990_DACR_VOL_MASK,
+       0,
+       out_dac_tlv),
+
+SOC_ENUM("Left Digital Sidetone", wm8990_left_digital_sidetone_enum),
+SOC_ENUM("Right Digital Sidetone", wm8990_right_digital_sidetone_enum),
+
+SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8990_DIGITAL_SIDE_TONE,
+       WM8990_ADCL_DAC_SVOL_SHIFT, WM8990_ADCL_DAC_SVOL_MASK, 0,
+       out_sidetone_tlv),
+SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8990_DIGITAL_SIDE_TONE,
+       WM8990_ADCR_DAC_SVOL_SHIFT, WM8990_ADCR_DAC_SVOL_MASK, 0,
+       out_sidetone_tlv),
+
+SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8990_ADC_CTRL,
+       WM8990_ADC_HPF_ENA_BIT, 1, 0),
+
+SOC_ENUM("ADC HPF Mode", wm8990_right_adcmode_enum),
+
+SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume",
+       WM8990_LEFT_ADC_DIGITAL_VOLUME,
+       WM8990_ADCL_VOL_SHIFT,
+       WM8990_ADCL_VOL_MASK,
+       0,
+       in_adc_tlv),
+
+SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume",
+       WM8990_RIGHT_ADC_DIGITAL_VOLUME,
+       WM8990_ADCR_VOL_SHIFT,
+       WM8990_ADCR_VOL_MASK,
+       0,
+       in_adc_tlv),
+
+SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN12 Volume",
+       WM8990_LEFT_LINE_INPUT_1_2_VOLUME,
+       WM8990_LIN12VOL_SHIFT,
+       WM8990_LIN12VOL_MASK,
+       0,
+       in_pga_tlv),
+
+SOC_SINGLE("LIN12 ZC Switch", WM8990_LEFT_LINE_INPUT_1_2_VOLUME,
+       WM8990_LI12ZC_BIT, 1, 0),
+
+SOC_SINGLE("LIN12 Mute Switch", WM8990_LEFT_LINE_INPUT_1_2_VOLUME,
+       WM8990_LI12MUTE_BIT, 1, 0),
+
+SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN34 Volume",
+       WM8990_LEFT_LINE_INPUT_3_4_VOLUME,
+       WM8990_LIN34VOL_SHIFT,
+       WM8990_LIN34VOL_MASK,
+       0,
+       in_pga_tlv),
+
+SOC_SINGLE("LIN34 ZC Switch", WM8990_LEFT_LINE_INPUT_3_4_VOLUME,
+       WM8990_LI34ZC_BIT, 1, 0),
+
+SOC_SINGLE("LIN34 Mute Switch", WM8990_LEFT_LINE_INPUT_3_4_VOLUME,
+       WM8990_LI34MUTE_BIT, 1, 0),
+
+SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN12 Volume",
+       WM8990_RIGHT_LINE_INPUT_1_2_VOLUME,
+       WM8990_RIN12VOL_SHIFT,
+       WM8990_RIN12VOL_MASK,
+       0,
+       in_pga_tlv),
+
+SOC_SINGLE("RIN12 ZC Switch", WM8990_RIGHT_LINE_INPUT_1_2_VOLUME,
+       WM8990_RI12ZC_BIT, 1, 0),
+
+SOC_SINGLE("RIN12 Mute Switch", WM8990_RIGHT_LINE_INPUT_1_2_VOLUME,
+       WM8990_RI12MUTE_BIT, 1, 0),
+
+SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN34 Volume",
+       WM8990_RIGHT_LINE_INPUT_3_4_VOLUME,
+       WM8990_RIN34VOL_SHIFT,
+       WM8990_RIN34VOL_MASK,
+       0,
+       in_pga_tlv),
+
+SOC_SINGLE("RIN34 ZC Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME,
+       WM8990_RI34ZC_BIT, 1, 0),
+
+SOC_SINGLE("RIN34 Mute Switch", WM8990_RIGHT_LINE_INPUT_3_4_VOLUME,
+       WM8990_RI34MUTE_BIT, 1, 0),
+
+};
+
+/* add non dapm controls */
+static int wm8990_add_controls(struct snd_soc_codec *codec)
+{
+       int err, i;
+
+       for (i = 0; i < ARRAY_SIZE(wm8990_snd_controls); i++) {
+               err = snd_ctl_add(codec->card,
+                               snd_soc_cnew(&wm8990_snd_controls[i], codec,
+                                       NULL));
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
+/*
+ * _DAPM_ Controls
+ */
+
+static int inmixer_event(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       u16 reg, fakepower;
+
+       reg = wm8990_read_reg_cache(w->codec, WM8990_POWER_MANAGEMENT_2);
+       fakepower = wm8990_read_reg_cache(w->codec, WM8990_INTDRIVBITS);
+
+       if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) |
+               (1 << WM8990_AINLMUX_PWR_BIT))) {
+               reg |= WM8990_AINL_ENA;
+       } else {
+               reg &= ~WM8990_AINL_ENA;
+       }
+
+       if (fakepower & ((1 << WM8990_INMIXR_PWR_BIT) |
+               (1 << WM8990_AINRMUX_PWR_BIT))) {
+               reg |= WM8990_AINR_ENA;
+       } else {
+               reg &= ~WM8990_AINL_ENA;
+       }
+       wm8990_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
+
+       return 0;
+}
+
+static int outmixer_event(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       u32 reg_shift = kcontrol->private_value & 0xfff;
+       int ret = 0;
+       u16 reg;
+
+       switch (reg_shift) {
+       case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) :
+               reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER1);
+               if (reg & WM8990_LDLO) {
+                       printk(KERN_WARNING
+                       "Cannot set as Output Mixer 1 LDLO Set\n");
+                       ret = -1;
+               }
+               break;
+       case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8):
+               reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER2);
+               if (reg & WM8990_RDRO) {
+                       printk(KERN_WARNING
+                       "Cannot set as Output Mixer 2 RDRO Set\n");
+                       ret = -1;
+               }
+               break;
+       case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8):
+               reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER);
+               if (reg & WM8990_LDSPK) {
+                       printk(KERN_WARNING
+                       "Cannot set as Speaker Mixer LDSPK Set\n");
+                       ret = -1;
+               }
+               break;
+       case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8):
+               reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER);
+               if (reg & WM8990_RDSPK) {
+                       printk(KERN_WARNING
+                       "Cannot set as Speaker Mixer RDSPK Set\n");
+                       ret = -1;
+               }
+               break;
+       }
+
+       return ret;
+}
+
+/* INMIX dB values */
+static const unsigned int in_mix_tlv[] = {
+       TLV_DB_RANGE_HEAD(1),
+       0, 7, TLV_DB_LINEAR_ITEM(-1200, 600),
+};
+
+/* Left In PGA Connections */
+static const struct snd_kcontrol_new wm8990_dapm_lin12_pga_controls[] = {
+SOC_DAPM_SINGLE("LIN1 Switch", WM8990_INPUT_MIXER2, WM8990_LMN1_BIT, 1, 0),
+SOC_DAPM_SINGLE("LIN2 Switch", WM8990_INPUT_MIXER2, WM8990_LMP2_BIT, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8990_dapm_lin34_pga_controls[] = {
+SOC_DAPM_SINGLE("LIN3 Switch", WM8990_INPUT_MIXER2, WM8990_LMN3_BIT, 1, 0),
+SOC_DAPM_SINGLE("LIN4 Switch", WM8990_INPUT_MIXER2, WM8990_LMP4_BIT, 1, 0),
+};
+
+/* Right In PGA Connections */
+static const struct snd_kcontrol_new wm8990_dapm_rin12_pga_controls[] = {
+SOC_DAPM_SINGLE("RIN1 Switch", WM8990_INPUT_MIXER2, WM8990_RMN1_BIT, 1, 0),
+SOC_DAPM_SINGLE("RIN2 Switch", WM8990_INPUT_MIXER2, WM8990_RMP2_BIT, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8990_dapm_rin34_pga_controls[] = {
+SOC_DAPM_SINGLE("RIN3 Switch", WM8990_INPUT_MIXER2, WM8990_RMN3_BIT, 1, 0),
+SOC_DAPM_SINGLE("RIN4 Switch", WM8990_INPUT_MIXER2, WM8990_RMP4_BIT, 1, 0),
+};
+
+/* INMIXL */
+static const struct snd_kcontrol_new wm8990_dapm_inmixl_controls[] = {
+SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8990_INPUT_MIXER3,
+       WM8990_LDBVOL_SHIFT, WM8990_LDBVOL_MASK, 0, in_mix_tlv),
+SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8990_INPUT_MIXER5, WM8990_LI2BVOL_SHIFT,
+       7, 0, in_mix_tlv),
+SOC_DAPM_SINGLE("LINPGA12 Switch", WM8990_INPUT_MIXER3, WM8990_L12MNB_BIT,
+       1, 0),
+SOC_DAPM_SINGLE("LINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT,
+       1, 0),
+};
+
+/* INMIXR */
+static const struct snd_kcontrol_new wm8990_dapm_inmixr_controls[] = {
+SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8990_INPUT_MIXER4,
+       WM8990_RDBVOL_SHIFT, WM8990_RDBVOL_MASK, 0, in_mix_tlv),
+SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8990_INPUT_MIXER6, WM8990_RI2BVOL_SHIFT,
+       7, 0, in_mix_tlv),
+SOC_DAPM_SINGLE("RINPGA12 Switch", WM8990_INPUT_MIXER3, WM8990_L12MNB_BIT,
+       1, 0),
+SOC_DAPM_SINGLE("RINPGA34 Switch", WM8990_INPUT_MIXER3, WM8990_L34MNB_BIT,
+       1, 0),
+};
+
+/* AINLMUX */
+static const char *wm8990_ainlmux[] =
+       {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
+
+static const struct soc_enum wm8990_ainlmux_enum =
+SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINLMODE_SHIFT,
+       ARRAY_SIZE(wm8990_ainlmux), wm8990_ainlmux);
+
+static const struct snd_kcontrol_new wm8990_dapm_ainlmux_controls =
+SOC_DAPM_ENUM("Route", wm8990_ainlmux_enum);
+
+/* DIFFINL */
+
+/* AINRMUX */
+static const char *wm8990_ainrmux[] =
+       {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
+
+static const struct soc_enum wm8990_ainrmux_enum =
+SOC_ENUM_SINGLE(WM8990_INPUT_MIXER1, WM8990_AINRMODE_SHIFT,
+       ARRAY_SIZE(wm8990_ainrmux), wm8990_ainrmux);
+
+static const struct snd_kcontrol_new wm8990_dapm_ainrmux_controls =
+SOC_DAPM_ENUM("Route", wm8990_ainrmux_enum);
+
+/* RXVOICE */
+static const struct snd_kcontrol_new wm8990_dapm_rxvoice_controls[] = {
+SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8990_INPUT_MIXER5, WM8990_LR4BVOL_SHIFT,
+                       WM8990_LR4BVOL_MASK, 0, in_mix_tlv),
+SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8990_INPUT_MIXER6, WM8990_RL4BVOL_SHIFT,
+                       WM8990_RL4BVOL_MASK, 0, in_mix_tlv),
+};
+
+/* LOMIX */
+static const struct snd_kcontrol_new wm8990_dapm_lomix_controls[] = {
+SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8990_OUTPUT_MIXER1,
+       WM8990_LRBLO_BIT, 1, 0),
+SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8990_OUTPUT_MIXER1,
+       WM8990_LLBLO_BIT, 1, 0),
+SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8990_OUTPUT_MIXER1,
+       WM8990_LRI3LO_BIT, 1, 0),
+SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8990_OUTPUT_MIXER1,
+       WM8990_LLI3LO_BIT, 1, 0),
+SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER1,
+       WM8990_LR12LO_BIT, 1, 0),
+SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER1,
+       WM8990_LL12LO_BIT, 1, 0),
+SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8990_OUTPUT_MIXER1,
+       WM8990_LDLO_BIT, 1, 0),
+};
+
+/* ROMIX */
+static const struct snd_kcontrol_new wm8990_dapm_romix_controls[] = {
+SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8990_OUTPUT_MIXER2,
+       WM8990_RLBRO_BIT, 1, 0),
+SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8990_OUTPUT_MIXER2,
+       WM8990_RRBRO_BIT, 1, 0),
+SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8990_OUTPUT_MIXER2,
+       WM8990_RLI3RO_BIT, 1, 0),
+SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8990_OUTPUT_MIXER2,
+       WM8990_RRI3RO_BIT, 1, 0),
+SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER2,
+       WM8990_RL12RO_BIT, 1, 0),
+SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8990_OUTPUT_MIXER2,
+       WM8990_RR12RO_BIT, 1, 0),
+SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8990_OUTPUT_MIXER2,
+       WM8990_RDRO_BIT, 1, 0),
+};
+
+/* LONMIX */
+static const struct snd_kcontrol_new wm8990_dapm_lonmix_controls[] = {
+SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8990_LINE_MIXER1,
+       WM8990_LLOPGALON_BIT, 1, 0),
+SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8990_LINE_MIXER1,
+       WM8990_LROPGALON_BIT, 1, 0),
+SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8990_LINE_MIXER1,
+       WM8990_LOPLON_BIT, 1, 0),
+};
+
+/* LOPMIX */
+static const struct snd_kcontrol_new wm8990_dapm_lopmix_controls[] = {
+SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8990_LINE_MIXER1,
+       WM8990_LR12LOP_BIT, 1, 0),
+SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8990_LINE_MIXER1,
+       WM8990_LL12LOP_BIT, 1, 0),
+SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8990_LINE_MIXER1,
+       WM8990_LLOPGALOP_BIT, 1, 0),
+};
+
+/* RONMIX */
+static const struct snd_kcontrol_new wm8990_dapm_ronmix_controls[] = {
+SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8990_LINE_MIXER2,
+       WM8990_RROPGARON_BIT, 1, 0),
+SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8990_LINE_MIXER2,
+       WM8990_RLOPGARON_BIT, 1, 0),
+SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8990_LINE_MIXER2,
+       WM8990_ROPRON_BIT, 1, 0),
+};
+
+/* ROPMIX */
+static const struct snd_kcontrol_new wm8990_dapm_ropmix_controls[] = {
+SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8990_LINE_MIXER2,
+       WM8990_RL12ROP_BIT, 1, 0),
+SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8990_LINE_MIXER2,
+       WM8990_RR12ROP_BIT, 1, 0),
+SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8990_LINE_MIXER2,
+       WM8990_RROPGAROP_BIT, 1, 0),
+};
+
+/* OUT3MIX */
+static const struct snd_kcontrol_new wm8990_dapm_out3mix_controls[] = {
+SOC_DAPM_SINGLE("OUT3MIX LIN4/RXP Bypass Switch", WM8990_OUT3_4_MIXER,
+       WM8990_LI4O3_BIT, 1, 0),
+SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8990_OUT3_4_MIXER,
+       WM8990_LPGAO3_BIT, 1, 0),
+};
+
+/* OUT4MIX */
+static const struct snd_kcontrol_new wm8990_dapm_out4mix_controls[] = {
+SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8990_OUT3_4_MIXER,
+       WM8990_RPGAO4_BIT, 1, 0),
+SOC_DAPM_SINGLE("OUT4MIX RIN4/RXP Bypass Switch", WM8990_OUT3_4_MIXER,
+       WM8990_RI4O4_BIT, 1, 0),
+};
+
+/* SPKMIX */
+static const struct snd_kcontrol_new wm8990_dapm_spkmix_controls[] = {
+SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8990_SPEAKER_MIXER,
+       WM8990_LI2SPK_BIT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8990_SPEAKER_MIXER,
+       WM8990_LB2SPK_BIT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8990_SPEAKER_MIXER,
+       WM8990_LOPGASPK_BIT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8990_SPEAKER_MIXER,
+       WM8990_LDSPK_BIT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8990_SPEAKER_MIXER,
+       WM8990_RDSPK_BIT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8990_SPEAKER_MIXER,
+       WM8990_ROPGASPK_BIT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8990_SPEAKER_MIXER,
+       WM8990_RL12ROP_BIT, 1, 0),
+SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8990_SPEAKER_MIXER,
+       WM8990_RI2SPK_BIT, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget wm8990_dapm_widgets[] = {
+/* Input Side */
+/* Input Lines */
+SND_SOC_DAPM_INPUT("LIN1"),
+SND_SOC_DAPM_INPUT("LIN2"),
+SND_SOC_DAPM_INPUT("LIN3"),
+SND_SOC_DAPM_INPUT("LIN4/RXN"),
+SND_SOC_DAPM_INPUT("RIN3"),
+SND_SOC_DAPM_INPUT("RIN4/RXP"),
+SND_SOC_DAPM_INPUT("RIN1"),
+SND_SOC_DAPM_INPUT("RIN2"),
+SND_SOC_DAPM_INPUT("Internal ADC Source"),
+
+/* DACs */
+SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8990_POWER_MANAGEMENT_2,
+       WM8990_ADCL_ENA_BIT, 0),
+SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8990_POWER_MANAGEMENT_2,
+       WM8990_ADCR_ENA_BIT, 0),
+
+/* Input PGAs */
+SND_SOC_DAPM_MIXER("LIN12 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_LIN12_ENA_BIT,
+       0, &wm8990_dapm_lin12_pga_controls[0],
+       ARRAY_SIZE(wm8990_dapm_lin12_pga_controls)),
+SND_SOC_DAPM_MIXER("LIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_LIN34_ENA_BIT,
+       0, &wm8990_dapm_lin34_pga_controls[0],
+       ARRAY_SIZE(wm8990_dapm_lin34_pga_controls)),
+SND_SOC_DAPM_MIXER("RIN12 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN12_ENA_BIT,
+       0, &wm8990_dapm_rin12_pga_controls[0],
+       ARRAY_SIZE(wm8990_dapm_rin12_pga_controls)),
+SND_SOC_DAPM_MIXER("RIN34 PGA", WM8990_POWER_MANAGEMENT_2, WM8990_RIN34_ENA_BIT,
+       0, &wm8990_dapm_rin34_pga_controls[0],
+       ARRAY_SIZE(wm8990_dapm_rin34_pga_controls)),
+
+/* INMIXL */
+SND_SOC_DAPM_MIXER_E("INMIXL", WM8990_INTDRIVBITS, WM8990_INMIXL_PWR_BIT, 0,
+       &wm8990_dapm_inmixl_controls[0],
+       ARRAY_SIZE(wm8990_dapm_inmixl_controls),
+       inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+/* AINLMUX */
+SND_SOC_DAPM_MUX_E("AILNMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0,
+       &wm8990_dapm_ainlmux_controls, inmixer_event,
+       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+/* INMIXR */
+SND_SOC_DAPM_MIXER_E("INMIXR", WM8990_INTDRIVBITS, WM8990_INMIXR_PWR_BIT, 0,
+       &wm8990_dapm_inmixr_controls[0],
+       ARRAY_SIZE(wm8990_dapm_inmixr_controls),
+       inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+/* AINRMUX */
+SND_SOC_DAPM_MUX_E("AIRNMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0,
+       &wm8990_dapm_ainrmux_controls, inmixer_event,
+       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+/* Output Side */
+/* DACs */
+SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8990_POWER_MANAGEMENT_3,
+       WM8990_DACL_ENA_BIT, 0),
+SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8990_POWER_MANAGEMENT_3,
+       WM8990_DACR_ENA_BIT, 0),
+
+/* LOMIX */
+SND_SOC_DAPM_MIXER_E("LOMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LOMIX_ENA_BIT,
+       0, &wm8990_dapm_lomix_controls[0],
+       ARRAY_SIZE(wm8990_dapm_lomix_controls),
+       outmixer_event, SND_SOC_DAPM_PRE_REG),
+
+/* LONMIX */
+SND_SOC_DAPM_MIXER("LONMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LON_ENA_BIT, 0,
+       &wm8990_dapm_lonmix_controls[0],
+       ARRAY_SIZE(wm8990_dapm_lonmix_controls)),
+
+/* LOPMIX */
+SND_SOC_DAPM_MIXER("LOPMIX", WM8990_POWER_MANAGEMENT_3, WM8990_LOP_ENA_BIT, 0,
+       &wm8990_dapm_lopmix_controls[0],
+       ARRAY_SIZE(wm8990_dapm_lopmix_controls)),
+
+/* OUT3MIX */
+SND_SOC_DAPM_MIXER("OUT3MIX", WM8990_POWER_MANAGEMENT_1, WM8990_OUT3_ENA_BIT, 0,
+       &wm8990_dapm_out3mix_controls[0],
+       ARRAY_SIZE(wm8990_dapm_out3mix_controls)),
+
+/* SPKMIX */
+SND_SOC_DAPM_MIXER_E("SPKMIX", WM8990_POWER_MANAGEMENT_1, WM8990_SPK_ENA_BIT, 0,
+       &wm8990_dapm_spkmix_controls[0],
+       ARRAY_SIZE(wm8990_dapm_spkmix_controls), outmixer_event,
+       SND_SOC_DAPM_PRE_REG),
+
+/* OUT4MIX */
+SND_SOC_DAPM_MIXER("OUT4MIX", WM8990_POWER_MANAGEMENT_1, WM8990_OUT4_ENA_BIT, 0,
+       &wm8990_dapm_out4mix_controls[0],
+       ARRAY_SIZE(wm8990_dapm_out4mix_controls)),
+
+/* ROPMIX */
+SND_SOC_DAPM_MIXER("ROPMIX", WM8990_POWER_MANAGEMENT_3, WM8990_ROP_ENA_BIT, 0,
+       &wm8990_dapm_ropmix_controls[0],
+       ARRAY_SIZE(wm8990_dapm_ropmix_controls)),
+
+/* RONMIX */
+SND_SOC_DAPM_MIXER("RONMIX", WM8990_POWER_MANAGEMENT_3, WM8990_RON_ENA_BIT, 0,
+       &wm8990_dapm_ronmix_controls[0],
+       ARRAY_SIZE(wm8990_dapm_ronmix_controls)),
+
+/* ROMIX */
+SND_SOC_DAPM_MIXER_E("ROMIX", WM8990_POWER_MANAGEMENT_3, WM8990_ROMIX_ENA_BIT,
+       0, &wm8990_dapm_romix_controls[0],
+       ARRAY_SIZE(wm8990_dapm_romix_controls),
+       outmixer_event, SND_SOC_DAPM_PRE_REG),
+
+/* LOUT PGA */
+SND_SOC_DAPM_PGA("LOUT PGA", WM8990_POWER_MANAGEMENT_1, WM8990_LOUT_ENA_BIT, 0,
+       NULL, 0),
+
+/* ROUT PGA */
+SND_SOC_DAPM_PGA("ROUT PGA", WM8990_POWER_MANAGEMENT_1, WM8990_ROUT_ENA_BIT, 0,
+       NULL, 0),
+
+/* LOPGA */
+SND_SOC_DAPM_PGA("LOPGA", WM8990_POWER_MANAGEMENT_3, WM8990_LOPGA_ENA_BIT, 0,
+       NULL, 0),
+
+/* ROPGA */
+SND_SOC_DAPM_PGA("ROPGA", WM8990_POWER_MANAGEMENT_3, WM8990_ROPGA_ENA_BIT, 0,
+       NULL, 0),
+
+/* MICBIAS */
+SND_SOC_DAPM_MICBIAS("MICBIAS", WM8990_POWER_MANAGEMENT_1,
+       WM8990_MICBIAS_ENA_BIT, 0),
+
+SND_SOC_DAPM_OUTPUT("LON"),
+SND_SOC_DAPM_OUTPUT("LOP"),
+SND_SOC_DAPM_OUTPUT("OUT3"),
+SND_SOC_DAPM_OUTPUT("LOUT"),
+SND_SOC_DAPM_OUTPUT("SPKN"),
+SND_SOC_DAPM_OUTPUT("SPKP"),
+SND_SOC_DAPM_OUTPUT("ROUT"),
+SND_SOC_DAPM_OUTPUT("OUT4"),
+SND_SOC_DAPM_OUTPUT("ROP"),
+SND_SOC_DAPM_OUTPUT("RON"),
+
+SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+       /* Make DACs turn on when playing even if not mixed into any outputs */
+       {"Internal DAC Sink", NULL, "Left DAC"},
+       {"Internal DAC Sink", NULL, "Right DAC"},
+
+       /* Make ADCs turn on when recording even if not mixed from any inputs */
+       {"Left ADC", NULL, "Internal ADC Source"},
+       {"Right ADC", NULL, "Internal ADC Source"},
+
+       /* Input Side */
+       /* LIN12 PGA */
+       {"LIN12 PGA", "LIN1 Switch", "LIN1"},
+       {"LIN12 PGA", "LIN2 Switch", "LIN2"},
+       /* LIN34 PGA */
+       {"LIN34 PGA", "LIN3 Switch", "LIN3"},
+       {"LIN34 PGA", "LIN4 Switch", "LIN4"},
+       /* INMIXL */
+       {"INMIXL", "Record Left Volume", "LOMIX"},
+       {"INMIXL", "LIN2 Volume", "LIN2"},
+       {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"},
+       {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"},
+       /* AILNMUX */
+       {"AILNMUX", "INMIXL Mix", "INMIXL"},
+       {"AILNMUX", "DIFFINL Mix", "LIN12PGA"},
+       {"AILNMUX", "DIFFINL Mix", "LIN34PGA"},
+       {"AILNMUX", "RXVOICE Mix", "LIN4/RXN"},
+       {"AILNMUX", "RXVOICE Mix", "RIN4/RXP"},
+       /* ADC */
+       {"Left ADC", NULL, "AILNMUX"},
+
+       /* RIN12 PGA */
+       {"RIN12 PGA", "RIN1 Switch", "RIN1"},
+       {"RIN12 PGA", "RIN2 Switch", "RIN2"},
+       /* RIN34 PGA */
+       {"RIN34 PGA", "RIN3 Switch", "RIN3"},
+       {"RIN34 PGA", "RIN4 Switch", "RIN4"},
+       /* INMIXL */
+       {"INMIXR", "Record Right Volume", "ROMIX"},
+       {"INMIXR", "RIN2 Volume", "RIN2"},
+       {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"},
+       {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"},
+       /* AIRNMUX */
+       {"AIRNMUX", "INMIXR Mix", "INMIXR"},
+       {"AIRNMUX", "DIFFINR Mix", "RIN12PGA"},
+       {"AIRNMUX", "DIFFINR Mix", "RIN34PGA"},
+       {"AIRNMUX", "RXVOICE Mix", "RIN4/RXN"},
+       {"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"},
+       /* ADC */
+       {"Right ADC", NULL, "AIRNMUX"},
+
+       /* LOMIX */
+       {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"},
+       {"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"},
+       {"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
+       {"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
+       {"LOMIX", "LOMIX Right ADC Bypass Switch", "AINRMUX"},
+       {"LOMIX", "LOMIX Left ADC Bypass Switch", "AINLMUX"},
+       {"LOMIX", "LOMIX Left DAC Switch", "Left DAC"},
+
+       /* ROMIX */
+       {"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"},
+       {"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"},
+       {"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
+       {"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
+       {"ROMIX", "ROMIX Right ADC Bypass Switch", "AINRMUX"},
+       {"ROMIX", "ROMIX Left ADC Bypass Switch", "AINLMUX"},
+       {"ROMIX", "ROMIX Right DAC Switch", "Right DAC"},
+
+       /* SPKMIX */
+       {"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"},
+       {"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"},
+       {"SPKMIX", "SPKMIX LADC Bypass Switch", "AINLMUX"},
+       {"SPKMIX", "SPKMIX RADC Bypass Switch", "AINRMUX"},
+       {"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"},
+       {"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"},
+       {"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"},
+       {"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"},
+
+       /* LONMIX */
+       {"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"},
+       {"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"},
+       {"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"},
+
+       /* LOPMIX */
+       {"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"},
+       {"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"},
+       {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"},
+
+       /* OUT3MIX */
+       {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXP"},
+       {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"},
+
+       /* OUT4MIX */
+       {"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"},
+       {"OUT4MIX", "OUT4MIX RIN4/RXP Bypass Switch", "RIN4/RXP"},
+
+       /* RONMIX */
+       {"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"},
+       {"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"},
+       {"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"},
+
+       /* ROPMIX */
+       {"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"},
+       {"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"},
+       {"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"},
+
+       /* Out Mixer PGAs */
+       {"LOPGA", NULL, "LOMIX"},
+       {"ROPGA", NULL, "ROMIX"},
+
+       {"LOUT PGA", NULL, "LOMIX"},
+       {"ROUT PGA", NULL, "ROMIX"},
+
+       /* Output Pins */
+       {"LON", NULL, "LONMIX"},
+       {"LOP", NULL, "LOPMIX"},
+       {"OUT", NULL, "OUT3MIX"},
+       {"LOUT", NULL, "LOUT PGA"},
+       {"SPKN", NULL, "SPKMIX"},
+       {"ROUT", NULL, "ROUT PGA"},
+       {"OUT4", NULL, "OUT4MIX"},
+       {"ROP", NULL, "ROPMIX"},
+       {"RON", NULL, "RONMIX"},
+};
+
+static int wm8990_add_widgets(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, wm8990_dapm_widgets,
+                                 ARRAY_SIZE(wm8990_dapm_widgets));
+
+       /* set up the WM8990 audio map */
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+       snd_soc_dapm_new_widgets(codec);
+       return 0;
+}
+
+/* PLL divisors */
+struct _pll_div {
+       u32 div2;
+       u32 n;
+       u32 k;
+};
+
+/* The size in bits of the pll divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_PLL_SIZE ((1 << 16) * 10)
+
+static void pll_factors(struct _pll_div *pll_div, unsigned int target,
+       unsigned int source)
+{
+       u64 Kpart;
+       unsigned int K, Ndiv, Nmod;
+
+
+       Ndiv = target / source;
+       if (Ndiv < 6) {
+               source >>= 1;
+               pll_div->div2 = 1;
+               Ndiv = target / source;
+       } else
+               pll_div->div2 = 0;
+
+       if ((Ndiv < 6) || (Ndiv > 12))
+               printk(KERN_WARNING
+               "WM8990 N value outwith recommended range! N = %d\n", Ndiv);
+
+       pll_div->n = Ndiv;
+       Nmod = target % source;
+       Kpart = FIXED_PLL_SIZE * (long long)Nmod;
+
+       do_div(Kpart, source);
+
+       K = Kpart & 0xFFFFFFFF;
+
+       /* Check if we need to round */
+       if ((K % 10) >= 5)
+               K += 5;
+
+       /* Move down to proper range now rounding is done */
+       K /= 10;
+
+       pll_div->k = K;
+}
+
+static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai,
+               int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+       u16 reg;
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct _pll_div pll_div;
+
+       if (freq_in && freq_out) {
+               pll_factors(&pll_div, freq_out * 4, freq_in);
+
+               /* Turn on PLL */
+               reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
+               reg |= WM8990_PLL_ENA;
+               wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
+
+               /* sysclk comes from PLL */
+               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2);
+               wm8990_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
+
+               /* set up N , fractional mode and pre-divisor if neccessary */
+               wm8990_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
+                       (pll_div.div2?WM8990_PRESCALE:0));
+               wm8990_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
+               wm8990_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
+       } else {
+               /* Turn on PLL */
+               reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
+               reg &= ~WM8990_PLL_ENA;
+               wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
+       }
+       return 0;
+}
+
+/*
+ * Clock after PLL and dividers
+ */
+static int wm8990_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+               int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct wm8990_priv *wm8990 = codec->private_data;
+
+       wm8990->sysclk = freq;
+       return 0;
+}
+
+/*
+ * Set's ADC and Voice DAC format.
+ */
+static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai,
+               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 audio1, audio3;
+
+       audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1);
+       audio3 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_3);
+
+       /* set master/slave audio interface */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               audio3 &= ~WM8990_AIF_MSTR1;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               audio3 |= WM8990_AIF_MSTR1;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       audio1 &= ~WM8990_AIF_FMT_MASK;
+
+       /* interface format */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               audio1 |= WM8990_AIF_TMF_I2S;
+               audio1 &= ~WM8990_AIF_LRCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               audio1 |= WM8990_AIF_TMF_RIGHTJ;
+               audio1 &= ~WM8990_AIF_LRCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               audio1 |= WM8990_AIF_TMF_LEFTJ;
+               audio1 &= ~WM8990_AIF_LRCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               audio1 |= WM8990_AIF_TMF_DSP;
+               audio1 &= ~WM8990_AIF_LRCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               audio1 |= WM8990_AIF_TMF_DSP | WM8990_AIF_LRCLK_INV;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
+       wm8990_write(codec, WM8990_AUDIO_INTERFACE_3, audio3);
+       return 0;
+}
+
+static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
+               int div_id, int div)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 reg;
+
+       switch (div_id) {
+       case WM8990_MCLK_DIV:
+               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
+                       ~WM8990_MCLK_DIV_MASK;
+               wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
+               break;
+       case WM8990_DACCLK_DIV:
+               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
+                       ~WM8990_DAC_CLKDIV_MASK;
+               wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
+               break;
+       case WM8990_ADCCLK_DIV:
+               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
+                       ~WM8990_ADC_CLKDIV_MASK;
+               wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
+               break;
+       case WM8990_BCLK_DIV:
+               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_1) &
+                       ~WM8990_BCLK_DIV_MASK;
+               wm8990_write(codec, WM8990_CLOCKING_1, reg | div);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * Set PCM DAI bit size and sample rate.
+ */
+static int wm8990_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->codec;
+       u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1);
+
+       audio1 &= ~WM8990_AIF_WL_MASK;
+       /* bit size */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               audio1 |= WM8990_AIF_WL_20BITS;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               audio1 |= WM8990_AIF_WL_24BITS;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               audio1 |= WM8990_AIF_WL_32BITS;
+               break;
+       }
+
+       wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
+       return 0;
+}
+
+static int wm8990_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u16 val;
+
+       val  = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE;
+
+       if (mute)
+               wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
+       else
+               wm8990_write(codec, WM8990_DAC_CTRL, val);
+
+       return 0;
+}
+
+static int wm8990_set_bias_level(struct snd_soc_codec *codec,
+       enum snd_soc_bias_level level)
+{
+       u16 val;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               break;
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->bias_level == SND_SOC_BIAS_OFF) {
+                       /* Enable all output discharge bits */
+                       wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
+                               WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
+                               WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
+                               WM8990_DIS_ROUT);
+
+                       /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */
+                       wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+                                    WM8990_BUFDCOPEN | WM8990_POBCTRL |
+                                    WM8990_VMIDTOG);
+
+                       /* Delay to allow output caps to discharge */
+                       msleep(msecs_to_jiffies(300));
+
+                       /* Disable VMIDTOG */
+                       wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+                                    WM8990_BUFDCOPEN | WM8990_POBCTRL);
+
+                       /* disable all output discharge bits */
+                       wm8990_write(codec, WM8990_ANTIPOP1, 0);
+
+                       /* Enable outputs */
+                       wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00);
+
+                       msleep(msecs_to_jiffies(50));
+
+                       /* Enable VMID at 2x50k */
+                       wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02);
+
+                       msleep(msecs_to_jiffies(100));
+
+                       /* Enable VREF */
+                       wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
+
+                       msleep(msecs_to_jiffies(600));
+
+                       /* Enable BUFIOEN */
+                       wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+                                    WM8990_BUFDCOPEN | WM8990_POBCTRL |
+                                    WM8990_BUFIOEN);
+
+                       /* Disable outputs */
+                       wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3);
+
+                       /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
+                       wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
+               } else {
+                       /* ON -> standby */
+
+               }
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               /* Enable POBCTRL and SOFT_ST */
+               wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+                       WM8990_POBCTRL | WM8990_BUFIOEN);
+
+               /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */
+               wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+                       WM8990_BUFDCOPEN | WM8990_POBCTRL |
+                       WM8990_BUFIOEN);
+
+               /* mute DAC */
+               val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL);
+               wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
+
+               /* Enable any disabled outputs */
+               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
+
+               /* Disable VMID */
+               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01);
+
+               msleep(msecs_to_jiffies(300));
+
+               /* Enable all output discharge bits */
+               wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
+                       WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
+                       WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
+                       WM8990_DIS_ROUT);
+
+               /* Disable VREF */
+               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0);
+
+               /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
+               wm8990_write(codec, WM8990_ANTIPOP2, 0x0);
+               break;
+       }
+
+       codec->bias_level = level;
+       return 0;
+}
+
+#define WM8990_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+       SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
+       SNDRV_PCM_RATE_48000)
+
+#define WM8990_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+/*
+ * The WM8990 supports 2 different and mutually exclusive DAI
+ * configurations.
+ *
+ * 1. ADC/DAC on Primary Interface
+ * 2. ADC on Primary Interface/DAC on secondary
+ */
+struct snd_soc_dai wm8990_dai = {
+/* ADC/DAC on primary */
+       .name = "WM8990 ADC/DAC Primary",
+       .id = 1,
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = WM8990_RATES,
+               .formats = WM8990_FORMATS,},
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = WM8990_RATES,
+               .formats = WM8990_FORMATS,},
+       .ops = {
+               .hw_params = wm8990_hw_params,},
+       .dai_ops = {
+               .digital_mute = wm8990_mute,
+               .set_fmt = wm8990_set_dai_fmt,
+               .set_clkdiv = wm8990_set_dai_clkdiv,
+               .set_pll = wm8990_set_dai_pll,
+               .set_sysclk = wm8990_set_dai_sysclk,
+       },
+};
+EXPORT_SYMBOL_GPL(wm8990_dai);
+
+static int wm8990_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       /* we only need to suspend if we are a valid card */
+       if (!codec->card)
+               return 0;
+
+       wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int wm8990_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+       int i;
+       u8 data[2];
+       u16 *cache = codec->reg_cache;
+
+       /* we only need to resume if we are a valid card */
+       if (!codec->card)
+               return 0;
+
+       /* Sync reg_cache with the hardware */
+       for (i = 0; i < ARRAY_SIZE(wm8990_reg); i++) {
+               if (i + 1 == WM8990_RESET)
+                       continue;
+               data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
+               data[1] = cache[i] & 0x00ff;
+               codec->hw_write(codec->control_data, data, 2);
+       }
+
+       wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       return 0;
+}
+
+/*
+ * initialise the WM8990 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int wm8990_init(struct snd_soc_device *socdev)
+{
+       struct snd_soc_codec *codec = socdev->codec;
+       u16 reg;
+       int ret = 0;
+
+       codec->name = "WM8990";
+       codec->owner = THIS_MODULE;
+       codec->read = wm8990_read_reg_cache;
+       codec->write = wm8990_write;
+       codec->set_bias_level = wm8990_set_bias_level;
+       codec->dai = &wm8990_dai;
+       codec->num_dai = 2;
+       codec->reg_cache_size = ARRAY_SIZE(wm8990_reg);
+       codec->reg_cache = kmemdup(wm8990_reg, sizeof(wm8990_reg), GFP_KERNEL);
+
+       if (codec->reg_cache == NULL)
+               return -ENOMEM;
+
+       wm8990_reset(codec);
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               printk(KERN_ERR "wm8990: failed to create pcms\n");
+               goto pcm_err;
+       }
+
+       /* charge output caps */
+       codec->bias_level = SND_SOC_BIAS_OFF;
+       wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       reg = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_4);
+       wm8990_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
+
+       reg = wm8990_read_reg_cache(codec, WM8990_GPIO1_GPIO2) &
+               ~WM8990_GPIO1_SEL_MASK;
+       wm8990_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
+
+       reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
+       wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
+
+       wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
+       wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
+
+       wm8990_add_controls(codec);
+       wm8990_add_widgets(codec);
+       ret = snd_soc_register_card(socdev);
+       if (ret < 0) {
+               printk(KERN_ERR "wm8990: failed to register card\n");
+               goto card_err;
+       }
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       kfree(codec->reg_cache);
+       return ret;
+}
+
+/* If the i2c layer weren't so broken, we could pass this kind of data
+   around */
+static struct snd_soc_device *wm8990_socdev;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+/*
+ * WM891 2 wire address is determined by GPIO5
+ * state during powerup.
+ *    low  = 0x34
+ *    high = 0x36
+ */
+static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
+
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver wm8990_i2c_driver;
+static struct i2c_client client_template;
+
+static int wm8990_codec_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+       struct snd_soc_device *socdev = wm8990_socdev;
+       struct wm8990_setup_data *setup = socdev->codec_data;
+       struct snd_soc_codec *codec = socdev->codec;
+       struct i2c_client *i2c;
+       int ret;
+
+       if (addr != setup->i2c_address)
+               return -ENODEV;
+
+       client_template.adapter = adap;
+       client_template.addr = addr;
+
+       i2c =  kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
+       if (i2c == NULL) {
+               kfree(codec);
+               return -ENOMEM;
+       }
+       i2c_set_clientdata(i2c, codec);
+       codec->control_data = i2c;
+
+       ret = i2c_attach_client(i2c);
+       if (ret < 0) {
+               pr_err("failed to attach codec at addr %x\n", addr);
+               goto err;
+       }
+
+       ret = wm8990_init(socdev);
+       if (ret < 0) {
+               pr_err("failed to initialise WM8990\n");
+               goto err;
+       }
+       return ret;
+
+err:
+       kfree(codec);
+       kfree(i2c);
+       return ret;
+}
+
+static int wm8990_i2c_detach(struct i2c_client *client)
+{
+       struct snd_soc_codec *codec = i2c_get_clientdata(client);
+       i2c_detach_client(client);
+       kfree(codec->reg_cache);
+       kfree(client);
+       return 0;
+}
+
+static int wm8990_i2c_attach(struct i2c_adapter *adap)
+{
+       return i2c_probe(adap, &addr_data, wm8990_codec_probe);
+}
+
+static struct i2c_driver wm8990_i2c_driver = {
+       .driver = {
+               .name = "WM8990 I2C Codec",
+               .owner = THIS_MODULE,
+       },
+       .attach_adapter = wm8990_i2c_attach,
+       .detach_client =  wm8990_i2c_detach,
+       .command =        NULL,
+};
+
+static struct i2c_client client_template = {
+       .name =   "WM8990",
+       .driver = &wm8990_i2c_driver,
+};
+#endif
+
+static int wm8990_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct wm8990_setup_data *setup;
+       struct snd_soc_codec *codec;
+       struct wm8990_priv *wm8990;
+       int ret = 0;
+
+       pr_info("WM8990 Audio Codec %s\n", WM8990_VERSION);
+
+       setup = socdev->codec_data;
+       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+       if (codec == NULL)
+               return -ENOMEM;
+
+       wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL);
+       if (wm8990 == NULL) {
+               kfree(codec);
+               return -ENOMEM;
+       }
+
+       codec->private_data = wm8990;
+       socdev->codec = codec;
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+       wm8990_socdev = socdev;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       if (setup->i2c_address) {
+               normal_i2c[0] = setup->i2c_address;
+               codec->hw_write = (hw_write_t)i2c_master_send;
+               ret = i2c_add_driver(&wm8990_i2c_driver);
+               if (ret != 0)
+                       printk(KERN_ERR "can't add i2c driver");
+       }
+#else
+               /* Add other interfaces here */
+#endif
+       return ret;
+}
+
+/* power down chip */
+static int wm8990_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->codec;
+
+       if (codec->control_data)
+               wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&wm8990_i2c_driver);
+#endif
+       kfree(codec->private_data);
+       kfree(codec);
+
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8990 = {
+       .probe =        wm8990_probe,
+       .remove =       wm8990_remove,
+       .suspend =      wm8990_suspend,
+       .resume =       wm8990_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990);
+
+MODULE_DESCRIPTION("ASoC WM8990 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h
new file mode 100644 (file)
index 0000000..6bea574
--- /dev/null
@@ -0,0 +1,832 @@
+/*
+ * wm8990.h  --  audio driver for WM8990
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC.
+ * Author: Graeme Gregory
+ *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.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.
+ *
+ */
+
+#ifndef __WM8990REGISTERDEFS_H__
+#define __WM8990REGISTERDEFS_H__
+
+/*
+ * Register values.
+ */
+#define WM8990_RESET                            0x00
+#define WM8990_POWER_MANAGEMENT_1               0x01
+#define WM8990_POWER_MANAGEMENT_2               0x02
+#define WM8990_POWER_MANAGEMENT_3               0x03
+#define WM8990_AUDIO_INTERFACE_1                0x04
+#define WM8990_AUDIO_INTERFACE_2                0x05
+#define WM8990_CLOCKING_1                       0x06
+#define WM8990_CLOCKING_2                       0x07
+#define WM8990_AUDIO_INTERFACE_3                0x08
+#define WM8990_AUDIO_INTERFACE_4                0x09
+#define WM8990_DAC_CTRL                         0x0A
+#define WM8990_LEFT_DAC_DIGITAL_VOLUME          0x0B
+#define WM8990_RIGHT_DAC_DIGITAL_VOLUME         0x0C
+#define WM8990_DIGITAL_SIDE_TONE                0x0D
+#define WM8990_ADC_CTRL                         0x0E
+#define WM8990_LEFT_ADC_DIGITAL_VOLUME          0x0F
+#define WM8990_RIGHT_ADC_DIGITAL_VOLUME         0x10
+#define WM8990_GPIO_CTRL_1                      0x12
+#define WM8990_GPIO1_GPIO2                      0x13
+#define WM8990_GPIO3_GPIO4                      0x14
+#define WM8990_GPIO5_GPIO6                      0x15
+#define WM8990_GPIOCTRL_2                       0x16
+#define WM8990_GPIO_POL                         0x17
+#define WM8990_LEFT_LINE_INPUT_1_2_VOLUME       0x18
+#define WM8990_LEFT_LINE_INPUT_3_4_VOLUME       0x19
+#define WM8990_RIGHT_LINE_INPUT_1_2_VOLUME      0x1A
+#define WM8990_RIGHT_LINE_INPUT_3_4_VOLUME      0x1B
+#define WM8990_LEFT_OUTPUT_VOLUME               0x1C
+#define WM8990_RIGHT_OUTPUT_VOLUME              0x1D
+#define WM8990_LINE_OUTPUTS_VOLUME              0x1E
+#define WM8990_OUT3_4_VOLUME                    0x1F
+#define WM8990_LEFT_OPGA_VOLUME                 0x20
+#define WM8990_RIGHT_OPGA_VOLUME                0x21
+#define WM8990_SPEAKER_VOLUME                   0x22
+#define WM8990_CLASSD1                          0x23
+#define WM8990_CLASSD3                          0x25
+#define WM8990_INPUT_MIXER1                     0x27
+#define WM8990_INPUT_MIXER2                     0x28
+#define WM8990_INPUT_MIXER3                     0x29
+#define WM8990_INPUT_MIXER4                     0x2A
+#define WM8990_INPUT_MIXER5                     0x2B
+#define WM8990_INPUT_MIXER6                     0x2C
+#define WM8990_OUTPUT_MIXER1                    0x2D
+#define WM8990_OUTPUT_MIXER2                    0x2E
+#define WM8990_OUTPUT_MIXER3                    0x2F
+#define WM8990_OUTPUT_MIXER4                    0x30
+#define WM8990_OUTPUT_MIXER5                    0x31
+#define WM8990_OUTPUT_MIXER6                    0x32
+#define WM8990_OUT3_4_MIXER                     0x33
+#define WM8990_LINE_MIXER1                      0x34
+#define WM8990_LINE_MIXER2                      0x35
+#define WM8990_SPEAKER_MIXER                    0x36
+#define WM8990_ADDITIONAL_CONTROL               0x37
+#define WM8990_ANTIPOP1                         0x38
+#define WM8990_ANTIPOP2                         0x39
+#define WM8990_MICBIAS                          0x3A
+#define WM8990_PLL1                             0x3C
+#define WM8990_PLL2                             0x3D
+#define WM8990_PLL3                             0x3E
+#define WM8990_INTDRIVBITS                     0x3F
+
+#define WM8990_REGISTER_COUNT                   60
+#define WM8990_MAX_REGISTER                     0x3F
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Reset
+ */
+#define WM8990_SW_RESET_CHIP_ID_MASK            0xFFFF  /* SW_RESET_CHIP_ID */
+
+/*
+ * R1 (0x01) - Power Management (1)
+ */
+#define WM8990_SPK_ENA                          0x1000  /* SPK_ENA */
+#define WM8990_SPK_ENA_BIT                     12
+#define WM8990_OUT3_ENA                         0x0800  /* OUT3_ENA */
+#define WM8990_OUT3_ENA_BIT                    11
+#define WM8990_OUT4_ENA                         0x0400  /* OUT4_ENA */
+#define WM8990_OUT4_ENA_BIT                    10
+#define WM8990_LOUT_ENA                         0x0200  /* LOUT_ENA */
+#define WM8990_LOUT_ENA_BIT                    9
+#define WM8990_ROUT_ENA                         0x0100  /* ROUT_ENA */
+#define WM8990_ROUT_ENA_BIT                    8
+#define WM8990_MICBIAS_ENA                      0x0010  /* MICBIAS_ENA */
+#define WM8990_MICBIAS_ENA_BIT                 4
+#define WM8990_VMID_MODE_MASK                   0x0006  /* VMID_MODE - [2:1] */
+#define WM8990_VREF_ENA                         0x0001  /* VREF_ENA */
+#define WM8990_VREF_ENA_BIT                    0
+
+/*
+ * R2 (0x02) - Power Management (2)
+ */
+#define WM8990_PLL_ENA                          0x8000  /* PLL_ENA */
+#define WM8990_PLL_ENA_BIT                     15
+#define WM8990_TSHUT_ENA                        0x4000  /* TSHUT_ENA */
+#define WM8990_TSHUT_ENA_BIT                   14
+#define WM8990_TSHUT_OPDIS                      0x2000  /* TSHUT_OPDIS */
+#define WM8990_TSHUT_OPDIS_BIT                 13
+#define WM8990_OPCLK_ENA                        0x0800  /* OPCLK_ENA */
+#define WM8990_OPCLK_ENA_BIT                   11
+#define WM8990_AINL_ENA                         0x0200  /* AINL_ENA */
+#define WM8990_AINL_ENA_BIT                    9
+#define WM8990_AINR_ENA                         0x0100  /* AINR_ENA */
+#define WM8990_AINR_ENA_BIT                    8
+#define WM8990_LIN34_ENA                        0x0080  /* LIN34_ENA */
+#define WM8990_LIN34_ENA_BIT                   7
+#define WM8990_LIN12_ENA                        0x0040  /* LIN12_ENA */
+#define WM8990_LIN12_ENA_BIT                   6
+#define WM8990_RIN34_ENA                        0x0020  /* RIN34_ENA */
+#define WM8990_RIN34_ENA_BIT                   5
+#define WM8990_RIN12_ENA                        0x0010  /* RIN12_ENA */
+#define WM8990_RIN12_ENA_BIT                   4
+#define WM8990_ADCL_ENA                         0x0002  /* ADCL_ENA */
+#define WM8990_ADCL_ENA_BIT                    1
+#define WM8990_ADCR_ENA                         0x0001  /* ADCR_ENA */
+#define WM8990_ADCR_ENA_BIT                    0
+
+/*
+ * R3 (0x03) - Power Management (3)
+ */
+#define WM8990_LON_ENA                          0x2000  /* LON_ENA */
+#define WM8990_LON_ENA_BIT                     13
+#define WM8990_LOP_ENA                          0x1000  /* LOP_ENA */
+#define WM8990_LOP_ENA_BIT                     12
+#define WM8990_RON_ENA                          0x0800  /* RON_ENA */
+#define WM8990_RON_ENA_BIT                     11
+#define WM8990_ROP_ENA                          0x0400  /* ROP_ENA */
+#define WM8990_ROP_ENA_BIT                     10
+#define WM8990_LOPGA_ENA                        0x0080  /* LOPGA_ENA */
+#define WM8990_LOPGA_ENA_BIT                   7
+#define WM8990_ROPGA_ENA                        0x0040  /* ROPGA_ENA */
+#define WM8990_ROPGA_ENA_BIT                   6
+#define WM8990_LOMIX_ENA                        0x0020  /* LOMIX_ENA */
+#define WM8990_LOMIX_ENA_BIT                   5
+#define WM8990_ROMIX_ENA                        0x0010  /* ROMIX_ENA */
+#define WM8990_ROMIX_ENA_BIT                   4
+#define WM8990_DACL_ENA                         0x0002  /* DACL_ENA */
+#define WM8990_DACL_ENA_BIT                    1
+#define WM8990_DACR_ENA                         0x0001  /* DACR_ENA */
+#define WM8990_DACR_ENA_BIT                    0
+
+/*
+ * R4 (0x04) - Audio Interface (1)
+ */
+#define WM8990_AIFADCL_SRC                      0x8000  /* AIFADCL_SRC */
+#define WM8990_AIFADCR_SRC                      0x4000  /* AIFADCR_SRC */
+#define WM8990_AIFADC_TDM                       0x2000  /* AIFADC_TDM */
+#define WM8990_AIFADC_TDM_CHAN                  0x1000  /* AIFADC_TDM_CHAN */
+#define WM8990_AIF_BCLK_INV                     0x0100  /* AIF_BCLK_INV */
+#define WM8990_AIF_LRCLK_INV                    0x0080  /* AIF_LRCLK_INV */
+#define WM8990_AIF_WL_MASK                      0x0060  /* AIF_WL - [6:5] */
+#define WM8990_AIF_WL_16BITS                   (0 << 5)
+#define WM8990_AIF_WL_20BITS                   (1 << 5)
+#define WM8990_AIF_WL_24BITS                   (2 << 5)
+#define WM8990_AIF_WL_32BITS                   (3 << 5)
+#define WM8990_AIF_FMT_MASK                     0x0018  /* AIF_FMT - [4:3] */
+#define WM8990_AIF_TMF_RIGHTJ                  (0 << 3)
+#define WM8990_AIF_TMF_LEFTJ                   (1 << 3)
+#define WM8990_AIF_TMF_I2S                     (2 << 3)
+#define WM8990_AIF_TMF_DSP                     (3 << 3)
+
+/*
+ * R5 (0x05) - Audio Interface (2)
+ */
+#define WM8990_DACL_SRC                         0x8000  /* DACL_SRC */
+#define WM8990_DACR_SRC                         0x4000  /* DACR_SRC */
+#define WM8990_AIFDAC_TDM                       0x2000  /* AIFDAC_TDM */
+#define WM8990_AIFDAC_TDM_CHAN                  0x1000  /* AIFDAC_TDM_CHAN */
+#define WM8990_DAC_BOOST_MASK                   0x0C00  /* DAC_BOOST */
+#define WM8990_DAC_COMP                         0x0010  /* DAC_COMP */
+#define WM8990_DAC_COMPMODE                     0x0008  /* DAC_COMPMODE */
+#define WM8990_ADC_COMP                         0x0004  /* ADC_COMP */
+#define WM8990_ADC_COMPMODE                     0x0002  /* ADC_COMPMODE */
+#define WM8990_LOOPBACK                         0x0001  /* LOOPBACK */
+
+/*
+ * R6 (0x06) - Clocking (1)
+ */
+#define WM8990_TOCLK_RATE                       0x8000  /* TOCLK_RATE */
+#define WM8990_TOCLK_ENA                        0x4000  /* TOCLK_ENA */
+#define WM8990_OPCLKDIV_MASK                    0x1E00  /* OPCLKDIV - [12:9] */
+#define WM8990_DCLKDIV_MASK                     0x01C0  /* DCLKDIV - [8:6] */
+#define WM8990_BCLK_DIV_MASK                    0x001E  /* BCLK_DIV - [4:1] */
+#define WM8990_BCLK_DIV_1                      (0x0 << 1)
+#define WM8990_BCLK_DIV_1_5                    (0x1 << 1)
+#define WM8990_BCLK_DIV_2                      (0x2 << 1)
+#define WM8990_BCLK_DIV_3                      (0x3 << 1)
+#define WM8990_BCLK_DIV_4                      (0x4 << 1)
+#define WM8990_BCLK_DIV_5_5                    (0x5 << 1)
+#define WM8990_BCLK_DIV_6                      (0x6 << 1)
+#define WM8990_BCLK_DIV_8                      (0x7 << 1)
+#define WM8990_BCLK_DIV_11                     (0x8 << 1)
+#define WM8990_BCLK_DIV_12                     (0x9 << 1)
+#define WM8990_BCLK_DIV_16                     (0xA << 1)
+#define WM8990_BCLK_DIV_22                     (0xB << 1)
+#define WM8990_BCLK_DIV_24                     (0xC << 1)
+#define WM8990_BCLK_DIV_32                     (0xD << 1)
+#define WM8990_BCLK_DIV_44                     (0xE << 1)
+#define WM8990_BCLK_DIV_48                     (0xF << 1)
+
+/*
+ * R7 (0x07) - Clocking (2)
+ */
+#define WM8990_MCLK_SRC                         0x8000  /* MCLK_SRC */
+#define WM8990_SYSCLK_SRC                       0x4000  /* SYSCLK_SRC */
+#define WM8990_CLK_FORCE                        0x2000  /* CLK_FORCE */
+#define WM8990_MCLK_DIV_MASK                    0x1800  /* MCLK_DIV - [12:11] */
+#define WM8990_MCLK_DIV_1                      (0 << 11)
+#define WM8990_MCLK_DIV_2                      (2 << 11)
+#define WM8990_MCLK_INV                         0x0400  /* MCLK_INV */
+#define WM8990_ADC_CLKDIV_MASK                  0x00E0  /* ADC_CLKDIV */
+#define WM8990_ADC_CLKDIV_1                    (0 << 5)
+#define WM8990_ADC_CLKDIV_1_5                  (1 << 5)
+#define WM8990_ADC_CLKDIV_2                    (2 << 5)
+#define WM8990_ADC_CLKDIV_3                    (3 << 5)
+#define WM8990_ADC_CLKDIV_4                    (4 << 5)
+#define WM8990_ADC_CLKDIV_5_5                  (5 << 5)
+#define WM8990_ADC_CLKDIV_6                    (6 << 5)
+#define WM8990_DAC_CLKDIV_MASK                  0x001C  /* DAC_CLKDIV - [4:2] */
+#define WM8990_DAC_CLKDIV_1                    (0 << 2)
+#define WM8990_DAC_CLKDIV_1_5                  (1 << 2)
+#define WM8990_DAC_CLKDIV_2                    (2 << 2)
+#define WM8990_DAC_CLKDIV_3                    (3 << 2)
+#define WM8990_DAC_CLKDIV_4                    (4 << 2)
+#define WM8990_DAC_CLKDIV_5_5                  (5 << 2)
+#define WM8990_DAC_CLKDIV_6                    (6 << 2)
+
+/*
+ * R8 (0x08) - Audio Interface (3)
+ */
+#define WM8990_AIF_MSTR1                        0x8000  /* AIF_MSTR1 */
+#define WM8990_AIF_MSTR2                        0x4000  /* AIF_MSTR2 */
+#define WM8990_AIF_SEL                          0x2000  /* AIF_SEL */
+#define WM8990_ADCLRC_DIR                       0x0800  /* ADCLRC_DIR */
+#define WM8990_ADCLRC_RATE_MASK                 0x07FF  /* ADCLRC_RATE */
+
+/*
+ * R9 (0x09) - Audio Interface (4)
+ */
+#define WM8990_ALRCGPIO1                        0x8000  /* ALRCGPIO1 */
+#define WM8990_ALRCBGPIO6                       0x4000  /* ALRCBGPIO6 */
+#define WM8990_AIF_TRIS                         0x2000  /* AIF_TRIS */
+#define WM8990_DACLRC_DIR                       0x0800  /* DACLRC_DIR */
+#define WM8990_DACLRC_RATE_MASK                 0x07FF  /* DACLRC_RATE */
+
+/*
+ * R10 (0x0A) - DAC CTRL
+ */
+#define WM8990_AIF_LRCLKRATE                    0x0400  /* AIF_LRCLKRATE */
+#define WM8990_DAC_MONO                         0x0200  /* DAC_MONO */
+#define WM8990_DAC_SB_FILT                      0x0100  /* DAC_SB_FILT */
+#define WM8990_DAC_MUTERATE                     0x0080  /* DAC_MUTERATE */
+#define WM8990_DAC_MUTEMODE                     0x0040  /* DAC_MUTEMODE */
+#define WM8990_DEEMP_MASK                       0x0030  /* DEEMP - [5:4] */
+#define WM8990_DAC_MUTE                         0x0004  /* DAC_MUTE */
+#define WM8990_DACL_DATINV                      0x0002  /* DACL_DATINV */
+#define WM8990_DACR_DATINV                      0x0001  /* DACR_DATINV */
+
+/*
+ * R11 (0x0B) - Left DAC Digital Volume
+ */
+#define WM8990_DAC_VU                           0x0100  /* DAC_VU */
+#define WM8990_DACL_VOL_MASK                    0x00FF  /* DACL_VOL - [7:0] */
+#define WM8990_DACL_VOL_SHIFT                  0
+/*
+ * R12 (0x0C) - Right DAC Digital Volume
+ */
+#define WM8990_DAC_VU                           0x0100  /* DAC_VU */
+#define WM8990_DACR_VOL_MASK                    0x00FF  /* DACR_VOL - [7:0] */
+#define WM8990_DACR_VOL_SHIFT                  0
+/*
+ * R13 (0x0D) - Digital Side Tone
+ */
+#define WM8990_ADCL_DAC_SVOL_MASK               0x0F  /* ADCL_DAC_SVOL */
+#define WM8990_ADCL_DAC_SVOL_SHIFT             9
+#define WM8990_ADCR_DAC_SVOL_MASK               0x0F  /* ADCR_DAC_SVOL */
+#define WM8990_ADCR_DAC_SVOL_SHIFT             5
+#define WM8990_ADC_TO_DACL_MASK                 0x03  /* ADC_TO_DACL - [3:2] */
+#define WM8990_ADC_TO_DACL_SHIFT               2
+#define WM8990_ADC_TO_DACR_MASK                 0x03  /* ADC_TO_DACR - [1:0] */
+#define WM8990_ADC_TO_DACR_SHIFT               0
+
+/*
+ * R14 (0x0E) - ADC CTRL
+ */
+#define WM8990_ADC_HPF_ENA                      0x0100  /* ADC_HPF_ENA */
+#define WM8990_ADC_HPF_ENA_BIT                 8
+#define WM8990_ADC_HPF_CUT_MASK                 0x03  /* ADC_HPF_CUT - [6:5] */
+#define WM8990_ADC_HPF_CUT_SHIFT               5
+#define WM8990_ADCL_DATINV                      0x0002  /* ADCL_DATINV */
+#define WM8990_ADCL_DATINV_BIT                 1
+#define WM8990_ADCR_DATINV                      0x0001  /* ADCR_DATINV */
+#define WM8990_ADCR_DATINV_BIT                 0
+
+/*
+ * R15 (0x0F) - Left ADC Digital Volume
+ */
+#define WM8990_ADC_VU                           0x0100  /* ADC_VU */
+#define WM8990_ADCL_VOL_MASK                    0x00FF  /* ADCL_VOL - [7:0] */
+#define WM8990_ADCL_VOL_SHIFT                  0
+
+/*
+ * R16 (0x10) - Right ADC Digital Volume
+ */
+#define WM8990_ADC_VU                           0x0100  /* ADC_VU */
+#define WM8990_ADCR_VOL_MASK                    0x00FF  /* ADCR_VOL - [7:0] */
+#define WM8990_ADCR_VOL_SHIFT                  0
+
+/*
+ * R18 (0x12) - GPIO CTRL 1
+ */
+#define WM8990_IRQ                              0x1000  /* IRQ */
+#define WM8990_TEMPOK                           0x0800  /* TEMPOK */
+#define WM8990_MICSHRT                          0x0400  /* MICSHRT */
+#define WM8990_MICDET                           0x0200  /* MICDET */
+#define WM8990_PLL_LCK                          0x0100  /* PLL_LCK */
+#define WM8990_GPI8_STATUS                      0x0080  /* GPI8_STATUS */
+#define WM8990_GPI7_STATUS                      0x0040  /* GPI7_STATUS */
+#define WM8990_GPIO6_STATUS                     0x0020  /* GPIO6_STATUS */
+#define WM8990_GPIO5_STATUS                     0x0010  /* GPIO5_STATUS */
+#define WM8990_GPIO4_STATUS                     0x0008  /* GPIO4_STATUS */
+#define WM8990_GPIO3_STATUS                     0x0004  /* GPIO3_STATUS */
+#define WM8990_GPIO2_STATUS                     0x0002  /* GPIO2_STATUS */
+#define WM8990_GPIO1_STATUS                     0x0001  /* GPIO1_STATUS */
+
+/*
+ * R19 (0x13) - GPIO1 & GPIO2
+ */
+#define WM8990_GPIO2_DEB_ENA                    0x8000  /* GPIO2_DEB_ENA */
+#define WM8990_GPIO2_IRQ_ENA                    0x4000  /* GPIO2_IRQ_ENA */
+#define WM8990_GPIO2_PU                         0x2000  /* GPIO2_PU */
+#define WM8990_GPIO2_PD                         0x1000  /* GPIO2_PD */
+#define WM8990_GPIO2_SEL_MASK                   0x0F00  /* GPIO2_SEL - [11:8] */
+#define WM8990_GPIO1_DEB_ENA                    0x0080  /* GPIO1_DEB_ENA */
+#define WM8990_GPIO1_IRQ_ENA                    0x0040  /* GPIO1_IRQ_ENA */
+#define WM8990_GPIO1_PU                         0x0020  /* GPIO1_PU */
+#define WM8990_GPIO1_PD                         0x0010  /* GPIO1_PD */
+#define WM8990_GPIO1_SEL_MASK                   0x000F  /* GPIO1_SEL - [3:0] */
+
+/*
+ * R20 (0x14) - GPIO3 & GPIO4
+ */
+#define WM8990_GPIO4_DEB_ENA                    0x8000  /* GPIO4_DEB_ENA */
+#define WM8990_GPIO4_IRQ_ENA                    0x4000  /* GPIO4_IRQ_ENA */
+#define WM8990_GPIO4_PU                         0x2000  /* GPIO4_PU */
+#define WM8990_GPIO4_PD                         0x1000  /* GPIO4_PD */
+#define WM8990_GPIO4_SEL_MASK                   0x0F00  /* GPIO4_SEL - [11:8] */
+#define WM8990_GPIO3_DEB_ENA                    0x0080  /* GPIO3_DEB_ENA */
+#define WM8990_GPIO3_IRQ_ENA                    0x0040  /* GPIO3_IRQ_ENA */
+#define WM8990_GPIO3_PU                         0x0020  /* GPIO3_PU */
+#define WM8990_GPIO3_PD                         0x0010  /* GPIO3_PD */
+#define WM8990_GPIO3_SEL_MASK                   0x000F  /* GPIO3_SEL - [3:0] */
+
+/*
+ * R21 (0x15) - GPIO5 & GPIO6
+ */
+#define WM8990_GPIO6_DEB_ENA                    0x8000  /* GPIO6_DEB_ENA */
+#define WM8990_GPIO6_IRQ_ENA                    0x4000  /* GPIO6_IRQ_ENA */
+#define WM8990_GPIO6_PU                         0x2000  /* GPIO6_PU */
+#define WM8990_GPIO6_PD                         0x1000  /* GPIO6_PD */
+#define WM8990_GPIO6_SEL_MASK                   0x0F00  /* GPIO6_SEL - [11:8] */
+#define WM8990_GPIO5_DEB_ENA                    0x0080  /* GPIO5_DEB_ENA */
+#define WM8990_GPIO5_IRQ_ENA                    0x0040  /* GPIO5_IRQ_ENA */
+#define WM8990_GPIO5_PU                         0x0020  /* GPIO5_PU */
+#define WM8990_GPIO5_PD                         0x0010  /* GPIO5_PD */
+#define WM8990_GPIO5_SEL_MASK                   0x000F  /* GPIO5_SEL - [3:0] */
+
+/*
+ * R22 (0x16) - GPIOCTRL 2
+ */
+#define WM8990_RD_3W_ENA                        0x8000  /* RD_3W_ENA */
+#define WM8990_MODE_3W4W                        0x4000  /* MODE_3W4W */
+#define WM8990_TEMPOK_IRQ_ENA                   0x0800  /* TEMPOK_IRQ_ENA */
+#define WM8990_MICSHRT_IRQ_ENA                  0x0400  /* MICSHRT_IRQ_ENA */
+#define WM8990_MICDET_IRQ_ENA                   0x0200  /* MICDET_IRQ_ENA */
+#define WM8990_PLL_LCK_IRQ_ENA                  0x0100  /* PLL_LCK_IRQ_ENA */
+#define WM8990_GPI8_DEB_ENA                     0x0080  /* GPI8_DEB_ENA */
+#define WM8990_GPI8_IRQ_ENA                     0x0040  /* GPI8_IRQ_ENA */
+#define WM8990_GPI8_ENA                         0x0010  /* GPI8_ENA */
+#define WM8990_GPI7_DEB_ENA                     0x0008  /* GPI7_DEB_ENA */
+#define WM8990_GPI7_IRQ_ENA                     0x0004  /* GPI7_IRQ_ENA */
+#define WM8990_GPI7_ENA                         0x0001  /* GPI7_ENA */
+
+/*
+ * R23 (0x17) - GPIO_POL
+ */
+#define WM8990_IRQ_INV                          0x1000  /* IRQ_INV */
+#define WM8990_TEMPOK_POL                       0x0800  /* TEMPOK_POL */
+#define WM8990_MICSHRT_POL                      0x0400  /* MICSHRT_POL */
+#define WM8990_MICDET_POL                       0x0200  /* MICDET_POL */
+#define WM8990_PLL_LCK_POL                      0x0100  /* PLL_LCK_POL */
+#define WM8990_GPI8_POL                         0x0080  /* GPI8_POL */
+#define WM8990_GPI7_POL                         0x0040  /* GPI7_POL */
+#define WM8990_GPIO6_POL                        0x0020  /* GPIO6_POL */
+#define WM8990_GPIO5_POL                        0x0010  /* GPIO5_POL */
+#define WM8990_GPIO4_POL                        0x0008  /* GPIO4_POL */
+#define WM8990_GPIO3_POL                        0x0004  /* GPIO3_POL */
+#define WM8990_GPIO2_POL                        0x0002  /* GPIO2_POL */
+#define WM8990_GPIO1_POL                        0x0001  /* GPIO1_POL */
+
+/*
+ * R24 (0x18) - Left Line Input 1&2 Volume
+ */
+#define WM8990_IPVU                             0x0100  /* IPVU */
+#define WM8990_LI12MUTE                         0x0080  /* LI12MUTE */
+#define WM8990_LI12MUTE_BIT                    7
+#define WM8990_LI12ZC                           0x0040  /* LI12ZC */
+#define WM8990_LI12ZC_BIT                      6
+#define WM8990_LIN12VOL_MASK                    0x001F  /* LIN12VOL - [4:0] */
+#define WM8990_LIN12VOL_SHIFT                  0
+/*
+ * R25 (0x19) - Left Line Input 3&4 Volume
+ */
+#define WM8990_IPVU                             0x0100  /* IPVU */
+#define WM8990_LI34MUTE                         0x0080  /* LI34MUTE */
+#define WM8990_LI34MUTE_BIT                    7
+#define WM8990_LI34ZC                           0x0040  /* LI34ZC */
+#define WM8990_LI34ZC_BIT                      6
+#define WM8990_LIN34VOL_MASK                    0x001F  /* LIN34VOL - [4:0] */
+#define WM8990_LIN34VOL_SHIFT                  0
+
+/*
+ * R26 (0x1A) - Right Line Input 1&2 Volume
+ */
+#define WM8990_IPVU                             0x0100  /* IPVU */
+#define WM8990_RI12MUTE                         0x0080  /* RI12MUTE */
+#define WM8990_RI12MUTE_BIT                    7
+#define WM8990_RI12ZC                           0x0040  /* RI12ZC */
+#define WM8990_RI12ZC_BIT                      6
+#define WM8990_RIN12VOL_MASK                    0x001F  /* RIN12VOL - [4:0] */
+#define WM8990_RIN12VOL_SHIFT                  0
+
+/*
+ * R27 (0x1B) - Right Line Input 3&4 Volume
+ */
+#define WM8990_IPVU                             0x0100  /* IPVU */
+#define WM8990_RI34MUTE                         0x0080  /* RI34MUTE */
+#define WM8990_RI34MUTE_BIT                    7
+#define WM8990_RI34ZC                           0x0040  /* RI34ZC */
+#define WM8990_RI34ZC_BIT                      6
+#define WM8990_RIN34VOL_MASK                    0x001F  /* RIN34VOL - [4:0] */
+#define WM8990_RIN34VOL_SHIFT                  0
+
+/*
+ * R28 (0x1C) - Left Output Volume
+ */
+#define WM8990_OPVU                             0x0100  /* OPVU */
+#define WM8990_LOZC                             0x0080  /* LOZC */
+#define WM8990_LOZC_BIT                                7
+#define WM8990_LOUTVOL_MASK                     0x007F  /* LOUTVOL - [6:0] */
+#define WM8990_LOUTVOL_SHIFT                   0
+/*
+ * R29 (0x1D) - Right Output Volume
+ */
+#define WM8990_OPVU                             0x0100  /* OPVU */
+#define WM8990_ROZC                             0x0080  /* ROZC */
+#define WM8990_ROZC_BIT                                7
+#define WM8990_ROUTVOL_MASK                     0x007F  /* ROUTVOL - [6:0] */
+#define WM8990_ROUTVOL_SHIFT                   0
+/*
+ * R30 (0x1E) - Line Outputs Volume
+ */
+#define WM8990_LONMUTE                          0x0040  /* LONMUTE */
+#define WM8990_LONMUTE_BIT                     6
+#define WM8990_LOPMUTE                          0x0020  /* LOPMUTE */
+#define WM8990_LOPMUTE_BIT                     5
+#define WM8990_LOATTN                           0x0010  /* LOATTN */
+#define WM8990_LOATTN_BIT                      4
+#define WM8990_RONMUTE                          0x0004  /* RONMUTE */
+#define WM8990_RONMUTE_BIT                     2
+#define WM8990_ROPMUTE                          0x0002  /* ROPMUTE */
+#define WM8990_ROPMUTE_BIT                     1
+#define WM8990_ROATTN                           0x0001  /* ROATTN */
+#define WM8990_ROATTN_BIT                      0
+
+/*
+ * R31 (0x1F) - Out3/4 Volume
+ */
+#define WM8990_OUT3MUTE                         0x0020  /* OUT3MUTE */
+#define WM8990_OUT3MUTE_BIT                    5
+#define WM8990_OUT3ATTN                         0x0010  /* OUT3ATTN */
+#define WM8990_OUT3ATTN_BIT                    4
+#define WM8990_OUT4MUTE                         0x0002  /* OUT4MUTE */
+#define WM8990_OUT4MUTE_BIT                    1
+#define WM8990_OUT4ATTN                         0x0001  /* OUT4ATTN */
+#define WM8990_OUT4ATTN_BIT                    0
+
+/*
+ * R32 (0x20) - Left OPGA Volume
+ */
+#define WM8990_OPVU                             0x0100  /* OPVU */
+#define WM8990_LOPGAZC                          0x0080  /* LOPGAZC */
+#define WM8990_LOPGAZC_BIT                     7
+#define WM8990_LOPGAVOL_MASK                    0x007F  /* LOPGAVOL - [6:0] */
+#define WM8990_LOPGAVOL_SHIFT                  0
+
+/*
+ * R33 (0x21) - Right OPGA Volume
+ */
+#define WM8990_OPVU                             0x0100  /* OPVU */
+#define WM8990_ROPGAZC                          0x0080  /* ROPGAZC */
+#define WM8990_ROPGAZC_BIT                     7
+#define WM8990_ROPGAVOL_MASK                    0x007F  /* ROPGAVOL - [6:0] */
+#define WM8990_ROPGAVOL_SHIFT                  0
+/*
+ * R34 (0x22) - Speaker Volume
+ */
+#define WM8990_SPKVOL_MASK                      0x0003  /* SPKVOL - [1:0] */
+#define WM8990_SPKVOL_SHIFT                    0
+
+/*
+ * R35 (0x23) - ClassD1
+ */
+#define WM8990_CDMODE                           0x0100  /* CDMODE */
+#define WM8990_CDMODE_BIT                      8
+
+/*
+ * R37 (0x25) - ClassD3
+ */
+#define WM8990_DCGAIN_MASK                      0x0007  /* DCGAIN - [5:3] */
+#define WM8990_DCGAIN_SHIFT                    3
+#define WM8990_ACGAIN_MASK                      0x0007  /* ACGAIN - [2:0] */
+#define WM8990_ACGAIN_SHIFT                    0
+/*
+ * R39 (0x27) - Input Mixer1
+ */
+#define WM8990_AINLMODE_MASK                    0x000C  /* AINLMODE - [3:2] */
+#define WM8990_AINLMODE_SHIFT                  2
+#define WM8990_AINRMODE_MASK                    0x0003  /* AINRMODE - [1:0] */
+#define WM8990_AINRMODE_SHIFT                  0
+
+/*
+ * R40 (0x28) - Input Mixer2
+ */
+#define WM8990_LMP4                            0x0080  /* LMP4 */
+#define WM8990_LMP4_BIT                         7      /* LMP4 */
+#define WM8990_LMN3                             0x0040  /* LMN3 */
+#define WM8990_LMN3_BIT                         6       /* LMN3 */
+#define WM8990_LMP2                             0x0020  /* LMP2 */
+#define WM8990_LMP2_BIT                         5       /* LMP2 */
+#define WM8990_LMN1                             0x0010  /* LMN1 */
+#define WM8990_LMN1_BIT                         4       /* LMN1 */
+#define WM8990_RMP4                             0x0008  /* RMP4 */
+#define WM8990_RMP4_BIT                         3       /* RMP4 */
+#define WM8990_RMN3                             0x0004  /* RMN3 */
+#define WM8990_RMN3_BIT                         2       /* RMN3 */
+#define WM8990_RMP2                             0x0002  /* RMP2 */
+#define WM8990_RMP2_BIT                         1       /* RMP2 */
+#define WM8990_RMN1                             0x0001  /* RMN1 */
+#define WM8990_RMN1_BIT                         0       /* RMN1 */
+
+/*
+ * R41 (0x29) - Input Mixer3
+ */
+#define WM8990_L34MNB                           0x0100  /* L34MNB */
+#define WM8990_L34MNB_BIT                      8
+#define WM8990_L34MNBST                         0x0080  /* L34MNBST */
+#define WM8990_L34MNBST_BIT                    7
+#define WM8990_L12MNB                           0x0020  /* L12MNB */
+#define WM8990_L12MNB_BIT                      5
+#define WM8990_L12MNBST                         0x0010  /* L12MNBST */
+#define WM8990_L12MNBST_BIT                    4
+#define WM8990_LDBVOL_MASK                      0x0007  /* LDBVOL - [2:0] */
+#define WM8990_LDBVOL_SHIFT                    0
+
+/*
+ * R42 (0x2A) - Input Mixer4
+ */
+#define WM8990_R34MNB                           0x0100  /* R34MNB */
+#define WM8990_R34MNB_BIT                      8
+#define WM8990_R34MNBST                         0x0080  /* R34MNBST */
+#define WM8990_R34MNBST_BIT                    7
+#define WM8990_R12MNB                           0x0020  /* R12MNB */
+#define WM8990_R12MNB_BIT                      5
+#define WM8990_R12MNBST                         0x0010  /* R12MNBST */
+#define WM8990_R12MNBST_BIT                    4
+#define WM8990_RDBVOL_MASK                      0x0007  /* RDBVOL - [2:0] */
+#define WM8990_RDBVOL_SHIFT                    0
+
+/*
+ * R43 (0x2B) - Input Mixer5
+ */
+#define WM8990_LI2BVOL_MASK                     0x07  /* LI2BVOL - [8:6] */
+#define WM8990_LI2BVOL_SHIFT                   6
+#define WM8990_LR4BVOL_MASK                     0x07  /* LR4BVOL - [5:3] */
+#define WM8990_LR4BVOL_SHIFT                   3
+#define WM8990_LL4BVOL_MASK                     0x07  /* LL4BVOL - [2:0] */
+#define WM8990_LL4BVOL_SHIFT                   0
+
+/*
+ * R44 (0x2C) - Input Mixer6
+ */
+#define WM8990_RI2BVOL_MASK                     0x07  /* RI2BVOL - [8:6] */
+#define WM8990_RI2BVOL_SHIFT                   6
+#define WM8990_RL4BVOL_MASK                     0x07  /* RL4BVOL - [5:3] */
+#define WM8990_RL4BVOL_SHIFT                   3
+#define WM8990_RR4BVOL_MASK                     0x07  /* RR4BVOL - [2:0] */
+#define WM8990_RR4BVOL_SHIFT                   0
+
+/*
+ * R45 (0x2D) - Output Mixer1
+ */
+#define WM8990_LRBLO                            0x0080  /* LRBLO */
+#define WM8990_LRBLO_BIT                       7
+#define WM8990_LLBLO                            0x0040  /* LLBLO */
+#define WM8990_LLBLO_BIT                       6
+#define WM8990_LRI3LO                           0x0020  /* LRI3LO */
+#define WM8990_LRI3LO_BIT                      5
+#define WM8990_LLI3LO                           0x0010  /* LLI3LO */
+#define WM8990_LLI3LO_BIT                      4
+#define WM8990_LR12LO                           0x0008  /* LR12LO */
+#define WM8990_LR12LO_BIT                      3
+#define WM8990_LL12LO                           0x0004  /* LL12LO */
+#define WM8990_LL12LO_BIT                      2
+#define WM8990_LDLO                             0x0001  /* LDLO */
+#define WM8990_LDLO_BIT                                0
+
+/*
+ * R46 (0x2E) - Output Mixer2
+ */
+#define WM8990_RLBRO                            0x0080  /* RLBRO */
+#define WM8990_RLBRO_BIT                       7
+#define WM8990_RRBRO                            0x0040  /* RRBRO */
+#define WM8990_RRBRO_BIT                       6
+#define WM8990_RLI3RO                           0x0020  /* RLI3RO */
+#define WM8990_RLI3RO_BIT                      5
+#define WM8990_RRI3RO                           0x0010  /* RRI3RO */
+#define WM8990_RRI3RO_BIT                      4
+#define WM8990_RL12RO                           0x0008  /* RL12RO */
+#define WM8990_RL12RO_BIT                      3
+#define WM8990_RR12RO                           0x0004  /* RR12RO */
+#define WM8990_RR12RO_BIT                      2
+#define WM8990_RDRO                             0x0001  /* RDRO */
+#define WM8990_RDRO_BIT                                0
+
+/*
+ * R47 (0x2F) - Output Mixer3
+ */
+#define WM8990_LLI3LOVOL_MASK                   0x07  /* LLI3LOVOL - [8:6] */
+#define WM8990_LLI3LOVOL_SHIFT                 6
+#define WM8990_LR12LOVOL_MASK                   0x07  /* LR12LOVOL - [5:3] */
+#define WM8990_LR12LOVOL_SHIFT                 3
+#define WM8990_LL12LOVOL_MASK                   0x07  /* LL12LOVOL - [2:0] */
+#define WM8990_LL12LOVOL_SHIFT                 0
+
+/*
+ * R48 (0x30) - Output Mixer4
+ */
+#define WM8990_RRI3ROVOL_MASK                   0x07  /* RRI3ROVOL - [8:6] */
+#define WM8990_RRI3ROVOL_SHIFT                 6
+#define WM8990_RL12ROVOL_MASK                   0x07  /* RL12ROVOL - [5:3] */
+#define WM8990_RL12ROVOL_SHIFT                 3
+#define WM8990_RR12ROVOL_MASK                   0x07  /* RR12ROVOL - [2:0] */
+#define WM8990_RR12ROVOL_SHIFT                 0
+
+/*
+ * R49 (0x31) - Output Mixer5
+ */
+#define WM8990_LRI3LOVOL_MASK                   0x07  /* LRI3LOVOL - [8:6] */
+#define WM8990_LRI3LOVOL_SHIFT                 6
+#define WM8990_LRBLOVOL_MASK                    0x07  /* LRBLOVOL - [5:3] */
+#define WM8990_LRBLOVOL_SHIFT                  3
+#define WM8990_LLBLOVOL_MASK                    0x07  /* LLBLOVOL - [2:0] */
+#define WM8990_LLBLOVOL_SHIFT                  0
+
+/*
+ * R50 (0x32) - Output Mixer6
+ */
+#define WM8990_RLI3ROVOL_MASK                   0x07  /* RLI3ROVOL - [8:6] */
+#define WM8990_RLI3ROVOL_SHIFT                 6
+#define WM8990_RLBROVOL_MASK                    0x07  /* RLBROVOL - [5:3] */
+#define WM8990_RLBROVOL_SHIFT                  3
+#define WM8990_RRBROVOL_MASK                    0x07  /* RRBROVOL - [2:0] */
+#define WM8990_RRBROVOL_SHIFT                  0
+
+/*
+ * R51 (0x33) - Out3/4 Mixer
+ */
+#define WM8990_VSEL_MASK                        0x0180  /* VSEL - [8:7] */
+#define WM8990_LI4O3                            0x0020  /* LI4O3 */
+#define WM8990_LI4O3_BIT                       5
+#define WM8990_LPGAO3                           0x0010  /* LPGAO3 */
+#define WM8990_LPGAO3_BIT                      4
+#define WM8990_RI4O4                            0x0002  /* RI4O4 */
+#define WM8990_RI4O4_BIT                       1
+#define WM8990_RPGAO4                           0x0001  /* RPGAO4 */
+#define WM8990_RPGAO4_BIT                      0
+/*
+ * R52 (0x34) - Line Mixer1
+ */
+#define WM8990_LLOPGALON                        0x0040  /* LLOPGALON */
+#define WM8990_LLOPGALON_BIT                   6
+#define WM8990_LROPGALON                        0x0020  /* LROPGALON */
+#define WM8990_LROPGALON_BIT                   5
+#define WM8990_LOPLON                           0x0010  /* LOPLON */
+#define WM8990_LOPLON_BIT                      4
+#define WM8990_LR12LOP                          0x0004  /* LR12LOP */
+#define WM8990_LR12LOP_BIT                     2
+#define WM8990_LL12LOP                          0x0002  /* LL12LOP */
+#define WM8990_LL12LOP_BIT                     1
+#define WM8990_LLOPGALOP                        0x0001  /* LLOPGALOP */
+#define WM8990_LLOPGALOP_BIT                   0
+/*
+ * R53 (0x35) - Line Mixer2
+ */
+#define WM8990_RROPGARON                        0x0040  /* RROPGARON */
+#define WM8990_RROPGARON_BIT                   6
+#define WM8990_RLOPGARON                        0x0020  /* RLOPGARON */
+#define WM8990_RLOPGARON_BIT                   5
+#define WM8990_ROPRON                           0x0010  /* ROPRON */
+#define WM8990_ROPRON_BIT                      4
+#define WM8990_RL12ROP                          0x0004  /* RL12ROP */
+#define WM8990_RL12ROP_BIT                     2
+#define WM8990_RR12ROP                          0x0002  /* RR12ROP */
+#define WM8990_RR12ROP_BIT                     1
+#define WM8990_RROPGAROP                        0x0001  /* RROPGAROP */
+#define WM8990_RROPGAROP_BIT                   0
+
+/*
+ * R54 (0x36) - Speaker Mixer
+ */
+#define WM8990_LB2SPK                           0x0080  /* LB2SPK */
+#define WM8990_LB2SPK_BIT                      7
+#define WM8990_RB2SPK                           0x0040  /* RB2SPK */
+#define WM8990_RB2SPK_BIT                      6
+#define WM8990_LI2SPK                           0x0020  /* LI2SPK */
+#define WM8990_LI2SPK_BIT                      5
+#define WM8990_RI2SPK                           0x0010  /* RI2SPK */
+#define WM8990_RI2SPK_BIT                      4
+#define WM8990_LOPGASPK                         0x0008  /* LOPGASPK */
+#define WM8990_LOPGASPK_BIT                    3
+#define WM8990_ROPGASPK                         0x0004  /* ROPGASPK */
+#define WM8990_ROPGASPK_BIT                    2
+#define WM8990_LDSPK                            0x0002  /* LDSPK */
+#define WM8990_LDSPK_BIT                       1
+#define WM8990_RDSPK                            0x0001  /* RDSPK */
+#define WM8990_RDSPK_BIT                       0
+
+/*
+ * R55 (0x37) - Additional Control
+ */
+#define WM8990_VROI                             0x0001  /* VROI */
+
+/*
+ * R56 (0x38) - AntiPOP1
+ */
+#define WM8990_DIS_LLINE                        0x0020  /* DIS_LLINE */
+#define WM8990_DIS_RLINE                        0x0010  /* DIS_RLINE */
+#define WM8990_DIS_OUT3                         0x0008  /* DIS_OUT3 */
+#define WM8990_DIS_OUT4                         0x0004  /* DIS_OUT4 */
+#define WM8990_DIS_LOUT                         0x0002  /* DIS_LOUT */
+#define WM8990_DIS_ROUT                         0x0001  /* DIS_ROUT */
+
+/*
+ * R57 (0x39) - AntiPOP2
+ */
+#define WM8990_SOFTST                           0x0040  /* SOFTST */
+#define WM8990_BUFIOEN                          0x0008  /* BUFIOEN */
+#define WM8990_BUFDCOPEN                        0x0004  /* BUFDCOPEN */
+#define WM8990_POBCTRL                          0x0002  /* POBCTRL */
+#define WM8990_VMIDTOG                          0x0001  /* VMIDTOG */
+
+/*
+ * R58 (0x3A) - MICBIAS
+ */
+#define WM8990_MCDSCTH_MASK                     0x00C0  /* MCDSCTH - [7:6] */
+#define WM8990_MCDTHR_MASK                      0x0038  /* MCDTHR - [5:3] */
+#define WM8990_MCD                              0x0004  /* MCD */
+#define WM8990_MBSEL                            0x0001  /* MBSEL */
+
+/*
+ * R60 (0x3C) - PLL1
+ */
+#define WM8990_SDM                              0x0080  /* SDM */
+#define WM8990_PRESCALE                         0x0040  /* PRESCALE */
+#define WM8990_PLLN_MASK                        0x000F  /* PLLN - [3:0] */
+
+/*
+ * R61 (0x3D) - PLL2
+ */
+#define WM8990_PLLK1_MASK                       0x00FF  /* PLLK1 - [7:0] */
+
+/*
+ * R62 (0x3E) - PLL3
+ */
+#define WM8990_PLLK2_MASK                       0x00FF  /* PLLK2 - [7:0] */
+
+/*
+ * R63 (0x3F) - Internal Driver Bits
+ */
+#define WM8990_INMIXL_PWR_BIT                  0
+#define WM8990_AINLMUX_PWR_BIT                 1
+#define WM8990_INMIXR_PWR_BIT                  2
+#define WM8990_AINRMUX_PWR_BIT                 3
+
+struct wm8990_setup_data {
+       unsigned short i2c_address;
+};
+
+#define WM8990_MCLK_DIV 0
+#define WM8990_DACCLK_DIV 1
+#define WM8990_ADCCLK_DIV 2
+#define WM8990_BCLK_DIV 3
+
+extern struct snd_soc_dai wm8990_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8990;
+
+#endif /* __WM8990REGISTERDEFS_H__ */
+/*------------------------------ END OF FILE ---------------------------------*/
index 76c1e2d33e7d0b8d0b5d22a6dd7dc5fbf7fa37f6..9fc8edd82225cfe98dfbcb6aabadddf48eb1e9c5 100644 (file)
@@ -9,9 +9,6 @@
  *  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.
- *
- *  Revision history
- *    4th Feb 2006   Initial version.
  */
 
 #include <linux/init.h>
@@ -25,6 +22,7 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
+#include "wm9712.h"
 
 #define WM9712_VERSION "0.4"
 
@@ -351,7 +349,7 @@ SND_SOC_DAPM_INPUT("MIC1"),
 SND_SOC_DAPM_INPUT("MIC2"),
 };
 
-static const char *audio_map[][3] = {
+static const struct snd_soc_dapm_route audio_map[] = {
        /* virtual mixer - mixes left & right channels for spk and mono */
        {"AC97 Mixer", NULL, "Left DAC"},
        {"AC97 Mixer", NULL, "Right DAC"},
@@ -446,21 +444,14 @@ static const char *audio_map[][3] = {
        {"Speaker PGA", NULL, "Speaker Mux"},
        {"LOUT2", NULL, "Speaker PGA"},
        {"ROUT2", NULL, "Speaker PGA"},
-
-       {NULL, NULL, NULL},
 };
 
 static int wm9712_add_widgets(struct snd_soc_codec *codec)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(wm9712_dapm_widgets); i++)
-               snd_soc_dapm_new_control(codec, &wm9712_dapm_widgets[i]);
+       snd_soc_dapm_new_controls(codec, wm9712_dapm_widgets,
+                                 ARRAY_SIZE(wm9712_dapm_widgets));
 
-       /* set up audio path connects */
-       for (i = 0; audio_map[i][0] != NULL; i++)
-               snd_soc_dapm_connect_input(codec, audio_map[i][0],
-                                          audio_map[i][1], audio_map[i][2]);
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
 
        snd_soc_dapm_new_widgets(codec);
        return 0;
@@ -541,7 +532,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream)
                SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
                SNDRV_PCM_RATE_48000)
 
-struct snd_soc_codec_dai wm9712_dai[] = {
+struct snd_soc_dai wm9712_dai[] = {
 {
        .name = "AC97 HiFi",
        .type = SND_SOC_DAI_AC97_BUS,
@@ -574,23 +565,23 @@ struct snd_soc_codec_dai wm9712_dai[] = {
 };
 EXPORT_SYMBOL_GPL(wm9712_dai);
 
-static int wm9712_dapm_event(struct snd_soc_codec *codec, int event)
+static int wm9712_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
 {
-       switch (event) {
-       case SNDRV_CTL_POWER_D0: /* full On */
-       case SNDRV_CTL_POWER_D1: /* partial On */
-       case SNDRV_CTL_POWER_D2: /* partial On */
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+       case SND_SOC_BIAS_PREPARE:
                break;
-       case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+       case SND_SOC_BIAS_STANDBY:
                ac97_write(codec, AC97_POWERDOWN, 0x0000);
                break;
-       case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+       case SND_SOC_BIAS_OFF:
                /* disable everything including AC link */
                ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
                ac97_write(codec, AC97_POWERDOWN, 0xffff);
                break;
        }
-       codec->dapm_state = event;
+       codec->bias_level = level;
        return 0;
 }
 
@@ -598,12 +589,12 @@ static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
 {
        if (try_warm && soc_ac97_ops.warm_reset) {
                soc_ac97_ops.warm_reset(codec->ac97);
-               if (!(ac97_read(codec, 0) & 0x8000))
+               if (ac97_read(codec, 0) == wm9712_reg[0])
                        return 1;
        }
 
        soc_ac97_ops.reset(codec->ac97);
-       if (ac97_read(codec, 0) & 0x8000)
+       if (ac97_read(codec, 0) != wm9712_reg[0])
                goto err;
        return 0;
 
@@ -618,7 +609,7 @@ static int wm9712_soc_suspend(struct platform_device *pdev,
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_codec *codec = socdev->codec;
 
-       wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+       wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
@@ -635,7 +626,7 @@ static int wm9712_soc_resume(struct platform_device *pdev)
                return ret;
        }
 
-       wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+       wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        if (ret == 0) {
                /* Sync reg_cache with the hardware after cold reset */
@@ -647,8 +638,8 @@ static int wm9712_soc_resume(struct platform_device *pdev)
                }
        }
 
-       if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0)
-               wm9712_dapm_event(codec, SNDRV_CTL_POWER_D0);
+       if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
+               wm9712_set_bias_level(codec, SND_SOC_BIAS_ON);
 
        return ret;
 }
@@ -682,7 +673,7 @@ static int wm9712_soc_probe(struct platform_device *pdev)
        codec->num_dai = ARRAY_SIZE(wm9712_dai);
        codec->write = ac97_write;
        codec->read = ac97_read;
-       codec->dapm_event = wm9712_dapm_event;
+       codec->set_bias_level = wm9712_set_bias_level;
        INIT_LIST_HEAD(&codec->dapm_widgets);
        INIT_LIST_HEAD(&codec->dapm_paths);
 
@@ -706,7 +697,7 @@ static int wm9712_soc_probe(struct platform_device *pdev)
        /* set alc mux to none */
        ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
 
-       wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+       wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        wm9712_add_controls(codec);
        wm9712_add_widgets(codec);
        ret = snd_soc_register_card(socdev);
index 719105d61e6504c1083e7fdf920251ba075b4575..d29e8a18ca6d2abc6aa67d1c717f571978703a82 100644 (file)
@@ -8,7 +8,7 @@
 #define WM9712_DAI_AC97_HIFI   0
 #define WM9712_DAI_AC97_AUX            1
 
-extern struct snd_soc_codec_dai wm9712_dai[2];
+extern struct snd_soc_dai wm9712_dai[2];
 extern struct snd_soc_codec_device soc_codec_dev_wm9712;
 
 #endif
index 1f241161445ce423135c62adcc9e325d14d4bd05..38d1fe0971fc7faf328c6a19ca0f6f6516f42577 100644 (file)
@@ -10,9 +10,6 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  *
- *  Revision history
- *    4th Feb 2006   Initial version.
- *
  *  Features:-
  *
  *   o Support for AC97 Codec, Voice DAC and Aux DAC
@@ -456,7 +453,7 @@ SND_SOC_DAPM_INPUT("MIC2B"),
 SND_SOC_DAPM_VMID("VMID"),
 };
 
-static const char *audio_map[][3] = {
+static const struct snd_soc_dapm_route audio_map[] = {
        /* left HP mixer */
        {"Left HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
        {"Left HP Mixer", "Voice Playback Switch",   "Voice DAC"},
@@ -607,21 +604,14 @@ static const char *audio_map[][3] = {
        {"Capture Mono Mux", "Stereo", "Capture Mixer"},
        {"Capture Mono Mux", "Left", "Left Capture Source"},
        {"Capture Mono Mux", "Right", "Right Capture Source"},
-
-       {NULL, NULL, NULL},
 };
 
 static int wm9713_add_widgets(struct snd_soc_codec *codec)
 {
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(wm9713_dapm_widgets); i++)
-               snd_soc_dapm_new_control(codec, &wm9713_dapm_widgets[i]);
+       snd_soc_dapm_new_controls(codec, wm9713_dapm_widgets,
+                                 ARRAY_SIZE(wm9713_dapm_widgets));
 
-       /* set up audio path audio_mapnects */
-       for (i = 0; audio_map[i][0] != NULL; i++)
-               snd_soc_dapm_connect_input(codec, audio_map[i][0],
-                       audio_map[i][1], audio_map[i][2]);
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
 
        snd_soc_dapm_new_widgets(codec);
        return 0;
@@ -799,7 +789,7 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
        return 0;
 }
 
-static int wm9713_set_dai_pll(struct snd_soc_codec_dai *codec_dai,
+static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai,
                int pll_id, unsigned int freq_in, unsigned int freq_out)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -810,7 +800,7 @@ static int wm9713_set_dai_pll(struct snd_soc_codec_dai *codec_dai,
  * Tristate the PCM DAI lines, tristate can be disabled by calling
  * wm9713_set_dai_fmt()
  */
-static int wm9713_set_dai_tristate(struct snd_soc_codec_dai *codec_dai,
+static int wm9713_set_dai_tristate(struct snd_soc_dai *codec_dai,
        int tristate)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -826,7 +816,7 @@ static int wm9713_set_dai_tristate(struct snd_soc_codec_dai *codec_dai,
  * Configure WM9713 clock dividers.
  * Voice DAC needs 256 FS
  */
-static int wm9713_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
+static int wm9713_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
                int div_id, int div)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -868,7 +858,7 @@ static int wm9713_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
        return 0;
 }
 
-static int wm9713_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -886,7 +876,7 @@ static int wm9713_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
                gpio |= 0x0018;
                break;
        case SND_SOC_DAIFMT_CBS_CFS:
-               reg |= 0x0200;
+               reg |= 0x2000;
                gpio |= 0x001a;
                break;
        case SND_SOC_DAIFMT_CBS_CFM:
@@ -1011,15 +1001,24 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream)
        return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
 }
 
-#define WM9713_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
-               SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
-               SNDRV_PCM_RATE_48000)
+#define WM9713_RATES (SNDRV_PCM_RATE_8000  |   \
+                     SNDRV_PCM_RATE_11025 |    \
+                     SNDRV_PCM_RATE_22050 |    \
+                     SNDRV_PCM_RATE_44100 |    \
+                     SNDRV_PCM_RATE_48000)
+
+#define WM9713_PCM_RATES (SNDRV_PCM_RATE_8000  |       \
+                         SNDRV_PCM_RATE_11025 |        \
+                         SNDRV_PCM_RATE_16000 |        \
+                         SNDRV_PCM_RATE_22050 |        \
+                         SNDRV_PCM_RATE_44100 |        \
+                         SNDRV_PCM_RATE_48000)
 
 #define WM9713_PCM_FORMATS \
        (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
         SNDRV_PCM_FORMAT_S24_LE)
 
-struct snd_soc_codec_dai wm9713_dai[] = {
+struct snd_soc_dai wm9713_dai[] = {
 {
        .name = "AC97 HiFi",
        .type = SND_SOC_DAI_AC97_BUS,
@@ -1061,13 +1060,13 @@ struct snd_soc_codec_dai wm9713_dai[] = {
                .stream_name = "Voice Playback",
                .channels_min = 1,
                .channels_max = 1,
-               .rates = WM9713_RATES,
+               .rates = WM9713_PCM_RATES,
                .formats = WM9713_PCM_FORMATS,},
        .capture = {
                .stream_name = "Voice Capture",
                .channels_min = 1,
                .channels_max = 2,
-               .rates = WM9713_RATES,
+               .rates = WM9713_PCM_RATES,
                .formats = WM9713_PCM_FORMATS,},
        .ops = {
                .hw_params = wm9713_pcm_hw_params,
@@ -1086,44 +1085,44 @@ int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
 {
        if (try_warm && soc_ac97_ops.warm_reset) {
                soc_ac97_ops.warm_reset(codec->ac97);
-               if (!(ac97_read(codec, 0) & 0x8000))
+               if (ac97_read(codec, 0) == wm9713_reg[0])
                        return 1;
        }
 
        soc_ac97_ops.reset(codec->ac97);
-       if (ac97_read(codec, 0) & 0x8000)
+       if (ac97_read(codec, 0) != wm9713_reg[0])
                return -EIO;
        return 0;
 }
 EXPORT_SYMBOL_GPL(wm9713_reset);
 
-static int wm9713_dapm_event(struct snd_soc_codec *codec, int event)
+static int wm9713_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
 {
        u16 reg;
 
-       switch (event) {
-       case SNDRV_CTL_POWER_D0: /* full On */
+       switch (level) {
+       case SND_SOC_BIAS_ON:
                /* enable thermal shutdown */
                reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff;
                ac97_write(codec, AC97_EXTENDED_MID, reg);
                break;
-       case SNDRV_CTL_POWER_D1: /* partial On */
-       case SNDRV_CTL_POWER_D2: /* partial On */
+       case SND_SOC_BIAS_PREPARE:
                break;
-       case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+       case SND_SOC_BIAS_STANDBY:
                /* enable master bias and vmid */
                reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff;
                ac97_write(codec, AC97_EXTENDED_MID, reg);
                ac97_write(codec, AC97_POWERDOWN, 0x0000);
                break;
-       case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+       case SND_SOC_BIAS_OFF:
                /* disable everything including AC link */
                ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
                ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
                ac97_write(codec, AC97_POWERDOWN, 0xffff);
                break;
        }
-       codec->dapm_state = event;
+       codec->bias_level = level;
        return 0;
 }
 
@@ -1160,7 +1159,7 @@ static int wm9713_soc_resume(struct platform_device *pdev)
                return ret;
        }
 
-       wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+       wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* do we need to re-start the PLL ? */
        if (wm9713->pll_out)
@@ -1176,8 +1175,8 @@ static int wm9713_soc_resume(struct platform_device *pdev)
                }
        }
 
-       if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0)
-               wm9713_dapm_event(codec, SNDRV_CTL_POWER_D0);
+       if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
+               wm9713_set_bias_level(codec, SND_SOC_BIAS_ON);
 
        return ret;
 }
@@ -1216,7 +1215,7 @@ static int wm9713_soc_probe(struct platform_device *pdev)
        codec->num_dai = ARRAY_SIZE(wm9713_dai);
        codec->write = ac97_write;
        codec->read = ac97_read;
-       codec->dapm_event = wm9713_dapm_event;
+       codec->set_bias_level = wm9713_set_bias_level;
        INIT_LIST_HEAD(&codec->dapm_widgets);
        INIT_LIST_HEAD(&codec->dapm_paths);
 
@@ -1238,7 +1237,7 @@ static int wm9713_soc_probe(struct platform_device *pdev)
                goto reset_err;
        }
 
-       wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+       wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* unmute the adc - move to kcontrol */
        reg = ac97_read(codec, AC97_CD) & 0x7fff;
index d357b6c8134b7833f13113cd64107fbc8888e85f..63b8d81756e3a50daaeffd777da56539a6f2ad9f 100644 (file)
@@ -46,7 +46,7 @@
 #define WM9713_DAI_PCM_VOICE   2
 
 extern struct snd_soc_codec_device soc_codec_dev_wm9713;
-extern struct snd_soc_codec_dai wm9713_dai[3];
+extern struct snd_soc_dai wm9713_dai[3];
 
 int wm9713_reset(struct snd_soc_codec *codec,  int try_warm);
 
index 20680c551aabc8047fcaf6cd5210dc8914d1736b..8f7e3383490246e81c66c4dc7b92849d768b804e 100644 (file)
@@ -1,6 +1,6 @@
 config SND_DAVINCI_SOC
        tristate "SoC Audio for the TI DAVINCI chip"
-       depends on ARCH_DAVINCI && SND_SOC
+       depends on ARCH_DAVINCI
        help
          Say Y or M if you want to add support for codecs attached to
          the DAVINCI AC97 or I2S interface. You will also need
index fcd165240333ff3e0880164a71657cbe4d54e5b3..5e2c306399edac83170615b47bab77e379113036 100644 (file)
@@ -33,24 +33,24 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
                         struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        int ret = 0;
 
        /* set codec DAI configuration */
-       ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
                                         SND_SOC_DAIFMT_CBM_CFM);
        if (ret < 0)
                return ret;
 
        /* set cpu DAI configuration */
-       ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM |
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM |
                                       SND_SOC_DAIFMT_IB_NF);
        if (ret < 0)
                return ret;
 
        /* set the codec system clock */
-       ret = codec_dai->dai_ops.set_sysclk(codec_dai, 0, EVM_CODEC_CLOCK,
+       ret = snd_soc_dai_set_sysclk(codec_dai, 0, EVM_CODEC_CLOCK,
                                            SND_SOC_CLOCK_OUT);
        if (ret < 0)
                return ret;
@@ -71,7 +71,7 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
 };
 
 /* davinci-evm machine audio_mapnections to the codec pins */
-static const char *audio_map[][3] = {
+static const struct snd_soc_dapm_route audio_map[] = {
        /* Headphone connected to HPLOUT, HPROUT */
        {"Headphone Jack", NULL, "HPLOUT"},
        {"Headphone Jack", NULL, "HPROUT"},
@@ -90,36 +90,30 @@ static const char *audio_map[][3] = {
        {"LINE2L", NULL, "Line In"},
        {"LINE1R", NULL, "Line In"},
        {"LINE2R", NULL, "Line In"},
-
-       {NULL, NULL, NULL},
 };
 
 /* Logic for a aic3x as connected on a davinci-evm */
 static int evm_aic3x_init(struct snd_soc_codec *codec)
 {
-       int i;
-
        /* Add davinci-evm specific widgets */
-       for (i = 0; i < ARRAY_SIZE(aic3x_dapm_widgets); i++)
-               snd_soc_dapm_new_control(codec, &aic3x_dapm_widgets[i]);
+       snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
+                                 ARRAY_SIZE(aic3x_dapm_widgets));
 
        /* Set up davinci-evm specific audio path audio_map */
-       for (i = 0; audio_map[i][0] != NULL; i++)
-               snd_soc_dapm_connect_input(codec, audio_map[i][0],
-                                          audio_map[i][1], audio_map[i][2]);
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
 
        /* not connected */
-       snd_soc_dapm_set_endpoint(codec, "MONO_LOUT", 0);
-       snd_soc_dapm_set_endpoint(codec, "HPLCOM", 0);
-       snd_soc_dapm_set_endpoint(codec, "HPRCOM", 0);
+       snd_soc_dapm_disable_pin(codec, "MONO_LOUT");
+       snd_soc_dapm_disable_pin(codec, "HPLCOM");
+       snd_soc_dapm_disable_pin(codec, "HPRCOM");
 
        /* always connected */
-       snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
-       snd_soc_dapm_set_endpoint(codec, "Line Out", 1);
-       snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
-       snd_soc_dapm_set_endpoint(codec, "Line In", 1);
+       snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+       snd_soc_dapm_enable_pin(codec, "Line Out");
+       snd_soc_dapm_enable_pin(codec, "Mic Jack");
+       snd_soc_dapm_enable_pin(codec, "Line In");
 
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
 
        return 0;
 }
index c421774b33ee9b58d9705ada66e546bd4ba9fce9..5ebf1ff71c4cbce6451ecd63dbe080586ac531ea 100644 (file)
@@ -147,7 +147,7 @@ static void davinci_mcbsp_stop(struct snd_pcm_substream *substream)
 static int davinci_i2s_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
 
        cpu_dai->dma_data = dev->dma_params[substream->stream];
@@ -155,7 +155,7 @@ static int davinci_i2s_startup(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static int davinci_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
+static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                                   unsigned int fmt)
 {
        struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
@@ -295,11 +295,12 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
        return ret;
 }
 
-static int davinci_i2s_probe(struct platform_device *pdev)
+static int davinci_i2s_probe(struct platform_device *pdev,
+                            struct snd_soc_dai *dai)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_machine *machine = socdev->machine;
-       struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
+       struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
        struct davinci_mcbsp_dev *dev;
        struct resource *mem, *ioarea;
        struct evm_snd_platform_data *pdata;
@@ -356,11 +357,12 @@ err_release_region:
        return ret;
 }
 
-static void davinci_i2s_remove(struct platform_device *pdev)
+static void davinci_i2s_remove(struct platform_device *pdev,
+                              struct snd_soc_dai *dai)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_machine *machine = socdev->machine;
-       struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
+       struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
        struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
        struct resource *mem;
 
@@ -376,7 +378,7 @@ static void davinci_i2s_remove(struct platform_device *pdev)
 
 #define DAVINCI_I2S_RATES      SNDRV_PCM_RATE_8000_96000
 
-struct snd_soc_cpu_dai davinci_i2s_dai = {
+struct snd_soc_dai davinci_i2s_dai = {
        .name = "davinci-i2s",
        .id = 0,
        .type = SND_SOC_DAI_I2S,
index 9592d17db320c88524901eebcf6da5ef9bb518fc..c5b091807eecf891bb71baa1a208933da3c62a17 100644 (file)
@@ -12,6 +12,6 @@
 #ifndef _DAVINCI_I2S_H
 #define _DAVINCI_I2S_H
 
-extern struct snd_soc_cpu_dai davinci_i2s_dai;
+extern struct snd_soc_dai davinci_i2s_dai;
 
 #endif
index 6a76927c997144c4d6dcbd1e0e317c7d39c82c62..6a5e56a782bb2f9a13551aa3365a6b2b7db85e4a 100644 (file)
@@ -350,7 +350,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
 static u64 davinci_pcm_dmamask = 0xffffffff;
 
 static int davinci_pcm_new(struct snd_card *card,
-                          struct snd_soc_codec_dai *dai, struct snd_pcm *pcm)
+                          struct snd_soc_dai *dai, struct snd_pcm *pcm)
 {
        int ret;
 
index 257101f44e9e168de81dcbd2429b740b8c699954..3368ace60977eac389f1b57254e3fcb6c832ab4d 100644 (file)
@@ -1,8 +1,6 @@
-menu "ALSA SoC audio for Freescale SOCs"
-
 config SND_SOC_MPC8610
        bool "ALSA SoC support for the MPC8610 SOC"
-       depends on SND_SOC && MPC8610_HPCD
+       depends on MPC8610_HPCD
        default y if MPC8610
        help
          Say Y if you want to add support for codecs attached to the SSI
@@ -16,5 +14,3 @@ config SND_SOC_MPC8610_HPCD
        default y if MPC8610_HPCD
        help
          Say Y if you want to enable audio on the Freescale MPC8610 HPCD.
-
-endmenu
index 78de7168d2ba506c767c397f6362ae0c248ef190..da2bc590286438fe7b000cea43e24baf4b6bb417 100644 (file)
@@ -282,7 +282,7 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
  * once for each .dai_link in the machine driver's snd_soc_machine
  * structure.
  */
-static int fsl_dma_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
+static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
        struct snd_pcm *pcm)
 {
        static u64 fsl_dma_dmamask = DMA_BIT_MASK(32);
index 430a6ce8b0d0964f1c2591b07463e4c2e6d6b255..385d4a42603cf3b681ab12c6f050ccd3e11f7bb0 100644 (file)
@@ -126,7 +126,7 @@ struct fsl_dma_link_descriptor {
        u8 res[4];      /* Reserved */
 } __attribute__ ((aligned(32), packed));
 
-/* DMA information needed to create a snd_soc_cpu_dai object
+/* DMA information needed to create a snd_soc_dai object
  *
  * ssi_stx_phys: bus address of SSI STX register to use
  * ssi_srx_phys: bus address of SSI SRX register to use
index f588545698f3687f75941977b8e597791c964e9e..71bff33f5528fe5e34849c06bbc1e88b91fbbcbb 100644 (file)
@@ -82,7 +82,7 @@ struct fsl_ssi_private {
        struct device *dev;
        unsigned int playback;
        unsigned int capture;
-       struct snd_soc_cpu_dai cpu_dai;
+       struct snd_soc_dai cpu_dai;
        struct device_attribute dev_attr;
 
        struct {
@@ -479,7 +479,7 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream)
  * @freq: the frequency of the given clock ID, currently ignored
  * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master)
  */
-static int fsl_ssi_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+static int fsl_ssi_set_sysclk(struct snd_soc_dai *cpu_dai,
                              int clk_id, unsigned int freq, int dir)
 {
 
@@ -497,7 +497,7 @@ static int fsl_ssi_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
  *
  * @format: one of SND_SOC_DAIFMT_xxx
  */
-static int fsl_ssi_set_fmt(struct snd_soc_cpu_dai *cpu_dai, unsigned int format)
+static int fsl_ssi_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
 {
        return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
 }
@@ -505,7 +505,7 @@ static int fsl_ssi_set_fmt(struct snd_soc_cpu_dai *cpu_dai, unsigned int format)
 /**
  * fsl_ssi_dai_template: template CPU DAI for the SSI
  */
-static struct snd_soc_cpu_dai fsl_ssi_dai_template = {
+static struct snd_soc_dai fsl_ssi_dai_template = {
        .playback = {
                /* The SSI does not support monaural audio. */
                .channels_min = 2,
@@ -569,15 +569,15 @@ static ssize_t fsl_sysfs_ssi_show(struct device *dev,
 }
 
 /**
- * fsl_ssi_create_dai: create a snd_soc_cpu_dai structure
+ * fsl_ssi_create_dai: create a snd_soc_dai structure
  *
- * This function is called by the machine driver to create a snd_soc_cpu_dai
+ * This function is called by the machine driver to create a snd_soc_dai
  * structure.  The function creates an ssi_private object, which contains
- * the snd_soc_cpu_dai.  It also creates the sysfs statistics device.
+ * the snd_soc_dai.  It also creates the sysfs statistics device.
  */
-struct snd_soc_cpu_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
+struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
 {
-       struct snd_soc_cpu_dai *fsl_ssi_dai;
+       struct snd_soc_dai *fsl_ssi_dai;
        struct fsl_ssi_private *ssi_private;
        int ret = 0;
        struct device_attribute *dev_attr;
@@ -588,7 +588,7 @@ struct snd_soc_cpu_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
                return NULL;
        }
        memcpy(&ssi_private->cpu_dai, &fsl_ssi_dai_template,
-              sizeof(struct snd_soc_cpu_dai));
+              sizeof(struct snd_soc_dai));
 
        fsl_ssi_dai = &ssi_private->cpu_dai;
        dev_attr = &ssi_private->dev_attr;
@@ -623,11 +623,11 @@ struct snd_soc_cpu_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
 EXPORT_SYMBOL_GPL(fsl_ssi_create_dai);
 
 /**
- * fsl_ssi_destroy_dai: destroy the snd_soc_cpu_dai object
+ * fsl_ssi_destroy_dai: destroy the snd_soc_dai object
  *
  * This function undoes the operations of fsl_ssi_create_dai()
  */
-void fsl_ssi_destroy_dai(struct snd_soc_cpu_dai *fsl_ssi_dai)
+void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai)
 {
        struct fsl_ssi_private *ssi_private =
        container_of(fsl_ssi_dai, struct fsl_ssi_private, cpu_dai);
index c5ce88e1565190ae5acd6322c71f665c4850d761..83b44d700e3328fbf973d25c616751555211f202 100644 (file)
@@ -217,8 +217,8 @@ struct fsl_ssi_info {
        struct device *dev;
 };
 
-struct snd_soc_cpu_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info);
-void fsl_ssi_destroy_dai(struct snd_soc_cpu_dai *fsl_ssi_dai);
+struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info);
+void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai);
 
 #endif
 
index a00aac7a71f1c10e88b681e4867647bf96d9c328..4bdc9d8fc90e0d8fa3f4f7d6d5f14813c4abe5da 100644 (file)
@@ -58,9 +58,9 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
                sound_device->dev.platform_data;
 
        /* Program the signal routing between the SSI and the DMA */
-       guts_set_dmacr(machine_data->guts, machine_data->dma_id + 1,
+       guts_set_dmacr(machine_data->guts, machine_data->dma_id,
                machine_data->dma_channel_id[0], CCSR_GUTS_DMACR_DEV_SSI);
-       guts_set_dmacr(machine_data->guts, machine_data->dma_id + 1,
+       guts_set_dmacr(machine_data->guts, machine_data->dma_id,
                machine_data->dma_channel_id[1], CCSR_GUTS_DMACR_DEV_SSI);
 
        guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id,
@@ -96,62 +96,52 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
 static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct mpc8610_hpcd_data *machine_data =
                rtd->socdev->dev->platform_data;
        int ret = 0;
 
        /* Tell the CPU driver what the serial protocol is. */
-       if (cpu_dai->dai_ops.set_fmt) {
-               ret = cpu_dai->dai_ops.set_fmt(cpu_dai,
-                       machine_data->dai_format);
-               if (ret < 0) {
-                       dev_err(substream->pcm->card->dev,
-                               "could not set CPU driver audio format\n");
-                       return ret;
-               }
+       ret = snd_soc_dai_set_fmt(cpu_dai, machine_data->dai_format);
+       if (ret < 0) {
+               dev_err(substream->pcm->card->dev,
+                       "could not set CPU driver audio format\n");
+               return ret;
        }
 
        /* Tell the codec driver what the serial protocol is. */
-       if (codec_dai->dai_ops.set_fmt) {
-               ret = codec_dai->dai_ops.set_fmt(codec_dai,
-                       machine_data->dai_format);
-               if (ret < 0) {
-                       dev_err(substream->pcm->card->dev,
-                               "could not set codec driver audio format\n");
-                       return ret;
-               }
+       ret = snd_soc_dai_set_fmt(codec_dai, machine_data->dai_format);
+       if (ret < 0) {
+               dev_err(substream->pcm->card->dev,
+                       "could not set codec driver audio format\n");
+               return ret;
        }
 
        /*
         * Tell the CPU driver what the clock frequency is, and whether it's a
         * slave or master.
         */
-       if (cpu_dai->dai_ops.set_sysclk) {
-               ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, 0,
-                       machine_data->clk_frequency,
-                       machine_data->cpu_clk_direction);
-               if (ret < 0) {
-                       dev_err(substream->pcm->card->dev,
-                               "could not set CPU driver clock parameters\n");
-                       return ret;
-               }
+       ret = snd_soc_dai_set_sysclk(cpu_dai, 0,
+                                       machine_data->clk_frequency,
+                                       machine_data->cpu_clk_direction);
+       if (ret < 0) {
+               dev_err(substream->pcm->card->dev,
+                       "could not set CPU driver clock parameters\n");
+               return ret;
        }
 
        /*
         * Tell the codec driver what the MCLK frequency is, and whether it's
         * a slave or master.
         */
-       if (codec_dai->dai_ops.set_sysclk) {
-               ret = codec_dai->dai_ops.set_sysclk(codec_dai, 0,
-                       machine_data->clk_frequency,
-                       machine_data->codec_clk_direction);
-               if (ret < 0) {
-                       dev_err(substream->pcm->card->dev,
-                               "could not set codec driver clock params\n");
-                       return ret;
-               }
+       ret = snd_soc_dai_set_sysclk(codec_dai, 0,
+                                       machine_data->clk_frequency,
+                                       machine_data->codec_clk_direction);
+       if (ret < 0) {
+               dev_err(substream->pcm->card->dev,
+                       "could not set codec driver clock params\n");
+               return ret;
        }
 
        return 0;
@@ -170,9 +160,9 @@ int mpc8610_hpcd_machine_remove(struct platform_device *sound_device)
 
        /* Restore the signal routing */
 
-       guts_set_dmacr(machine_data->guts, machine_data->dma_id + 1,
+       guts_set_dmacr(machine_data->guts, machine_data->dma_id,
                machine_data->dma_channel_id[0], 0);
-       guts_set_dmacr(machine_data->guts, machine_data->dma_id + 1,
+       guts_set_dmacr(machine_data->guts, machine_data->dma_id,
                machine_data->dma_channel_id[1], 0);
 
        switch (machine_data->ssi_id) {
@@ -182,7 +172,7 @@ int mpc8610_hpcd_machine_remove(struct platform_device *sound_device)
                break;
        case 1:
                clrsetbits_be32(&machine_data->guts->pmuxcr,
-                       CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI1_LA);
+                       CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_LA);
                break;
        }
 
index 0230d83e8e5ef83739f1f4ae4c602e2cffc392ae..aea27e70043cf8f687884227c117ceed224c98f4 100644 (file)
@@ -1,5 +1,3 @@
-menu "SoC Audio for the Texas Instruments OMAP"
-
 config SND_OMAP_SOC
        tristate "SoC Audio for the Texas Instruments OMAP chips"
        depends on ARCH_OMAP && SND_SOC
@@ -15,5 +13,3 @@ config SND_OMAP_SOC_N810
        select SND_SOC_TLV320AIC3X
        help
          Say Y if you want to add support for SoC audio on Nokia N810.
-
-endmenu
index 6533563a6011d01ccb71084c136f79d7a1b808d6..02cec96859b8444133a1cf3a464533bdd87c67cf 100644 (file)
 
 #include <asm/mach-types.h>
 #include <asm/arch/hardware.h>
-#include <asm/arch/gpio.h>
+#include <linux/gpio.h>
 #include <asm/arch/mcbsp.h>
 
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
 #include "../codecs/tlv320aic3x.h"
 
-#define RX44_HEADSET_AMP_GPIO  10
-#define RX44_SPEAKER_AMP_GPIO  101
+#define N810_HEADSET_AMP_GPIO  10
+#define N810_SPEAKER_AMP_GPIO  101
 
 static struct clk *sys_clkout2;
 static struct clk *sys_clkout2_src;
@@ -46,13 +46,26 @@ static struct clk *func96m_clk;
 
 static int n810_spk_func;
 static int n810_jack_func;
+static int n810_dmic_func;
 
 static void n810_ext_control(struct snd_soc_codec *codec)
 {
-       snd_soc_dapm_set_endpoint(codec, "Ext Spk", n810_spk_func);
-       snd_soc_dapm_set_endpoint(codec, "Headphone Jack", n810_jack_func);
+       if (n810_spk_func)
+               snd_soc_dapm_enable_pin(codec, "Ext Spk");
+       else
+               snd_soc_dapm_disable_pin(codec, "Ext Spk");
+
+       if (n810_jack_func)
+               snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+       else
+               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
 
-       snd_soc_dapm_sync_endpoints(codec);
+       if (n810_dmic_func)
+               snd_soc_dapm_enable_pin(codec, "DMic");
+       else
+               snd_soc_dapm_disable_pin(codec, "DMic");
+
+       snd_soc_dapm_sync(codec);
 }
 
 static int n810_startup(struct snd_pcm_substream *substream)
@@ -73,12 +86,12 @@ static int n810_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        int err;
 
        /* Set codec DAI configuration */
-       err = codec_dai->dai_ops.set_fmt(codec_dai,
+       err = snd_soc_dai_set_fmt(codec_dai,
                                         SND_SOC_DAIFMT_I2S |
                                         SND_SOC_DAIFMT_NB_NF |
                                         SND_SOC_DAIFMT_CBM_CFM);
@@ -86,7 +99,7 @@ static int n810_hw_params(struct snd_pcm_substream *substream,
                return err;
 
        /* Set cpu DAI configuration */
-       err = cpu_dai->dai_ops.set_fmt(cpu_dai,
+       err = snd_soc_dai_set_fmt(cpu_dai,
                                       SND_SOC_DAIFMT_I2S |
                                       SND_SOC_DAIFMT_NB_NF |
                                       SND_SOC_DAIFMT_CBM_CFM);
@@ -94,7 +107,7 @@ static int n810_hw_params(struct snd_pcm_substream *substream,
                return err;
 
        /* Set the codec system clock for DAC and ADC */
-       err = codec_dai->dai_ops.set_sysclk(codec_dai, 0, 12000000,
+       err = snd_soc_dai_set_sysclk(codec_dai, 0, 12000000,
                                            SND_SOC_CLOCK_IN);
 
        return err;
@@ -150,13 +163,35 @@ static int n810_set_jack(struct snd_kcontrol *kcontrol,
        return 1;
 }
 
+static int n810_get_input(struct snd_kcontrol *kcontrol,
+                         struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.integer.value[0] = n810_dmic_func;
+
+       return 0;
+}
+
+static int n810_set_input(struct snd_kcontrol *kcontrol,
+                         struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+       if (n810_dmic_func == ucontrol->value.integer.value[0])
+               return 0;
+
+       n810_dmic_func = ucontrol->value.integer.value[0];
+       n810_ext_control(codec);
+
+       return 1;
+}
+
 static int n810_spk_event(struct snd_soc_dapm_widget *w,
                          struct snd_kcontrol *k, int event)
 {
        if (SND_SOC_DAPM_EVENT_ON(event))
-               omap_set_gpio_dataout(RX44_SPEAKER_AMP_GPIO, 1);
+               gpio_set_value(N810_SPEAKER_AMP_GPIO, 1);
        else
-               omap_set_gpio_dataout(RX44_SPEAKER_AMP_GPIO, 0);
+               gpio_set_value(N810_SPEAKER_AMP_GPIO, 0);
 
        return 0;
 }
@@ -165,9 +200,9 @@ static int n810_jack_event(struct snd_soc_dapm_widget *w,
                           struct snd_kcontrol *k, int event)
 {
        if (SND_SOC_DAPM_EVENT_ON(event))
-               omap_set_gpio_dataout(RX44_HEADSET_AMP_GPIO, 1);
+               gpio_set_value(N810_HEADSET_AMP_GPIO, 1);
        else
-               omap_set_gpio_dataout(RX44_HEADSET_AMP_GPIO, 0);
+               gpio_set_value(N810_HEADSET_AMP_GPIO, 0);
 
        return 0;
 }
@@ -175,21 +210,27 @@ static int n810_jack_event(struct snd_soc_dapm_widget *w,
 static const struct snd_soc_dapm_widget aic33_dapm_widgets[] = {
        SND_SOC_DAPM_SPK("Ext Spk", n810_spk_event),
        SND_SOC_DAPM_HP("Headphone Jack", n810_jack_event),
+       SND_SOC_DAPM_MIC("DMic", NULL),
 };
 
-static const char *audio_map[][3] = {
+static const struct snd_soc_dapm_route audio_map[] = {
        {"Headphone Jack", NULL, "HPLOUT"},
        {"Headphone Jack", NULL, "HPROUT"},
 
        {"Ext Spk", NULL, "LLOUT"},
        {"Ext Spk", NULL, "RLOUT"},
+
+       {"DMic Rate 64", NULL, "Mic Bias 2V"},
+       {"Mic Bias 2V", NULL, "DMic"},
 };
 
 static const char *spk_function[] = {"Off", "On"};
 static const char *jack_function[] = {"Off", "Headphone"};
+static const char *input_function[] = {"ADC", "Digital Mic"};
 static const struct soc_enum n810_enum[] = {
        SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
        SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function),
+       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function),
 };
 
 static const struct snd_kcontrol_new aic33_n810_controls[] = {
@@ -197,6 +238,8 @@ static const struct snd_kcontrol_new aic33_n810_controls[] = {
                     n810_get_spk, n810_set_spk),
        SOC_ENUM_EXT("Jack Function", n810_enum[1],
                     n810_get_jack, n810_set_jack),
+       SOC_ENUM_EXT("Input Select",  n810_enum[2],
+                    n810_get_input, n810_set_input),
 };
 
 static int n810_aic33_init(struct snd_soc_codec *codec)
@@ -204,9 +247,9 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
        int i, err;
 
        /* Not connected */
-       snd_soc_dapm_set_endpoint(codec, "MONO_LOUT", 0);
-       snd_soc_dapm_set_endpoint(codec, "HPLCOM", 0);
-       snd_soc_dapm_set_endpoint(codec, "HPRCOM", 0);
+       snd_soc_dapm_disable_pin(codec, "MONO_LOUT");
+       snd_soc_dapm_disable_pin(codec, "HPLCOM");
+       snd_soc_dapm_disable_pin(codec, "HPRCOM");
 
        /* Add N810 specific controls */
        for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) {
@@ -217,15 +260,13 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
        }
 
        /* Add N810 specific widgets */
-       for (i = 0; i < ARRAY_SIZE(aic33_dapm_widgets); i++)
-               snd_soc_dapm_new_control(codec, &aic33_dapm_widgets[i]);
+       snd_soc_dapm_new_controls(codec, aic33_dapm_widgets,
+                                 ARRAY_SIZE(aic33_dapm_widgets));
 
        /* Set up N810 specific audio path audio_map */
-       for (i = 0; i < ARRAY_SIZE(audio_map); i++)
-               snd_soc_dapm_connect_input(codec, audio_map[i][0],
-                       audio_map[i][1], audio_map[i][2]);
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
 
        return 0;
 }
@@ -250,6 +291,8 @@ static struct snd_soc_machine snd_soc_machine_n810 = {
 /* Audio private data */
 static struct aic3x_setup_data n810_aic33_setup = {
        .i2c_address = 0x18,
+       .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
+       .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
 };
 
 /* Audio subsystem */
@@ -267,7 +310,7 @@ static int __init n810_soc_init(void)
        int err;
        struct device *dev;
 
-       if (!machine_is_nokia_n810())
+       if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax()))
                return -ENODEV;
 
        n810_snd_device = platform_device_alloc("soc-audio", -1);
@@ -305,12 +348,12 @@ static int __init n810_soc_init(void)
        clk_set_parent(sys_clkout2_src, func96m_clk);
        clk_set_rate(sys_clkout2, 12000000);
 
-       if (omap_request_gpio(RX44_HEADSET_AMP_GPIO) < 0)
+       if (gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0)
                BUG();
-       if (omap_request_gpio(RX44_SPEAKER_AMP_GPIO) < 0)
+       if (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0)
                BUG();
-       omap_set_gpio_direction(RX44_HEADSET_AMP_GPIO, 0);
-       omap_set_gpio_direction(RX44_SPEAKER_AMP_GPIO, 0);
+       gpio_direction_output(N810_HEADSET_AMP_GPIO, 0);
+       gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0);
 
        return 0;
 err2:
@@ -325,6 +368,9 @@ err1:
 
 static void __exit n810_soc_exit(void)
 {
+       gpio_free(N810_SPEAKER_AMP_GPIO);
+       gpio_free(N810_HEADSET_AMP_GPIO);
+
        platform_device_unregister(n810_snd_device);
 }
 
index 40d87e6d0de8672f7463328de6b112805d36eab5..00b0c9d73cd4ee7460f1260c32efae8d31e5bf18 100644 (file)
@@ -103,7 +103,7 @@ static const unsigned long omap2420_mcbsp_port[][2] = {};
 static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
        int err = 0;
 
@@ -116,7 +116,7 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
 static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
 
        if (!cpu_dai->active) {
@@ -128,7 +128,7 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream)
 static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
        int err = 0;
 
@@ -157,7 +157,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
                                    struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
        int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
@@ -223,7 +223,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
  * This must be called before _set_clkdiv and _set_sysclk since McBSP register
  * cache is initialized here
  */
-static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
+static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                                      unsigned int fmt)
 {
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
@@ -292,7 +292,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
        return 0;
 }
 
-static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
+static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
                                     int div_id, int div)
 {
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
@@ -347,7 +347,7 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
        return 0;
 }
 
-static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                                         int clk_id, unsigned int freq,
                                         int dir)
 {
@@ -376,7 +376,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
        return err;
 }
 
-struct snd_soc_cpu_dai omap_mcbsp_dai[NUM_LINKS] = {
+struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS] = {
 {
        .name = "omap-mcbsp-dai",
        .id = 0,
index 9965fd4b042708f581ac76f073864bf8479cc7c5..ed8afb55067173fc4969b2984ae20e10f5cabdea 100644 (file)
@@ -44,6 +44,6 @@ enum omap_mcbsp_div {
  */
 #define NUM_LINKS      1
 
-extern struct snd_soc_cpu_dai omap_mcbsp_dai[NUM_LINKS];
+extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS];
 
 #endif
index 62370202c649c5aac50e542626b574a7079909e2..e092f3d836d0a080a2579f4a93aa0237dd6cc1d3 100644 (file)
@@ -316,7 +316,7 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm)
        }
 }
 
-int omap_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
+int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
                 struct snd_pcm *pcm)
 {
        int ret = 0;
index 484f883459e086a95af2ff2edd881b8c8b9a0500..12f6ac99b04c4386b28f68cbcbe3d404b5cc2efe 100644 (file)
@@ -1,6 +1,6 @@
 config SND_PXA2XX_SOC
        tristate "SoC Audio for the Intel PXA2xx chip"
-       depends on ARCH_PXA && SND_SOC
+       depends on ARCH_PXA
        help
          Say Y or M if you want to add support for codecs attached to
          the PXA2xx AC97, I2S or SSP interface. You will also need
@@ -62,3 +62,12 @@ config SND_PXA2XX_SOC_E800
        help
          Say Y if you want to add support for SoC audio on the
          Toshiba e800 PDA
+
+config SND_PXA2XX_SOC_EM_X270
+       tristate "SoC Audio support for CompuLab EM-x270"
+       depends on SND_PXA2XX_SOC && MACH_EM_X270
+       select SND_PXA2XX_SOC_AC97
+       select SND_SOC_WM9712
+       help
+         Say Y if you want to add support for SoC audio on
+         CompuLab EM-x270.
index 04e5646f75ba3f8d77cc5a0caf4d162439c87b53..5bc8edf9dca9ec8532ec6e56e1c7e7ea88f463fc 100644 (file)
@@ -13,10 +13,11 @@ snd-soc-poodle-objs := poodle.o
 snd-soc-tosa-objs := tosa.o
 snd-soc-e800-objs := e800_wm9712.o
 snd-soc-spitz-objs := spitz.o
+snd-soc-em-x270-objs := em-x270.o
 
 obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
 obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
 obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o
 obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
 obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
-
+obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
index 7f32a1167572c7cf67171a0468f0174cfb4da682..c0294464a23aef4f14c099b989dc058168b4da6a 100644 (file)
  *  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.
- *
- *  Revision history
- *    30th Nov 2005   Initial version.
- *
  */
 
 #include <linux/module.h>
@@ -54,47 +50,51 @@ static int corgi_spk_func;
 
 static void corgi_ext_control(struct snd_soc_codec *codec)
 {
-       int spk = 0, mic = 0, line = 0, hp = 0, hs = 0;
-
        /* set up jack connection */
        switch (corgi_jack_func) {
        case CORGI_HP:
-               hp = 1;
                /* set = unmute headphone */
                set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
                set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
+               snd_soc_dapm_disable_pin(codec, "Mic Jack");
+               snd_soc_dapm_disable_pin(codec, "Line Jack");
+               snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+               snd_soc_dapm_disable_pin(codec, "Headset Jack");
                break;
        case CORGI_MIC:
-               mic = 1;
                /* reset = mute headphone */
                reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
                reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
+               snd_soc_dapm_enable_pin(codec, "Mic Jack");
+               snd_soc_dapm_disable_pin(codec, "Line Jack");
+               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+               snd_soc_dapm_disable_pin(codec, "Headset Jack");
                break;
        case CORGI_LINE:
-               line = 1;
                reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
                reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
+               snd_soc_dapm_disable_pin(codec, "Mic Jack");
+               snd_soc_dapm_enable_pin(codec, "Line Jack");
+               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+               snd_soc_dapm_disable_pin(codec, "Headset Jack");
                break;
        case CORGI_HEADSET:
-               hs = 1;
-               mic = 1;
                reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
                set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
+               snd_soc_dapm_enable_pin(codec, "Mic Jack");
+               snd_soc_dapm_disable_pin(codec, "Line Jack");
+               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+               snd_soc_dapm_enable_pin(codec, "Headset Jack");
                break;
        }
 
        if (corgi_spk_func == CORGI_SPK_ON)
-               spk = 1;
-
-       /* set the enpoints to their new connetion states */
-       snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk);
-       snd_soc_dapm_set_endpoint(codec, "Mic Jack", mic);
-       snd_soc_dapm_set_endpoint(codec, "Line Jack", line);
-       snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp);
-       snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs);
+               snd_soc_dapm_enable_pin(codec, "Ext Spk");
+       else
+               snd_soc_dapm_disable_pin(codec, "Ext Spk");
 
        /* signal a DAPM event */
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
 }
 
 static int corgi_startup(struct snd_pcm_substream *substream)
@@ -123,8 +123,8 @@ static int corgi_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        unsigned int clk = 0;
        int ret = 0;
 
@@ -143,25 +143,25 @@ static int corgi_hw_params(struct snd_pcm_substream *substream,
        }
 
        /* set codec DAI configuration */
-       ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
        if (ret < 0)
                return ret;
 
        /* set cpu DAI configuration */
-       ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
        if (ret < 0)
                return ret;
 
        /* set the codec system clock for DAC and ADC */
-       ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK, clk,
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk,
                SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
 
        /* set the I2S system clock as input (unused) */
-       ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
+       ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
                SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
@@ -247,7 +247,7 @@ SND_SOC_DAPM_HP("Headset Jack", NULL),
 };
 
 /* Corgi machine audio map (connections to the codec pins) */
-static const char *audio_map[][3] = {
+static const struct snd_soc_dapm_route audio_map[] = {
 
        /* headset Jack  - in = micin, out = LHPOUT*/
        {"Headset Jack", NULL, "LHPOUT"},
@@ -265,8 +265,6 @@ static const char *audio_map[][3] = {
 
        /* Same as the above but no mic bias for line signals */
        {"MICIN", NULL, "Line Jack"},
-
-       {NULL, NULL, NULL},
 };
 
 static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
@@ -291,8 +289,8 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
 {
        int i, err;
 
-       snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
-       snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
+       snd_soc_dapm_disable_pin(codec, "LLINEIN");
+       snd_soc_dapm_disable_pin(codec, "RLINEIN");
 
        /* Add corgi specific controls */
        for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
@@ -303,15 +301,13 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
        }
 
        /* Add corgi specific widgets */
-       for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
-               snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
+       snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
+                                 ARRAY_SIZE(wm8731_dapm_widgets));
 
        /* Set up corgi specific audio path audio_map */
-       for (i = 0; audio_map[i][0] != NULL; i++)
-               snd_soc_dapm_connect_input(codec, audio_map[i][0],
-                       audio_map[i][1], audio_map[i][2]);
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
        return 0;
 }
 
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
new file mode 100644 (file)
index 0000000..02dcac3
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * em-x270.c  --  SoC audio for EM-X270
+ *
+ * Copyright 2007 CompuLab, Ltd.
+ *
+ * Author: Mike Rapoport <mike@compulab.co.il>
+ *
+ * Copied from tosa.c:
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Copyright 2005 Openedhand Ltd.
+ *
+ * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
+ *          Richard Purdie <richard@openedhand.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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/audio.h>
+
+#include "../codecs/wm9712.h"
+#include "pxa2xx-pcm.h"
+#include "pxa2xx-ac97.h"
+
+static struct snd_soc_dai_link em_x270_dai[] = {
+       {
+               .name = "AC97",
+               .stream_name = "AC97 HiFi",
+               .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
+               .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
+       },
+       {
+               .name = "AC97 Aux",
+               .stream_name = "AC97 Aux",
+               .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
+               .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
+       },
+};
+
+static struct snd_soc_machine em_x270 = {
+       .name = "EM-X270",
+       .dai_link = em_x270_dai,
+       .num_links = ARRAY_SIZE(em_x270_dai),
+};
+
+static struct snd_soc_device em_x270_snd_devdata = {
+       .machine = &em_x270,
+       .platform = &pxa2xx_soc_platform,
+       .codec_dev = &soc_codec_dev_wm9712,
+};
+
+static struct platform_device *em_x270_snd_device;
+
+static int __init em_x270_init(void)
+{
+       int ret;
+
+       if (!machine_is_em_x270())
+               return -ENODEV;
+
+       em_x270_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!em_x270_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(em_x270_snd_device, &em_x270_snd_devdata);
+       em_x270_snd_devdata.dev = &em_x270_snd_device->dev;
+       ret = platform_device_add(em_x270_snd_device);
+
+       if (ret)
+               platform_device_put(em_x270_snd_device);
+
+       return ret;
+}
+
+static void __exit em_x270_exit(void)
+{
+       platform_device_unregister(em_x270_snd_device);
+}
+
+module_init(em_x270_init);
+module_exit(em_x270_exit);
+
+/* Module information */
+MODULE_AUTHOR("Mike Rapoport");
+MODULE_DESCRIPTION("ALSA SoC EM-X270");
+MODULE_LICENSE("GPL");
index 7e830b218943e90090cebddbedd4cc6ec511bba8..65a4e9a8c39e18ec4dc0b45f44dd780ff6c54b36 100644 (file)
@@ -48,8 +48,6 @@ static int poodle_spk_func;
 
 static void poodle_ext_control(struct snd_soc_codec *codec)
 {
-       int spk = 0;
-
        /* set up jack connection */
        if (poodle_jack_func == POODLE_HP) {
                /* set = unmute headphone */
@@ -57,23 +55,23 @@ static void poodle_ext_control(struct snd_soc_codec *codec)
                        POODLE_LOCOMO_GPIO_MUTE_L, 1);
                locomo_gpio_write(&poodle_locomo_device.dev,
                        POODLE_LOCOMO_GPIO_MUTE_R, 1);
-               snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
+               snd_soc_dapm_enable_pin(codec, "Headphone Jack");
        } else {
                locomo_gpio_write(&poodle_locomo_device.dev,
                        POODLE_LOCOMO_GPIO_MUTE_L, 0);
                locomo_gpio_write(&poodle_locomo_device.dev,
                        POODLE_LOCOMO_GPIO_MUTE_R, 0);
-               snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
+               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
        }
 
-       if (poodle_spk_func == POODLE_SPK_ON)
-               spk = 1;
-
        /* set the enpoints to their new connetion states */
-       snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk);
+       if (poodle_spk_func == POODLE_SPK_ON)
+               snd_soc_dapm_enable_pin(codec, "Ext Spk");
+       else
+               snd_soc_dapm_disable_pin(codec, "Ext Spk");
 
        /* signal a DAPM event */
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
 }
 
 static int poodle_startup(struct snd_pcm_substream *substream)
@@ -104,8 +102,8 @@ static int poodle_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        unsigned int clk = 0;
        int ret = 0;
 
@@ -124,25 +122,25 @@ static int poodle_hw_params(struct snd_pcm_substream *substream,
        }
 
        /* set codec DAI configuration */
-       ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
        if (ret < 0)
                return ret;
 
        /* set cpu DAI configuration */
-       ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
        if (ret < 0)
                return ret;
 
        /* set the codec system clock for DAC and ADC */
-       ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK, clk,
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk,
                SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
 
        /* set the I2S system clock as input (unused) */
-       ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
+       ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
                SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
@@ -215,8 +213,8 @@ SND_SOC_DAPM_HP("Headphone Jack", NULL),
 SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event),
 };
 
-/* Corgi machine audio_mapnections to the codec pins */
-static const char *audio_map[][3] = {
+/* Corgi machine connections to the codec pins */
+static const struct snd_soc_dapm_route audio_map[] = {
 
        /* headphone connected to LHPOUT1, RHPOUT1 */
        {"Headphone Jack", NULL, "LHPOUT"},
@@ -225,8 +223,6 @@ static const char *audio_map[][3] = {
        /* speaker connected to LOUT, ROUT */
        {"Ext Spk", NULL, "ROUT"},
        {"Ext Spk", NULL, "LOUT"},
-
-       {NULL, NULL, NULL},
 };
 
 static const char *jack_function[] = {"Off", "Headphone"};
@@ -250,9 +246,9 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
 {
        int i, err;
 
-       snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
-       snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
-       snd_soc_dapm_set_endpoint(codec, "MICIN", 1);
+       snd_soc_dapm_disable_pin(codec, "LLINEIN");
+       snd_soc_dapm_disable_pin(codec, "RLINEIN");
+       snd_soc_dapm_enable_pin(codec, "MICIN");
 
        /* Add poodle specific controls */
        for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) {
@@ -263,15 +259,13 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
        }
 
        /* Add poodle specific widgets */
-       for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++)
-               snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
+       snd_soc_dapm_new_controls(codec, wm8731_dapm_widgets,
+                                 ARRAY_SIZE(wm8731_dapm_widgets));
 
        /* Set up poodle specific audio path audio_map */
-       for (i = 0; audio_map[i][0] != NULL; i++)
-               snd_soc_dapm_connect_input(codec, audio_map[i][0],
-                       audio_map[i][1], audio_map[i][2]);
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
        return 0;
 }
 
index 97ec2d90547c30e64a177f9f250168d02073d6c0..059af815ea0c65f449d31ea9aa73dee1c86a27ac 100644 (file)
@@ -283,7 +283,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
 
 #ifdef CONFIG_PM
 static int pxa2xx_ac97_suspend(struct platform_device *pdev,
-       struct snd_soc_cpu_dai *dai)
+       struct snd_soc_dai *dai)
 {
        GCR |= GCR_ACLINK_OFF;
        clk_disable(ac97_clk);
@@ -291,7 +291,7 @@ static int pxa2xx_ac97_suspend(struct platform_device *pdev,
 }
 
 static int pxa2xx_ac97_resume(struct platform_device *pdev,
-       struct snd_soc_cpu_dai *dai)
+       struct snd_soc_dai *dai)
 {
        pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
        pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
@@ -310,7 +310,8 @@ static int pxa2xx_ac97_resume(struct platform_device *pdev,
 #define pxa2xx_ac97_resume     NULL
 #endif
 
-static int pxa2xx_ac97_probe(struct platform_device *pdev)
+static int pxa2xx_ac97_probe(struct platform_device *pdev,
+                            struct snd_soc_dai *dai)
 {
        int ret;
 
@@ -355,7 +356,8 @@ static int pxa2xx_ac97_probe(struct platform_device *pdev)
        return ret;
 }
 
-static void pxa2xx_ac97_remove(struct platform_device *pdev)
+static void pxa2xx_ac97_remove(struct platform_device *pdev,
+                              struct snd_soc_dai *dai)
 {
        GCR |= GCR_ACLINK_OFF;
        free_irq(IRQ_AC97, NULL);
@@ -372,7 +374,7 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out;
@@ -386,7 +388,7 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
@@ -400,7 +402,7 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                return -ENODEV;
@@ -418,7 +420,7 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
  * There is only 1 physical AC97 interface for pxa2xx, but it
  * has extra fifo's that can be used for aux DACs and ADCs.
  */
-struct snd_soc_cpu_dai pxa_ac97_dai[] = {
+struct snd_soc_dai pxa_ac97_dai[] = {
 {
        .name = "pxa2xx-ac97",
        .id = 0,
index b8ccfee095c4711ce17b0fc80176d5b9d409da28..e390de8edcd48724558f63c4338a9e83b19d1762 100644 (file)
@@ -14,7 +14,7 @@
 #define PXA2XX_DAI_AC97_AUX            1
 #define PXA2XX_DAI_AC97_MIC            2
 
-extern struct snd_soc_cpu_dai pxa_ac97_dai[3];
+extern struct snd_soc_dai pxa_ac97_dai[3];
 
 /* platform data */
 extern struct snd_ac97_bus_ops pxa2xx_ac97_ops;
index 425071030970bf07fae6f50b3d863cf89d7c9022..9c06553b92674436619cd0261d19f410e6764f79 100644 (file)
@@ -9,9 +9,6 @@
  *  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.
- *
- *  Revision history
- *    12th Aug 2005   Initial version.
  */
 
 #include <linux/init.h>
@@ -80,7 +77,7 @@ static struct pxa2xx_gpio gpio_bus[] = {
 static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 
        if (!cpu_dai->active) {
                SACR0 |= SACR0_RST;
@@ -101,7 +98,7 @@ static int pxa_i2s_wait(void)
        return 0;
 }
 
-static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
+static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
        /* interface format */
@@ -127,7 +124,7 @@ static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
        return 0;
 }
 
-static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                int clk_id, unsigned int freq, int dir)
 {
        if (clk_id != PXA2XX_I2S_SYSCLK)
@@ -143,7 +140,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 
        pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx);
        pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
@@ -240,7 +237,7 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
 
 #ifdef CONFIG_PM
 static int pxa2xx_i2s_suspend(struct platform_device *dev,
-       struct snd_soc_cpu_dai *dai)
+       struct snd_soc_dai *dai)
 {
        if (!dai->active)
                return 0;
@@ -258,7 +255,7 @@ static int pxa2xx_i2s_suspend(struct platform_device *dev,
 }
 
 static int pxa2xx_i2s_resume(struct platform_device *pdev,
-       struct snd_soc_cpu_dai *dai)
+       struct snd_soc_dai *dai)
 {
        if (!dai->active)
                return 0;
@@ -283,7 +280,7 @@ static int pxa2xx_i2s_resume(struct platform_device *pdev,
                SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
                SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
 
-struct snd_soc_cpu_dai pxa_i2s_dai = {
+struct snd_soc_dai pxa_i2s_dai = {
        .name = "pxa2xx-i2s",
        .id = 0,
        .type = SND_SOC_DAI_I2S,
index 4435bd9f884faec12ab5532c43f5ba687f638367..e2def441153eee706ab6789a00385c6e13f49284 100644 (file)
@@ -15,6 +15,6 @@
 /* I2S clock */
 #define PXA2XX_I2S_SYSCLK              0
 
-extern struct snd_soc_cpu_dai pxa_i2s_dai;
+extern struct snd_soc_dai pxa_i2s_dai;
 
 #endif
index 01ad7bf716b7b03f95f99157cabece01d16d67bd..2df03ee5819ec7ae44b38e1e47955b1983fce247 100644 (file)
@@ -330,7 +330,7 @@ static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 
 static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK;
 
-int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
+int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
        struct snd_pcm *pcm)
 {
        int ret = 0;
index d8b8372db00e76c9412364867025628f3b8d957e..64385797da5d3e0c959c737eaea442e22c0778f0 100644 (file)
@@ -12,9 +12,6 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  *
- *  Revision history
- *    30th Nov 2005   Initial version.
- *
  */
 
 #include <linux/module.h>
@@ -54,60 +51,60 @@ static int spitz_spk_func;
 static void spitz_ext_control(struct snd_soc_codec *codec)
 {
        if (spitz_spk_func == SPITZ_SPK_ON)
-               snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1);
+               snd_soc_dapm_enable_pin(codec, "Ext Spk");
        else
-               snd_soc_dapm_set_endpoint(codec, "Ext Spk", 0);
+               snd_soc_dapm_disable_pin(codec, "Ext Spk");
 
        /* set up jack connection */
        switch (spitz_jack_func) {
        case SPITZ_HP:
                /* enable and unmute hp jack, disable mic bias */
-               snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
+               snd_soc_dapm_disable_pin(codec, "Headset Jack");
+               snd_soc_dapm_disable_pin(codec, "Mic Jack");
+               snd_soc_dapm_disable_pin(codec, "Line Jack");
+               snd_soc_dapm_enable_pin(codec, "Headphone Jack");
                set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
                set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
                break;
        case SPITZ_MIC:
                /* enable mic jack and bias, mute hp */
-               snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
+               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+               snd_soc_dapm_disable_pin(codec, "Headset Jack");
+               snd_soc_dapm_disable_pin(codec, "Line Jack");
+               snd_soc_dapm_enable_pin(codec, "Mic Jack");
                reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
                reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
                break;
        case SPITZ_LINE:
                /* enable line jack, disable mic bias and mute hp */
-               snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Line Jack", 1);
+               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+               snd_soc_dapm_disable_pin(codec, "Headset Jack");
+               snd_soc_dapm_disable_pin(codec, "Mic Jack");
+               snd_soc_dapm_enable_pin(codec, "Line Jack");
                reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
                reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
                break;
        case SPITZ_HEADSET:
                /* enable and unmute headset jack enable mic bias, mute L hp */
-               snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
-               snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Headset Jack", 1);
+               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+               snd_soc_dapm_enable_pin(codec, "Mic Jack");
+               snd_soc_dapm_disable_pin(codec, "Line Jack");
+               snd_soc_dapm_enable_pin(codec, "Headset Jack");
                reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
                set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
                break;
        case SPITZ_HP_OFF:
 
                /* jack removed, everything off */
-               snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
-               snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
+               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+               snd_soc_dapm_disable_pin(codec, "Headset Jack");
+               snd_soc_dapm_disable_pin(codec, "Mic Jack");
+               snd_soc_dapm_disable_pin(codec, "Line Jack");
                reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
                reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
                break;
        }
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
 }
 
 static int spitz_startup(struct snd_pcm_substream *substream)
@@ -124,8 +121,8 @@ static int spitz_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        unsigned int clk = 0;
        int ret = 0;
 
@@ -144,25 +141,25 @@ static int spitz_hw_params(struct snd_pcm_substream *substream,
        }
 
        /* set codec DAI configuration */
-       ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
        if (ret < 0)
                return ret;
 
        /* set cpu DAI configuration */
-       ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
        if (ret < 0)
                return ret;
 
        /* set the codec system clock for DAC and ADC */
-       ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8750_SYSCLK, clk,
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
                SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
 
        /* set the I2S system clock as input (unused) */
-       ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
+       ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
                SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
@@ -250,7 +247,7 @@ static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
 };
 
 /* Spitz machine audio_map */
-static const char *audio_map[][3] = {
+static const struct snd_soc_dapm_route audio_map[] = {
 
        /* headphone connected to LOUT1, ROUT1 */
        {"Headphone Jack", NULL, "LOUT1"},
@@ -269,8 +266,6 @@ static const char *audio_map[][3] = {
 
        /* line is connected to input 1 - no bias */
        {"LINPUT1", NULL, "Line Jack"},
-
-       {NULL, NULL, NULL},
 };
 
 static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
@@ -296,13 +291,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
        int i, err;
 
        /* NC codec pins */
-       snd_soc_dapm_set_endpoint(codec, "RINPUT1", 0);
-       snd_soc_dapm_set_endpoint(codec, "LINPUT2", 0);
-       snd_soc_dapm_set_endpoint(codec, "RINPUT2", 0);
-       snd_soc_dapm_set_endpoint(codec, "LINPUT3", 0);
-       snd_soc_dapm_set_endpoint(codec, "RINPUT3", 0);
-       snd_soc_dapm_set_endpoint(codec, "OUT3", 0);
-       snd_soc_dapm_set_endpoint(codec, "MONO", 0);
+       snd_soc_dapm_disable_pin(codec, "RINPUT1");
+       snd_soc_dapm_disable_pin(codec, "LINPUT2");
+       snd_soc_dapm_disable_pin(codec, "RINPUT2");
+       snd_soc_dapm_disable_pin(codec, "LINPUT3");
+       snd_soc_dapm_disable_pin(codec, "RINPUT3");
+       snd_soc_dapm_disable_pin(codec, "OUT3");
+       snd_soc_dapm_disable_pin(codec, "MONO");
 
        /* Add spitz specific controls */
        for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
@@ -313,15 +308,13 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
        }
 
        /* Add spitz specific widgets */
-       for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++)
-               snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
+       snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
+                                 ARRAY_SIZE(wm8750_dapm_widgets));
 
-       /* Set up spitz specific audio path audio_map */
-       for (i = 0; audio_map[i][0] != NULL; i++)
-               snd_soc_dapm_connect_input(codec, audio_map[i][0],
-                       audio_map[i][1], audio_map[i][2]);
+       /* Set up spitz specific audio paths */
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
        return 0;
 }
 
index 7346d7e5d066e71b84669f0fe6c054e77b003ca1..b6edb61a3a30f8591e89944d002fb7eff1c253ac 100644 (file)
@@ -12,9 +12,6 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  *
- *  Revision history
- *    30th Nov 2005   Initial version.
- *
  * GPIO's
  *  1 - Jack Insertion
  *  5 - Hookswitch (headset answer/hang up switch)
@@ -55,29 +52,31 @@ static int tosa_spk_func;
 
 static void tosa_ext_control(struct snd_soc_codec *codec)
 {
-       int spk = 0, mic_int = 0, hp = 0, hs = 0;
-
        /* set up jack connection */
        switch (tosa_jack_func) {
        case TOSA_HP:
-               hp = 1;
+               snd_soc_dapm_disable_pin(codec, "Mic (Internal)");
+               snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+               snd_soc_dapm_disable_pin(codec, "Headset Jack");
                break;
        case TOSA_MIC_INT:
-               mic_int = 1;
+               snd_soc_dapm_enable_pin(codec, "Mic (Internal)");
+               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+               snd_soc_dapm_disable_pin(codec, "Headset Jack");
                break;
        case TOSA_HEADSET:
-               hs = 1;
+               snd_soc_dapm_disable_pin(codec, "Mic (Internal)");
+               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
+               snd_soc_dapm_enable_pin(codec, "Headset Jack");
                break;
        }
 
        if (tosa_spk_func == TOSA_SPK_ON)
-               spk = 1;
+               snd_soc_dapm_enable_pin(codec, "Speaker");
+       else
+               snd_soc_dapm_disable_pin(codec, "Speaker");
 
-       snd_soc_dapm_set_endpoint(codec, "Speaker", spk);
-       snd_soc_dapm_set_endpoint(codec, "Mic (Internal)", mic_int);
-       snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp);
-       snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs);
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
 }
 
 static int tosa_startup(struct snd_pcm_substream *substream)
@@ -154,7 +153,7 @@ SND_SOC_DAPM_SPK("Speaker", NULL),
 };
 
 /* tosa audio map */
-static const char *audio_map[][3] = {
+static const struct snd_soc_dapm_route audio_map[] = {
 
        /* headphone connected to HPOUTL, HPOUTR */
        {"Headphone Jack", NULL, "HPOUTL"},
@@ -173,8 +172,6 @@ static const char *audio_map[][3] = {
        {"Headset Jack", NULL, "HPOUTR"},
        {"LINEINR", NULL, "Mic Bias"},
        {"Mic Bias", NULL, "Headset Jack"},
-
-       {NULL, NULL, NULL},
 };
 
 static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
@@ -196,8 +193,8 @@ static int tosa_ac97_init(struct snd_soc_codec *codec)
 {
        int i, err;
 
-       snd_soc_dapm_set_endpoint(codec, "OUT3", 0);
-       snd_soc_dapm_set_endpoint(codec, "MONOOUT", 0);
+       snd_soc_dapm_disable_pin(codec, "OUT3");
+       snd_soc_dapm_disable_pin(codec, "MONOOUT");
 
        /* add tosa specific controls */
        for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) {
@@ -208,17 +205,13 @@ static int tosa_ac97_init(struct snd_soc_codec *codec)
        }
 
        /* add tosa specific widgets */
-       for (i = 0; i < ARRAY_SIZE(tosa_dapm_widgets); i++) {
-               snd_soc_dapm_new_control(codec, &tosa_dapm_widgets[i]);
-       }
+       snd_soc_dapm_new_controls(codec, tosa_dapm_widgets,
+                                 ARRAY_SIZE(tosa_dapm_widgets));
 
        /* set up tosa specific audio path audio_map */
-       for (i = 0; audio_map[i][0] != NULL; i++) {
-               snd_soc_dapm_connect_input(codec, audio_map[i][0],
-                       audio_map[i][1], audio_map[i][2]);
-       }
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
 
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
        return 0;
 }
 
index 1f6dbfc4caa85352412ba297e8094860e968fe00..b9f2353effebfba49cf5010c10bcf5b2794781c6 100644 (file)
@@ -1,7 +1,6 @@
 config SND_S3C24XX_SOC
        tristate "SoC Audio for the Samsung S3C24XX chips"
-       depends on ARCH_S3C2410 && SND_SOC
-       select SND_PCM
+       depends on ARCH_S3C2410
        help
          Say Y or M if you want to add support for codecs attached to
          the S3C24XX AC97, I2S or SSP interface. You will also need
@@ -16,7 +15,6 @@ config SND_S3C2412_SOC_I2S
 config SND_S3C2443_SOC_AC97
        tristate
        select AC97_BUS
-       select SND_AC97_CODEC
        select SND_SOC_AC97_BUS
        
 config SND_S3C24XX_SOC_NEO1973_WM8753
index 0e9d1c5f24840dab0d640d6f733aba13237742a2..4d7a9aa15f1a8cc20f41d390f5a0f87bcb35dcaf 100644 (file)
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  *
- *  Revision history
- *    20th Jan 2007   Initial version.
- *    05th Feb 2007   Rename all to Neo1973
- *
  */
 
 #include <linux/module.h>
@@ -26,6 +22,7 @@
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
+#include <sound/tlv.h>
 
 #include <asm/mach-types.h>
 #include <asm/hardware/scoop.h>
 #include "s3c24xx-pcm.h"
 #include "s3c24xx-i2s.h"
 
+/* Debugging stuff */
+#define S3C24XX_SOC_NEO1973_WM8753_DEBUG 0
+#if S3C24XX_SOC_NEO1973_WM8753_DEBUG
+#define DBG(x...) printk(KERN_DEBUG "s3c24xx-soc-neo1973-wm8753: " x)
+#else
+#define DBG(x...)
+#endif
+
 /* define the scenarios */
 #define NEO_AUDIO_OFF                  0
 #define NEO_GSM_CALL_AUDIO_HANDSET     1
@@ -61,12 +66,14 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        unsigned int pll_out = 0, bclk = 0;
        int ret = 0;
        unsigned long iis_clkrate;
 
+       DBG("Entered %s\n", __func__);
+
        iis_clkrate = s3c24xx_i2s_get_clockrate();
 
        switch (params_rate(params)) {
@@ -101,44 +108,44 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
        }
 
        /* set codec DAI configuration */
-       ret = codec_dai->dai_ops.set_fmt(codec_dai,
+       ret = snd_soc_dai_set_fmt(codec_dai,
                SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
                SND_SOC_DAIFMT_CBM_CFM);
        if (ret < 0)
                return ret;
 
        /* set cpu DAI configuration */
-       ret = cpu_dai->dai_ops.set_fmt(cpu_dai,
+       ret = snd_soc_dai_set_fmt(cpu_dai,
                SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
                SND_SOC_DAIFMT_CBM_CFM);
        if (ret < 0)
                return ret;
 
        /* set the codec system clock for DAC and ADC */
-       ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_MCLK, pll_out,
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
                SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
 
        /* set MCLK division for sample rate */
-       ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
+       ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
                S3C2410_IISMOD_32FS);
        if (ret < 0)
                return ret;
 
        /* set codec BCLK division for sample rate */
-       ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
+       ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
        if (ret < 0)
                return ret;
 
        /* set prescaler division for sample rate */
-       ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
+       ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
                S3C24XX_PRESCALE(4, 4));
        if (ret < 0)
                return ret;
 
        /* codec PLL input is PCLK/4 */
-       ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1,
+       ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1,
                iis_clkrate / 4, pll_out);
        if (ret < 0)
                return ret;
@@ -149,10 +156,12 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
 static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+
+       DBG("Entered %s\n", __func__);
 
        /* disable the PLL */
-       return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1, 0, 0);
+       return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0);
 }
 
 /*
@@ -167,11 +176,13 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
        unsigned int pcmdiv = 0;
        int ret = 0;
        unsigned long iis_clkrate;
 
+       DBG("Entered %s\n", __func__);
+
        iis_clkrate = s3c24xx_i2s_get_clockrate();
 
        if (params_rate(params) != 8000)
@@ -183,24 +194,24 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
 
        /* todo: gg check mode (DSP_B) against CSR datasheet */
        /* set codec DAI configuration */
-       ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
                SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
        if (ret < 0)
                return ret;
 
        /* set the codec system clock for DAC and ADC */
-       ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_PCMCLK, 12288000,
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, 12288000,
                SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
 
        /* set codec PCM division for sample rate */
-       ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
+       ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
        if (ret < 0)
                return ret;
 
        /* configue and enable PLL for 12.288MHz output */
-       ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2,
+       ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2,
                iis_clkrate / 4, 12288000);
        if (ret < 0)
                return ret;
@@ -211,10 +222,12 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
 static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+
+       DBG("Entered %s\n", __func__);
 
        /* disable the PLL */
-       return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2, 0, 0);
+       return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0);
 }
 
 static struct snd_soc_ops neo1973_voice_ops = {
@@ -233,79 +246,81 @@ static int neo1973_get_scenario(struct snd_kcontrol *kcontrol,
 
 static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario)
 {
+       DBG("Entered %s\n", __func__);
+
        switch (neo1973_scenario) {
        case NEO_AUDIO_OFF:
-               snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-               snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-               snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
+               snd_soc_dapm_disable_pin(codec, "Audio Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line In");
+               snd_soc_dapm_disable_pin(codec, "Headset Mic");
+               snd_soc_dapm_disable_pin(codec, "Call Mic");
                break;
        case NEO_GSM_CALL_AUDIO_HANDSET:
-               snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line In",  1);
-               snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-               snd_soc_dapm_set_endpoint(codec, "Call Mic",     1);
+               snd_soc_dapm_enable_pin(codec, "Audio Out");
+               snd_soc_dapm_enable_pin(codec, "GSM Line Out");
+               snd_soc_dapm_enable_pin(codec, "GSM Line In");
+               snd_soc_dapm_disable_pin(codec, "Headset Mic");
+               snd_soc_dapm_enable_pin(codec, "Call Mic");
                break;
        case NEO_GSM_CALL_AUDIO_HEADSET:
-               snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line In",  1);
-               snd_soc_dapm_set_endpoint(codec, "Headset Mic",  1);
-               snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
+               snd_soc_dapm_enable_pin(codec, "Audio Out");
+               snd_soc_dapm_enable_pin(codec, "GSM Line Out");
+               snd_soc_dapm_enable_pin(codec, "GSM Line In");
+               snd_soc_dapm_enable_pin(codec, "Headset Mic");
+               snd_soc_dapm_disable_pin(codec, "Call Mic");
                break;
        case NEO_GSM_CALL_AUDIO_BLUETOOTH:
-               snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line In",  1);
-               snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-               snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
+               snd_soc_dapm_disable_pin(codec, "Audio Out");
+               snd_soc_dapm_enable_pin(codec, "GSM Line Out");
+               snd_soc_dapm_enable_pin(codec, "GSM Line In");
+               snd_soc_dapm_disable_pin(codec, "Headset Mic");
+               snd_soc_dapm_disable_pin(codec, "Call Mic");
                break;
        case NEO_STEREO_TO_SPEAKERS:
-               snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-               snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-               snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
+               snd_soc_dapm_enable_pin(codec, "Audio Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line In");
+               snd_soc_dapm_disable_pin(codec, "Headset Mic");
+               snd_soc_dapm_disable_pin(codec, "Call Mic");
                break;
        case NEO_STEREO_TO_HEADPHONES:
-               snd_soc_dapm_set_endpoint(codec, "Audio Out",    1);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-               snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-               snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
+               snd_soc_dapm_enable_pin(codec, "Audio Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line In");
+               snd_soc_dapm_disable_pin(codec, "Headset Mic");
+               snd_soc_dapm_disable_pin(codec, "Call Mic");
                break;
        case NEO_CAPTURE_HANDSET:
-               snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-               snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-               snd_soc_dapm_set_endpoint(codec, "Call Mic",     1);
+               snd_soc_dapm_disable_pin(codec, "Audio Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line In");
+               snd_soc_dapm_disable_pin(codec, "Headset Mic");
+               snd_soc_dapm_enable_pin(codec, "Call Mic");
                break;
        case NEO_CAPTURE_HEADSET:
-               snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-               snd_soc_dapm_set_endpoint(codec, "Headset Mic",  1);
-               snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
+               snd_soc_dapm_disable_pin(codec, "Audio Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line In");
+               snd_soc_dapm_enable_pin(codec, "Headset Mic");
+               snd_soc_dapm_disable_pin(codec, "Call Mic");
                break;
        case NEO_CAPTURE_BLUETOOTH:
-               snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-               snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-               snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
+               snd_soc_dapm_disable_pin(codec, "Audio Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line In");
+               snd_soc_dapm_disable_pin(codec, "Headset Mic");
+               snd_soc_dapm_disable_pin(codec, "Call Mic");
                break;
        default:
-               snd_soc_dapm_set_endpoint(codec, "Audio Out",    0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0);
-               snd_soc_dapm_set_endpoint(codec, "GSM Line In",  0);
-               snd_soc_dapm_set_endpoint(codec, "Headset Mic",  0);
-               snd_soc_dapm_set_endpoint(codec, "Call Mic",     0);
+               snd_soc_dapm_disable_pin(codec, "Audio Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line Out");
+               snd_soc_dapm_disable_pin(codec, "GSM Line In");
+               snd_soc_dapm_disable_pin(codec, "Headset Mic");
+               snd_soc_dapm_disable_pin(codec, "Call Mic");
        }
 
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
 
        return 0;
 }
@@ -315,6 +330,8 @@ static int neo1973_set_scenario(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 
+       DBG("Entered %s\n", __func__);
+
        if (neo1973_scenario == ucontrol->value.integer.value[0])
                return 0;
 
@@ -327,6 +344,8 @@ static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0};
 
 static void lm4857_write_regs(void)
 {
+       DBG("Entered %s\n", __func__);
+
        if (i2c_master_send(i2c, lm4857_regs, 4) != 4)
                printk(KERN_ERR "lm4857: i2c write failed\n");
 }
@@ -338,6 +357,8 @@ static int lm4857_get_reg(struct snd_kcontrol *kcontrol,
        int shift = (kcontrol->private_value >> 8) & 0x0F;
        int mask = (kcontrol->private_value >> 16) & 0xFF;
 
+       DBG("Entered %s\n", __func__);
+
        ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask;
        return 0;
 }
@@ -364,6 +385,8 @@ static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
 {
        u8 value = lm4857_regs[LM4857_CTRL] & 0x0F;
 
+       DBG("Entered %s\n", __func__);
+
        if (value)
                value -= 5;
 
@@ -376,6 +399,8 @@ static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
 {
        u8 value = ucontrol->value.integer.value[0];
 
+       DBG("Entered %s\n", __func__);
+
        if (value)
                value += 5;
 
@@ -397,8 +422,7 @@ static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
 };
 
 
-/* example machine audio_mapnections */
-static const char *audio_map[][3] = {
+static const struct snd_soc_dapm_route dapm_routes[] = {
 
        /* Connections to the lm4857 amp */
        {"Audio Out", NULL, "LOUT1"},
@@ -421,8 +445,6 @@ static const char *audio_map[][3] = {
 
        /* Connect the ALC pins */
        {"ACIN", NULL, "ACOP"},
-
-       {NULL, NULL, NULL},
 };
 
 static const char *lm4857_mode[] = {
@@ -453,13 +475,16 @@ static const struct soc_enum neo_scenario_enum[] = {
        SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios), neo_scenarios),
 };
 
+static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0);
+static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0);
+
 static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
-       SOC_SINGLE_EXT("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0,
-               lm4857_get_reg, lm4857_set_reg),
-       SOC_SINGLE_EXT("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0,
-               lm4857_get_reg, lm4857_set_reg),
-       SOC_SINGLE_EXT("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
-               lm4857_get_reg, lm4857_set_reg),
+       SOC_SINGLE_EXT_TLV("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0,
+               lm4857_get_reg, lm4857_set_reg, stereo_tlv),
+       SOC_SINGLE_EXT_TLV("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0,
+               lm4857_get_reg, lm4857_set_reg, stereo_tlv),
+       SOC_SINGLE_EXT_TLV("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
+               lm4857_get_reg, lm4857_set_reg, mono_tlv),
        SOC_ENUM_EXT("Amp Mode", lm4857_mode_enum[0],
                lm4857_get_mode, lm4857_set_mode),
        SOC_ENUM_EXT("Neo Mode", neo_scenario_enum[0],
@@ -483,21 +508,23 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
 {
        int i, err;
 
+       DBG("Entered %s\n", __func__);
+
        /* set up NC codec pins */
-       snd_soc_dapm_set_endpoint(codec, "LOUT2", 0);
-       snd_soc_dapm_set_endpoint(codec, "ROUT2", 0);
-       snd_soc_dapm_set_endpoint(codec, "OUT3",  0);
-       snd_soc_dapm_set_endpoint(codec, "OUT4",  0);
-       snd_soc_dapm_set_endpoint(codec, "LINE1", 0);
-       snd_soc_dapm_set_endpoint(codec, "LINE2", 0);
+       snd_soc_dapm_disable_pin(codec, "LOUT2");
+       snd_soc_dapm_disable_pin(codec, "ROUT2");
+       snd_soc_dapm_disable_pin(codec, "OUT3");
+       snd_soc_dapm_disable_pin(codec, "OUT4");
+       snd_soc_dapm_disable_pin(codec, "LINE1");
+       snd_soc_dapm_disable_pin(codec, "LINE2");
 
 
        /* set endpoints to default mode */
        set_scenario_endpoints(codec, NEO_AUDIO_OFF);
 
        /* Add neo1973 specific widgets */
-       for (i = 0; i < ARRAY_SIZE(wm8753_dapm_widgets); i++)
-               snd_soc_dapm_new_control(codec, &wm8753_dapm_widgets[i]);
+       snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
+                                 ARRAY_SIZE(wm8753_dapm_widgets));
 
        /* add neo1973 specific controls */
        for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) {
@@ -508,20 +535,18 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
                        return err;
        }
 
-       /* set up neo1973 specific audio path audio_mapnects */
-       for (i = 0; audio_map[i][0] != NULL; i++) {
-               snd_soc_dapm_connect_input(codec, audio_map[i][0],
-                       audio_map[i][1], audio_map[i][2]);
-       }
+       /* set up neo1973 specific audio routes */
+       err = snd_soc_dapm_add_routes(codec, dapm_routes,
+                                     ARRAY_SIZE(dapm_routes));
 
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
        return 0;
 }
 
 /*
  * BT Codec DAI
  */
-static struct snd_soc_cpu_dai bt_dai = {
+static struct snd_soc_dai bt_dai = {
        .name = "Bluetooth",
        .id = 0,
        .type = SND_SOC_DAI_PCM,
@@ -583,6 +608,8 @@ static int lm4857_amp_probe(struct i2c_adapter *adap, int addr, int kind)
 {
        int ret;
 
+       DBG("Entered %s\n", __func__);
+
        client_template.adapter = adap;
        client_template.addr = addr;
 
@@ -606,6 +633,8 @@ exit_err:
 
 static int lm4857_i2c_detach(struct i2c_client *client)
 {
+       DBG("Entered %s\n", __func__);
+
        i2c_detach_client(client);
        kfree(client);
        return 0;
@@ -613,6 +642,8 @@ static int lm4857_i2c_detach(struct i2c_client *client)
 
 static int lm4857_i2c_attach(struct i2c_adapter *adap)
 {
+       DBG("Entered %s\n", __func__);
+
        return i2c_probe(adap, &addr_data, lm4857_amp_probe);
 }
 
@@ -620,6 +651,8 @@ static u8 lm4857_state;
 
 static int lm4857_suspend(struct i2c_client *dev, pm_message_t state)
 {
+       DBG("Entered %s\n", __func__);
+
        dev_dbg(&dev->dev, "lm4857_suspend\n");
        lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf;
        if (lm4857_state) {
@@ -631,6 +664,8 @@ static int lm4857_suspend(struct i2c_client *dev, pm_message_t state)
 
 static int lm4857_resume(struct i2c_client *dev)
 {
+       DBG("Entered %s\n", __func__);
+
        if (lm4857_state) {
                lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f);
                lm4857_write_regs();
@@ -640,6 +675,8 @@ static int lm4857_resume(struct i2c_client *dev)
 
 static void lm4857_shutdown(struct i2c_client *dev)
 {
+       DBG("Entered %s\n", __func__);
+
        dev_dbg(&dev->dev, "lm4857_shutdown\n");
        lm4857_regs[LM4857_CTRL] &= 0xf0;
        lm4857_write_regs();
@@ -671,6 +708,8 @@ static int __init neo1973_init(void)
 {
        int ret;
 
+       DBG("Entered %s\n", __func__);
+
        neo1973_snd_device = platform_device_alloc("soc-audio", -1);
        if (!neo1973_snd_device)
                return -ENOMEM;
@@ -691,6 +730,8 @@ static int __init neo1973_init(void)
 
 static void __exit neo1973_exit(void)
 {
+       DBG("Entered %s\n", __func__);
+
        i2c_del_driver(&lm4857_i2c_driver);
        platform_device_unregister(neo1973_snd_device);
 }
index c4a46dd589b3b1565f6c3d2e450465a3a4c6744b..ee4676ed1283c80729a0b1314f6730c82b2ab1b1 100644 (file)
@@ -295,7 +295,7 @@ static inline int s3c2412_snd_is_clkmaster(void)
 /*
  * Set S3C2412 I2S DAI format
  */
-static int s3c2412_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai,
+static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
                               unsigned int fmt)
 {
        u32 iismod;
@@ -500,7 +500,7 @@ EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate);
 /*
  * Set S3C2412 Clock source
  */
-static int s3c2412_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+static int s3c2412_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
                                  int clk_id, unsigned int freq, int dir)
 {
        u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
@@ -528,7 +528,7 @@ static int s3c2412_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
 /*
  * Set S3C2412 Clock dividers
  */
-static int s3c2412_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
+static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
                                  int div_id, int div)
 {
        struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
@@ -601,7 +601,8 @@ struct clk *s3c2412_get_iisclk(void)
 EXPORT_SYMBOL_GPL(s3c2412_get_iisclk);
 
 
-static int s3c2412_i2s_probe(struct platform_device *pdev)
+static int s3c2412_i2s_probe(struct platform_device *pdev,
+                            struct snd_soc_dai *dai)
 {
        DBG("Entered %s\n", __func__);
 
@@ -647,7 +648,7 @@ static int s3c2412_i2s_probe(struct platform_device *pdev)
 
 #ifdef CONFIG_PM
 static int s3c2412_i2s_suspend(struct platform_device *dev,
-                             struct snd_soc_cpu_dai *dai)
+                             struct snd_soc_dai *dai)
 {
        struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
        u32 iismod;
@@ -675,7 +676,7 @@ static int s3c2412_i2s_suspend(struct platform_device *dev,
 }
 
 static int s3c2412_i2s_resume(struct platform_device *pdev,
-                             struct snd_soc_cpu_dai *dai)
+                             struct snd_soc_dai *dai)
 {
        struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
 
@@ -707,7 +708,7 @@ static int s3c2412_i2s_resume(struct platform_device *pdev,
        SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
        SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 
-struct snd_soc_cpu_dai s3c2412_i2s_dai = {
+struct snd_soc_dai s3c2412_i2s_dai = {
        .name   = "s3c2412-i2s",
        .id     = 0,
        .type   = SND_SOC_DAI_I2S,
index 27f48e1ffa8610feb8e1d02740bd31bd607f59e9..aac08a25e541df2dc2cb6e0c0ebba094029105c7 100644 (file)
@@ -24,7 +24,7 @@
 
 extern struct clk *s3c2412_get_iisclk(void);
 
-extern struct snd_soc_cpu_dai s3c2412_i2s_dai;
+extern struct snd_soc_dai s3c2412_i2s_dai;
 
 struct s3c2412_rate_calc {
        unsigned int    clk_div;        /* for prescaler */
index e81d9a6c83dac829f356d12d52c3539418f2aea8..783349b7fedec91aec58fd30d1f8838cd026cc04 100644 (file)
@@ -10,9 +10,6 @@
  *  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.
- *
- *  Revision history
- *     21st Mar 2007   Initial Version
  */
 
 #include <linux/init.h>
@@ -212,7 +209,8 @@ static struct s3c24xx_pcm_dma_params s3c2443_ac97_mic_mono_in = {
        .dma_size       = 4,
 };
 
-static int s3c2443_ac97_probe(struct platform_device *pdev)
+static int s3c2443_ac97_probe(struct platform_device *pdev,
+                             struct snd_soc_dai *dai)
 {
        int ret;
        u32 ac_glbctrl;
@@ -263,7 +261,8 @@ static int s3c2443_ac97_probe(struct platform_device *pdev)
        return ret;
 }
 
-static void s3c2443_ac97_remove(struct platform_device *pdev)
+static void s3c2443_ac97_remove(struct platform_device *pdev,
+                               struct snd_soc_dai *dai)
 {
        free_irq(IRQ_S3C244x_AC97, NULL);
        clk_disable(s3c24xx_ac97.ac97_clk);
@@ -275,7 +274,7 @@ static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                cpu_dai->dma_data = &s3c2443_ac97_pcm_stereo_out;
@@ -317,7 +316,7 @@ static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                return -ENODEV;
@@ -353,7 +352,7 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
                SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
 
-struct snd_soc_cpu_dai s3c2443_ac97_dai[] = {
+struct snd_soc_dai s3c2443_ac97_dai[] = {
 {
        .name = "s3c2443-ac97",
        .id = 0,
index bf03e8ed16c30a8b22b4cf5d37e151b12ffc6a00..a96dcadf28b4a0726cf91240d8b4440888cdfb6d 100644 (file)
@@ -26,6 +26,6 @@
 #define IRQ_S3C244x_AC97 IRQ_S3C2443_AC97
 #endif
 
-extern struct snd_soc_cpu_dai s3c2443_ac97_dai[];
+extern struct snd_soc_dai s3c2443_ac97_dai[];
 
 #endif /*S3C24XXAC97_H_*/
index 1ed6afd454591ac9c5cab7b82b13b4105681826e..397524282b57f3ce865255d5bf7e3899df718be0 100644 (file)
  *  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.
- *
- *
- *  Revision history
- *    11th Dec 2006   Merged with Simtec driver
- *    10th Nov 2006   Initial version.
  */
 
 #include <linux/init.h>
@@ -180,7 +175,7 @@ static void s3c24xx_snd_rxctrl(int on)
 static int s3c24xx_snd_lrsync(void)
 {
        u32 iiscon;
-       unsigned long timeout = jiffies + msecs_to_jiffies(5);
+       int timeout = 50; /* 5ms */
 
        DBG("Entered %s\n", __func__);
 
@@ -189,8 +184,9 @@ static int s3c24xx_snd_lrsync(void)
                if (iiscon & S3C2410_IISCON_LRINDEX)
                        break;
 
-               if (time_after(jiffies, timeout))
+               if (!timeout--)
                        return -ETIMEDOUT;
+               udelay(100);
        }
 
        return 0;
@@ -209,7 +205,7 @@ static inline int s3c24xx_snd_is_clkmaster(void)
 /*
  * Set S3C24xx I2S DAI format
  */
-static int s3c24xx_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai,
+static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
        u32 iismod;
@@ -317,7 +313,7 @@ exit_err:
 /*
  * Set S3C24xx Clock source
  */
-static int s3c24xx_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+static int s3c24xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
        int clk_id, unsigned int freq, int dir)
 {
        u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
@@ -343,7 +339,7 @@ static int s3c24xx_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
 /*
  * Set S3C24xx Clock dividers
  */
-static int s3c24xx_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
+static int s3c24xx_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
        int div_id, int div)
 {
        u32 reg;
@@ -381,7 +377,8 @@ u32 s3c24xx_i2s_get_clockrate(void)
 }
 EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate);
 
-static int s3c24xx_i2s_probe(struct platform_device *pdev)
+static int s3c24xx_i2s_probe(struct platform_device *pdev,
+                            struct snd_soc_dai *dai)
 {
        DBG("Entered %s\n", __func__);
 
@@ -414,7 +411,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev)
 
 #ifdef CONFIG_PM
 static int s3c24xx_i2s_suspend(struct platform_device *pdev,
-               struct snd_soc_cpu_dai *cpu_dai)
+               struct snd_soc_dai *cpu_dai)
 {
        DBG("Entered %s\n", __func__);
 
@@ -429,7 +426,7 @@ static int s3c24xx_i2s_suspend(struct platform_device *pdev,
 }
 
 static int s3c24xx_i2s_resume(struct platform_device *pdev,
-               struct snd_soc_cpu_dai *cpu_dai)
+               struct snd_soc_dai *cpu_dai)
 {
        DBG("Entered %s\n", __func__);
        clk_enable(s3c24xx_i2s.iis_clk);
@@ -452,7 +449,7 @@ static int s3c24xx_i2s_resume(struct platform_device *pdev,
        SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
        SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 
-struct snd_soc_cpu_dai s3c24xx_i2s_dai = {
+struct snd_soc_dai s3c24xx_i2s_dai = {
        .name = "s3c24xx-i2s",
        .id = 0,
        .type = SND_SOC_DAI_I2S,
index 537b4ecce8a39e46847c442839d038282e4b8532..726d91cf4e1cfcbf624facdf7c0a697962bab190 100644 (file)
@@ -32,6 +32,6 @@
 
 u32 s3c24xx_i2s_get_clockrate(void);
 
-extern struct snd_soc_cpu_dai s3c24xx_i2s_dai;
+extern struct snd_soc_dai s3c24xx_i2s_dai;
 
 #endif /*S3C24XXI2S_H_*/
index 7806ae614617ca13f2c8c3325cf2daa800820f35..cef79b34dc6fc22e8789adef0e9c4be8e6ae8bbc 100644 (file)
  *  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.
- *
- *  Revision history
- *    11th Dec 2006   Merged with Simtec driver
- *    10th Nov 2006   Initial version.
  */
 
 #include <linux/module.h>
@@ -433,7 +429,7 @@ static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
 static u64 s3c24xx_pcm_dmamask = DMA_32BIT_MASK;
 
 static int s3c24xx_pcm_new(struct snd_card *card,
-       struct snd_soc_codec_dai *dai, struct snd_pcm *pcm)
+       struct snd_soc_dai *dai, struct snd_pcm *pcm)
 {
        int ret = 0;
 
index b4a56302b9ab091203427333c2174c35d4341ca2..8515d6ff03f2c50c5220f8a39cf9ec7a0389693d 100644 (file)
@@ -10,9 +10,6 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  *
- *  Revision history
- *    8th Mar 2007   Initial version.
- *
  */
 
 #include <linux/module.h>
index 4c1e013381c9dbc1f7a70a38527f302334db1d34..54bd604012af6ce2d96fab4a111f7ba519292b2c 100644 (file)
@@ -3,7 +3,7 @@ menu "SoC Audio support for SuperH"
 
 config SND_SOC_PCM_SH7760
        tristate "SoC Audio support for Renesas SH7760"
-       depends on CPU_SUBTYPE_SH7760 && SND_SOC && SH_DMABRG
+       depends on CPU_SUBTYPE_SH7760 && SH_DMABRG
        help
          Enable this option for SH7760 AC97/I2S audio support.
 
@@ -13,10 +13,9 @@ config SND_SOC_PCM_SH7760
 ##
 
 config SND_SOC_SH4_HAC
+       tristate
        select AC97_BUS
        select SND_SOC_AC97_BUS
-       select SND_AC97_CODEC
-       tristate
 
 config SND_SOC_SH4_SSI
        tristate
index 7a3ce80d6727dbe2daea6fa691ef0daff4974481..9faa12622d09c07895c48cdf5d96ff6cfd47e38e 100644 (file)
@@ -326,7 +326,7 @@ static void camelot_pcm_free(struct snd_pcm *pcm)
 }
 
 static int camelot_pcm_new(struct snd_card *card,
-                          struct snd_soc_codec_dai *dai,
+                          struct snd_soc_dai *dai,
                           struct snd_pcm *pcm)
 {
        /* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
index b7b676b3d6715c38fd6196ce10162d245daca36d..df7bc345c3205cc0ae069322f6243e1027b71492 100644 (file)
@@ -266,7 +266,7 @@ static int hac_hw_params(struct snd_pcm_substream *substream,
 #define AC97_FMTS      \
        SNDRV_PCM_FMTBIT_S16_LE
 
-struct snd_soc_cpu_dai sh4_hac_dai[] = {
+struct snd_soc_dai sh4_hac_dai[] = {
 {
        .name                   = "HAC0",
        .id                     = 0,
index 2f91de84c5c762a2896c14230140c90b216d39a9..92bfaf4774a7d05fec84bf270539c8be09a6b05d 100644 (file)
 #define IPSEL 0xFE400034
 
 /* platform specific structs can be declared here */
-extern struct snd_soc_cpu_dai sh4_hac_dai[2];
+extern struct snd_soc_dai sh4_hac_dai[2];
 extern struct snd_soc_platform sh7760_soc_platform;
 
 static int machine_init(struct snd_soc_codec *codec)
 {
-       snd_soc_dapm_sync_endpoints(codec);
+       snd_soc_dapm_sync(codec);
        return 0;
 }
 
index 3388bc3d62d10fbef92a56c148ea4259ae2a6654..55c3464163ab45b50b7c359ef50b138c994bfcd1 100644 (file)
@@ -208,7 +208,7 @@ static int ssi_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int ssi_set_sysclk(struct snd_soc_cpu_dai *cpu_dai, int clk_id,
+static int ssi_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
                          unsigned int freq, int dir)
 {
        struct ssi_priv *ssi = &ssi_cpu_data[cpu_dai->id];
@@ -222,7 +222,7 @@ static int ssi_set_sysclk(struct snd_soc_cpu_dai *cpu_dai, int clk_id,
  * This divider is used to generate the SSI_SCK (I2S bitclock) from the
  * clock at the HAC_BIT_CLK ("oversampling clock") pin.
  */
-static int ssi_set_clkdiv(struct snd_soc_cpu_dai *dai, int did, int div)
+static int ssi_set_clkdiv(struct snd_soc_dai *dai, int did, int div)
 {
        struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
        unsigned long ssicr;
@@ -245,7 +245,7 @@ static int ssi_set_clkdiv(struct snd_soc_cpu_dai *dai, int did, int div)
        return 0;
 }
 
-static int ssi_set_fmt(struct snd_soc_cpu_dai *dai, unsigned int fmt)
+static int ssi_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
        struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
        unsigned long ssicr = SSIREG(SSICR);
@@ -332,7 +332,7 @@ static int ssi_set_fmt(struct snd_soc_cpu_dai *dai, unsigned int fmt)
         SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE |  \
         SNDRV_PCM_FMTBIT_S32_LE  | SNDRV_PCM_FMTBIT_U32_LE)
 
-struct snd_soc_cpu_dai sh4_ssi_dai[] = {
+struct snd_soc_dai sh4_ssi_dai[] = {
 {
        .name                   = "SSI0",
        .id                     = 0,
index e148db940cfc77ecb4521df7191909f00e672761..83f1190293a8287c2a516a81a07575dc7f4933c7 100644 (file)
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  *
- *  Revision history
- *    12th Aug 2005   Initial version.
- *    25th Oct 2005   Working Codec, Interface and Platform registration.
- *
  *  TODO:
  *   o Add hw rules to enforce rates, etc.
  *   o More testing with other codecs/machines.
@@ -112,9 +108,9 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
 }
 #endif
 
-static inline const charget_dai_name(int type)
+static inline const char *get_dai_name(int type)
 {
-       switch(type) {
+       switch (type) {
        case SND_SOC_DAI_AC97_BUS:
        case SND_SOC_DAI_AC97:
                return "AC97";
@@ -138,8 +134,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_dai_link *machine = rtd->dai;
        struct snd_soc_platform *platform = socdev->platform;
-       struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
+       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
+       struct snd_soc_dai *codec_dai = machine->codec_dai;
        int ret = 0;
 
        mutex_lock(&pcm_mutex);
@@ -182,9 +178,11 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        /* Check that the codec and cpu DAI's are compatible */
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                runtime->hw.rate_min =
-                       max(codec_dai->playback.rate_min, cpu_dai->playback.rate_min);
+                       max(codec_dai->playback.rate_min,
+                           cpu_dai->playback.rate_min);
                runtime->hw.rate_max =
-                       min(codec_dai->playback.rate_max, cpu_dai->playback.rate_max);
+                       min(codec_dai->playback.rate_max,
+                           cpu_dai->playback.rate_max);
                runtime->hw.channels_min =
                        max(codec_dai->playback.channels_min,
                                cpu_dai->playback.channels_min);
@@ -197,9 +195,11 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                        codec_dai->playback.rates & cpu_dai->playback.rates;
        } else {
                runtime->hw.rate_min =
-                       max(codec_dai->capture.rate_min, cpu_dai->capture.rate_min);
+                       max(codec_dai->capture.rate_min,
+                           cpu_dai->capture.rate_min);
                runtime->hw.rate_max =
-                       min(codec_dai->capture.rate_max, cpu_dai->capture.rate_max);
+                       min(codec_dai->capture.rate_max,
+                           cpu_dai->capture.rate_max);
                runtime->hw.channels_min =
                        max(codec_dai->capture.channels_min,
                                cpu_dai->capture.channels_min);
@@ -229,7 +229,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                goto machine_err;
        }
 
-       dbg("asoc: %s <-> %s info:\n",codec_dai->name, cpu_dai->name);
+       dbg("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
        dbg("asoc: rate mask 0x%x\n", runtime->hw.rates);
        dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
                runtime->hw.channels_max);
@@ -272,11 +272,11 @@ static void close_delayed_work(struct work_struct *work)
        struct snd_soc_device *socdev =
                container_of(work, struct snd_soc_device, delayed_work.work);
        struct snd_soc_codec *codec = socdev->codec;
-       struct snd_soc_codec_dai *codec_dai;
+       struct snd_soc_dai *codec_dai;
        int i;
 
        mutex_lock(&pcm_mutex);
-       for(i = 0; i < codec->num_dai; i++) {
+       for (i = 0; i < codec->num_dai; i++) {
                codec_dai = &codec->dai[i];
 
                dbg("pop wq checking: %s status: %s waiting: %s\n",
@@ -287,12 +287,12 @@ static void close_delayed_work(struct work_struct *work)
                /* are we waiting on this codec DAI stream */
                if (codec_dai->pop_wait == 1) {
 
-                       /* power down the codec to D1 if no longer active */
+                       /* Reduce power if no longer active */
                        if (codec->active == 0) {
                                dbg("pop wq D1 %s %s\n", codec->name,
                                        codec_dai->playback.stream_name);
-                               snd_soc_dapm_device_event(socdev,
-                                       SNDRV_CTL_POWER_D1);
+                               snd_soc_dapm_set_bias_level(socdev,
+                                       SND_SOC_BIAS_PREPARE);
                        }
 
                        codec_dai->pop_wait = 0;
@@ -300,12 +300,12 @@ static void close_delayed_work(struct work_struct *work)
                                codec_dai->playback.stream_name,
                                SND_SOC_DAPM_STREAM_STOP);
 
-                       /* power down the codec power domain if no longer active */
+                       /* Fall into standby if no longer active */
                        if (codec->active == 0) {
                                dbg("pop wq D3 %s %s\n", codec->name,
                                        codec_dai->playback.stream_name);
-                               snd_soc_dapm_device_event(socdev,
-                                       SNDRV_CTL_POWER_D3hot);
+                               snd_soc_dapm_set_bias_level(socdev,
+                                       SND_SOC_BIAS_STANDBY);
                        }
                }
        }
@@ -323,8 +323,8 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_dai_link *machine = rtd->dai;
        struct snd_soc_platform *platform = socdev->platform;
-       struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
+       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
+       struct snd_soc_dai *codec_dai = machine->codec_dai;
        struct snd_soc_codec *codec = socdev->codec;
 
        mutex_lock(&pcm_mutex);
@@ -365,8 +365,8 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
                        SND_SOC_DAPM_STREAM_STOP);
 
                if (codec->active == 0 && codec_dai->pop_wait == 0)
-                       snd_soc_dapm_device_event(socdev,
-                                               SNDRV_CTL_POWER_D3hot);
+                       snd_soc_dapm_set_bias_level(socdev,
+                                               SND_SOC_BIAS_STANDBY);
        }
 
        mutex_unlock(&pcm_mutex);
@@ -384,8 +384,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_dai_link *machine = rtd->dai;
        struct snd_soc_platform *platform = socdev->platform;
-       struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
+       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
+       struct snd_soc_dai *codec_dai = machine->codec_dai;
        struct snd_soc_codec *codec = socdev->codec;
        int ret = 0;
 
@@ -434,14 +434,14 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
                else {
                        codec_dai->pop_wait = 0;
                        cancel_delayed_work(&socdev->delayed_work);
-                       if (codec_dai->dai_ops.digital_mute)
-                               codec_dai->dai_ops.digital_mute(codec_dai, 0);
+                       snd_soc_dai_digital_mute(codec_dai, 0);
                }
        } else {
                /* no delayed work - do we need to power up codec */
-               if (codec->dapm_state != SNDRV_CTL_POWER_D0) {
+               if (codec->bias_level != SND_SOC_BIAS_ON) {
 
-                       snd_soc_dapm_device_event(socdev,  SNDRV_CTL_POWER_D1);
+                       snd_soc_dapm_set_bias_level(socdev,
+                                                   SND_SOC_BIAS_PREPARE);
 
                        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                                snd_soc_dapm_stream_event(codec,
@@ -452,9 +452,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
                                        codec_dai->capture.stream_name,
                                        SND_SOC_DAPM_STREAM_START);
 
-                       snd_soc_dapm_device_event(socdev, SNDRV_CTL_POWER_D0);
-                       if (codec_dai->dai_ops.digital_mute)
-                               codec_dai->dai_ops.digital_mute(codec_dai, 0);
+                       snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
+                       snd_soc_dai_digital_mute(codec_dai, 0);
 
                } else {
                        /* codec already powered - power on widgets */
@@ -466,8 +465,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
                                snd_soc_dapm_stream_event(codec,
                                        codec_dai->capture.stream_name,
                                        SND_SOC_DAPM_STREAM_START);
-                       if (codec_dai->dai_ops.digital_mute)
-                               codec_dai->dai_ops.digital_mute(codec_dai, 0);
+
+                       snd_soc_dai_digital_mute(codec_dai, 0);
                }
        }
 
@@ -488,8 +487,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_dai_link *machine = rtd->dai;
        struct snd_soc_platform *platform = socdev->platform;
-       struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
+       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
+       struct snd_soc_dai *codec_dai = machine->codec_dai;
        int ret = 0;
 
        mutex_lock(&pcm_mutex);
@@ -514,7 +513,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (cpu_dai->ops.hw_params) {
                ret = cpu_dai->ops.hw_params(substream, params);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: can't set interface %s hw params\n",
+                       printk(KERN_ERR "asoc: interface %s hw params failed\n",
                                cpu_dai->name);
                        goto interface_err;
                }
@@ -523,7 +522,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (platform->pcm_ops->hw_params) {
                ret = platform->pcm_ops->hw_params(substream, params);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: can't set platform %s hw params\n",
+                       printk(KERN_ERR "asoc: platform %s hw params failed\n",
                                platform->name);
                        goto platform_err;
                }
@@ -542,7 +541,7 @@ interface_err:
                codec_dai->ops.hw_free(substream);
 
 codec_err:
-       if(machine->ops && machine->ops->hw_free)
+       if (machine->ops && machine->ops->hw_free)
                machine->ops->hw_free(substream);
 
        mutex_unlock(&pcm_mutex);
@@ -558,15 +557,15 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_dai_link *machine = rtd->dai;
        struct snd_soc_platform *platform = socdev->platform;
-       struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
+       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
+       struct snd_soc_dai *codec_dai = machine->codec_dai;
        struct snd_soc_codec *codec = socdev->codec;
 
        mutex_lock(&pcm_mutex);
 
        /* apply codec digital mute */
-       if (!codec->active && codec_dai->dai_ops.digital_mute)
-               codec_dai->dai_ops.digital_mute(codec_dai, 1);
+       if (!codec->active)
+               snd_soc_dai_digital_mute(codec_dai, 1);
 
        /* free any machine hw params */
        if (machine->ops && machine->ops->hw_free)
@@ -593,8 +592,8 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_dai_link *machine = rtd->dai;
        struct snd_soc_platform *platform = socdev->platform;
-       struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
+       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
+       struct snd_soc_dai *codec_dai = machine->codec_dai;
        int ret;
 
        if (codec_dai->ops.trigger) {
@@ -631,16 +630,26 @@ static struct snd_pcm_ops soc_pcm_ops = {
 /* powers down audio subsystem for suspend */
 static int soc_suspend(struct platform_device *pdev, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_machine *machine = socdev->machine;
-       struct snd_soc_platform *platform = socdev->platform;
-       struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_machine *machine = socdev->machine;
+       struct snd_soc_platform *platform = socdev->platform;
+       struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
        struct snd_soc_codec *codec = socdev->codec;
        int i;
 
+       /* Due to the resume being scheduled into a workqueue we could
+       * suspend before that's finished - wait for it to complete.
+        */
+       snd_power_lock(codec->card);
+       snd_power_wait(codec->card, SNDRV_CTL_POWER_D0);
+       snd_power_unlock(codec->card);
+
+       /* we're going to block userspace touching us until resume completes */
+       snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot);
+
        /* mute any active DAC's */
-       for(i = 0; i < machine->num_links; i++) {
-               struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai;
+       for (i = 0; i < machine->num_links; i++) {
+               struct snd_soc_dai *dai = machine->dai_link[i].codec_dai;
                if (dai->dai_ops.digital_mute && dai->playback.active)
                        dai->dai_ops.digital_mute(dai, 1);
        }
@@ -652,8 +661,8 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
        if (machine->suspend_pre)
                machine->suspend_pre(pdev, state);
 
-       for(i = 0; i < machine->num_links; i++) {
-               struct snd_soc_cpu_dai  *cpu_dai = machine->dai_link[i].cpu_dai;
+       for (i = 0; i < machine->num_links; i++) {
+               struct snd_soc_dai  *cpu_dai = machine->dai_link[i].cpu_dai;
                if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97)
                        cpu_dai->suspend(pdev, cpu_dai);
                if (platform->suspend)
@@ -662,9 +671,9 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
 
        /* close any waiting streams and save state */
        run_delayed_work(&socdev->delayed_work);
-       codec->suspend_dapm_state = codec->dapm_state;
+       codec->suspend_bias_level = codec->bias_level;
 
-       for(i = 0; i < codec->num_dai; i++) {
+       for (i = 0; i < codec->num_dai; i++) {
                char *stream = codec->dai[i].playback.stream_name;
                if (stream != NULL)
                        snd_soc_dapm_stream_event(codec, stream,
@@ -678,8 +687,8 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
        if (codec_dev->suspend)
                codec_dev->suspend(pdev, state);
 
-       for(i = 0; i < machine->num_links; i++) {
-               struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+       for (i = 0; i < machine->num_links; i++) {
+               struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
                if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97)
                        cpu_dai->suspend(pdev, cpu_dai);
        }
@@ -690,21 +699,32 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
        return 0;
 }
 
-/* powers up audio subsystem after a suspend */
-static int soc_resume(struct platform_device *pdev)
+/* deferred resume work, so resume can complete before we finished
+ * setting our codec back up, which can be very slow on I2C
+ */
+static void soc_resume_deferred(struct work_struct *work)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_machine *machine = socdev->machine;
-       struct snd_soc_platform *platform = socdev->platform;
-       struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
+       struct snd_soc_device *socdev = container_of(work,
+                                                    struct snd_soc_device,
+                                                    deferred_resume_work);
+       struct snd_soc_machine *machine = socdev->machine;
+       struct snd_soc_platform *platform = socdev->platform;
+       struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
        struct snd_soc_codec *codec = socdev->codec;
+       struct platform_device *pdev = to_platform_device(socdev->dev);
        int i;
 
+       /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,
+        * so userspace apps are blocked from touching us
+        */
+
+       dev_info(socdev->dev, "starting resume work\n");
+
        if (machine->resume_pre)
                machine->resume_pre(pdev);
 
-       for(i = 0; i < machine->num_links; i++) {
-               struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+       for (i = 0; i < machine->num_links; i++) {
+               struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
                if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97)
                        cpu_dai->resume(pdev, cpu_dai);
        }
@@ -712,8 +732,8 @@ static int soc_resume(struct platform_device *pdev)
        if (codec_dev->resume)
                codec_dev->resume(pdev);
 
-       for(i = 0; i < codec->num_dai; i++) {
-               charstream = codec->dai[i].playback.stream_name;
+       for (i = 0; i < codec->num_dai; i++) {
+               char *stream = codec->dai[i].playback.stream_name;
                if (stream != NULL)
                        snd_soc_dapm_stream_event(codec, stream,
                                SND_SOC_DAPM_STREAM_RESUME);
@@ -723,15 +743,15 @@ static int soc_resume(struct platform_device *pdev)
                                SND_SOC_DAPM_STREAM_RESUME);
        }
 
-       /* unmute any active DAC's */
-       for(i = 0; i < machine->num_links; i++) {
-               struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai;
+       /* unmute any active DACs */
+       for (i = 0; i < machine->num_links; i++) {
+               struct snd_soc_dai *dai = machine->dai_link[i].codec_dai;
                if (dai->dai_ops.digital_mute && dai->playback.active)
                        dai->dai_ops.digital_mute(dai, 0);
        }
 
-       for(i = 0; i < machine->num_links; i++) {
-               struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+       for (i = 0; i < machine->num_links; i++) {
+               struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
                if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97)
                        cpu_dai->resume(pdev, cpu_dai);
                if (platform->resume)
@@ -741,6 +761,22 @@ static int soc_resume(struct platform_device *pdev)
        if (machine->resume_post)
                machine->resume_post(pdev);
 
+       dev_info(socdev->dev, "resume work completed\n");
+
+       /* userspace can access us now we are back as we were before */
+       snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0);
+}
+
+/* powers up audio subsystem after a suspend */
+static int soc_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+       dev_info(socdev->dev, "scheduling resume work\n");
+
+       if (!schedule_work(&socdev->deferred_resume_work))
+               dev_err(socdev->dev, "work item may be lost\n");
+
        return 0;
 }
 
@@ -760,33 +796,38 @@ static int soc_probe(struct platform_device *pdev)
 
        if (machine->probe) {
                ret = machine->probe(pdev);
-               if(ret < 0)
+               if (ret < 0)
                        return ret;
        }
 
        for (i = 0; i < machine->num_links; i++) {
-               struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+               struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
                if (cpu_dai->probe) {
-                       ret = cpu_dai->probe(pdev);
-                       if(ret < 0)
+                       ret = cpu_dai->probe(pdev, cpu_dai);
+                       if (ret < 0)
                                goto cpu_dai_err;
                }
        }
 
        if (codec_dev->probe) {
                ret = codec_dev->probe(pdev);
-               if(ret < 0)
+               if (ret < 0)
                        goto cpu_dai_err;
        }
 
        if (platform->probe) {
                ret = platform->probe(pdev);
-               if(ret < 0)
+               if (ret < 0)
                        goto platform_err;
        }
 
        /* DAPM stream work */
        INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work);
+#ifdef CONFIG_PM
+       /* deferred resume work */
+       INIT_WORK(&socdev->deferred_resume_work, soc_resume_deferred);
+#endif
+
        return 0;
 
 platform_err:
@@ -795,9 +836,9 @@ platform_err:
 
 cpu_dai_err:
        for (i--; i >= 0; i--) {
-               struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+               struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
                if (cpu_dai->remove)
-                       cpu_dai->remove(pdev);
+                       cpu_dai->remove(pdev, cpu_dai);
        }
 
        if (machine->remove)
@@ -824,9 +865,9 @@ static int soc_remove(struct platform_device *pdev)
                codec_dev->remove(pdev);
 
        for (i = 0; i < machine->num_links; i++) {
-               struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+               struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
                if (cpu_dai->remove)
-                       cpu_dai->remove(pdev);
+                       cpu_dai->remove(pdev, cpu_dai);
        }
 
        if (machine->remove)
@@ -852,8 +893,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
        struct snd_soc_dai_link *dai_link, int num)
 {
        struct snd_soc_codec *codec = socdev->codec;
-       struct snd_soc_codec_dai *codec_dai = dai_link->codec_dai;
-       struct snd_soc_cpu_dai *cpu_dai = dai_link->cpu_dai;
+       struct snd_soc_dai *codec_dai = dai_link->codec_dai;
+       struct snd_soc_dai *cpu_dai = dai_link->cpu_dai;
        struct snd_soc_pcm_runtime *rtd;
        struct snd_pcm *pcm;
        char new_name[64];
@@ -868,7 +909,7 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
        codec_dai->codec = socdev->codec;
 
        /* check client and interface hw capabilities */
-       sprintf(new_name, "%s %s-%s-%d",dai_link->stream_name, codec_dai->name,
+       sprintf(new_name, "%s %s-%s-%d", dai_link->stream_name, codec_dai->name,
                get_dai_name(cpu_dai->type), num);
 
        if (codec_dai->playback.channels_min)
@@ -879,7 +920,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
        ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback,
                capture, &pcm);
        if (ret < 0) {
-               printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
+               printk(KERN_ERR "asoc: can't create pcm for codec %s\n",
+                       codec->name);
                kfree(rtd);
                return ret;
        }
@@ -928,8 +970,9 @@ static ssize_t codec_reg_show(struct device *dev,
                step = codec->reg_cache_step;
 
        count += sprintf(buf, "%s registers\n", codec->name);
-       for(i = 0; i < codec->reg_cache_size; i += step)
-               count += sprintf(buf + count, "%2x: %4x\n", i, codec->read(codec, i));
+       for (i = 0; i < codec->reg_cache_size; i += step)
+               count += sprintf(buf + count, "%2x: %4x\n", i,
+                       codec->read(codec, i));
 
        return count;
 }
@@ -1072,7 +1115,7 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
        strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
 
        /* create the pcms */
-       for(i = 0; i < machine->num_links; i++) {
+       for (i = 0; i < machine->num_links; i++) {
                ret = soc_new_pcm(socdev, &machine->dai_link[i], i);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: can't create pcm %s\n",
@@ -1102,7 +1145,7 @@ int snd_soc_register_card(struct snd_soc_device *socdev)
        struct snd_soc_machine *machine = socdev->machine;
        int ret = 0, i, ac97 = 0, err = 0;
 
-       for(i = 0; i < machine->num_links; i++) {
+       for (i = 0; i < machine->num_links; i++) {
                if (socdev->machine->dai_link[i].init) {
                        err = socdev->machine->dai_link[i].init(codec);
                        if (err < 0) {
@@ -1111,7 +1154,7 @@ int snd_soc_register_card(struct snd_soc_device *socdev)
                                continue;
                        }
                }
-               if (socdev->machine->dai_link[i].codec_dai->type == 
+               if (socdev->machine->dai_link[i].codec_dai->type ==
                        SND_SOC_DAI_AC97_BUS)
                        ac97 = 1;
        }
@@ -1122,7 +1165,7 @@ int snd_soc_register_card(struct snd_soc_device *socdev)
 
        ret = snd_card_register(codec->card);
        if (ret < 0) {
-               printk(KERN_ERR "asoc: failed to register soundcard for codec %s\n",
+               printk(KERN_ERR "asoc: failed to register soundcard for %s\n",
                                codec->name);
                goto out;
        }
@@ -1146,7 +1189,7 @@ int snd_soc_register_card(struct snd_soc_device *socdev)
 
        err = device_create_file(socdev->dev, &dev_attr_codec_reg);
        if (err < 0)
-               printk(KERN_WARNING "asoc: failed to add codec sysfs entries\n");
+               printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
 
        mutex_unlock(&codec->mutex);
 
@@ -1166,13 +1209,13 @@ void snd_soc_free_pcms(struct snd_soc_device *socdev)
 {
        struct snd_soc_codec *codec = socdev->codec;
 #ifdef CONFIG_SND_SOC_AC97_BUS
-       struct snd_soc_codec_dai *codec_dai;
+       struct snd_soc_dai *codec_dai;
        int i;
 #endif
 
        mutex_lock(&codec->mutex);
 #ifdef CONFIG_SND_SOC_AC97_BUS
-       for(i = 0; i < codec->num_dai; i++) {
+       for (i = 0; i < codec->num_dai; i++) {
                codec_dai = &codec->dai[i];
                if (codec_dai->type == SND_SOC_DAI_AC97_BUS && codec->ac97) {
                        soc_ac97_dev_unregister(codec);
@@ -1282,7 +1325,8 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
        for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
                ;
        val = snd_soc_read(codec, e->reg);
-       ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
+       ucontrol->value.enumerated.item[0]
+               = (val >> e->shift_l) & (bitmask - 1);
        if (e->shift_l != e->shift_r)
                ucontrol->value.enumerated.item[1] =
                        (val >> e->shift_r) & (bitmask - 1);
@@ -1576,7 +1620,8 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
        val = val << shift;
        val2 = val2 << shift;
 
-       if ((err = snd_soc_update_bits(codec, reg, val_mask, val)) < 0)
+       err = snd_soc_update_bits(codec, reg, val_mask, val);
+       if (err < 0)
                return err;
 
        err = snd_soc_update_bits(codec, reg2, val_mask, val2);
@@ -1584,6 +1629,204 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
 
+/**
+ * snd_soc_info_volsw_s8 - signed mixer info callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about a signed mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       int max = (signed char)((kcontrol->private_value >> 16) & 0xff);
+       int min = (signed char)((kcontrol->private_value >> 24) & 0xff);
+
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = max-min;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8);
+
+/**
+ * snd_soc_get_volsw_s8 - signed mixer get callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to get the value of a signed mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       int reg = kcontrol->private_value & 0xff;
+       int min = (signed char)((kcontrol->private_value >> 24) & 0xff);
+       int val = snd_soc_read(codec, reg);
+
+       ucontrol->value.integer.value[0] =
+               ((signed char)(val & 0xff))-min;
+       ucontrol->value.integer.value[1] =
+               ((signed char)((val >> 8) & 0xff))-min;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_get_volsw_s8);
+
+/**
+ * snd_soc_put_volsw_sgn - signed mixer put callback
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to set the value of a signed mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       int reg = kcontrol->private_value & 0xff;
+       int min = (signed char)((kcontrol->private_value >> 24) & 0xff);
+       unsigned short val;
+
+       val = (ucontrol->value.integer.value[0]+min) & 0xff;
+       val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8;
+
+       return snd_soc_update_bits(codec, reg, 0xffff, val);
+}
+EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
+
+/**
+ * snd_soc_dai_set_sysclk - configure DAI system or master clock.
+ * @dai: DAI
+ * @clk_id: DAI specific clock ID
+ * @freq: new clock frequency in Hz
+ * @dir: new clock direction - input/output.
+ *
+ * Configures the DAI master (MCLK) or system (SYSCLK) clocking.
+ */
+int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+       unsigned int freq, int dir)
+{
+       if (dai->dai_ops.set_sysclk)
+               return dai->dai_ops.set_sysclk(dai, clk_id, freq, dir);
+       else
+               return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
+
+/**
+ * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
+ * @dai: DAI
+ * @clk_id: DAI specific clock divider ID
+ * @div: new clock divisor.
+ *
+ * Configures the clock dividers. This is used to derive the best DAI bit and
+ * frame clocks from the system or master clock. It's best to set the DAI bit
+ * and frame clocks as low as possible to save system power.
+ */
+int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
+       int div_id, int div)
+{
+       if (dai->dai_ops.set_clkdiv)
+               return dai->dai_ops.set_clkdiv(dai, div_id, div);
+       else
+               return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
+
+/**
+ * snd_soc_dai_set_pll - configure DAI PLL.
+ * @dai: DAI
+ * @pll_id: DAI specific PLL ID
+ * @freq_in: PLL input clock frequency in Hz
+ * @freq_out: requested PLL output clock frequency in Hz
+ *
+ * Configures and enables PLL to generate output clock based on input clock.
+ */
+int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
+       int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+       if (dai->dai_ops.set_pll)
+               return dai->dai_ops.set_pll(dai, pll_id, freq_in, freq_out);
+       else
+               return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
+
+/**
+ * snd_soc_dai_set_fmt - configure DAI hardware audio format.
+ * @dai: DAI
+ * @clk_id: DAI specific clock ID
+ * @fmt: SND_SOC_DAIFMT_ format value.
+ *
+ * Configures the DAI hardware format and clocking.
+ */
+int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       if (dai->dai_ops.set_fmt)
+               return dai->dai_ops.set_fmt(dai, fmt);
+       else
+               return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
+
+/**
+ * snd_soc_dai_set_tdm_slot - configure DAI TDM.
+ * @dai: DAI
+ * @mask: DAI specific mask representing used slots.
+ * @slots: Number of slots in use.
+ *
+ * Configures a DAI for TDM operation. Both mask and slots are codec and DAI
+ * specific.
+ */
+int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
+       unsigned int mask, int slots)
+{
+       if (dai->dai_ops.set_sysclk)
+               return dai->dai_ops.set_tdm_slot(dai, mask, slots);
+       else
+               return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
+
+/**
+ * snd_soc_dai_set_tristate - configure DAI system or master clock.
+ * @dai: DAI
+ * @tristate: tristate enable
+ *
+ * Tristates the DAI so that others can use it.
+ */
+int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
+{
+       if (dai->dai_ops.set_sysclk)
+               return dai->dai_ops.set_tristate(dai, tristate);
+       else
+               return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
+
+/**
+ * snd_soc_dai_digital_mute - configure DAI system or master clock.
+ * @dai: DAI
+ * @mute: mute enable
+ *
+ * Mutes the DAI DAC.
+ */
+int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+       if (dai->dai_ops.digital_mute)
+               return dai->dai_ops.digital_mute(dai, mute);
+       else
+               return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
+
 static int __devinit snd_soc_init(void)
 {
        printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION);
@@ -1592,7 +1835,7 @@ static int __devinit snd_soc_init(void)
 
 static void snd_soc_exit(void)
 {
-       platform_driver_unregister(&soc_driver);
+       platform_driver_unregister(&soc_driver);
 }
 
 module_init(snd_soc_init);
index af3326c635041da0c852ecc0ca11ea91212484f1..2c87061c2a6b4d7b9c35d7479d782462a0d8b3c1 100644 (file)
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  *
- *  Revision history
- *    12th Aug 2005   Initial version.
- *    25th Oct 2005   Implemented path power domain.
- *    18th Dec 2005   Implemented machine and stream level power domain.
- *
  *  Features:
  *    o Changes power status of internal codec blocks depending on the
  *      dynamic configuration of codec internal audio paths and active
 #include <sound/initval.h>
 
 /* debug */
-#define DAPM_DEBUG 0
-#if DAPM_DEBUG
+#ifdef DEBUG
 #define dump_dapm(codec, action) dbg_dump_dapm(codec, action)
-#define dbg(format, arg...) printk(format, ## arg)
 #else
 #define dump_dapm(codec, action)
-#define dbg(format, arg...)
-#endif
-
-#define POP_DEBUG 0
-#if POP_DEBUG
-#define POP_TIME 500 /* 500 msecs - change if pop debug is too fast */
-#define pop_wait(time) schedule_timeout_uninterruptible(msecs_to_jiffies(time))
-#define pop_dbg(format, arg...) printk(format, ## arg); pop_wait(POP_TIME)
-#else
-#define pop_dbg(format, arg...)
-#define pop_wait(time)
 #endif
 
 /* dapm power sequences - make this per codec in the future */
@@ -85,6 +67,28 @@ static int dapm_status = 1;
 module_param(dapm_status, int, 0);
 MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
 
+static unsigned int pop_time;
+
+static void pop_wait(void)
+{
+       if (pop_time)
+               schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
+}
+
+static void pop_dbg(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+
+       if (pop_time) {
+               vprintk(fmt, args);
+               pop_wait();
+       }
+
+       va_end(args);
+}
+
 /* create a new dapm widget */
 static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
        const struct snd_soc_dapm_widget *_widget)
@@ -222,11 +226,12 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
        change = old != new;
        if (change) {
                pop_dbg("pop test %s : %s in %d ms\n", widget->name,
-                       widget->power ? "on" : "off", POP_TIME);
+                       widget->power ? "on" : "off", pop_time);
                snd_soc_write(codec, widget->reg, new);
-               pop_wait(POP_TIME);
+               pop_wait();
        }
-       dbg("reg %x old %x new %x change %d\n", widget->reg, old, new, change);
+       pr_debug("reg %x old %x new %x change %d\n", widget->reg,
+                old, new, change);
        return change;
 }
 
@@ -447,6 +452,25 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
        return con;
 }
 
+/*
+ * Handler for generic register modifier widget.
+ */
+int dapm_reg_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event)
+{
+       unsigned int val;
+
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               val = w->on_val;
+       else
+               val = w->off_val;
+
+       snd_soc_update_bits(w->codec, -(w->reg + 1),
+                           w->mask << w->shift, val << w->shift);
+
+       return 0;
+}
+
 /*
  * Scan each dapm widget for complete audio path.
  * A complete path is a route that has valid endpoints i.e.:-
@@ -565,8 +589,8 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
                        /* call any power change event handlers */
                        if (power_change) {
                                if (w->event) {
-                                       dbg("power %s event for %s flags %x\n",
-                                               w->power ? "on" : "off", w->name, w->event_flags);
+                                       pr_debug("power %s event for %s flags %x\n",
+                                                w->power ? "on" : "off", w->name, w->event_flags);
                                        if (power) {
                                                /* power up event */
                                                if (w->event_flags & SND_SOC_DAPM_PRE_PMU) {
@@ -608,7 +632,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
        return ret;
 }
 
-#if DAPM_DEBUG
+#ifdef DEBUG
 static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
 {
        struct snd_soc_dapm_widget *w;
@@ -693,8 +717,10 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
                        path->connect = 0; /* old connection must be powered down */
        }
 
-       if (found)
+       if (found) {
                dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
+               dump_dapm(widget->codec, "mux power update");
+       }
 
        return 0;
 }
@@ -730,8 +756,10 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
                break;
        }
 
-       if (found)
+       if (found) {
                dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
+               dump_dapm(widget->codec, "mixer power update");
+       }
 
        return 0;
 }
@@ -768,21 +796,18 @@ static ssize_t dapm_widget_show(struct device *dev,
                }
        }
 
-       switch(codec->dapm_state){
-       case SNDRV_CTL_POWER_D0:
-               state = "D0";
+       switch (codec->bias_level) {
+       case SND_SOC_BIAS_ON:
+               state = "On";
                break;
-       case SNDRV_CTL_POWER_D1:
-               state = "D1";
+       case SND_SOC_BIAS_PREPARE:
+               state = "Prepare";
                break;
-       case SNDRV_CTL_POWER_D2:
-               state = "D2";
+       case SND_SOC_BIAS_STANDBY:
+               state = "Standby";
                break;
-       case SNDRV_CTL_POWER_D3hot:
-               state = "D3hot";
-               break;
-       case SNDRV_CTL_POWER_D3cold:
-               state = "D3cold";
+       case SND_SOC_BIAS_OFF:
+               state = "Off";
                break;
        }
        count += sprintf(buf + count, "PM State: %s\n", state);
@@ -792,20 +817,51 @@ static ssize_t dapm_widget_show(struct device *dev,
 
 static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
 
+/* pop/click delay times */
+static ssize_t dapm_pop_time_show(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", pop_time);
+}
+
+static ssize_t dapm_pop_time_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
+
+{
+       unsigned long val;
+
+       if (strict_strtoul(buf, 10, &val) >= 0)
+               pop_time = val;
+       else
+               printk(KERN_ERR "Unable to parse pop_time setting\n");
+
+       return count;
+}
+
+static DEVICE_ATTR(dapm_pop_time, 0744, dapm_pop_time_show,
+                  dapm_pop_time_store);
+
 int snd_soc_dapm_sys_add(struct device *dev)
 {
        int ret = 0;
 
-       if (dapm_status)
+       if (dapm_status) {
                ret = device_create_file(dev, &dev_attr_dapm_widget);
 
+               if (ret == 0)
+                       ret = device_create_file(dev, &dev_attr_dapm_pop_time);
+       }
+
        return ret;
 }
 
 static void snd_soc_dapm_sys_remove(struct device *dev)
 {
-       if (dapm_status)
+       if (dapm_status) {
+               device_remove_file(dev, &dev_attr_dapm_pop_time);
                device_remove_file(dev, &dev_attr_dapm_widget);
+       }
 }
 
 /* free all dapm widgets and resources */
@@ -826,8 +882,25 @@ static void dapm_free_widgets(struct snd_soc_codec *codec)
        }
 }
 
+static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
+       char *pin, int status)
+{
+       struct snd_soc_dapm_widget *w;
+
+       list_for_each_entry(w, &codec->dapm_widgets, list) {
+               if (!strcmp(w->name, pin)) {
+                       pr_debug("dapm: %s: pin %s\n", codec->name, pin);
+                       w->connected = status;
+                       return 0;
+               }
+       }
+
+       pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin);
+       return -EINVAL;
+}
+
 /**
- * snd_soc_dapm_sync_endpoints - scan and power dapm paths
+ * snd_soc_dapm_sync - scan and power dapm paths
  * @codec: audio codec
  *
  * Walks all dapm audio paths and powers widgets according to their
@@ -835,27 +908,16 @@ static void dapm_free_widgets(struct snd_soc_codec *codec)
  *
  * Returns 0 for success.
  */
-int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec)
+int snd_soc_dapm_sync(struct snd_soc_codec *codec)
 {
-       return dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
+       int ret = dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
+       dump_dapm(codec, "sync");
+       return ret;
 }
-EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_endpoints);
+EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
 
-/**
- * snd_soc_dapm_connect_input - connect dapm widgets
- * @codec: audio codec
- * @sink: name of target widget
- * @control: mixer control name
- * @source: name of source name
- *
- * Connects 2 dapm widgets together via a named audio path. The sink is
- * the widget receiving the audio signal, whilst the source is the sender
- * of the audio signal.
- *
- * Returns 0 for success else error.
- */
-int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
-       const char * control, const char *source)
+static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
+       const char *sink, const char *control, const char *source)
 {
        struct snd_soc_dapm_path *path;
        struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
@@ -957,8 +1019,63 @@ err:
        kfree(path);
        return ret;
 }
+
+/**
+ * snd_soc_dapm_connect_input - connect dapm widgets
+ * @codec: audio codec
+ * @sink: name of target widget
+ * @control: mixer control name
+ * @source: name of source name
+ *
+ * Connects 2 dapm widgets together via a named audio path. The sink is
+ * the widget receiving the audio signal, whilst the source is the sender
+ * of the audio signal.
+ *
+ * This function has been deprecated in favour of snd_soc_dapm_add_routes().
+ *
+ * Returns 0 for success else error.
+ */
+int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
+       const char *control, const char *source)
+{
+       return snd_soc_dapm_add_route(codec, sink, control, source);
+}
 EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input);
 
+/**
+ * snd_soc_dapm_add_routes - Add routes between DAPM widgets
+ * @codec: codec
+ * @route: audio routes
+ * @num: number of routes
+ *
+ * Connects 2 dapm widgets together via a named audio path. The sink is
+ * the widget receiving the audio signal, whilst the source is the sender
+ * of the audio signal.
+ *
+ * Returns 0 for success else error. On error all resources can be freed
+ * with a call to snd_soc_card_free().
+ */
+int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
+                           const struct snd_soc_dapm_route *route, int num)
+{
+       int i, ret;
+
+       for (i = 0; i < num; i++) {
+               ret = snd_soc_dapm_add_route(codec, route->sink,
+                                            route->control, route->source);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to add route %s->%s\n",
+                              route->source,
+                              route->sink);
+                       return ret;
+               }
+               route++;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes);
+
 /**
  * snd_soc_dapm_new_widgets - add new dapm widgets
  * @codec: audio codec
@@ -1233,6 +1350,33 @@ int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
 
+/**
+ * snd_soc_dapm_new_controls - create new dapm controls
+ * @codec: audio codec
+ * @widget: widget array
+ * @num: number of widgets
+ *
+ * Creates new DAPM controls based upon the templates.
+ *
+ * Returns 0 for success else error.
+ */
+int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
+       const struct snd_soc_dapm_widget *widget,
+       int num)
+{
+       int i, ret;
+
+       for (i = 0; i < num; i++) {
+               ret = snd_soc_dapm_new_control(codec, widget);
+               if (ret < 0)
+                       return ret;
+               widget++;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
+
+
 /**
  * snd_soc_dapm_stream_event - send a stream event to the dapm core
  * @codec: audio codec
@@ -1257,8 +1401,8 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
        {
                if (!w->sname)
                        continue;
-               dbg("widget %s\n %s stream %s event %d\n", w->name, w->sname,
-                       stream, event);
+               pr_debug("widget %s\n %s stream %s event %d\n",
+                        w->name, w->sname, stream, event);
                if (strstr(w->sname, stream)) {
                        switch(event) {
                        case SND_SOC_DAPM_STREAM_START:
@@ -1294,53 +1438,81 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
 EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
 
 /**
- * snd_soc_dapm_device_event - send a device event to the dapm core
+ * snd_soc_dapm_set_bias_level - set the bias level for the system
  * @socdev: audio device
- * @event: device event
+ * @level: level to configure
  *
- * Sends a device event to the dapm core. The core then makes any
- * necessary machine or codec power changes..
+ * Configure the bias (power) levels for the SoC audio device.
  *
  * Returns 0 for success else error.
  */
-int snd_soc_dapm_device_event(struct snd_soc_device *socdev, int event)
+int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
+                               enum snd_soc_bias_level level)
 {
        struct snd_soc_codec *codec = socdev->codec;
        struct snd_soc_machine *machine = socdev->machine;
+       int ret = 0;
 
-       if (machine->dapm_event)
-               machine->dapm_event(machine, event);
-       if (codec->dapm_event)
-               codec->dapm_event(codec, event);
-       return 0;
+       if (machine->set_bias_level)
+               ret = machine->set_bias_level(machine, level);
+       if (ret == 0 && codec->set_bias_level)
+               ret = codec->set_bias_level(codec, level);
+
+       return ret;
 }
-EXPORT_SYMBOL_GPL(snd_soc_dapm_device_event);
 
 /**
- * snd_soc_dapm_set_endpoint - set audio endpoint status
+ * snd_soc_dapm_enable_pin - enable pin.
+ * @snd_soc_codec: SoC codec
+ * @pin: pin name
+ *
+ * Enables input/output pin and it's parents or children widgets iff there is
+ * a valid audio route and active audio stream.
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin)
+{
+       return snd_soc_dapm_set_pin(codec, pin, 1);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin);
+
+/**
+ * snd_soc_dapm_disable_pin - disable pin.
+ * @codec: SoC codec
+ * @pin: pin name
+ *
+ * Disables input/output pin and it's parents or children widgets.
+ * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
+ * do any widget power switching.
+ */
+int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin)
+{
+       return snd_soc_dapm_set_pin(codec, pin, 0);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin);
+
+/**
+ * snd_soc_dapm_get_pin_status - get audio pin status
  * @codec: audio codec
- * @endpoint: audio signal endpoint (or start point)
- * @status: point status
+ * @pin: audio signal pin endpoint (or start point)
  *
- * Set audio endpoint status - connected or disconnected.
+ * Get audio pin status - connected or disconnected.
  *
- * Returns 0 for success else error.
+ * Returns 1 for connected otherwise 0.
  */
-int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
-       char *endpoint, int status)
+int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin)
 {
        struct snd_soc_dapm_widget *w;
 
        list_for_each_entry(w, &codec->dapm_widgets, list) {
-               if (!strcmp(w->name, endpoint)) {
-                       w->connected = status;
-                       return 0;
-               }
+               if (!strcmp(w->name, pin))
+                       return w->connected;
        }
 
-       return -ENODEV;
+       return 0;
 }
-EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);
+EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
 
 /**
  * snd_soc_dapm_free - free dapm resources
index 079e22af074c08cf45bdc0bc0559f327869dcce8..d75deba5617db05dc02407b6c669d61ee1695a5e 100644 (file)
@@ -1,11 +1,17 @@
 # ALSA Sparc drivers
 
-menu "ALSA Sparc devices"
-       depends on SND!=n && SPARC
+menuconfig SND_SPARC
+       bool "Sparc sound devices"
+       depends on SPARC
+       default y
+       help
+         Support for sound devices specific to Sun SPARC architectures.
+
+if SND_SPARC
 
 config SND_SUN_AMD7930
        tristate "Sun AMD7930"
-       depends on SBUS && SND
+       depends on SBUS
        select SND_PCM
        help
          Say Y here to include support for AMD7930 sound device on Sun.
@@ -15,7 +21,6 @@ config SND_SUN_AMD7930
 
 config SND_SUN_CS4231
        tristate "Sun CS4231"
-       depends on SND
        select SND_PCM
        help
          Say Y here to include support for CS4231 sound device on Sun.
@@ -25,7 +30,7 @@ config SND_SUN_CS4231
 
 config SND_SUN_DBRI
        tristate "Sun DBRI"
-       depends on SND && SBUS
+       depends on SBUS
        select SND_PCM
        help
          Say Y here to include support for DBRI sound device on Sun.
@@ -33,4 +38,4 @@ config SND_SUN_DBRI
          To compile this driver as a module, choose M here: the module
          will be called snd-sun-dbri.
 
-endmenu
+endif  # SND_SPARC
index 3d00e0797b11899042e5af98fa64a224ebc13597..ee2e1b4f35514dfa999dabcccfb689bf9ecd077d 100644 (file)
@@ -2490,7 +2490,7 @@ static void dbri_debug_read(struct snd_info_entry *entry,
 }
 #endif
 
-void __devinit snd_dbri_proc(struct snd_card *card)
+static void __devinit snd_dbri_proc(struct snd_card *card)
 {
        struct snd_dbri *dbri = card->private_data;
        struct snd_info_entry *entry;
index 0d08c29213c8ffa9db4ceea7195ba01e1c746053..e6485be2e6f7a70c1762041ca89e323eb5c5c3e4 100644 (file)
@@ -1,7 +1,13 @@
 #SPI drivers
 
-menu "SPI devices"
-       depends on SND != n
+menuconfig SND_SPI
+       bool "SPI sound devices"
+       depends on SPI
+       default y
+       help
+         Support for sound devices connected via the SPI bus.
+
+if SND_SPI
 
 config SND_AT73C213
        tristate "Atmel AT73C213 DAC driver"
@@ -28,4 +34,5 @@ config SND_AT73C213_TARGET_BITRATE
 
          Set to 48000 Hz by default.
 
-endmenu
+endif  # SND_SPI
+
index 9351b8a765b9c6de7f5069e2c3c6d09b0f54a50d..ffcdc8f4ef66de645e41ffa2881d12fc1ce5e0e9 100644 (file)
@@ -1,11 +1,16 @@
 # ALSA USB drivers
 
-menu "USB devices"
-       depends on SND!=n && USB!=n
+menuconfig SND_USB
+       bool "USB sound devices"
+       depends on USB
+       default y
+       help
+         Support for sound devices connected via the USB bus.
+
+if SND_USB && USB
 
 config SND_USB_AUDIO
        tristate "USB Audio/MIDI driver"
-       depends on SND && USB
        select SND_HWDEP
        select SND_RAWMIDI
        select SND_PCM
@@ -18,7 +23,7 @@ config SND_USB_AUDIO
 
 config SND_USB_USX2Y
        tristate "Tascam US-122, US-224 and US-428 USB driver"
-       depends on SND && USB && (X86 || PPC || ALPHA)
+       depends on X86 || PPC || ALPHA
        select SND_HWDEP
        select SND_RAWMIDI
        select SND_PCM
@@ -31,7 +36,6 @@ config SND_USB_USX2Y
 
 config SND_USB_CAIAQ
        tristate "Native Instruments USB audio devices"
-       depends on SND && USB
        select SND_HWDEP
        select SND_RAWMIDI
        select SND_PCM
@@ -63,5 +67,5 @@ config SND_USB_CAIAQ_INPUT
           * Native Instruments Kore Controller 2
           * Native Instruments Audio Kontrol 1
 
-endmenu
+endif  # SND_USB
 
index 24970a5c888f6e2f26453712a3b12cfd544b5355..b3a60332583534735cfd54504cc8141cdb4587cd 100644 (file)
@@ -637,6 +637,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
        switch (dev->chip.usb_id) {
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
+       case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_SESSIONIO):
                dev->samplerates |= SNDRV_PCM_RATE_88200;
                dev->samplerates |= SNDRV_PCM_RATE_192000;
                break;
index a972f77bd7856e6d9bf400f79923bb7d1ecafebc..83175083e50f8c60852cc0250fd26ace2038afba 100644 (file)
 #endif
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.6");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.8");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
                         "{Native Instruments, RigKontrol3},"
                         "{Native Instruments, Kore Controller},"
                         "{Native Instruments, Kore Controller 2},"
-                        "{Native Instruments, Audio Kontrol 1}"
-                        "{Native Instruments, Audio 8 DJ}}");
+                        "{Native Instruments, Audio Kontrol 1},"
+                        "{Native Instruments, Audio 8 DJ},"
+                        "{Native Instruments, Session I/O}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
 static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
@@ -110,6 +111,11 @@ static struct usb_device_id snd_usb_id_table[] = {
                .idVendor =     USB_VID_NATIVEINSTRUMENTS,
                .idProduct =    USB_PID_AUDIO8DJ
        },
+       {
+               .match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+               .idVendor =     USB_VID_NATIVEINSTRUMENTS,
+               .idProduct =    USB_PID_SESSIONIO
+       },
        { /* terminator */ }
 };
 
index 96a491379c6062b540ff2a063f64735f1e2f640e..f9fbdbae269d21491d2dc84f726cfc12cdf51261 100644 (file)
@@ -11,6 +11,7 @@
 #define USB_PID_KORECONTROLLER2        0x4712
 #define USB_PID_AK1            0x0815
 #define USB_PID_AUDIO8DJ       0x1978
+#define USB_PID_SESSIONIO      0x1915
 
 #define EP1_BUFSIZE 64
 #define CAIAQ_USB_STR_LEN 0xff
index 410be4aff1baed739dac2d88fa178d58f640e993..b8cfb7c2276872a05f40a07a0ed57d0b57357e8e 100644 (file)
@@ -819,10 +819,6 @@ static const char *usb_error_string(int err)
                return "device disabled";
        case -EHOSTUNREACH:
                return "device suspended";
-#ifndef CONFIG_USB_EHCI_SPLIT_ISO
-       case -ENOSYS:
-               return "enable CONFIG_USB_EHCI_SPLIT_ISO to play through a hub";
-#endif
        case -EINVAL:
        case -EAGAIN:
        case -EFBIG:
index 82a8d14c26af26671513990291db6426c2de05c4..9ea726c049c6c1f5d7b891e2e25bcd62ff934e40 100644 (file)
@@ -210,6 +210,11 @@ YAMAHA_DEVICE(0x1042, NULL),
 YAMAHA_DEVICE(0x1043, NULL),
 YAMAHA_DEVICE(0x1044, NULL),
 YAMAHA_DEVICE(0x1045, NULL),
+YAMAHA_INTERFACE(0x104e, 0, NULL),
+YAMAHA_DEVICE(0x104f, NULL),
+YAMAHA_DEVICE(0x1050, NULL),
+YAMAHA_DEVICE(0x1051, NULL),
+YAMAHA_DEVICE(0x1052, NULL),
 YAMAHA_DEVICE(0x2000, "DGP-7"),
 YAMAHA_DEVICE(0x2001, "DGP-5"),
 YAMAHA_DEVICE(0x2002, NULL),
@@ -1379,6 +1384,39 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 
+{
+       /* Roland SonicCell */
+       USB_DEVICE(0x0582, 0x00c2),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .vendor_name = "Roland",
+               .product_name = "SonicCell",
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const struct snd_usb_midi_endpoint_info) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+
+
 /* Guillemot devices */
 {
        /*
index 1dcf9f3d110717582db05ce3bc9f7f808a2e32ba..44589088941fa591c9ac2b149a6bab4af20e4994 100644 (file)
@@ -278,7 +278,7 @@ static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int gsi)
 
        ent->fields.remote_irr = 0;
        if (!ent->fields.mask && (ioapic->irr & (1 << gsi)))
-               ioapic_deliver(ioapic, gsi);
+               ioapic_service(ioapic, gsi);
 }
 
 void kvm_ioapic_update_eoi(struct kvm *kvm, int vector)